Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RDFDisplay.cxx
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (C) 1995-2021, Rene Brun and Fons Rademakers. *
3 * All rights reserved. *
4 * *
5 * For the licensing terms see $ROOTSYS/LICENSE. *
6 * For the list of contributors see $ROOTSYS/README/CREDITS. *
7 *************************************************************************/
8
10#include "TInterpreter.h"
11
12#include <iomanip>
13#include <limits>
14
15namespace ROOT {
16namespace Internal {
17namespace RDF {
18
19
20/**
21 * \class ROOT::Internal::RDF::RDisplayElement
22 * \ingroup dataframe
23 * Helper class to let Display print compact tabular representations of the events
24 *
25 * This class is internal and not meant to be explicitly instantiated by the user.
26 * It is needed during printing to understand if a value can be
27 * skipped or must be printed. Each RDisplayElement represents a cell.
28 */
29
30////////////////////////////////////////////////////////////////////////////
31/// Constructor
32/// \param[in] representation The representation string
33RDisplayElement::RDisplayElement(const std::string &representation) : fRepresentation(representation)
34{
35 SetPrint();
36}
37
38////////////////////////////////////////////////////////////////////////////
39/// Constructor assuming an empty representation to be printed
41{
42 SetPrint();
43}
44
45////////////////////////////////////////////////////////////////////////////
46/// Flag this cell as to be printed
48{
50}
51
52////////////////////////////////////////////////////////////////////////////
53/// Flag this cell as to be skipped
55{
57}
58
59////////////////////////////////////////////////////////////////////////////
60/// Flag this cell to be replaced by "..."
62{
64}
65
66////////////////////////////////////////////////////////////////////////////
67/// Return if the cell has to be printed
69{
71}
72
73////////////////////////////////////////////////////////////////////////////
74/// Return if the cell has to be skipped
76{
78}
79
80////////////////////////////////////////////////////////////////////////////
81/// Return if the cell has to be replaced by "..."
83{
85}
86
87const std::string &RDisplayElement::GetRepresentation() const
88{
89 return fRepresentation;
90}
91
93{
94 return fRepresentation.empty();
95}
96
97} // namespace RDF
98} // namespace Internal
99
100namespace RDF {
101
103{
104 // If the current element is wider than the widest element found, update the width
105 if (fWidths[fCurrentColumn] < w) {
106 if (w > std::numeric_limits<unsigned short>::max()) {
107 w = std::numeric_limits<unsigned short>::max();
108 }
109 fWidths[fCurrentColumn] = (unsigned short) w;
110 }
111}
112
113void RDisplay::AddToRow(const std::string &stringEle)
114{
115 // If the current element is wider than the widest element found, update the width
116 EnsureCurrentColumnWidth(stringEle.length());
117
118 // Save the element...
120
121 // ...and move to the next
122 MovePosition();
123}
124
125void RDisplay::AddCollectionToRow(const std::vector<std::string> &collection)
126{
127 auto row = fCurrentRow;
128 // For each element of the collection, save it. The first element will be in the current row, next ones will have
129 // their own row.
130 size_t collectionSize = collection.size();
131 for (size_t index = 0; index < collectionSize; ++index) {
132 auto stringEle = collection[index];
133 auto element = DElement_t(stringEle);
134
135 // Update the width if this element is the biggest found
136 EnsureCurrentColumnWidth(stringEle.length());
137
138 if (index < fNMaxCollectionElements) {
139 // Do nothing, by default DisplayElement is printed
140 } else if (index == fNMaxCollectionElements) {
141 element.SetDots();
142 // Be sure the "..." fit
144 } else {
145 // In the Print(), after the dots, all element will just be ignored.
146 element.SetIgnore();
147 }
148
149 // Save the element
150 fTable[row][fCurrentColumn] = element;
151 ++row;
152
153 if (index != collectionSize - 1 && fTable.size() <= row) {
154 // This is not the last element, prepare the next row for the next element, if not already done by another
155 // collection
156 fTable.push_back(std::vector<DElement_t>(fNColumns));
157 }
158 }
159 fNextRow = (fNextRow > row) ? fNextRow : row;
160 MovePosition();
161}
162
164{
165 // Go to the next element. If it is outside the row, just go the first element of the next row.
167 if (fCurrentColumn == fNColumns) {
169 fCurrentColumn = 0;
170 fNextRow = fCurrentRow + 1;
171 fTable.push_back(std::vector<DElement_t>(fNColumns));
172 }
173}
174
175RDisplay::RDisplay(const VecStr_t &columnNames, const VecStr_t &types, size_t nMaxCollectionElements)
176 : fTypes(types), fWidths(columnNames.size(), 0), fRepresentations(columnNames.size()),
177 fCollectionsRepresentations(columnNames.size()), fNColumns(columnNames.size()),
178 fNMaxCollectionElements(nMaxCollectionElements)
179{
180 // Add the first row with the names of the columns
181 fTable.push_back(std::vector<DElement_t>(columnNames.size()));
182 AddToRow("Row"); // Change the name of the first column from rdfentry_ to Row
183 for (auto name = columnNames.begin() + 1; name != columnNames.end(); ++name) {
184 AddToRow(*name);
185 }
186}
187
189{
190 size_t totalWidth = 0;
191
192 auto size = fWidths.size();
193 for (size_t i = 0; i < size; ++i) {
194 // The total width of the printed table also includes two spaces and a |,
195 // which are 3 extra characters per entry on the table.
196 totalWidth += fWidths[i] + 3;
197 if (totalWidth > fgMaxWidth) {
198 return size - i;
199 }
200 }
201 return 0;
202}
203
204std::string RDisplay::DashesBetweenLines(size_t lastColToPrint, bool allColumnsFit) const
205{
206 std::string DashesStr = "+";
207 for (size_t i = 0; i < lastColToPrint; ++i){
208 DashesStr += std::string(fWidths[i] + 2, '-'); // Need to add 2, because of the spaces, when printing
209 DashesStr += "+";
210 }
211 if (!allColumnsFit){ // The Print method has ... in case of long columns, which need to be surrounded by dashes
212 DashesStr += "-----+";
213 }
214 DashesStr += "\n";
215 return DashesStr;
216}
217
218void RDisplay::Print() const
219{
220 size_t columnsToPrint = fNColumns;
221 const size_t columnsToShorten = GetNColumnsToShorten();
222 bool allColumnsFit = true;
223 if (fNColumns > 2u && columnsToShorten > 0u){ // Checking 2u, since first column is keeping track of rows
224 if (fNColumns > columnsToShorten + 1) { // Provided that the first column is "Row",
225 // columnsToShorten is guaranteed to be smaller than fNColumns
226 // Need to check if actual first column is being shortened
227 columnsToPrint = fNColumns - columnsToShorten;
228 } else { // Table has many columns and the first column is very wide;
229 // Thus, the first column is only the Row column and the actual first column is printed
230 columnsToPrint = 2;
231 }
232 Info("Print", "Only showing %lu columns out of %lu\n", columnsToPrint, fNColumns);
233 allColumnsFit = false;
234 }
235
237 Info("Print", "No collections shown since fNMaxCollectionElements is %lu\n", fNMaxCollectionElements);
238
239 auto nrRows = fTable.size();
240 std::cout << DashesBetweenLines(columnsToPrint, allColumnsFit); // Print dashes in the top of the table
241 for (size_t rowIndex = 0; rowIndex < nrRows; ++rowIndex) {
242 auto &row = fTable[rowIndex];
243
244 std::stringstream stringRow;
245 bool isRowEmpty = true; // It may happen during compacting that some rows are empty, this happens for example if
246 // collections have different size. Thanks to this flag, these rows are just ignored.
247 if (std::any_of(row[0].GetRepresentation().begin(), row[0].GetRepresentation().end(), ::isdigit)){
248 // Check if the first column (Row) contains a digit to use it as indication for new row/entry
249 std::cout << DashesBetweenLines(columnsToPrint, allColumnsFit);
250 }
251 stringRow << "| ";
252 for (size_t columnIndex = 0; columnIndex < columnsToPrint; ++columnIndex) {
253 const auto &element = row[columnIndex];
254 std::string printedElement = "";
255
256 if (element.IsDot()) {
257 printedElement = "...";
258 } else if (element.IsPrint()) {
259 printedElement = element.GetRepresentation();
260 } else { // IsIgnore
261 // Do nothing, printedElement remains ""
262 }
263 if (!printedElement.empty()) {
264 // Found at least one element, so the row is not empty.
265 isRowEmpty = false;
266 }
267
268 stringRow << std::left << std::setw(fWidths[columnIndex]) << std::setfill(fgSeparator) << printedElement
269 << " | ";
270 }
271 if (!isRowEmpty) {
272 if (!allColumnsFit){ // If there are column(s), that do not fit, a single column of dots is displayed
273 // in the right end of each (non-empty) row.
274 stringRow << "... | ";
275 }
276 std::cout << stringRow.str() << std::endl;
277 }
278 }
279 std::cout << DashesBetweenLines(columnsToPrint, allColumnsFit); // Print dashes in the bottom of the table
280}
281
282std::string RDisplay::AsString() const
283{
284 // This method works as Print() but without any check on collection. It just returns a string with the whole
285 // representation
286 std::stringstream stringRepresentation;
287 auto size = fWidths.size(); // To be used for the number of columns passed to the DashesBetweenLines
288 stringRepresentation << DashesBetweenLines(size, true); // 'true' since no columns are skipped
289 for (auto row : fTable) {
290 if (std::any_of(row[0].GetRepresentation().begin(), row[0].GetRepresentation().end(), ::isdigit)){
291 stringRepresentation << DashesBetweenLines(size, true);
292 }
293 stringRepresentation << "| ";
294 for (size_t i = 0; i < row.size(); ++i) {
295 stringRepresentation << std::left << std::setw(fWidths[i]) << std::setfill(fgSeparator)
296 << row[i].GetRepresentation() << " | ";
297 }
298 stringRepresentation << "\n";
299 }
300 stringRepresentation << DashesBetweenLines(size, true);
301 return stringRepresentation.str();
302}
303
304} // namespace RDF
305} // namespace ROOT
l unsigned short
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
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.
void AddCollectionToRow(const VecStr_t &collection)
Adds a collection to the table.
size_t fCurrentColumn
Column that is being filled.
Definition RDisplay.hxx:89
ROOT::Internal::RDF::RDisplayElement DElement_t
Definition RDisplay.hxx:70
RDisplay(const VecStr_t &columnNames, const VecStr_t &types, size_t nMaxCollectionElements)
Creates an RDisplay to print the event values.
size_t fNMaxCollectionElements
Definition RDisplay.hxx:91
std::vector< std::vector< DElement_t > > fTable
String representation of the data to be printed.
Definition RDisplay.hxx:77
std::string AsString() const
Returns the representation as a string.
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
Maximum width of the table that Print() displays.
Definition RDisplay.hxx:72
void EnsureCurrentColumnWidth(size_t w)
size_t fNextRow
Next row to be filled.
Definition RDisplay.hxx:88
std::string DashesBetweenLines(size_t lastColToPrint, bool allColumnsFit) const
Generate dashes between entries in Print() and AsString() Methods.
std::vector< std::string > VecStr_t
Definition RDisplay.hxx:69
void Print() const
Prints the representation to the standard output.
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...