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