Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RDFDisplay.cxx
Go to the documentation of this file.
2#include "TInterpreter.h"
3
4#include <iomanip>
5#include <limits>
6
7namespace ROOT {
8namespace Internal {
9namespace RDF {
10
11
12/**
13 * \class ROOT::Internal::RDF::RDisplayElement
14 * \ingroup dataframe
15 * Helper class to let Display print compact tabular representations of the events
16 *
17 * This class is internal and not meant to be explicitly instantiated by the user.
18 * It is needed during printing to understand if a value can be
19 * skipped or must be printed. Each RDisplayElement represents a cell.
20 */
21
22////////////////////////////////////////////////////////////////////////////
23/// Constructor
24/// \param[in] representation The representation string
25RDisplayElement::RDisplayElement(const std::string &representation) : fRepresentation(representation)
26{
27 SetPrint();
28}
29
30////////////////////////////////////////////////////////////////////////////
31/// Constructor assuming an empty representation to be printed
33{
34 SetPrint();
35}
36
37////////////////////////////////////////////////////////////////////////////
38/// Flag this cell as to be printed
40{
42}
43
44////////////////////////////////////////////////////////////////////////////
45/// Flag this cell as to be skipped
47{
49}
50
51////////////////////////////////////////////////////////////////////////////
52/// Flag this cell to be replaced by "..."
54{
56}
57
58////////////////////////////////////////////////////////////////////////////
59/// Return if the cell has to be printed
61{
63}
64
65////////////////////////////////////////////////////////////////////////////
66/// Return if the cell has to be skipped
68{
70}
71
72////////////////////////////////////////////////////////////////////////////
73/// Return if the cell has to be replaced by "..."
75{
77}
78
79const std::string &RDisplayElement::GetRepresentation() const
80{
81 return fRepresentation;
82}
83
85{
86 return fRepresentation.empty();
87}
88
89} // namespace RDF
90} // namespace Internal
91
92namespace RDF {
93
94void RDisplay::EnsureCurrentColumnWidth(size_t w)
95{
96 // If the current element is wider than the widest element found, update the width
97 if (fWidths[fCurrentColumn] < w) {
98 if (w > std::numeric_limits<unsigned short>::max()) {
99 w = std::numeric_limits<unsigned short>::max();
100 }
101 fWidths[fCurrentColumn] = (unsigned short) w;
102 }
103}
104
105void RDisplay::AddToRow(const std::string &stringEle)
106{
107 // If the current element is wider than the widest element found, update the width
108 EnsureCurrentColumnWidth(stringEle.length());
109
110 // Save the element...
112
113 // ...and move to the next
114 MovePosition();
115}
116
117void RDisplay::AddCollectionToRow(const std::vector<std::string> &collection)
118{
119 auto row = fCurrentRow;
120 // For each element of the collection, save it. The first element will be in the current row, next ones will have
121 // their own row.
122 size_t collectionSize = collection.size();
123 for (size_t index = 0; index < collectionSize; ++index) {
124 auto stringEle = collection[index];
125 auto element = DElement_t(stringEle);
126
127 // Update the width if this element is the biggest found
128 EnsureCurrentColumnWidth(stringEle.length());
129
130 if (index == 0 || index == collectionSize - 1) {
131 // Do nothing, by default DisplayElement is printed
132 } else if (index == 1) {
133 element.SetDots();
134 // Be sure the "..." fit
136 } else {
137 // In the Print(), after the dots, all element will just be ignored except the last one.
138 element.SetIgnore();
139 }
140
141 // Save the element
142 fTable[row][fCurrentColumn] = element;
143 ++row;
144
145 if (index != collectionSize - 1 && fTable.size() <= row) {
146 // This is not the last element, prepare the next row for the next element, if not already done by another
147 // collection
148 fTable.push_back(std::vector<DElement_t>(fNColumns));
149 }
150 }
151 fNextRow = (fNextRow > row) ? fNextRow : row;
152 MovePosition();
153}
154
155void RDisplay::MovePosition()
156{
157 // Go to the next element. If it is outside the row, just go the first element of the next row.
159 if (fCurrentColumn == fNColumns) {
161 fCurrentColumn = 0;
162 fNextRow = fCurrentRow + 1;
163 fTable.push_back(std::vector<DElement_t>(fNColumns));
164 }
165}
166
167RDisplay::RDisplay(const VecStr_t &columnNames, const VecStr_t &types, int entries)
168 : fTypes(types), fWidths(columnNames.size(), 0), fRepresentations(columnNames.size()),
169 fCollectionsRepresentations(columnNames.size()), fNColumns(columnNames.size()), fEntries(entries)
170{
171
172 // Add the first row with the names of the columns
173 fTable.push_back(std::vector<DElement_t>(columnNames.size()));
174 for (auto name : columnNames) {
175 AddToRow(name);
176 }
177}
178
179size_t RDisplay::GetNColumnsToShorten() const
180{
181 size_t totalWidth = 0;
182
183 auto size = fWidths.size();
184 for (size_t i = 0; i < size; ++i) {
185 totalWidth += fWidths[i];
186 if (totalWidth > fgMaxWidth) {
187 return size - i;
188 }
189 }
190
191 return 0;
192}
193
194void RDisplay::Print() const
195{
196 auto columnsToPrint =
197 fNColumns - GetNColumnsToShorten(); // Get the number of columns that fit in the characters limit
198 std::vector<bool> hasPrintedNext(fNColumns,
199 false); // Keeps track if the collection as already been shortened, allowing to skip
200 // all elements until the next printable element.
201
202 if (columnsToPrint < fNColumns)
203 Info("Print", "Only showing %lu columns out of %lu\n", columnsToPrint, fNColumns);
204
205 auto nrRows = fTable.size();
206 for (size_t rowIndex = 0; rowIndex < nrRows; ++rowIndex) {
207 auto &row = fTable[rowIndex];
208
209 std::stringstream stringRow;
210 bool isRowEmpty = true; // It may happen during compacting that some rows are empty, this happens for example if
211 // collections have different size. Thanks to this flag, these rows are just ignored.
212 for (size_t columnIndex = 0; columnIndex < columnsToPrint; ++columnIndex) {
213 const auto &element = row[columnIndex];
214 std::string printedElement = "";
215
216 if (element.IsDot()) {
217 printedElement = "...";
218 } else if (element.IsPrint()) {
219 // Maybe the element is part of a collection that is being shortened, and so it was already printed.
220 if (!hasPrintedNext[columnIndex]) {
221 printedElement = element.GetRepresentation();
222 }
223 hasPrintedNext[columnIndex] =
224 false; // Encountered "next printable element", shortening can start again when needed.
225 } else { // IsIgnore
226 // Shortening is starting here. Print directly the last element, to have something like 1 ... 3, and don't
227 // print anything else.
228 if (!hasPrintedNext[columnIndex]) {
229 size_t i = rowIndex + 1; // Starting from the next row...
230 for (; !fTable[i][columnIndex].IsPrint(); ++i) {
231 // .. look for the first element that can be printed, it will be the last of the collection.
232 }
233 printedElement = fTable[i][columnIndex].GetRepresentation(); // Print the element
234 hasPrintedNext[columnIndex] = true; // And start ignoring anything else until the next collection.
235 }
236 }
237 if (!printedElement.empty()) {
238 // Found at least one element, so the row is not empty.
239 isRowEmpty = false;
240 }
241
242 stringRow << std::left << std::setw(fWidths[columnIndex]) << std::setfill(fgSeparator) << printedElement
243 << " | ";
244 }
245 if (!isRowEmpty) {
246 std::cout << stringRow.str() << std::endl;
247 }
248 }
249}
250
251std::string RDisplay::AsString() const
252{
253 // This method works as Print() but without any check on collection. It just returns a string with the whole
254 // representation
255 std::stringstream stringRepresentation;
256 for (auto row : fTable) {
257 for (size_t i = 0; i < row.size(); ++i) {
258 stringRepresentation << std::left << std::setw(fWidths[i]) << std::setfill(fgSeparator)
259 << row[i].GetRepresentation() << " | ";
260 }
261 stringRepresentation << "\n";
262 }
263 return stringRepresentation.str();
264}
265
266} // namespace RDF
267} // namespace ROOT
l unsigned short
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:220
char name[80]
Definition TGX11.cxx:110
bool IsIgnore() const
Return if the cell has to be skipped.
bool IsDot() const
Return if the cell has to be replaced by "...".
const std::string & GetRepresentation() const
bool IsPrint() const
Return if the cell has to be printed.
void SetDots()
Flag this cell to be replaced by "...".
void SetPrint()
Flag this cell as to be printed.
void SetIgnore()
Flag this cell as to be skipped.
RDisplayElement()
Constructor assuming an empty representation to be printed.
size_t fCurrentColumn
Column that is being filled.
Definition RDisplay.hxx:89
ROOT::Internal::RDF::RDisplayElement DElement_t
Definition RDisplay.hxx:70
std::vector< std::vector< DElement_t > > fTable
String representation of the data to be printed.
Definition RDisplay.hxx:77
void AddToRow(const std::string &stringEle)
Adds a single element to the next slot in the table.
size_t fCurrentRow
Row that is being filled.
Definition RDisplay.hxx:87
void MovePosition()
Moves to the next cell.
std::vector< unsigned short > fWidths
Tracks the maximum width of each column, based on the largest element.
Definition RDisplay.hxx:78
static constexpr unsigned fgMaxWidth
Definition RDisplay.hxx:72
void EnsureCurrentColumnWidth(size_t w)
size_t fNextRow
Next row to be filled.
Definition RDisplay.hxx:88
std::vector< std::string > VecStr_t
Definition RDisplay.hxx:69
size_t GetNColumnsToShorten() const
Get the number of columns that do NOT fit in the characters limit.
static constexpr char fgSeparator
Spacing used to align the table entries.
Definition RDisplay.hxx:71
size_t fNColumns
Number of columns to be printed.
Definition RDisplay.hxx:85
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...