yoda is hosted by Hepforge, IPPP Durham
YODA - Yet more Objects for Data Analysis 2.0.2
WriterYODA1.cc
Go to the documentation of this file.
1// -*- C++ -*-
2//
3// This file is part of YODA -- Yet more Objects for Data Analysis
4// Copyright (C) 2008-2024 The YODA collaboration (see AUTHORS for details)
5//
6#include "YODA/WriterYODA1.h"
7
8#include "yaml-cpp/yaml.h"
9#ifdef YAML_NAMESPACE
10#define YAML YAML_NAMESPACE
11#endif
12
13#include <iostream>
14#include <iomanip>
15using namespace std;
16
17namespace YODA {
18
19
22 static WriterYODA1 _instance;
23 _instance.setPrecision(6);
24 return _instance;
25 }
26
27
28 void WriterYODA1::_writeAnnotations(std::ostream& os, const AnalysisObject& ao) {
29 os << scientific << setprecision(_aoprecision);
30 for (const string& a : ao.annotations()) {
31 if (a.empty()) continue;
33 string ann = ao.annotation(a);
34 // remove stpurious line returns at the end of a string so that we don't
35 // end up with two line returns.
36 ann.erase(std::remove(ann.begin(), ann.end(), '\n'), ann.end());
37 os << a << ": " << ann << "\n";
38 }
39 os << "---\n";
40 }
41
42 void WriterYODA1::writeAO(std::ostream& stream, const AnalysisObject& ao) {
43 const string aotype = ao.type();
44 if (aotype == "Counter") {
45 writeCounter(stream, dynamic_cast<const Counter&>(ao));
46 } else if (aotype == "Histo1D") {
47 writeHisto1D(stream, dynamic_cast<const Histo1D&>(ao));
48 } else if (aotype == "Histo2D") {
49 writeHisto2D(stream, dynamic_cast<const Histo2D&>(ao));
50 } else if (aotype == "Profile1D") {
51 writeProfile1D(stream, dynamic_cast<const Profile1D&>(ao));
52 } else if (aotype == "Profile2D") {
53 writeProfile2D(stream, dynamic_cast<const Profile2D&>(ao));
54 } else if (aotype == "Scatter1D") {
55 writeScatter1D(stream, dynamic_cast<const Scatter1D&>(ao));
56 } else if (aotype == "Scatter2D") {
57 writeScatter2D(stream, dynamic_cast<const Scatter2D&>(ao));
58 } else if (aotype == "Scatter3D") {
59 writeScatter3D(stream, dynamic_cast<const Scatter3D&>(ao));
60 } else {
61 stream << "# Type " << aotype << " not supported in the legacy writer.\n";
62 // Skip writing other AO types since they were not supported in YODA1.
63 }
64 }
65
66
67 void WriterYODA1::writeCounter(std::ostream& os, const Counter& c) {
68 ios_base::fmtflags oldflags = os.flags();
69 os << scientific << showpoint << setprecision(_aoprecision);
70
71 os << "BEGIN YODA_" << Utils::toUpper("COUNTER") << "_V2 " << c.path() << "\n";
72 _writeAnnotations(os, c);
73 os << "# sumW\t sumW2\t numEntries\n";
74 os << c.sumW() << "\t" << c.sumW2() << "\t" << c.numEntries() << "\n";
75 os << "END YODA_" << Utils::toUpper("COUNTER") << "_V2\n\n";
76
77 os.flags(oldflags);
78 }
79
80
81 void WriterYODA1::writeHisto1D(std::ostream& os, const Histo1D& h) {
82 ios_base::fmtflags oldflags = os.flags();
83 os << scientific << showpoint << setprecision(_aoprecision);
84
85 os << "BEGIN YODA_" << Utils::toUpper("HISTO1D") << "_V2 " << h.path() << "\n";
86 _writeAnnotations(os, h);
87 try {
88 os << "# Mean: " << h.xMean() << "\n";
89 os << "# Area: " << h.integral() << "\n";
90 } catch (LowStatsError& e) {
91 //
92 }
93 os << "# ID\t ID\t sumw\t sumw2\t sumwx\t sumwx2\t numEntries\n";
94 os << "Total \tTotal \t";
95 os << h.sumW() << "\t" << h.sumW2() << "\t";
96 os << h.sumWA(0) << "\t" << h.sumWA2(0) << "\t";
97 os << h.numEntries() << "\n";
98 os << "Underflow\tUnderflow\t";
99 os << h.bin(0).sumW() << "\t" << h.bin(0).sumW2() << "\t";
100 os << h.bin(0).sumWX() << "\t" << h.bin(0).sumWX2() << "\t";
101 os << h.bin(0).numEntries() << "\n";
102 os << "Overflow\tOverflow\t";
103 os << h.bin(h.numBins()+1).sumW() << "\t" << h.bin(h.numBins()+1).sumW2() << "\t";
104 os << h.bin(h.numBins()+1).sumWX() << "\t" << h.bin(h.numBins()+1).sumWX2() << "\t";
105 os << h.bin(h.numBins()+1).numEntries() << "\n";
106 os << "# xlow\t xhigh\t sumw\t sumw2\t sumwx\t sumwx2\t numEntries\n";
107 for (const auto& b : h.bins()) {
108 os << b.xMin() << "\t" << b.xMax() << "\t";
109 os << b.sumW() << "\t" << b.sumW2() << "\t";
110 os << b.sumWX() << "\t" << b.sumWX2() << "\t";
111 os << b.numEntries() << "\n";
112 }
113 os << "END YODA_" << Utils::toUpper("HISTO1D") << "_V2\n\n";
114
115 os.flags(oldflags);
116 }
117
118
119 void WriterYODA1::writeHisto2D(std::ostream& os, const Histo2D& h) {
120 ios_base::fmtflags oldflags = os.flags();
121 os << scientific << showpoint << setprecision(_aoprecision);
122 os << "BEGIN YODA_" << Utils::toUpper("HISTO2D") << "_V2 " << h.path() << "\n";
123 _writeAnnotations(os, h);
124 try {
125 //if ( h.totalDbn().numEntries() > 0 )
126 os << "# Mean: (" << h.xMean() << ", " << h.yMean() << ")\n";
127 os << "# Volume: " << h.integral() << "\n";
128 } catch (LowStatsError& e) {
129 //
130 }
131 os << "# ID\t ID\t sumw\t sumw2\t sumwx\t sumwx2\t sumwy\t sumwy2\t sumwxy\t numEntries\n";
132 // Total distribution
133 os << "Total \tTotal \t";
134 os << h.sumW() << "\t" << h.sumW2() << "\t";
135 os << h.sumWA(0) << "\t" << h.sumWA2(0) << "\t";
136 os << h.sumWA(1) << "\t" << h.sumWA2(1) << "\t";
137 os << h.crossTerm(0,1) << "\t";
138 os << h.numEntries() << "\n";
139 // Outflows
141 os << "# 2D outflow persistency not currently supported until API is stable\n";
142 // Bins
143 os << "# xlow\t xhigh\t ylow\t yhigh\t sumw\t sumw2\t sumwx\t sumwx2\t sumwy\t sumwy2\t sumwxy\t numEntries\n";
144 for (const auto& b : h.bins()) {
145 os << b.xMin() << "\t" << b.xMax() << "\t";
146 os << b.yMin() << "\t" << b.yMax() << "\t";
147 os << b.sumW() << "\t" << b.sumW2() << "\t";
148 os << b.sumWX() << "\t" << b.sumWX2() << "\t";
149 os << b.sumWY() << "\t" << b.sumWY2() << "\t";
150 os << b.sumWXY() << "\t";
151 os << b.numEntries() << "\n";
152 }
153 os << "END YODA_" << Utils::toUpper("HISTO2D") << "_V2\n\n";
154
155 os.flags(oldflags);
156 }
157
158
159 void WriterYODA1::writeProfile1D(std::ostream& os, const Profile1D& p) {
160 ios_base::fmtflags oldflags = os.flags();
161 os << scientific << showpoint << setprecision(_aoprecision);
162
163 os << "BEGIN YODA_" << Utils::toUpper("PROFILE1D") << "_V2 " << p.path() << "\n";
164 _writeAnnotations(os, p);
165 os << "# ID\t ID\t sumw\t sumw2\t sumwx\t sumwx2\t sumwy\t sumwy2\t numEntries\n";
166 os << "Total \tTotal \t";
167 os << p.sumW() << "\t" << p.sumW2() << "\t";
168 os << p.sumWA(0) << "\t" << p.sumWA2(0) << "\t";
169 os << p.sumWA(1) << "\t" << p.sumWA2(1) << "\t";
170 os << p.numEntries() << "\n";
171 os << "Underflow\tUnderflow\t";
172 os << p.bin(0).sumW() << "\t" << p.bin(0).sumW2() << "\t";
173 os << p.bin(0).sumWX() << "\t" << p.bin(0).sumWX2() << "\t";
174 os << p.bin(0).sumWY() << "\t" << p.bin(0).sumWY2() << "\t";
175 os << p.bin(0).numEntries() << "\n";
176 os << "Overflow\tOverflow\t";
177 os << p.bin(p.numBins()+1).sumW() << "\t" << p.bin(p.numBins()+1).sumW2() << "\t";
178 os << p.bin(p.numBins()+1).sumWX() << "\t" << p.bin(p.numBins()+1).sumWX2() << "\t";
179 os << p.bin(p.numBins()+1).sumWY() << "\t" << p.bin(p.numBins()+1).sumWY2() << "\t";
180 os << p.bin(p.numBins()+1).numEntries() << "\n";
181 os << "# xlow\t xhigh\t sumw\t sumw2\t sumwx\t sumwx2\t sumwy\t sumwy2\t numEntries\n";
182 for (const auto& b : p.bins()) {
183 os << b.xMin() << "\t" << b.xMax() << "\t";
184 os << b.sumW() << "\t" << b.sumW2() << "\t";
185 os << b.sumWX() << "\t" << b.sumWX2() << "\t";
186 os << b.sumWY() << "\t" << b.sumWY2() << "\t";
187 os << b.numEntries() << "\n";
188 }
189 os << "END YODA_" << Utils::toUpper("PROFILE1D") << "_V2\n\n";
190
191 os.flags(oldflags);
192 }
193
194
195 void WriterYODA1::writeProfile2D(std::ostream& os, const Profile2D& p) {
196 ios_base::fmtflags oldflags = os.flags();
197 os << scientific << showpoint << setprecision(_aoprecision);
198
199 os << "BEGIN YODA_" << Utils::toUpper("PROFILE2D") << "_V2 " << p.path() << "\n";
200 _writeAnnotations(os, p);
201 os << "# sumw\t sumw2\t sumwx\t sumwx2\t sumwy\t sumwy2\t sumwz\t sumwz2\t sumwxy\t numEntries\n";
202 // Total distribution
203 os << "Total \tTotal \t";
204 os << p.sumW() << "\t" << p.sumW2() << "\t";
205 os << p.sumWA(0) << "\t" << p.sumWA2(0) << "\t";
206 os << p.sumWA(1) << "\t" << p.sumWA2(1) << "\t";
207 os << p.sumWA(2) << "\t" << p.sumWA2(2) << "\t";
208 os << p.crossTerm(0,1) << "\t"; // << td.sumWXZ() << "\t" << td.sumWYZ() << "\t";
209 os << p.numEntries() << "\n";
210 // Outflows
212 os << "# 2D outflow persistency not currently supported until API is stable\n";
213 // Bins
214 os << "# xlow\t xhigh\t ylow\t yhigh\t sumw\t sumw2\t sumwx\t sumwx2\t sumwy\t sumwy2\t sumwz\t sumwz2\t sumwxy\t numEntries\n";
215 for (const auto& b : p.bins()) {
216 os << b.xMin() << "\t" << b.xMax() << "\t";
217 os << b.yMin() << "\t" << b.yMax() << "\t";
218 os << b.sumW() << "\t" << b.sumW2() << "\t";
219 os << b.sumWX() << "\t" << b.sumWX2() << "\t";
220 os << b.sumWY() << "\t" << b.sumWY2() << "\t";
221 os << b.sumWZ() << "\t" << b.sumWZ2() << "\t";
222 os << b.sumWXY() << "\t"; // << b.sumWXZ() << "\t" << b.sumWYZ() << "\t";
223 os << b.numEntries() << "\n";
224 }
225 os << "END YODA_" << Utils::toUpper("PROFILE2D") << "_V2\n\n";
226
227 os.flags(oldflags);
228 }
229
230
231 void WriterYODA1::writeScatter1D(std::ostream& os, const Scatter1D& s) {
232 ios_base::fmtflags oldflags = os.flags();
233 os << scientific << showpoint << setprecision(_aoprecision);
234
235 // we promised not to modify const s, but we want to add an annotation
236 // we did not promise to not modify the *clone* of s...
237 auto sclone = s.clone();
238
239 os << "BEGIN YODA_" << Utils::toUpper("SCATTER1D") << "_V2 " << s.path() << "\n";
240 _writeAnnotations(os, sclone);
241
242 //write headers
243 std::string headers="# xval\t xerr-\t xerr+\t";
244 os << headers << "\n";
245
246 //write points
247 for (const Point1D& pt : s.points()) {
248 // fill central value
249 os << pt.x() << "\t" << pt.xErrMinus() << "\t" << pt.xErrPlus() ;
250 os << "\n";
251 }
252 os << "END YODA_" << Utils::toUpper("SCATTER1D") << "_V2\n\n";
253
254 os << flush;
255 os.flags(oldflags);
256 }
257
258
259 void WriterYODA1::writeScatter2D(std::ostream& os, const Scatter2D& s) {
260 ios_base::fmtflags oldflags = os.flags();
261 os << scientific << showpoint << setprecision(_aoprecision);
262 os << "BEGIN YODA_" << Utils::toUpper("SCATTER2D") << "_V2 " << s.path() << "\n";
263
264 // Write annotations.
265 // We promised not to modify const s, but we want to add an annotation;
266 // We did not promise to not modify the *clone* of s;
267 // Judge not, lest ye be judged
268 auto sclone = s.clone();
269 _writeAnnotations(os, sclone);
270
271 //write headers
273 std::string headers="# xval\t xerr-\t xerr+\t yval\t yerr-\t yerr+\t";
274 os << headers << "\n";
275
276 //write points
277 for (const Point2D& pt : s.points()) {
279 // fill central value
280 os << pt.x() << "\t" << pt.xErrMinus() << "\t" << pt.xErrPlus() << "\t";
281 os << pt.y() << "\t" << pt.yErrMinus() << "\t" << pt.yErrPlus() ;
282 os << "\n";
283 }
284 os << "END YODA_" << Utils::toUpper("SCATTER2D") << "_V2\n\n";
285
286 os << flush;
287 os.flags(oldflags);
288 }
289
290
291 void WriterYODA1::writeScatter3D(std::ostream& os, const Scatter3D& s) {
292 ios_base::fmtflags oldflags = os.flags();
293 os << scientific << showpoint << setprecision(_aoprecision);
294 os << "BEGIN YODA_" << Utils::toUpper("SCATTER3D") << "_V2 " << s.path() << "\n";
295
296 // write annotations
297 // we promised not to modify const s, but we want to add an annotation
298 // we did not promise to not modify the *clone* of s...
299 auto sclone = s.clone();
300 _writeAnnotations(os, sclone);
301
302 //write headers
304 std::string headers="# xval\t xerr-\t xerr+\t yval\t yerr-\t yerr+\t zval\t zerr-\t zerr+\t";
305 os << headers << "\n";
306
307 //write points
308 for (const Point3D& pt : s.points()) {
310 // fill central value
311 os << pt.x() << "\t" << pt.xErrMinus() << "\t" << pt.xErrPlus() << "\t";
312 os << pt.y() << "\t" << pt.yErrMinus() << "\t" << pt.yErrPlus() << "\t";
313 os << pt.z() << "\t" << pt.zErrMinus() << "\t" << pt.zErrPlus() ;
314 os << "\n";
315 }
316 os << "END YODA_" << Utils::toUpper("SCATTER3D") << "_V2\n\n";
317
318 os << flush;
319 os.flags(oldflags);
320 }
321
322
323}
AnalysisObject is the base class for histograms and scatters.
virtual std::string type() const
Get name of the analysis object type.
const std::string path() const
Get the AO path.
const std::string & annotation(const std::string &name) const
Get an annotation by name (as a string)
User-facing BinnedDbn class in arbitrary dimension.
Definition BinnedDbn.h:50
BinT & bin(size_t idx) noexcept
Returns reference to the bin at idx.
size_t numBins(const bool includeOverflows=false, const bool includeMaskedBins=false) const noexcept
Number of bins in the BinnedStorage.
BinsVecWrapper< BinsVecT > bins(const bool includeOverflows=false, const bool includeMaskedBins=false) noexcept
Returns bins vector wrapper, which skips masked elements when iterated over.
A weighted counter.
Definition Counter.h:26
double sumW2(bool=false) const
Get the sum of squared weights.
Definition Counter.h:186
double numEntries(bool=false) const
Get the number of fills.
Definition Counter.h:177
double sumW(bool=false) const
Get the sum of weights.
Definition Counter.h:183
double sumWA(const size_t dim, const bool includeOverflows=true) const
Calculates first moment along axis dim in histo.
Definition BinnedDbn.h:538
double sumWA2(const size_t dim, const bool includeOverflows=true) const
Calculates second moment along axis dim in histo.
Definition BinnedDbn.h:547
double numEntries(const bool includeOverflows=true) const noexcept
Get the number of fills (fractional fills are possible).
Definition BinnedDbn.h:506
double crossTerm(const size_t A1, const size_t A2, const bool includeOverflows=true) const
Calculates cross-term along axes A1 and A2 in histo.
Definition BinnedDbn.h:557
double sumW(const bool includeOverflows=true) const noexcept
Calculates sum of weights in histo.
Definition BinnedDbn.h:522
double sumW2(const bool includeOverflows=true) const noexcept
Calculates sum of squared weights in histo.
Definition BinnedDbn.h:530
double integral(const bool includeOverflows=true) const noexcept
Get the total volume of the histogram.
Definition BinnedDbn.h:463
Errors relating to insufficient (effective) statistics.
Definition Exceptions.h:72
A 1D data point to be contained in a Scatter1D.
Definition Point.h:555
A 2D data point to be contained in a Scatter2D.
Definition Point.h:607
A 3D data point to be contained in a Scatter3D.
Definition Point.h:662
A generic data type which is just a collection of n-dim data points with errors.
Definition Scatter.h:154
ScatterND< N > clone() const
Make a copy on the stack.
Definition Scatter.h:284
Points & points()
Get the collection of points.
Definition Scatter.h:350
Persistency writer for YODA flat text format.
Definition WriterYODA1.h:20
void writeScatter1D(std::ostream &stream, const Scatter1D &s)
void writeAO(std::ostream &stream, const AnalysisObject &c)
void writeCounter(std::ostream &stream, const Counter &c)
void writeScatter3D(std::ostream &stream, const Scatter3D &s)
void writeScatter2D(std::ostream &stream, const Scatter2D &s)
void writeHisto1D(std::ostream &stream, const Histo1D &h)
void writeProfile1D(std::ostream &stream, const Profile1D &p)
static Writer & create()
Singleton creation function.
void writeProfile2D(std::ostream &stream, const Profile2D &p)
void writeHisto2D(std::ostream &stream, const Histo2D &h)
Pure virtual base class for various output writers.
Definition Writer.h:19
void setPrecision(int precision)
Set precision of numerical quantities in this writer's output.
Definition Writer.h:143
Anonymous namespace to limit visibility.