Logo ROOT  
Reference Guide
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
23namespace ROOT {
24namespace Internal {
25namespace RDF {
26
27template<typename T>
29std::string PrettyPrintAddr(const void *const addr);
30
32private:
33 enum class PrintingAction { ToBePrinted, ToBeIgnored, ToBeDotted };
34 std::string fRepresentation;
36
37public:
38 RDisplayElement(const std::string &representation);
40 void SetPrint();
41 void SetIgnore();
42 void SetDots();
43 bool IsPrint() const;
44 bool IsIgnore() const;
45 bool IsDot() const;
46 const std::string &GetRepresentation() const;
47 bool IsEmpty() const;
48};
49} // namespace RDF
50} // namespace Internal
51
52namespace RDF {
53
54/**
55 * \class ROOT::RDF::RDisplay
56 * \ingroup dataframe
57 * This class is the textual representation of the content of a columnar dataset.
58 *
59 * This class is provided to the user, and it can be used to print on screen
60 * the entries of the dataset requested through the Display action in a compact
61 * representation or to return the full representation of the events as a string.
62 * In order to apply proper formatting the content is buffered in memory as strings.
63 */
64class RDisplay {
65 template<typename T>
67private:
68 using VecStr_t = std::vector<std::string>;
70 static constexpr char fgSeparator = ' '; ///< Spacing used to align the table entries
71 static constexpr unsigned fgMaxWidth = 100; ///< Maximum width of the table that Print() displays
72
73 VecStr_t fTypes; ///< This attribute stores the type of each column. It is needed by the interpreter to print it.
74 std::vector<bool> fIsCollection; ///< True if the column contains a collection. Collections are treated differently
75 ///< during the printing.
76 std::vector<std::vector<DElement_t>> fTable; ///< String representation of the data to be printed.
77 std::vector<unsigned short> fWidths; ///< Tracks the maximum width of each column, based on the largest element.
78
79 VecStr_t fRepresentations; ///< Used by the JITted code to store the string representation of the data.
80 std::vector<VecStr_t> fCollectionsRepresentations; ///< Used by the JITted code to store the string representation of
81 ///< the data in case of collection. Each row corresponds to a
82 ///< column, each column to a value of the collection.
83
84 size_t fNColumns; ///< Number of columns to be printed
85
86 size_t fCurrentRow = 0; ///< Row that is being filled
87 size_t fNextRow = 1; ///< Next row to be filled.
88 size_t fCurrentColumn = 0; ///< Column that is being filled.
89
90 size_t fEntries; ///< Number of events to process for each column (i.e. number of rows).
91
92 size_t fNMaxCollectionElements = 10; // threshold on number of elements in collections to be Print()
93
94 ////////////////////////////////////////////////////////////////////////////
95 /// Appends a cling::printValue call to the stringstream.
96 /// \tparam T the type of the event to convert
97 /// \param[in] stream Where the conversion function call will be chained.
98 /// \param[in] element The event to convert to its string representation
99 /// \param[in] index To which column the event belongs to
100 /// \return false, the event is not a collection
102 bool AddInterpreterString(std::stringstream &stream, T &element, const int &index)
103 {
104 stream << "*((std::string*)" << ROOT::Internal::RDF::PrettyPrintAddr(&(fRepresentations[index]))
105 << ") = cling::printValue((" << fTypes[index] << "*)" << ROOT::Internal::RDF::PrettyPrintAddr(&element) << ");";
106 return false;
107 }
108
109 ////////////////////////////////////////////////////////////////////////////
110 /// Appends collection.size() cling::printValue calls to the stringstream.
111 /// \tparam T the type of the event to convert
112 /// \param[in] stream Where the conversion function call will be chained.
113 /// \param[in] collection The event to convert to its string representation
114 /// \param[in] index To which column the event belongs to
115 /// \return true, the event is a collection
116 /// This function chains a sequence of call to cling::printValue, one for each element of the collection.
118 bool AddInterpreterString(std::stringstream &stream, T &collection, const int &index)
119 {
120 size_t collectionSize = std::distance(std::begin(collection), std::end(collection));
121 // Prepare the row to contain as many elements as the number of elements in the collection
122 fCollectionsRepresentations[index] = VecStr_t(collectionSize);
123
124 // Use GetSplit to get the encapsulated type of the collection. For example, GetSplit on
125 // std::vector<std::vector<int>> will return std::vector<int>
127 int nestedLoc = 0;
128 TClassEdit::GetSplit(fTypes[index].c_str(), output, nestedLoc);
129
130 // For each element, append a call and feed the proper type returned by GetSplit
131 for (size_t i = 0; i < collectionSize; ++i) {
132 stream << "*((std::string*)" << ROOT::Internal::RDF::PrettyPrintAddr(&(fCollectionsRepresentations[index][i]))
133 << ") = cling::printValue((" << output[1] << "*)"
134 << ROOT::Internal::RDF::PrettyPrintAddr(&(collection[i])) << ");";
135 }
136 return true;
137 }
138
139 ////////////////////////////////////////////////////////////////////////////
140 /// AddInterpreterString overload for arrays of chars.
141 ///
142 /// \param[in] charArr The character array to convert to string representation
143 /// \param[in] index To which column the event belongs
144 /// \return false, the event is not a collection
145 ///
146 /// This specialization for arrays of characters skips the cling::printValue
147 /// (i.e. appends nothing to the stream) and directly writes to fRepresentations the
148 /// string representation of the array of chars.
149 bool AddInterpreterString(std::stringstream &, ROOT::RVec<char> &charArr, const int &index)
150 {
151 // if null-terminated char array, do not copy the null terminator into std::string, it makes columns misaligned.
152 const auto length = charArr[charArr.size()-1] == '\0' ? charArr.size() - 1 : charArr.size();
153 const std::string arrAsStr(charArr.data(), length); // also works for non-null-terminated strings
154 fRepresentations[index] = arrAsStr;
155 return false; // do not treat this as a collection
156 }
157
158 ////////////////////////////////////////////////////////////////////////////
159 /// AddInterpreterString overload for arrays of booleans.
160 ///
161 /// \param[in] boolArr The bool array to convert to string representation
162 /// \param[in] index To which column the event belongs
163 /// \return true, the event is a collection
164 ///
165 /// This specialization for arrays of booleans skips the cling::printValue
166 /// (i.e. appends nothing to the stream) and directly writes to fCollectionsRepresentations the
167 /// string representation of the array of chars.
168 bool AddInterpreterString(std::stringstream &, ROOT::RVec<bool> &boolArr, const int &index)
169 {
170 fCollectionsRepresentations[index].reserve(boolArr.size());
171 for (bool b : boolArr)
172 fCollectionsRepresentations[index].push_back(b ? "true" : "false");
173
174 return true; // treat this as a collection
175 }
176
177
178 ////////////////////////////////////////////////////////////////////////////
179 /// Adds a single element to the next slot in the table
180 void AddToRow(const std::string &stringEle);
181
182 ////////////////////////////////////////////////////////////////////////////
183 /// Adds a collection to the table
184 ///
185 /// Starting from the slot, the elements are added one under the other, each
186 /// one using a single cell of an entire row
187 void AddCollectionToRow(const VecStr_t &collection);
188
189 ////////////////////////////////////////////////////////////////////////////
190 /// Moves to the next cell
191 ///
192 /// Moves to the next cell, and if the row is full moves to the next row.
193 void MovePosition();
194
195 ////////////////////////////////////////////////////////////////////////////
196 /// Get the number of columns that do NOT fit in the characters limit
197 size_t GetNColumnsToShorten() const;
198
199 ////////////////////////////////////////////////////////////////////////////
200 /// Generate dashes between entries in Print() and AsString() Methods
201 std::string DashesBetweenLines(size_t lastColToPrint, bool allColumnsFit) const;
202
203 ////////////////////////////////////////////////////////////////////////////
204 /// Adds a row of events to the table
205 template <typename... Columns>
206 void AddRow(Columns &... columns)
207 {
208 std::stringstream calc; // JITted code
209 int columnIndex = 0;
210 // Unwrapping the parameters to create the JITted code.
211 fIsCollection = {AddInterpreterString(calc, columns, columnIndex++)...};
212
213 // Let cling::printValue handle the conversion. This can be done only through cling-compiled code.
214 const std::string toJit = calc.str();
215 if (!toJit.empty())
216 ROOT::Internal::RDF::InterpreterCalc(calc.str(), "Display");
217
218 // Populate the fTable using the results of the JITted code.
219 for (size_t i = 0; i < fNColumns; ++i) {
220 if (fIsCollection[i]) {
222 } else {
224 }
225 }
226 // This row has been parsed
227 fEntries--;
228 }
229
230 ////////////////////////////////////////////////////////////////////////////
231 /// If the number of required rows has been parsed, returns false.
232 bool HasNext() { return fEntries > 0; }
233
234 void EnsureCurrentColumnWidth(size_t w);
235
236public:
237 ////////////////////////////////////////////////////////////////////////////
238 /// Creates an RDisplay to print the event values
239 /// \param[in] columnNames Columns to print
240 /// \param[in] types The type of each column
241 /// \param[in] entries How many events per column (row) must be processed.
242 /// \param[in] nMaxCollectionElements Number of maximum elements in collection.
243 RDisplay(const VecStr_t &columnNames, const VecStr_t &types, int entries, size_t nMaxCollectionElements);
244
245 ////////////////////////////////////////////////////////////////////////////
246 /// Prints the representation to the standard output
247 ///
248 /// Collections are shortened to the first and last element. The overall width
249 /// is shortened to a fixed number of columns that should fit the screen width.
250 void Print() const;
251
252 ////////////////////////////////////////////////////////////////////////////
253 /// Returns the representation as a string
254 std::string AsString() const;
255};
256
257} // namespace RDF
258} // namespace ROOT
259
260#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 Float_t Float_t Float_t b
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
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Helper class to let Display print compact tabular representations of the events.
Definition: RDisplay.hxx:31
bool IsIgnore() const
Return if the cell has to be skipped.
Definition: RDFDisplay.cxx:78
bool IsDot() const
Return if the cell has to be replaced by "...".
Definition: RDFDisplay.cxx:85
const std::string & GetRepresentation() const
Definition: RDFDisplay.cxx:90
bool IsPrint() const
Return if the cell has to be printed.
Definition: RDFDisplay.cxx:71
void SetDots()
Flag this cell to be replaced by "...".
Definition: RDFDisplay.cxx:64
void SetPrint()
Flag this cell as to be printed.
Definition: RDFDisplay.cxx:50
void SetIgnore()
Flag this cell as to be skipped.
Definition: RDFDisplay.cxx:57
RDisplayElement()
Constructor assuming an empty representation to be printed.
Definition: RDFDisplay.cxx:43
pointer data() noexcept
Return a pointer to the vector's buffer, even if empty().
Definition: RVec.hxx:279
This class is the textual representation of the content of a columnar dataset.
Definition: RDisplay.hxx:64
bool AddInterpreterString(std::stringstream &, ROOT::RVec< bool > &boolArr, const int &index)
AddInterpreterString overload for arrays of booleans.
Definition: RDisplay.hxx:168
void AddRow(Columns &... columns)
Adds a row of events to the table.
Definition: RDisplay.hxx:206
size_t fEntries
Number of events to process for each column (i.e. number of rows).
Definition: RDisplay.hxx:90
void AddCollectionToRow(const VecStr_t &collection)
Adds a collection to the table.
Definition: RDFDisplay.cxx:128
size_t fCurrentColumn
Column that is being filled.
Definition: RDisplay.hxx:88
bool HasNext()
If the number of required rows has been parsed, returns false.
Definition: RDisplay.hxx:232
size_t fNMaxCollectionElements
Definition: RDisplay.hxx:92
std::vector< std::vector< DElement_t > > fTable
String representation of the data to be printed.
Definition: RDisplay.hxx:76
std::vector< bool > fIsCollection
True if the column contains a collection.
Definition: RDisplay.hxx:74
std::string AsString() const
Returns the representation as a string.
Definition: RDFDisplay.cxx:285
void AddToRow(const std::string &stringEle)
Adds a single element to the next slot in the table.
Definition: RDFDisplay.cxx:116
size_t fCurrentRow
Row that is being filled.
Definition: RDisplay.hxx:86
VecStr_t fRepresentations
Used by the JITted code to store the string representation of the data.
Definition: RDisplay.hxx:79
void MovePosition()
Moves to the next cell.
Definition: RDFDisplay.cxx:166
RDisplay(const VecStr_t &columnNames, const VecStr_t &types, int entries, size_t nMaxCollectionElements)
Creates an RDisplay to print the event values.
Definition: RDFDisplay.cxx:178
std::vector< unsigned short > fWidths
Tracks the maximum width of each column, based on the largest element.
Definition: RDisplay.hxx:77
bool AddInterpreterString(std::stringstream &stream, T &collection, const int &index)
Appends collection.size() cling::printValue calls to the stringstream.
Definition: RDisplay.hxx:118
static constexpr unsigned fgMaxWidth
Maximum width of the table that Print() displays.
Definition: RDisplay.hxx:71
void EnsureCurrentColumnWidth(size_t w)
Definition: RDFDisplay.cxx:105
size_t fNextRow
Next row to be filled.
Definition: RDisplay.hxx:87
bool AddInterpreterString(std::stringstream &, ROOT::RVec< char > &charArr, const int &index)
AddInterpreterString overload for arrays of chars.
Definition: RDisplay.hxx:149
std::string DashesBetweenLines(size_t lastColToPrint, bool allColumnsFit) const
Generate dashes between entries in Print() and AsString() Methods.
Definition: RDFDisplay.cxx:207
std::vector< std::string > VecStr_t
Definition: RDisplay.hxx:68
void Print() const
Prints the representation to the standard output.
Definition: RDFDisplay.cxx:221
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:80
size_t GetNColumnsToShorten() const
Get the number of columns that do NOT fit in the characters limit.
Definition: RDFDisplay.cxx:191
static constexpr char fgSeparator
Spacing used to align the table entries.
Definition: RDisplay.hxx:70
bool AddInterpreterString(std::stringstream &stream, T &element, const int &index)
Appends a cling::printValue call to the stringstream.
Definition: RDisplay.hxx:102
VecStr_t fTypes
This attribute stores the type of each column. It is needed by the interpreter to print it.
Definition: RDisplay.hxx:73
size_t fNColumns
Number of columns to be printed.
Definition: RDisplay.hxx:84
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition: RVec.hxx:1456
RooCmdArg Columns(Int_t ncol)
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
double T(double x)
Definition: ChebyshevPol.h:34
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
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.
static void output()