Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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>
68
69public:
70 enum class EPrintFormat {
72 kHtml
73 };
74
78
79private:
80 using VecStr_t = std::vector<std::string>;
82 static constexpr char fgSeparator = ' '; ///< Spacing used to align the table entries
83 static constexpr unsigned fgMaxWidth = 100; ///< Maximum width of the table that Print() displays
84
85 VecStr_t fTypes; ///< This attribute stores the type of each column. It is needed by the interpreter to print it.
86 std::vector<std::vector<DElement_t>> fTable; ///< String representation of the data to be printed.
87 std::vector<unsigned short> fWidths; ///< Tracks the maximum width of each column, based on the largest element.
88
89 VecStr_t fRepresentations; ///< Used by the JITted code to store the string representation of the data.
90 std::vector<VecStr_t> fCollectionsRepresentations; ///< Used by the JITted code to store the string representation of
91 ///< the data in case of collection. Each row corresponds to a
92 ///< column, each column to a value of the collection.
93
94 size_t fNColumns; ///< Number of columns to be printed
95
96 size_t fCurrentRow = 0; ///< Row that is being filled
97 size_t fNextRow = 1; ///< Next row to be filled.
98 size_t fCurrentColumn = 0; ///< Column that is being filled.
99
100 size_t fNMaxCollectionElements = 10; // threshold on number of elements in collections to be Print()
101
102 ////////////////////////////////////////////////////////////////////////////
103 /// Appends a cling::printValue call to the stringstream
104 /// This overload works for non-collection data types which are also not
105 /// trivially representable as strings.
106 /// \tparam T the type of the event to convert
107 /// \param[in] stream Where the conversion function call will be chained.
108 /// \param[in] element The event to convert to its string representation
109 /// \param[in] index To which column the event belongs to
110 /// \return false, the event is not a collection
111 template <typename T,
112 std::enable_if_t<!std::is_arithmetic_v<T> && !ROOT::Internal::RDF::IsDataContainer<T>::value, int> = 0>
113 bool AddInterpreterString(std::stringstream &stream, T &element, const int &index)
114 {
115 stream << "*((std::string*)" << ROOT::Internal::RDF::PrettyPrintAddr(&(fRepresentations[index]))
116 << ") = cling::printValue((" << fTypes[index] << "*)" << ROOT::Internal::RDF::PrettyPrintAddr(&element)
117 << ");";
118 return false;
119 }
120
121 ////////////////////////////////////////////////////////////////////////////
122 /// Appends a string if the T type is an arithmetic type.
123 /// This overload works for arithmetic data types that are trivially
124 /// convertible to string.
125 /// \tparam T the type of the event to convert
126 /// \param[in] element The event to convert to its string representation
127 /// \param[in] index To which column the event belongs to
128 /// \return false, the event is not a collection
129 template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
130 bool AddInterpreterString(std::stringstream &, T &element, const int &index)
131 {
132 // Short-circuit the logic and just insert the string representation of
133 // the symple type at the right index.
134 fRepresentations[index] = std::to_string(element);
135 return false;
136 }
137
138 ////////////////////////////////////////////////////////////////////////////
139 /// Appends a string if the T type is boolean.
140 /// \param[in] element The event to convert to its string representation
141 /// \param[in] index To which column the event belongs to
142 /// \return false, the event is not a collection
143 bool AddInterpreterString(std::stringstream &, bool &element, const int &index)
144 {
145 // Short-circuit the logic and just insert the string representation of
146 // the boolean value at the right index.
147 fRepresentations[index] = (element ? "true" : "false");
148 return false;
149 }
150
151 ////////////////////////////////////////////////////////////////////////////
152 /// Appends collection.size() cling::printValue calls to the stringstream.
153 /// \tparam T the type of the event to convert
154 /// \param[in] stream Where the conversion function call will be chained.
155 /// \param[in] collection The event to convert to its string representation
156 /// \param[in] index To which column the event belongs to
157 /// \return true, the event is a collection
158 /// This function chains a sequence of call to cling::printValue, one for each element of the collection.
160 !std::is_arithmetic_v<typename T::value_type>,
161 int> = 0>
162 bool AddInterpreterString(std::stringstream &stream, T &collection, const int &index)
163 {
164 size_t collectionSize = std::distance(std::begin(collection), std::end(collection));
165 // Prepare the row to contain as many elements as the number of elements in the collection
167
168 // Use GetSplit to get the encapsulated type of the collection. For example, GetSplit on
169 // std::vector<std::vector<int>> will return std::vector<int>
171 int nestedLoc = 0;
173
174 // For each element, append a call and feed the proper type returned by GetSplit
175 for (size_t i = 0; i < collectionSize; ++i) {
176 stream << "*((std::string*)" << ROOT::Internal::RDF::PrettyPrintAddr(&(fCollectionsRepresentations[index][i]))
177 << ") = cling::printValue((" << output[1] << "*)"
179 }
180 return true;
181 }
182
183 ////////////////////////////////////////////////////////////////////////////
184 /// Represent a collection of values as a collection of strings.
185 /// \tparam T the type of the event to convert. This must be a collection of
186 /// values of arithmetic type, but not boolean.
187 /// \param[in] collection The event to convert to its string representation
188 /// \param[in] index To which column the event belongs to
189 /// \return true, the event is a collection
191 std::is_arithmetic_v<typename T::value_type> &&
192 !std::is_same_v<typename T::value_type, bool>,
193 int> = 0>
194 bool AddInterpreterString(std::stringstream &, T &collection, const int &index)
195 {
196 auto collectionSize = std::distance(std::begin(collection), std::end(collection));
198 std::generate(collectionRepr.begin(), collectionRepr.end(), [i = 0, &collection]() mutable {
199 auto valRepr = std::to_string(collection[i]);
200 i++;
201 return valRepr;
202 });
204 return true;
205 }
206
207 ////////////////////////////////////////////////////////////////////////////
208 /// Represent a collection of booleans as a collection of strings.
209 /// \tparam T the type of the event to convert. This must be a collection of
210 /// boolean values.
211 /// \param[in] collection The event to convert to its string representation
212 /// \param[in] index To which column the event belongs to
213 /// \return true, the event is a collection
215 std::is_same_v<typename T::value_type, bool>,
216 int> = 0>
217 bool AddInterpreterString(std::stringstream &, T &collection, const int &index)
218 {
219 auto collectionSize = std::distance(std::begin(collection), std::end(collection));
221 std::generate(collectionRepr.begin(), collectionRepr.end(), [i = 0, &collection]() mutable {
222 auto valRepr = (collection[i] ? "true" : "false");
223 i++;
224 return valRepr;
225 });
227 return true;
228 }
229
230 ////////////////////////////////////////////////////////////////////////////
231 /// AddInterpreterString overload for arrays of chars.
232 ///
233 /// \param[in] charArr The character array to convert to string representation
234 /// \param[in] index To which column the event belongs
235 /// \return false, the event is not a collection
236 ///
237 /// This specialization for arrays of characters skips the cling::printValue
238 /// (i.e. appends nothing to the stream) and directly writes to fRepresentations the
239 /// string representation of the array of chars.
240 bool AddInterpreterString(std::stringstream &, ROOT::RVec<char> &charArr, const int &index)
241 {
242 // if null-terminated char array, do not copy the null terminator into std::string, it makes columns misaligned.
243 const auto length = charArr[charArr.size()-1] == '\0' ? charArr.size() - 1 : charArr.size();
244 const std::string arrAsStr(charArr.data(), length); // also works for non-null-terminated strings
246 return false; // do not treat this as a collection
247 }
248
249 ////////////////////////////////////////////////////////////////////////////
250 /// Adds a single element to the next slot in the table
251 void AddToRow(const std::string &stringEle);
252
253 ////////////////////////////////////////////////////////////////////////////
254 /// Adds a collection to the table
255 ///
256 /// Starting from the slot, the elements are added one under the other, each
257 /// one using a single cell of an entire row
259
260 ////////////////////////////////////////////////////////////////////////////
261 /// Moves to the next cell
262 ///
263 /// Moves to the next cell, and if the row is full moves to the next row.
264 void MovePosition();
265
266 ////////////////////////////////////////////////////////////////////////////
267 /// Get the number of columns that do NOT fit in the characters limit
268 size_t GetNColumnsToShorten() const;
269
270 ////////////////////////////////////////////////////////////////////////////
271 /// Generate dashes between entries in Print() and AsString() Methods
272 std::string DashesBetweenLines(size_t lastColToPrint, bool allColumnsFit) const;
273
274 ////////////////////////////////////////////////////////////////////////////
275 /// Adds a row of events to the table
276 template <typename... Columns>
277 void AddRow(Columns &... columns)
278 {
279 std::stringstream calc; // JITted code
280 int columnIndex = 0;
281 // Unwrapping the parameters to create the JITted code.
283
284 // Let cling::printValue handle the conversion. This can be done only through cling-compiled code.
285 const std::string toJit = calc.str();
286 if (!toJit.empty())
288
289 // Populate the fTable using the results of the JITted code.
290 for (size_t i = 0; i < fNColumns; ++i) {
291 if (isCollection[i]) {
293 } else {
295 }
296 }
297 }
298
299 void EnsureCurrentColumnWidth(size_t w);
300
301 std::string AsStringInternal(bool considerDots, const RPrintOptions &options = {EPrintFormat::kMarkdown}) const;
302 std::string AsStringMarkdown(bool considerDots) const;
303 std::string AsStringHtml() const;
304
305public:
306 ////////////////////////////////////////////////////////////////////////////
307 /// Creates an RDisplay to print the event values
308 /// \param[in] columnNames Columns to print
309 /// \param[in] types The type of each column
310 /// \param[in] nMaxCollectionElements Number of maximum elements in collection.
312
313 ////////////////////////////////////////////////////////////////////////////
314 /// Prints the representation to the standard output
315 ///
316 /// Collections are shortened to the first and last element. The overall width
317 /// is shortened to a fixed number of columns that should fit the screen width.
318 void Print(const RPrintOptions &options = {EPrintFormat::kMarkdown}) const;
319
320 ////////////////////////////////////////////////////////////////////////////
321 /// Returns the representation as a string
322 std::string AsString(const RPrintOptions &options = {EPrintFormat::kMarkdown}) const;
323};
324
325} // namespace RDF
326} // namespace ROOT
327
328#endif
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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.
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:277
void AddCollectionToRow(const VecStr_t &collection)
Adds a collection to the table.
size_t fCurrentColumn
Column that is being filled.
Definition RDisplay.hxx:98
bool AddInterpreterString(std::stringstream &, T &collection, const int &index)
Represent a collection of values as a collection of strings.
Definition RDisplay.hxx:194
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:100
std::vector< std::vector< DElement_t > > fTable
String representation of the data to be printed.
Definition RDisplay.hxx:86
std::string AsStringHtml() const
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:96
VecStr_t fRepresentations
Used by the JITted code to store the string representation of the data.
Definition RDisplay.hxx:89
std::string AsStringMarkdown(bool considerDots) const
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:87
bool AddInterpreterString(std::stringstream &stream, T &collection, const int &index)
Appends collection.size() cling::printValue calls to the stringstream.
Definition RDisplay.hxx:162
void Print(const RPrintOptions &options={EPrintFormat::kMarkdown}) const
Prints the representation to the standard output.
static constexpr unsigned fgMaxWidth
Maximum width of the table that Print() displays.
Definition RDisplay.hxx:83
std::string AsString(const RPrintOptions &options={EPrintFormat::kMarkdown}) const
Returns the representation as a string.
bool AddInterpreterString(std::stringstream &, bool &element, const int &index)
Appends a string if the T type is boolean.
Definition RDisplay.hxx:143
void EnsureCurrentColumnWidth(size_t w)
size_t fNextRow
Next row to be filled.
Definition RDisplay.hxx:97
bool AddInterpreterString(std::stringstream &, ROOT::RVec< char > &charArr, const int &index)
AddInterpreterString overload for arrays of chars.
Definition RDisplay.hxx:240
std::string DashesBetweenLines(size_t lastColToPrint, bool allColumnsFit) const
Generate dashes between entries in Print() and AsString() Methods.
std::string AsStringInternal(bool considerDots, const RPrintOptions &options={EPrintFormat::kMarkdown}) const
std::vector< std::string > VecStr_t
Definition RDisplay.hxx:80
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:90
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:82
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:113
bool AddInterpreterString(std::stringstream &, T &element, const int &index)
Appends a string if the T type is an arithmetic type.
Definition RDisplay.hxx:130
VecStr_t fTypes
This attribute stores the type of each column. It is needed by the interpreter to print it.
Definition RDisplay.hxx:85
size_t fNColumns
Number of columns to be printed.
Definition RDisplay.hxx:94
const_iterator begin() const
const_iterator end() const
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition RVec.hxx:1529
std::string PrettyPrintAddr(const void *const addr)
void 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:345
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:77
static void output()