cepgen is hosted by Hepforge, IPPP Durham
CepGen 1.2.5
Central exclusive processes event generator
Loading...
Searching...
No Matches
MatplotlibDrawer.cpp
Go to the documentation of this file.
1/*
2 * CepGen: a central exclusive processes event generator
3 * Copyright (C) 2022 Laurent Forthomme
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <matplotlibcpp.h>
20
22#include "CepGen/Utils/Drawer.h"
23#include "CepGen/Utils/Graph.h"
26#include "CepGen/Version.h"
27
28namespace plt = matplotlibcpp;
29
30namespace cepgen {
31 namespace utils {
32 class MatplotlibDrawer : public Drawer {
33 public:
34 explicit MatplotlibDrawer(const ParametersList&);
35
37 auto desc = Drawer::description();
38 desc.setDescription("Matplotlib plotter");
39 desc.add<bool>("tight", false).setDescription("use a compact layout with minimal margins");
40 return desc;
41 }
42
43 const MatplotlibDrawer& draw(const Graph1D&, const Mode&) const override;
44 const MatplotlibDrawer& draw(const Graph2D&, const Mode&) const override;
45 const MatplotlibDrawer& draw(const Hist1D&, const Mode&) const override;
46 const MatplotlibDrawer& draw(const Hist2D&, const Mode&) const override;
47
49 const std::string& name = "",
50 const std::string& title = "",
51 const Mode& mode = Mode::none) const override;
52
53 private:
54 static void plot(const Graph1D&, const Mode&);
55 static void plot(const Graph2D&, const Mode&);
56 static void plot(const Hist1D&, const Mode&);
57 void postDraw(const Drawable&, const Mode&) const;
58 const bool tight_;
59 };
60
61 MatplotlibDrawer::MatplotlibDrawer(const ParametersList& params) : Drawer(params), tight_(steer<bool>("tight")) {}
62
63 const MatplotlibDrawer& MatplotlibDrawer::draw(const Graph1D& graph, const Mode& mode) const {
64 plt::figure();
65 plot(graph, mode);
66 postDraw(graph, mode);
67 plt::title(graph.title());
68 plt::save(graph.name() + ".pdf");
69 return *this;
70 }
71
72 const MatplotlibDrawer& MatplotlibDrawer::draw(const Graph2D& graph, const Mode& mode) const {
73 plt::figure();
74 plot(graph, mode);
75 postDraw(graph, mode);
76 plt::title(graph.title());
77 plt::save(graph.name() + ".pdf");
78 return *this;
79 }
80
81 const MatplotlibDrawer& MatplotlibDrawer::draw(const Hist1D& hist, const Mode& mode) const {
82 plt::figure();
83 plot(hist, mode);
84 postDraw(hist, mode);
85 plt::title(hist.title());
86 plt::save(hist.name() + ".pdf");
87 return *this;
88 }
89
90 const MatplotlibDrawer& MatplotlibDrawer::draw(const Hist2D&, const Mode&) const {
91 CG_WARNING("MatplotlibDrawer:draw") << "Not yet implemented.";
92 return *this;
93 }
94
96 const std::string& name,
97 const std::string& title,
98 const Mode& mode) const {
99 try {
100 plt::figure();
101 const Drawable* first_obj = nullptr;
102 for (const auto* obj : objs)
103 if (obj->isHist1D()) {
104 auto* hist = dynamic_cast<const Hist1D*>(obj);
105 plot(*hist, mode);
106 if (!first_obj)
107 first_obj = hist;
108 } else if (obj->isGraph1D()) {
109 auto* gr = dynamic_cast<const Graph1D*>(obj);
110 plot(*gr, mode);
111 if (!first_obj)
112 first_obj = gr;
113 }
114 if (!title.empty())
115 plt::title(title);
116 if (first_obj)
117 postDraw(*first_obj, mode);
118 if (objs.size() > 1)
119 plt::legend();
120 plt::save(name + ".pdf");
121 } catch (const std::runtime_error& err) {
122 CG_WARNING("MatplotlibDrawer:draw") << "Failed to draw a plots collection. Matplotlib error: " << err.what();
123 }
124 return *this;
125 }
126
127 void MatplotlibDrawer::plot(const Graph1D& gr, const Mode& mode) {
128 std::vector<double> x, y, xerr, yerr;
129 for (const auto& pt : gr.points()) {
130 x.emplace_back(pt.first.value);
131 y.emplace_back(pt.second);
132 xerr.emplace_back(pt.first.value_unc);
133 yerr.emplace_back(pt.second.uncertainty());
134 }
135 if ((mode & Mode::logx) && (mode & Mode::logy))
136 plt::named_loglog(gr.title(), x, y);
137 else if (mode & Mode::logx)
138 plt::named_semilogx(gr.title(), x, y);
139 else if (mode & Mode::logy)
140 plt::named_semilogy(gr.title(), x, y);
141 else if (yerr != std::vector<double>(yerr.size(), 0.))
142 plt::errorbar(x, y, yerr, {{"label", gr.title()}, {"linestyle", ""}});
143 else
144 plt::plot(x, y, {{"label", gr.title()}});
145 }
146
147 void MatplotlibDrawer::plot(const Graph2D& gr, const Mode&) {
148 std::vector<std::vector<double> > x, y, z;
149 for (const auto& xv : gr.points()) {
150 const auto xval = xv.first.value;
151 std::vector<double> xrow, yrow, zrow;
152 for (const auto& yv : xv.second) {
153 xrow.emplace_back(xval);
154 yrow.emplace_back(yv.first.value);
155 zrow.emplace_back(yv.second);
156 }
157 x.emplace_back(xrow);
158 y.emplace_back(yrow);
159 z.emplace_back(zrow);
160 }
161 plt::plot_surface(x, y, z, {{"label", gr.title()}});
162 //plt::contour(x, y, z, {{"label", gr.title()}});
163 plt::set_zlabel(gr.zAxis().label());
164 }
165
166 void MatplotlibDrawer::plot(const Hist1D& hist, const Mode& mode) {
167 std::vector<double> x, y, yerr;
168 for (size_t ibin = 0; ibin < hist.nbins(); ++ibin) {
169 const auto val = hist.value(ibin);
170 x.emplace_back(hist.binRange(ibin).x(0.5));
171 y.emplace_back(val);
172 yerr.emplace_back(val.uncertainty());
173 }
174 //plt::bar(x, y, "", "", 1., {{"label", hist.title()}});
175 //plt::bar(x, y);
176 std::map<std::string, std::string> plot_style = {{"label", hist.title()}, {"drawstyle", "steps"}};
177 if ((mode & Mode::logx) && (mode & Mode::logy))
178 plt::named_loglog(hist.title(), x, y, "o");
179 else if (mode & Mode::logx)
180 plt::named_semilogx(hist.title(), x, y, "o");
181 else if (mode & Mode::logy)
182 plt::named_semilogy(hist.title(), x, y, "o");
183 else if (!yerr.empty() && yerr != std::vector<double>(yerr.size(), 0.))
184 plt::errorbar(x, y, yerr, plot_style);
185 else
186 plt::plot(x, y, plot_style);
187 }
188
189 void MatplotlibDrawer::postDraw(const Drawable& dr, const Mode& mode) const {
190 if (mode & Mode::grid)
191 plt::grid(true);
192 const auto& yrange = dr.yAxis().range();
193 if (yrange.valid()) {
194 auto rng = plt::ylim();
195 if (yrange.hasMin())
196 rng[0] = yrange.min();
197 if (yrange.hasMax())
198 rng[1] = yrange.max();
199 try {
200 plt::ylim(rng.at(0), rng.at(1));
201 } catch (const std::runtime_error& err) {
202 CG_WARNING("MatplotlibDrawer:postDraw")
203 << "Failed to set Y range to " << rng << ". Matplotlib error: " << err.what();
204 }
205 }
206 plt::xlabel(dr.xAxis().label());
207 plt::ylabel(dr.yAxis().label());
208 plt::suptitle("CepGen v" + version::tag);
209 if (tight_)
210 plt::tight_layout();
211 }
212 } // namespace utils
213} // namespace cepgen
#define REGISTER_DRAWER(name, obj)
Add a drawing utilitary.
cepgen::utils::MatplotlibDrawer MPLDrawer
#define CG_WARNING(mod)
Definition Message.h:228
const std::string & name() const
Module unique indexing name.
Definition NamedModule.h:42
A description object for parameters collection.
static ParametersDescription description()
Description of all object parameters.
Definition Steerable.cpp:42
A generic object which can be drawn in the standard output.
Definition Drawable.h:31
const std::string & name() const
Drawable name.
Definition Drawable.h:37
const std::string & title() const
Drawable name.
Definition Drawable.h:42
A generic drawing utility.
Definition Drawer.h:36
A one-dimensional graph object.
Definition Graph.h:29
A two-dimensional graph object.
Definition Graph.h:58
1D histogram container
Definition Histogram.h:72
2D histogram container
Definition Histogram.h:146
static ParametersDescription description()
MatplotlibDrawer(const ParametersList &)
const MatplotlibDrawer & draw(const Graph1D &, const Mode &) const override
Draw a one-dimensional graph.
std::vector< const Drawable * > DrawableColl
A collection of drawable objects.
Definition Drawer.h:34
Common namespace for this Monte Carlo generator.
static const std::string tag
CepGen version.
Definition Version.h:28