sciplot  0.3.1
A modern C++ plotting library powered by gnuplot
Plot3D.hpp
1 // sciplot - a modern C++ scientific plotting library powered by gnuplot
2 // https://github.com/sciplot/sciplot
3 //
4 // Licensed under the MIT License <http://opensource.org/licenses/MIT>.
5 //
6 // Copyright (c) 2018-2022 Allan Leal, Bim Overbohm
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 // SOFTWARE.
25 
26 #pragma once
27 
28 // C++ includes
29 #include <sstream>
30 #include <vector>
31 
32 // sciplot includes
33 #include <sciplot/Constants.hpp>
34 #include <sciplot/Default.hpp>
35 #include <sciplot/Enums.hpp>
36 #include <sciplot/Palettes.hpp>
37 #include <sciplot/Plot.hpp>
38 #include <sciplot/StringOrDouble.hpp>
39 #include <sciplot/Utils.hpp>
40 #include <sciplot/specs/AxisLabelSpecs.hpp>
41 #include <sciplot/specs/BorderSpecs.hpp>
42 #include <sciplot/specs/DrawSpecs.hpp>
43 #include <sciplot/specs/FillStyleSpecs.hpp>
44 #include <sciplot/specs/FontSpecsOf.hpp>
45 #include <sciplot/specs/GridSpecs.hpp>
46 #include <sciplot/specs/HistogramStyleSpecs.hpp>
47 #include <sciplot/specs/LegendSpecs.hpp>
48 #include <sciplot/specs/LineSpecsOf.hpp>
49 #include <sciplot/specs/TicsSpecs.hpp>
50 #include <sciplot/specs/TicsSpecsMajor.hpp>
51 #include <sciplot/specs/TicsSpecsMinor.hpp>
52 
53 namespace sciplot
54 {
55 
57 class Plot3D : public Plot
58 {
59  public:
61  Plot3D();
62 
64  auto zlabel(const std::string& label) -> AxisLabelSpecs&;
65 
67  auto zrange(StringOrDouble min, StringOrDouble max) -> void;
68 
69  //======================================================================
70  // METHODS FOR DRAWING PLOT ELEMENTS
71  //======================================================================
73 
74  template <typename X, typename... Vecs>
75  auto drawWithVecs(const std::string& with, const X&, const Vecs&... vecs) -> DrawSpecs&;
76 
78  template <typename X, typename Y, typename Z>
79  auto drawCurve(const X& x, const Y& y, const Z& z) -> DrawSpecs&;
80 
82  template <typename X, typename Y, typename Z>
83  auto drawCurveWithPoints(const X& x, const Y& y, const Z& z) -> DrawSpecs&;
84 
86  template <typename X, typename Y, typename Z>
87  auto drawDots(const X& x, const Y& y, const Z& z) -> DrawSpecs&;
88 
90  template <typename X, typename Y, typename Z>
91  auto drawPoints(const X& x, const Y& y, const Z& z) -> DrawSpecs&;
92 
94  template <typename X, typename Y, typename Z>
95  auto drawImpulses(const X& x, const Y& y, const Z& z) -> DrawSpecs&;
96 
98  template <typename Y>
99  auto drawHistogram(const Y& y) -> DrawSpecs&;
100 
101  //======================================================================
102  // METHODS FOR DRAWING PLOT ELEMENTS USING DATA FROM LOCAL FILES
103  //======================================================================
104 
106  auto drawWithCols(const std::string& fname, const std::string& with, const std::vector<ColumnIndex>& cols) -> DrawSpecs&;
107 
109  auto drawCurve(const std::string& fname, const ColumnIndex& col, const ColumnIndex& ycol) -> DrawSpecs&;
110 
112  auto drawCurveWithPoints(const std::string& fname, const ColumnIndex& xcol, const ColumnIndex& ycol) -> DrawSpecs&;
113 
115  auto drawDots(const std::string& fname, ColumnIndex xcol, ColumnIndex ycol) -> DrawSpecs&;
116 
118  auto drawPoints(const std::string& fname, ColumnIndex xcol, ColumnIndex ycol) -> DrawSpecs&;
119 
121  auto drawImpulses(const std::string& fname, ColumnIndex xcol, ColumnIndex ycol) -> DrawSpecs&;
122 
124  auto drawHistogram(const std::string& fname, ColumnIndex ycol) -> DrawSpecs&;
125 
126  //======================================================================
127  // MISCElLANEOUS METHODS
128  //======================================================================
129 
131  auto repr() const -> std::string override;
132 
133  private:
134  std::string m_zrange;
135  AxisLabelSpecs m_zlabel;
136 };
137 
139  : Plot(), m_zlabel("z")
140 {
141 }
142 
143 inline auto Plot3D::zlabel(const std::string& label) -> AxisLabelSpecs&
144 {
145  m_zlabel.text(label);
146  return m_zlabel;
147 }
148 
149 inline auto Plot3D::zrange(StringOrDouble min, StringOrDouble max) -> void
150 {
151  m_zrange = "[" + min.value + ":" + max.value + "]";
152 }
153 
154 //======================================================================
155 // METHODS FOR DRAWING PLOT ELEMENTS
156 //======================================================================
157 
158 template <typename X, typename... Vecs>
159 inline auto Plot3D::drawWithVecs(const std::string& with, const X& x, const Vecs&... vecs) -> DrawSpecs&
160 {
161  // Write the given vectors x and y as a new data set to the stream
162  std::ostringstream datastream;
163  gnuplot::writedataset(datastream, m_numdatasets, x, vecs...);
164 
165  // Set the using string to "" if X is not vector of strings.
166  // Otherwise, x contain xtics strings. Set the `using` string
167  // so that these are properly used as xtics.
168  std::string use;
169  if constexpr (internal::isStringVector<X>)
170  {
171  const auto nvecs = sizeof...(Vecs);
172  use = "0:"; // here, column 0 means the pseudo column with numbers 0, 1, 2, 3...
173  for (auto i = 2; i <= nvecs + 1; ++i)
174  use += std::to_string(i) + ":"; // this constructs 0:2:3:4:
175  use += "xtic(1)"; // this terminates the string with 0:2:3:4:xtic(1), and thus column 1 is used for the xtics
176  }
177 
178  // Append new data set to existing data
179  m_data += datastream.str();
180 
181  // Draw the data saved using a data set with index `m_numdatasets`. Increase number of data sets and set the line style specification (desired behavior is 1, 2, 3 (incrementing as new lines are plotted)).
182  return draw("'" + m_datafilename + "' index " + internal::str(m_numdatasets++), use, with).lineStyle(static_cast<int>(m_drawspecs.size()));
183 }
184 
185 template <typename X, typename Y, typename Z>
186 inline auto Plot3D::drawCurve(const X& x, const Y& y, const Z& z) -> DrawSpecs&
187 {
188  return drawWithVecs("lines", x, y, z);
189 }
190 
191 template <typename X, typename Y, typename Z>
192 inline auto Plot3D::drawCurveWithPoints(const X& x, const Y& y, const Z& z) -> DrawSpecs&
193 {
194 
195  return drawWithVecs("linespoints", x, y, z);
196 }
197 
198 template <typename X, typename Y, typename Z>
199 inline auto Plot3D::drawDots(const X& x, const Y& y, const Z& z) -> DrawSpecs&
200 {
201  return drawWithVecs("dots", x, y, z);
202 }
203 
204 template <typename X, typename Y, typename Z>
205 inline auto Plot3D::drawPoints(const X& x, const Y& y, const Z& z) -> DrawSpecs&
206 {
207  return drawWithVecs("points", x, y, z);
208 }
209 
210 template <typename X, typename Y, typename Z>
211 inline auto Plot3D::drawImpulses(const X& x, const Y& y, const Z& z) -> DrawSpecs&
212 {
213  return drawWithVecs("impulses", x, y, z);
214 }
215 
216 template <typename Y>
217 inline auto Plot3D::drawHistogram(const Y& y) -> DrawSpecs&
218 {
219  return drawWithVecs("", y); // empty string because we rely on `set style data histograms` since relying `with histograms` is not working very well (e.g., empty key/lenged appearing in columnstacked mode).
220 }
221 
222 //======================================================================
223 // METHODS FOR DRAWING PLOT ELEMENTS USING DATA FROM LOCAL FILES
224 //======================================================================
225 
226 inline auto Plot3D::drawWithCols(const std::string& fname, const std::string& with, const std::vector<ColumnIndex>& cols) -> DrawSpecs&
227 {
228  std::string use;
229  for (const auto& col : cols)
230  use += col.value + ":"; // e.g., "1:4:5:7:" (where 1 is x, 4 is y, 5 is ylow and 7 is yhigh for a yerrorlines plot)
231  use = internal::trimright(use, ':'); // e.g., "1:4:5:7:" => "1:4:5:7"
232  std::string what = "'" + fname + "'"; // e.g., "'myfile.dat'"
233  return draw(what, use, with).lineStyle(static_cast<int>(m_drawspecs.size())); // e.g., draw(what="'myfile.dat'", use="1:2", with="lines");
234 }
235 
236 inline auto Plot3D::drawCurve(const std::string& fname, const ColumnIndex& xcol, const ColumnIndex& ycol) -> DrawSpecs&
237 {
238  return drawWithCols(fname, "lines", {xcol, ycol});
239 }
240 
241 inline auto Plot3D::drawCurveWithPoints(const std::string& fname, const ColumnIndex& xcol, const ColumnIndex& ycol) -> DrawSpecs&
242 {
243  return drawWithCols(fname, "linespoints", {xcol, ycol});
244 }
245 
246 inline auto Plot3D::drawDots(const std::string& fname, ColumnIndex xcol, ColumnIndex ycol) -> DrawSpecs&
247 {
248  return drawWithCols(fname, "dots", {xcol, ycol});
249 }
250 
251 inline auto Plot3D::drawPoints(const std::string& fname, ColumnIndex xcol, ColumnIndex ycol) -> DrawSpecs&
252 {
253  return drawWithCols(fname, "points", {xcol, ycol});
254 }
255 
256 inline auto Plot3D::drawImpulses(const std::string& fname, ColumnIndex xcol, ColumnIndex ycol) -> DrawSpecs&
257 {
258  return drawWithCols(fname, "impulses", {xcol, ycol});
259 }
260 
261 inline auto Plot3D::drawHistogram(const std::string& fname, ColumnIndex ycol) -> DrawSpecs&
262 {
263  return drawWithCols(fname, "", {ycol});
264 }
265 
266 //======================================================================
267 // MISCElLANEOUS METHODS
268 //======================================================================
269 
270 inline auto Plot3D::repr() const -> std::string
271 {
272  std::stringstream script;
273 
274  // Add plot setup commands
275  script << "#==============================================================================" << std::endl;
276  script << "# SETUP COMMANDS" << std::endl;
277  script << "#==============================================================================" << std::endl;
278  // Add palette info if a palette was set
279  if (!m_palette.empty())
280  {
281  gnuplot::palettecmd(script, m_palette);
282  }
283  script << gnuplot::cmdValueStr("set xrange", m_xrange);
284  script << gnuplot::cmdValueStr("set yrange", m_yrange);
285  script << gnuplot::cmdValueStr("set zrange", m_zrange);
286  script << m_xlabel << std::endl;
287  script << m_ylabel << std::endl;
288  script << m_zlabel << std::endl;
289  script << m_rlabel << std::endl;
290  script << m_border << std::endl;
291  script << m_grid << std::endl;
292  script << m_style_fill << std::endl;
293  script << m_style_histogram << std::endl;
294  script << m_tics << std::endl;
295  script << m_xtics_major_bottom << std::endl;
296  script << m_xtics_major_top << std::endl;
297  script << m_xtics_minor_bottom << std::endl;
298  script << m_xtics_minor_top << std::endl;
299  script << m_ytics_major_left << std::endl;
300  script << m_ytics_major_right << std::endl;
301  script << m_ytics_minor_left << std::endl;
302  script << m_ytics_minor_right << std::endl;
303  script << m_ztics_major << std::endl;
304  script << m_ztics_minor << std::endl;
305  script << m_rtics_major << std::endl;
306  script << m_rtics_minor << std::endl;
307  script << m_legend << std::endl;
308  script << gnuplot::cmdValueStr("set boxwidth", m_boxwidth);
309  script << gnuplot::cmdValueStr("set samples", m_samples);
310  // unset palette info if a palette was set
311  if (!m_palette.empty())
312  {
313  gnuplot::unsetpalettecmd(script);
314  }
315  // Add custom gnuplot commands
316  if (!m_customcmds.empty())
317  {
318  script << "#==============================================================================" << std::endl;
319  script << "# CUSTOM EXPLICIT GNUPLOT COMMANDS" << std::endl;
320  script << "#==============================================================================" << std::endl;
321  for (const auto& c : m_customcmds)
322  {
323  script << c << std::endl;
324  }
325  }
326  // Add the actual plot commands for all drawXYZ() calls
327  script << "#==============================================================================" << std::endl;
328  script << "# PLOT COMMANDS" << std::endl;
329  script << "#==============================================================================" << std::endl;
330  script << "splot \\\n"; // use `\` to have a plot command in each individual line!
331  // Write plot commands and style per plot
332  const auto n = m_drawspecs.size();
333  for (std::size_t i = 0; i < n; ++i)
334  {
335  script << " " << m_drawspecs[i] << (i < n - 1 ? ", \\\n" : ""); // consider indentation with 4 spaces!
336  }
337  // Add an empty line at the end
338  script << std::endl;
339  return script.str();
340 }
341 
342 } // namespace sciplot
An auxiliary type used to store a string value, while the input can also be a double.
Definition: StringOrDouble.hpp:35
TicsSpecsMajor m_ytics_major_left
The specs for the major ytics at the left.
Definition: Plot.hpp:227
AxisLabelSpecs m_rlabel
The label of the r-axis.
Definition: Plot.hpp:237
auto drawHistogram(const Y &y) -> DrawSpecs &
Draw a histogram for the given y vector.
Definition: Plot3D.hpp:217
std::string m_xrange
The x-range of the plot as a gnuplot formatted string (e.g., "set xrange [0:1]")
Definition: Plot.hpp:219
LegendSpecs m_legend
The legend specs of the plot.
Definition: Plot.hpp:241
std::string m_samples
The number of sample points for functions.
Definition: Plot.hpp:240
TicsSpecs m_tics
The specs of the tics of the plot.
Definition: Plot.hpp:222
The class used to create a plot containing graphical elements.
Definition: Plot3D.hpp:58
std::string m_palette
The name of the gnuplot palette to be used.
Definition: Plot.hpp:210
GridSpecs m_grid
The vector of grid specs for the major and minor grid lines in the plot (for xtics,...
Definition: Plot.hpp:218
FillStyleSpecs m_style_fill
The specs for the fill style of the plot elements in the plot that can be painted.
Definition: Plot.hpp:239
The specifications for an axis label (e.g., xlabel, ylabel, etc.)
Definition: AxisLabelSpecs.hpp:37
TicsSpecsMajor m_xtics_major_top
The specs for the major xtics at the top.
Definition: Plot.hpp:224
auto repr() const -> std::string override
Convert this plot object into a gnuplot formatted string.
Definition: Plot3D.hpp:270
auto drawCurve(const X &x, const Y &y, const Z &z) -> DrawSpecs &
Draw a curve with given x and y vectors.
Definition: Plot3D.hpp:186
AxisLabelSpecs m_xlabel
The label of the x-axis.
Definition: Plot.hpp:235
TicsSpecsMajor m_ztics_major
The specs for the major ztics.
Definition: Plot.hpp:231
auto zrange(StringOrDouble min, StringOrDouble max) -> void
Set the z-range of the plot (also possible with empty values or autoscale options (e....
Definition: Plot3D.hpp:149
auto zlabel(const std::string &label) -> AxisLabelSpecs &
Set the label of the z-axis and return a reference to the corresponding specs object.
Definition: Plot3D.hpp:143
AxisLabelSpecs m_ylabel
The label of the y-axis.
Definition: Plot.hpp:236
auto drawCurveWithPoints(const X &x, const Y &y, const Z &z) -> DrawSpecs &
Draw a curve with points with given x and y vectors.
Definition: Plot3D.hpp:192
std::string m_boxwidth
The default width of boxes in plots containing boxes without given widths.
Definition: Plot.hpp:238
An auxiliary type used to represent a data column index.
Definition: ColumnIndex.hpp:35
auto text(std::string text) -> AxisLabelSpecs &
Set the text of the axis label.
Definition: AxisLabelSpecs.hpp:73
TicsSpecsMinor m_xtics_minor_bottom
The specs for the minor xtics at the bottom.
Definition: Plot.hpp:225
TicsSpecsMinor m_ytics_minor_left
The specs for the minor ytics at the left.
Definition: Plot.hpp:229
auto drawPoints(const X &x, const Y &y, const Z &z) -> DrawSpecs &
Draw points with given x and y vectors.
Definition: Plot3D.hpp:205
TicsSpecsMinor m_xtics_minor_top
The specs for the minor xtics at the top.
Definition: Plot.hpp:226
TicsSpecsMinor m_ztics_minor
The specs for the minor ztics.
Definition: Plot.hpp:232
TicsSpecsMajor m_ytics_major_right
The specs for the major ytics at the right.
Definition: Plot.hpp:228
TicsSpecsMajor m_xtics_major_bottom
The specs for the major xtics at the bottom.
Definition: Plot.hpp:223
auto drawWithVecs(const std::string &with, const X &, const Vecs &... vecs) -> DrawSpecs &
Draw plot object with given style and given vectors (e.g., plot.draw("lines", x, y)).
Definition: Plot3D.hpp:159
The class used to create a plot containing graphical elements.
Definition: Plot.hpp:57
Plot3D()
Construct a default Plot object.
Definition: Plot3D.hpp:138
auto drawWithCols(const std::string &fname, const std::string &with, const std::vector< ColumnIndex > &cols) -> DrawSpecs &
Draw plot object with given style and given vectors (e.g., plot.draw("lines", x, y)).
Definition: Plot3D.hpp:226
std::string m_yrange
The y-range of the plot as a gnuplot formatted string (e.g., "set yrange [0:1]")
Definition: Plot.hpp:220
HistogramStyleSpecs m_style_histogram
The specs for the histogram style of the plot.
Definition: Plot.hpp:221
std::vector< std::string > m_customcmds
The strings containing gnuplot custom commands.
Definition: Plot.hpp:243
auto drawImpulses(const X &x, const Y &y, const Z &z) -> DrawSpecs &
Draw impulses with given x and y vectors.
Definition: Plot3D.hpp:211
The class where options for the plotted element can be specified.
Definition: DrawSpecs.hpp:41
TicsSpecsMinor m_rtics_minor
The specs for the minor rtics.
Definition: Plot.hpp:234
TicsSpecsMajor m_rtics_major
The specs for the major rtics.
Definition: Plot.hpp:233
auto drawDots(const X &x, const Y &y, const Z &z) -> DrawSpecs &
Draw dots with given x and y vectors.
Definition: Plot3D.hpp:199
std::vector< DrawSpecs > m_drawspecs
The plot specs for each call to gnuplot plot function.
Definition: Plot.hpp:242
BorderSpecs m_border
The border style of the plot.
Definition: Plot.hpp:217
TicsSpecsMinor m_ytics_minor_right
The specs for the minor ytics at the right.
Definition: Plot.hpp:230