Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RDisplay.hxx
Go to the documentation of this file.
1// Author: Enrico Guiraud, Danilo Piparo CERN, Massimo Tumolo Politecnico di Torino 08/2018
2
3/*************************************************************************
4 * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10
11#ifndef ROOT_RDFDISPLAYER
12#define ROOT_RDFDISPLAYER
13
14#include "ROOT/RDF/Utils.hxx" // IsDataContainer, InterpreterCalc
15#include "ROOT/RVec.hxx"
16#include "ROOT/TypeTraits.hxx"
17#include "TClassEdit.h"
18
19#include <vector>
20#include <string>
21#include <sstream>
22#include <type_traits>
23
24namespace ROOT {
25namespace Internal {
26namespace RDF {
27
28template<typename T>
30std::string PrettyPrintAddr(const void *const addr);
31
33private:
35 std::string fRepresentation;
37
38public:
39 RDisplayElement(const std::string &representation);
41 void SetPrint();
42 void SetIgnore();
43 void SetDots();
44 bool IsPrint() const;
45 bool IsIgnore() const;
46 bool IsDot() const;
47 const std::string &GetRepresentation() const;
48 bool IsEmpty() const;
49};
50} // namespace RDF
51} // namespace Internal
52
53namespace RDF {
54
55/**
56 * \class ROOT::RDF::RDisplay
57 * \ingroup dataframe
58 * This class is the textual representation of the content of a columnar dataset.
59 *
60 * This class is provided to the user, and it can be used to print on screen
61 * the entries of the dataset requested through the Display action in a compact
62 * representation or to return the full representation of the events as a string.
63 * In order to apply proper formatting the content is buffered in memory as strings.
64 */
65class RDisplay {
66 template<typename T>
68private:
69 using VecStr_t = std::vector<std::string>;
71 static constexpr char fgSeparator = ' '; ///< Spacing used to align the table entries
72 static constexpr unsigned fgMaxWidth = 100; ///< Maximum width of the table that Print() displays
73
74 VecStr_t fTypes; ///< This attribute stores the type of each column. It is needed by the interpreter to print it.
75 std::vector<bool> fIsCollection; ///< True if the column contains a collection. Collections are treated differently
76 ///< during the printing.
77 std::vector<std::vector<DElement_t>> fTable; ///< String representation of the data to be printed.
78 std::vector<unsigned short> fWidths; ///< Tracks the maximum width of each column, based on the largest element.
79
80 VecStr_t fRepresentations; ///< Used by the JITted code to store the string representation of the data.
81 std::vector<VecStr_t> fCollectionsRepresentations; ///< Used by the JITted code to store the string representation of
82 ///< the data in case of collection. Each row corresponds to a
83 ///< column, each column to a value of the collection.
84
85 size_t fNColumns; ///< Number of columns to be printed
86
87 size_t fCurrentRow = 0; ///< Row that is being filled
88 size_t fNextRow = 1; ///< Next row to be filled.
89 size_t fCurrentColumn = 0; ///< Column that is being filled.
90
91 size_t fNMaxCollectionElements = 10; // threshold on number of elements in collections to be Print()
92
93 ////////////////////////////////////////////////////////////////////////////
94 /// Appends a cling::printValue call to the stringstream
95 /// This overload works for non-collection data types which are also not
96 /// trivially representable as strings.
97 /// \tparam T the type of the event to convert
98 /// \param[in] stream Where the conversion function call will be chained.
99 /// \param[in] element The event to convert to its string representation
100 /// \param[in] index To which column the event belongs to
101 /// \return false, the event is not a collection
102 template <typename T,
103 std::enable_if_t<!std::is_arithmetic_v<T> && !ROOT::Internal::RDF::IsDataContainer<T>::value, int> = 0>
104 bool AddInterpreterString(std::stringstream &stream, T &element, const int &index)
105 {
106 stream << "*((std::string*)" << ROOT::Internal::RDF::PrettyPrintAddr(&(fRepresentations[index]))
107 << ") = cling::printValue((" << fTypes[index] << "*)" << ROOT::Internal::RDF::PrettyPrintAddr(&element)
108 << ");";
109 return false;
110 }
111
112 ////////////////////////////////////////////////////////////////////////////
113 /// Appends a string if the T type is an arithmetic type.
114 /// This overload works for arithmetic data types that are trivially
115 /// convertible to string.
116 /// \tparam T the type of the event to convert
117 /// \param[in] element The event to convert to its string representation
118 /// \param[in] index To which column the event belongs to
119 /// \return false, the event is not a collection
120 template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
121 bool AddInterpreterString(std::stringstream &, T &element, const int &index)
122 {
123 // Short-circuit the logic and just insert the string representation of
124 // the symple type at the right index.
125 fRepresentations[index] = std::to_string(element);
126 return false;
127 }
128
129 ////////////////////////////////////////////////////////////////////////////
130 /// Appends a string if the T type is boolean.
131 /// \param[in] element The event to convert to its string representation
132 /// \param[in] index To which column the event belongs to
133 /// \return false, the event is not a collection
134 bool AddInterpreterString(std::stringstream &, bool &element, const int &index)
135 {
136 // Short-circuit the logic and just insert the string representation of
137 // the boolean value at the right index.
138 fRepresentations[index] = (element ? "true" : "false");
139 return false;
140 }
141
142 ////////////////////////////////////////////////////////////////////////////
143 /// Appends collection.size() cling::printValue calls to the stringstream.
144 /// \tparam T the type of the event to convert
145 /// \param[in] stream Where the conversion function call will be chained.
146 /// \param[in] collection The event to convert to its string representation
147 /// \param[in] index To which column the event belongs to
148 /// \return true, the event is a collection
149 /// This function chains a sequence of call to cling::printValue, one for each element of the collection.
150 template <typename T, std::enable_if_t<ROOT::Internal::RDF::IsDataContainer<T>::value &&
151 !std::is_arithmetic_v<typename T::value_type>,
152 int> = 0>
153 bool AddInterpreterString(std::stringstream &stream, T &collection, const int &index)
154 {
155 size_t collectionSize = std::distance(std::begin(collection), std::end(collection));
156 // Prepare the row to contain as many elements as the number of elements in the collection
157 fCollectionsRepresentations[index] = VecStr_t(collectionSize);
158
159 // Use GetSplit to get the encapsulated type of the collection. For example, GetSplit on
160 // std::vector<std::vector<int>> will return std::vector<int>
162 int nestedLoc = 0;
163 TClassEdit::GetSplit(fTypes[index].c_str(), output, nestedLoc);
164
165 // For each element, append a call and feed the proper type returned by GetSplit
166 for (size_t i = 0; i < collectionSize; ++i) {
167 stream << "*((std::string*)" << ROOT::Internal::RDF::PrettyPrintAddr(&(fCollectionsRepresentations[index][i]))
168 << ") = cling::printValue((" << output[1] << "*)"
169 << ROOT::Internal::RDF::PrettyPrintAddr(&(collection[i])) << ");";
170 }
171 return true;
172 }
173
174 ////////////////////////////////////////////////////////////////////////////
175 /// Represent a collection of values as a collection of strings.
176 /// \tparam T the type of the event to convert. This must be a collection of
177 /// values of arithmetic type, but not boolean.
178 /// \param[in] collection The event to convert to its string representation
179 /// \param[in] index To which column the event belongs to
180 /// \return true, the event is a collection
181 template <typename T, std::enable_if_t<ROOT::Internal::RDF::IsDataContainer<T>::value &&
182 std::is_arithmetic_v<typename T::value_type> &&
183 !std::is_same_v<typename T::value_type, bool>,
184 int> = 0>
185 bool AddInterpreterString(std::stringstream &, T &collection, const int &index)
186 {
187 auto collectionSize = std::distance(std::begin(collection), std::end(collection));
188 VecStr_t collectionRepr(collectionSize);
189 std::generate(collectionRepr.begin(), collectionRepr.end(), [i = 0, &collection]() mutable {
190 auto valRepr = std::to_string(collection[i]);
191 i++;
192 return valRepr;
193 });
194 fCollectionsRepresentations[index] = std::move(collectionRepr);
195 return true;
196 }
197
198 ////////////////////////////////////////////////////////////////////////////
199 /// Represent a collection of booleans as a collection of strings.
200 /// \tparam T the type of the event to convert. This must be a collection of
201 /// boolean values.
202 /// \param[in] collection The event to convert to its string representation
203 /// \param[in] index To which column the event belongs to
204 /// \return true, the event is a collection
205 template <typename T, std::enable_if_t<ROOT::Internal::RDF::IsDataContainer<T>::value &&
206 std::is_same_v<typename T::value_type, bool>,
207 int> = 0>
208 bool AddInterpreterString(std::stringstream &, T &collection, const int &index)
209 {
210 auto collectionSize = std::distance(std::begin(collection), std::end(collection));
211 VecStr_t collectionRepr(collectionSize);
212 std::generate(collectionRepr.begin(), collectionRepr.end(), [i = 0, &collection]() mutable {
213 auto valRepr = (collection[i] ? "true" : "false");
214 i++;
215 return valRepr;
216 });
217 fCollectionsRepresentations[index] = std::move(collectionRepr);
218 return true;
219 }
220
221 ////////////////////////////////////////////////////////////////////////////
222 /// AddInterpreterString overload for arrays of chars.
223 ///
224 /// \param[in] charArr The character array to convert to string representation
225 /// \param[in] index To which column the event belongs
226 /// \return false, the event is not a collection
227 ///
228 /// This specialization for arrays of characters skips the cling::printValue
229 /// (i.e. appends nothing to the stream) and directly writes to fRepresentations the
230 /// string representation of the array of chars.
231 bool AddInterpreterString(std::stringstream &, ROOT::RVec<char> &charArr, const int &index)
232 {
233 // if null-terminated char array, do not copy the null terminator into std::string, it makes columns misaligned.
234 const auto length = charArr[charArr.size()-1] == '\0' ? charArr.size() - 1 : charArr.size();
235 const std::string arrAsStr(charArr.data(), length); // also works for non-null-terminated strings
236 fRepresentations[index] = arrAsStr;
237 return false; // do not treat this as a collection
238 }
239
240 ////////////////////////////////////////////////////////////////////////////
241 /// Adds a single element to the next slot in the table
242 void AddToRow(const std::string &stringEle);
243
244 ////////////////////////////////////////////////////////////////////////////
245 /// Adds a collection to the table
246 ///
247 /// Starting from the slot, the elements are added one under the other, each
248 /// one using a single cell of an entire row
249 void AddCollectionToRow(const VecStr_t &collection);
250
251 ////////////////////////////////////////////////////////////////////////////
252 /// Moves to the next cell
253 ///
254 /// Moves to the next cell, and if the row is full moves to the next row.
255 void MovePosition();
256
257 ////////////////////////////////////////////////////////////////////////////
258 /// Get the number of columns that do NOT fit in the characters limit
259 size_t GetNColumnsToShorten() const;
260
261 ////////////////////////////////////////////////////////////////////////////
262 /// Generate dashes between entries in Print() and AsString() Methods
263 std::string DashesBetweenLines(size_t lastColToPrint, bool allColumnsFit) const;
264
265 ////////////////////////////////////////////////////////////////////////////
266 /// Adds a row of events to the table
267 template <typename... Columns>
268 void AddRow(Columns &... columns)
269 {
270 std::stringstream calc; // JITted code
271 int columnIndex = 0;
272 // Unwrapping the parameters to create the JITted code.
273 fIsCollection = {AddInterpreterString(calc, columns, columnIndex++)...};
274
275 // Let cling::printValue handle the conversion. This can be done only through cling-compiled code.
276 const std::string toJit = calc.str();
277 if (!toJit.empty())
278 ROOT::Internal::RDF::InterpreterCalc(calc.str(), "Display");
279
280 // Populate the fTable using the results of the JITted code.
281 for (size_t i = 0; i < fNColumns; ++i) {
282 if (fIsCollection[i]) {
284 } else {
286 }
287 }
288 }
289
290 void EnsureCurrentColumnWidth(size_t w);
291
292public:
293 ////////////////////////////////////////////////////////////////////////////
294 /// Creates an RDisplay to print the event values
295 /// \param[in] columnNames Columns to print
296 /// \param[in] types The type of each column
297 /// \param[in] nMaxCollectionElements Number of maximum elements in collection.
298 RDisplay(const VecStr_t &columnNames, const VecStr_t &types, size_t nMaxCollectionElements);
299
300 ////////////////////////////////////////////////////////////////////////////
301 /// Prints the representation to the standard output
302 ///
303 /// Collections are shortened to the first and last element. The overall width
304 /// is shortened to a fixed number of columns that should fit the screen width.
305 void Print() const;
306
307 ////////////////////////////////////////////////////////////////////////////
308 /// Returns the representation as a string
309 std::string AsString() const;
310};
311
312} // namespace RDF
313} // namespace ROOT
314
315#endif
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
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 length
Helper class to let Display print compact tabular representations of the events.
Definition RDisplay.hxx:32
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.
pointer data() noexcept
Return a pointer to the vector's buffer, even if empty().
Definition RVec.hxx:280
This class is the textual representation of the content of a columnar dataset.
Definition RDisplay.hxx:65
void AddRow(Columns &... columns)
Adds a row of events to the table.
Definition RDisplay.hxx:268
void AddCollectionToRow(const VecStr_t &collection)
Adds a collection to the table.
size_t fCurrentColumn
Column that is being filled.
Definition RDisplay.hxx:89
bool AddInterpreterString(std::stringstream &, T &collection, const int &index)
Represent a collection of values as a collection of strings.
Definition RDisplay.hxx:185
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::vector< bool > fIsCollection
True if the column contains a collection.
Definition RDisplay.hxx:75
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
VecStr_t fRepresentations
Used by the JITted code to store the string representation of the data.
Definition RDisplay.hxx:80
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
bool AddInterpreterString(std::stringstream &stream, T &collection, const int &index)
Appends collection.size() cling::printValue calls to the stringstream.
Definition RDisplay.hxx:153
static constexpr unsigned fgMaxWidth
Maximum width of the table that Print() displays.
Definition RDisplay.hxx:72
bool AddInterpreterString(std::stringstream &, bool &element, const int &index)
Appends a string if the T type is boolean.
Definition RDisplay.hxx:134
void EnsureCurrentColumnWidth(size_t w)
size_t fNextRow
Next row to be filled.
Definition RDisplay.hxx:88
bool AddInterpreterString(std::stringstream &, ROOT::RVec< char > &charArr, const int &index)
AddInterpreterString overload for arrays of chars.
Definition RDisplay.hxx:231
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.
std::vector< VecStr_t > fCollectionsRepresentations
Used by the JITted code to store the string representation of the data in case of collection.
Definition RDisplay.hxx:81
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
bool AddInterpreterString(std::stringstream &stream, T &element, const int &index)
Appends a cling::printValue call to the stringstream This overload works for non-collection data type...
Definition RDisplay.hxx:104
bool AddInterpreterString(std::stringstream &, T &element, const int &index)
Appends a string if the T type is an arithmetic type.
Definition RDisplay.hxx:121
VecStr_t fTypes
This attribute stores the type of each column. It is needed by the interpreter to print it.
Definition RDisplay.hxx:74
size_t fNColumns
Number of columns to be printed.
Definition RDisplay.hxx:85
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition RVec.hxx:1529
std::string PrettyPrintAddr(const void *const addr)
Long64_t InterpreterCalc(const std::string &code, const std::string &context="")
Jit code in the interpreter with TInterpreter::Calc, throw in case of errors.
Definition RDFUtils.cxx:327
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
int GetSplit(const char *type, std::vector< std::string > &output, int &nestedLoc, EModType mode=TClassEdit::kNone)
Stores in output (after emptying it) the split type.
Check for container traits.
Definition Utils.hxx:79
static void output()