Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RTreeMapBase.cxx
Go to the documentation of this file.
1/// \file RTreeMapBase.cxx
2/// \ingroup TreeMap ROOT7
3/// \author Patryk Tymoteusz Pilichowski <patryk.tymoteusz.pilichowski@cern.ch>
4/// \date 2025-08-21
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2025, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
16#include <ROOT/RTreeMapBase.hxx>
17
18#include <cmath>
19#include <iomanip>
20#include <iostream>
21#include <unordered_map>
22#include <algorithm>
23
24static constexpr float kIndentationOffset = 0.005f;
25static constexpr float kPadTextOffset = 0.004f;
26static constexpr float kTextSizeFactor = 0.009f;
27static constexpr const char *kUnits[] = {"B", "KB", "MB", "GB", "TB", "PB", "EB"};
28
29using namespace ROOT::Experimental;
30
31static uint64_t ComputeFnv(const std::string &str)
32{
33 uint64_t h = 14695981039346656037ULL;
34 for (char c : str)
35 h = (h ^ static_cast<uint8_t>(c)) * 1099511628211ULL;
36 return h;
37}
38
39static RTreeMapBase::RGBColor ComputeColor(const std::string &str)
40{
41 const uint64_t hash = ComputeFnv(str);
42 return RTreeMapBase::RGBColor((hash >> 16) & 0xFF, (hash >> 8) & 0xFF, hash & 0xFF);
43}
44
45static std::string GetFloatStr(const float &n, const uint8_t &precision)
46{
47 std::stringstream stream;
48 stream << std::fixed << std::setprecision(precision) << n;
49 return stream.str();
50}
51
52static std::string GetDataStr(uint64_t bytes)
53{
54 const uint64_t order = std::log10(bytes) / 3.0f;
55 const std::string unit = kUnits[order];
56 const float finalSize = static_cast<float>(bytes) / std::pow(1000, order);
57 return GetFloatStr(finalSize, 2) + unit;
58}
59
60static std::vector<std::pair<std::string, uint64_t>> GetDiskOccupation(const std::vector<RTreeMapBase::Node> &nodes)
61{
62 std::unordered_map<std::string, uint64_t> acc;
63 for (const auto &node : nodes) {
64 if (node.fNChildren > 0)
65 continue;
66 acc[node.fType] += node.fSize;
67 }
68
69 std::vector<std::pair<std::string, uint64_t>> vec;
70 vec.reserve(acc.size());
71 for (auto &p : acc)
72 vec.emplace_back(std::move(p.first), p.second);
73
74 std::sort(vec.begin(), vec.end(), [](const auto &a, const auto &b) { return a.second > b.second; });
75 return vec;
76}
77
78/* algorithm: https://vanwijk.win.tue.nl/stm.pdf */
79static float ComputeWorstRatio(const std::vector<RTreeMapBase::Node> &row, float width, float height,
80 uint64_t totalSize, bool horizontalRows)
81{
82 if (row.empty())
83 return 0.0f;
84 uint64_t sumRow = 0;
85 for (const auto &child : row)
86 sumRow += child.fSize;
87 if (sumRow == 0)
88 return 0.0f;
89 float worstRatio = 0.0f;
90 for (const auto &child : row) {
91 float ratio = horizontalRows ? static_cast<float>(child.fSize * width * totalSize) / (sumRow * sumRow * height)
92 : static_cast<float>(child.fSize * height * totalSize) / (sumRow * sumRow * width);
93 float aspectRatio = std::max(ratio, 1.0f / ratio);
96 }
97 return worstRatio;
98}
99
100static std::vector<std::pair<RTreeMapBase::Node, RTreeMapBase::Rect>>
101SquarifyChildren(const std::vector<RTreeMapBase::Node> &children, RTreeMapBase::Rect rect, bool horizontalRows,
102 uint64_t totalSize)
103{
104 float width = rect.fTopRight.x - rect.fBottomLeft.x;
105 float height = rect.fTopRight.y - rect.fBottomLeft.y;
106 std::vector<RTreeMapBase::Node> remainingChildren = children;
108 [](const RTreeMapBase::Node &a, const RTreeMapBase::Node &b) { return a.fSize > b.fSize; });
109 std::vector<std::pair<RTreeMapBase::Node, RTreeMapBase::Rect>> result;
111 while (!remainingChildren.empty()) {
112 std::vector<RTreeMapBase::Node> row;
113 float currentWorstRatio = std::numeric_limits<float>::max();
114 float remainingWidth = rect.fTopRight.x - remainingBegin.x;
115 float remainingHeight = rect.fTopRight.y - remainingBegin.y;
116 if (remainingWidth <= 0 || remainingHeight <= 0)
117 break;
118 while (!remainingChildren.empty()) {
119 row.push_back(remainingChildren.front());
123 remainingChildren.insert(remainingChildren.begin(), row.back());
124 row.pop_back();
125 break;
126 }
128 }
129 uint64_t sumRow = 0;
130 for (const auto &child : row)
131 sumRow += child.fSize;
132 if (sumRow == 0)
133 continue;
134 float dimension = horizontalRows ? (static_cast<float>(sumRow) / totalSize * height)
135 : (static_cast<float>(sumRow) / totalSize * width);
136 float position = 0.0f;
137 for (const auto &child : row) {
138 float childDimension = static_cast<float>(child.fSize) / sumRow * (horizontalRows ? width : height);
144 ? RTreeMapBase::Vec2{remainingBegin.x + position + childDimension, remainingBegin.y + dimension}
145 : RTreeMapBase::Vec2{remainingBegin.x + dimension, remainingBegin.y + position + childDimension};
146 result.push_back({child, {childBegin, childEnd}});
147 position += childDimension;
148 }
149 if (horizontalRows)
150 remainingBegin.y += dimension;
151 else
152 remainingBegin.x += dimension;
153 }
154 return result;
155}
157{
159
160 if (fNodes.empty())
161 return;
162 const uint64_t totalSize = fNodes[0].fSize;
163 if (totalSize == 0)
164 return;
165
166 uint8_t counter = 0;
167 for (const auto &entry : diskOccupation) {
168 const auto &typeName = entry.first;
169 const uint64_t entrySize = entry.second;
170 if (entrySize == 0)
171 continue;
172
173 const auto offset = 0.835f, factor = 0.05f;
174 const auto posY = offset - counter * factor;
175
176 AddBox(Rect(Vec2(offset, posY), Vec2(offset + factor, posY - factor)), ComputeColor(typeName));
177
178 const float percent = (entrySize / static_cast<float>(totalSize)) * 100.0f;
179 const auto content = "(" + GetDataStr(entrySize) + " / " + GetDataStr(totalSize) + ")";
180
181 float currOffset = 0.0125f;
182 for (const auto &currContent : {typeName, content, GetFloatStr(percent, 2) + "%"}) {
184 currOffset += 0.01f;
185 }
186
187 counter++;
188 }
189}
190
192{
194 RTreeMapBase::Vec2(rect.fTopRight.x, rect.fTopRight.y));
195 bool isLeaf = (element.fNChildren == 0);
197 AddBox(drawRect, boxColor, 0.15f);
198
199 const std::string label = element.fName + " (" + GetDataStr(element.fSize) + ")";
200 const Vec2 &labelPos = isLeaf ? Vec2((drawRect.fBottomLeft.x + drawRect.fTopRight.x) / 2.0f,
201 (drawRect.fBottomLeft.y + drawRect.fTopRight.y) / 2.0f)
202 : Vec2(drawRect.fBottomLeft.x + kPadTextOffset, drawRect.fTopRight.y - kPadTextOffset);
203
204 float rectWidth = rect.fTopRight.x - rect.fBottomLeft.x;
205 float rectHeight = rect.fTopRight.y - rect.fBottomLeft.y;
206 float textSize = std::min(std::min(rectWidth, rectHeight) * 0.1f, kTextSizeFactor);
207 AddText(labelPos, label, textSize, RTreeMapBase::RGBColor(255, 255, 255), isLeaf);
208
209 if (!isLeaf) {
212 RTreeMapBase::Rect(RTreeMapBase::Vec2(rect.fBottomLeft.x + indent, rect.fBottomLeft.y + indent),
213 RTreeMapBase::Vec2(rect.fTopRight.x - indent, rect.fTopRight.y - indent * 4.0f));
214 std::vector<RTreeMapBase::Node> children;
215 for (std::uint64_t i = 0; i < element.fNChildren; ++i)
216 children.push_back(fNodes[element.fChildrenIdx + i]);
217 uint64_t totalSize = 0;
218 for (const auto &child : children)
219 totalSize += child.fSize;
220 if (totalSize == 0)
221 return;
222 float width = innerRect.fTopRight.x - innerRect.fBottomLeft.x;
223 float height = innerRect.fTopRight.y - innerRect.fBottomLeft.y;
224 bool horizontalRows = width > height;
226 for (const auto &[child, childRect] : childRects)
228 }
229}
#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