Rivet API documentation

Rivet 4.1.3
Cutflow.hh
1#ifndef RIVET_Cutflow_HH
2#define RIVET_Cutflow_HH
3
4#include "Rivet/Tools/HistoGroup.hh"
5#include "Rivet/Tools/RivetYODA.hh"
6#include "Rivet/Tools/Utils.hh"
7
8#include <iomanip>
9#include <iostream>
10#include <sstream>
11#include <string>
12#include <vector>
13
14namespace Rivet {
15
16 namespace {
17
18 template <typename T>
19 std::vector<T> operator+(std::vector<T>&& res, const std::vector<T>& vadd) {
20 res.insert(std::end(res), std::begin(vadd), std::end(vadd));
21 return std::move(res);
22 }
23 } // namespace
24
26 class Cutflow : public YODA::BinnedHisto<std::string> {
27 public:
28
29 using BaseT = YODA::BinnedHisto<std::string>;
30 using BinningT = BaseT::BinningT;
31 using FillType = BaseT::FillType;
32 using BinType = BaseT::BinT;
33 using Ptr = std::shared_ptr<Cutflow>;
34 using AnalysisObject::operator=;
35
38 : BaseT(), icurr(0) { }
39
41 Cutflow(const BinningT& binning)
42 : BaseT(binning), icurr(0) { }
43
45 Cutflow(BinningT&& binning)
46 : BaseT(std::move(binning)), icurr(0) { }
47
51 Cutflow(const std::vector<std::string>& edges, const std::string& path = "")
52 : BaseT(std::vector<std::string>{""} + edges, path), icurr(0) { }
53
57 virtual int fill(FillType&& coords, const double weight = 1.0, const double fraction = 1.0) {
58 int pos = BaseT::fill(std::move(coords), weight, fraction);
59 icurr = (size_t)pos; // cannot be negative for discrete AOs
60 return pos;
61 }
62
64 //
66 virtual int fill(std::string val, const double weight = 1.0, const double fraction = 1.0) {
67 int pos = BaseT::fill({val}, weight, fraction);
68 icurr = (size_t)pos; // cannot be negative for discrete AOs
69 return pos;
70 }
71
73 virtual int fillinit(const double weight = 1.0, const double fraction = 1.0) {
74 return fill(""s, weight, fraction);
75 }
76
78 virtual int fillnext(const bool cutresult, const double weight = 1.0, const double fraction = 1.0) {
79 if (!cutresult) return 0;
80 const std::string edge = BaseT::bin(++icurr).xEdge();
81 return fill(edge, weight, fraction);
82 }
83
85 virtual int fillnext(const double weight = 1.0, const double fraction = 1.0) {
86 return fillnext(true, weight, fraction);
87 }
88
90 virtual int fillnext(const std::vector<bool>& cutresults,
91 const double weight = 1.0,
92 const double fraction = 1.0) {
93 if (icurr + cutresults.size() > BaseT::numBins() + 1) {
94 throw RangeError("Number of filled cut results needs to match the Cutflow construction (in cutflow '"
95 + BaseT::path() + "')");
96 }
97 for (size_t i = 0; i < cutresults.size(); ++i) {
98 if (!cutresults[i]) return 0;
99 fillnext(weight, fraction); // also incremenrs icurr
100 }
101 return (int)icurr;
102 }
103
105 size_t currentIndex() const {
106 return icurr;
107 }
108
110 void scale(const double factor) {
111 BaseT::scaleW(factor);
112 }
113
115 void normalizeStep(const std::string& edge, const double norm) {
116 const auto& b = BaseT::binAt(edge);
117 if (b.sumW() == 0) {
118 MSG_WARNING("Failed to scale Cutflow " << BaseT::path() << " as bin " << edge << " is empty");
119 return;
120 }
121 scale(norm / b.sumW());
122 }
123
125 void normalizeFirst(const double norm) {
126 normalizeStep(""s, norm);
127 }
128
130 string str() const {
131 using namespace std;
132 stringstream ss;
133 ss << fixed << std::setprecision(1) << BaseT::bin(1).sumW();
134 const size_t weight0len = ss.str().length();
135 ss << fixed << std::setprecision(1) << BaseT::bin(1).effNumEntries();
136 const size_t count0len = ss.str().length();
137 ss.str("");
138 ss << BaseT::path() << " cut-flow:\n";
139 size_t maxnamelen = 0;
140 for (const string& edge : BaseT::xEdges()) {
141 maxnamelen = std::max(edge.length(), maxnamelen);
142 }
143 ss << setw(maxnamelen + 5) << "" << " " << setw(weight0len) << right << "Weight" << " "
144 << setw(count0len) << right << "Count" << " " << setw(6) << right << "A_cumu" << " " << setw(6)
145 << right << "A_incr";
146 //for (size_t i = 0; i <= ncuts; ++i) {
147 const double wtot = BaseT::bin(1).sumW();
148 double wlast = wtot;
149 for (const auto& bin : BaseT::bins()) {
150 const size_t i = bin.index();
151 const int pcttot = (wtot == 0) ? -1 : round(100 * bin.sumW() / wtot);
152 const int pctinc = (i == 1 || wlast == 0) ? -1 : round(100 * bin.sumW() / wlast);
153 wlast = bin.sumW();
154 stringstream ss2;
155 ss2 << fixed << setprecision(1) << bin.sumW();
156 const string weightstr = ss2.str();
157 ss2.str("");
158 ss2 << fixed << setprecision(1) << bin.effNumEntries();
159 const string countstr = ss2.str();
160 ss2.str("");
161 ss2 << fixed << setprecision(3) << pcttot << "%";
162 const string pcttotstr = ss2.str();
163 ss2.str("");
164 ss2 << fixed << setprecision(3) << pctinc << "%";
165 const string pctincstr = ss2.str();
166 ss << "\n"
167 << setw(maxnamelen + 5) << left << (i == 1 ? "" : "Pass " + BaseT::bin(i).xEdge()) << " "
168 << setw(weight0len) << right << weightstr << " " << setw(count0len) << right << countstr
169 << " " << setw(6) << right << (pcttot < 0 ? "- " : pcttotstr) << " " << setw(6) << right
170 << (pctinc < 0 ? "- " : pctincstr);
171 }
172 return ss.str();
173 }
174
176 void print(std::ostream& os) const {
177 os << str() << std::flush;
178 }
179
180 protected:
181
183 Log& getLog() const {
184 return Rivet::Log::getLog("Rivet.Cutflow");
185 }
186
187 size_t icurr;
188 };
189
190
192 template <>
193 class FillCollector<Cutflow> : public Cutflow {
194 public:
195
196 using YAO = Cutflow;
197 using Ptr = shared_ptr<FillCollector<YAO>>;
198 using YAO::operator=;
199
200 FillCollector()
201 : YAO() { }
202
211 FillCollector(typename YAO::Ptr yao)
212 : YAO(yao->binning()) {
213 YAO::setPath(yao->path());
214 }
215
220 int fill(typename YAO::FillType&& fillCoords, const double weight = 1.0, const double fraction = 1.0) {
221 (void)fraction; // suppress unused variable warning
222 YAO::icurr = YAO::_binning.globalIndexAt(fillCoords);
223 _fills.insert(_fills.end(), {std::move(fillCoords), weight});
224 return (int)YAO::icurr;
225 }
226
227 int fill(const std::string val, const double weight = 1.0, const double fraction = 1.0) {
228 return fill(typename YAO::FillType{val}, weight, fraction);
229 }
230
231 int fillnext(const bool cutresult, const double weight = 1.0, const double fraction = 1.0) {
232 if (!cutresult) return 0;
233 return fill(YAO::bin(++YAO::icurr).xEdge(), weight, fraction);
234 }
235
236 int fillnext(const double weight = 1.0, const double fraction = 1.0) {
237 return fillnext(true, weight, fraction);
238 }
239
240 int fillnext(const std::vector<bool>& cutresults,
241 const double weight = 1.0,
242 const double fraction = 1.0) {
243 if (YAO::icurr + cutresults.size() > YAO::numBins() + 1) {
244 throw RangeError("Number of filled cut results needs to match the Cutflow construction (in cutflow '"
245 + YAO::path() + "')");
246 }
247 for (size_t i = 0; i < cutresults.size(); ++i) {
248 if (!cutresults[i]) return 0;
249 fillnext(weight, fraction);
250 }
251 return (int)YAO::icurr;
252 }
253
254 int fillinit(const double weight = 1.0, const double fraction = 1.0) {
255 return fill(""s, weight, fraction);
256 }
257
259 void reset() noexcept {
260 _fills.clear();
261 }
262
264 const Fills<YAO>& fills() const {
265 return _fills;
266 }
267
268 private:
269
270 Fills<YAO> _fills;
271 };
272
273
276
279
281 inline std::ostream& operator<<(std::ostream& os, const Cutflow& cf) {
282 return os << cf.str();
283 }
284
285 inline std::ostream& operator<<(std::ostream& os, const CutflowPtr& cf) {
286 return os << cf->str();
287 }
288
290
291
293 class Cutflows : public YODA::FillableStorage<2, CutflowPtr, std::string>, public YODA::Fillable {
294 public:
295
296 using BaseT = YODA::FillableStorage<2, CutflowPtr, std::string>;
297 using BinContentT = CutflowPtr;
298 using BinT = YODA::Bin<1, BinContentT, BaseT::BinningT>;
299 using FillDim = std::integral_constant<size_t, 2>;
300
303
306 : BaseT(groupAdapter<FillDim{}, BinContentT, std::string>) { }
307
309 Cutflows(const std::vector<std::string>& edges)
310 : BaseT(YODA::Axis<std::string>(edges), groupAdapter<FillDim{}, BinContentT, std::string>) { }
311
313 Cutflows(std::initializer_list<std::string>&& edges)
314 : BaseT(YODA::Axis<std::string>(std::move(edges)),
315 groupAdapter<FillDim{}, BinContentT, std::string>) { }
316
318
321
323 int fill(const std::string& grpCoord,
324 const std::string& edge,
325 const double weight = 1.0,
326 const double fraction = 1.0) {
327 auto& cfl = BaseT::binAt({grpCoord});
328 if (!cfl.raw()) return -1; // nullptr if bin not booked
329 return cfl->fill({edge}, weight, fraction);
330 }
331
333 int groupfillinit(const double weight = 1.0, const double fraction = 1.0) {
334 bool pass = true;
335 for (auto& cfl : BaseT::bins()) {
336 if (!cfl.get()) continue;
337 pass &= cfl->fillinit(weight, fraction);
338 }
339 return (int)pass;
340 }
341
343 int groupfillnext(const bool cutresult, const double weight = 1.0, const double fraction = 1.0) {
344 if (!cutresult) return 0;
345 bool pass = true;
346 for (auto& cfl : BaseT::bins()) {
347 if (!cfl.get()) continue;
348 pass &= cfl->fillnext(cutresult, weight, fraction);
349 }
350 return (int)pass;
351 }
352
354 int groupfillnext(const double weight = 1.0, const double fraction = 1.0) {
355 return groupfillnext(true, weight, fraction);
356 }
357
359 int groupfillnext(const std::vector<bool>& cutresults,
360 const double weight = 1.0,
361 const double fraction = 1.0) {
362 bool pass = true;
363 for (auto& cfl : BaseT::bins()) {
364 if (!cfl.get()) continue;
365 pass &= cfl->fillnext(cutresults, weight, fraction);
366 }
367 return (int)pass;
368 }
369
371 int fillnext(const std::string& grpCoord, const double weight = 1.0, const double fraction = 1.0) {
372 return BaseT::binAt(grpCoord)->fillnext(weight, fraction);
373 }
374
376 int fillnext(const std::string& grpCoord,
377 const bool cutresult,
378 const double weight = 1.0,
379 const double fraction = 1.0) {
380 return BaseT::binAt(grpCoord)->fillnext(cutresult, weight, fraction);
381 }
382
384 int fillnext(const std::string& grpCoord,
385 const std::vector<bool>& cutresults,
386 const double weight = 1.0,
387 const double fraction = 1.0) {
388 return BaseT::binAt(grpCoord)->fillnext(cutresults, weight, fraction);
389 }
390
392
395
399 void reset() noexcept {
400 BaseT::reset();
401 }
402
404
407
409 size_t fillDim() const noexcept {
410 return FillDim{};
411 }
412
414 size_t dim() const noexcept {
415 return fillDim() + 1;
416 }
417
419 double numEntries(const bool includeOverflows = true) const noexcept {
420 double n = 0;
421 for (const auto& cfl : BaseT::bins(includeOverflows)) {
422 if (!cfl.get()) continue;
423 n += cfl->numEntries(includeOverflows);
424 }
425 return n;
426 }
427
429 double effNumEntries(const bool includeOverflows = true) const noexcept {
430 double n = 0;
431 for (const auto& cfl : BaseT::bins(includeOverflows)) {
432 if (!cfl.get()) continue;
433 n += cfl->effNumEntries(includeOverflows);
434 }
435 return n;
436 }
437
439 double sumW(const bool includeOverflows = true) const noexcept {
440 double sumw = 0;
441 for (const auto& cfl : BaseT::bins(includeOverflows)) {
442 if (!cfl.get()) continue;
443 sumw += cfl->sumW(includeOverflows);
444 }
445 return sumw;
446 }
447
449 double sumW2(const bool includeOverflows = true) const noexcept {
450 double sumw2 = 0;
451 for (const auto& cfl : BaseT::bins(includeOverflows)) {
452 if (!cfl.get()) continue;
453 sumw2 += cfl->sumW2(includeOverflows);
454 }
455 return sumw2;
456 }
457
459 double integral(const bool includeOverflows = true) const noexcept {
460 return sumW(includeOverflows);
461 }
462
464 double integralError(const bool includeOverflows = true) const noexcept {
465 return sqrt(sumW2(includeOverflows));
466 }
467
469
472
474 void scaleW(const double scalefactor) noexcept {
475 for (auto& cfl : BaseT::bins(true, true)) {
476 if (!cfl.get()) continue;
477 cfl->scaleW(scalefactor);
478 }
479 }
480
482 void scale(const double scalefactor) noexcept {
483 for (auto& cfl : BaseT::bins(true, true)) {
484 if (!cfl.get()) continue;
485 cfl->scale(scalefactor);
486 }
487 }
488
492 void normalizeStep(const std::string& edge, const double norm) {
493 for (auto& cfl : BaseT::bins(true, true)) {
494 if (!cfl.get()) continue;
495 if (cfl->binAt(edge).sumW() != 0.) cfl->normalizeStep(edge, norm);
496 }
497 }
498
500 void normalizeFirst(const double norm) {
501 normalizeStep(""s, norm);
502 }
503
505
508
510 string str() const {
511 std::stringstream ss;
512 for (auto& cf : BaseT::bins(true, true)) {
513 if (!cf.get()) continue;
514 ss << cf << "\n\n";
515 }
516 return ss.str();
517 }
518
520 void print(std::ostream& os) const {
521 os << str() << std::flush;
522 }
523
525 };
526
529
531 using CutflowsPtr = std::shared_ptr<Cutflows>;
532
534 inline std::ostream& operator<<(std::ostream& os, const Cutflows& cfs) {
535 return os << cfs.str();
536 }
537
539 inline std::ostream& operator<<(std::ostream& os, const CutflowsPtr& cfs) {
540 return os << cfs->str();
541 }
542
544
545}
546
547#endif
A tracker of numbers & fractions of events passing sequential cuts.
Definition Cutflow.hh:26
virtual int fill(std::string val, const double weight=1.0, const double fraction=1.0)
Fill function using an explicit coordinate.
Definition Cutflow.hh:66
virtual int fillnext(const std::vector< bool > &cutresults, const double weight=1.0, const double fraction=1.0)
Convenience method to fill the next cut steps from an n-element results vector cutresult.
Definition Cutflow.hh:90
virtual int fillnext(const bool cutresult, const double weight=1.0, const double fraction=1.0)
Convenience method to fill the next cut step if cutresult is true.
Definition Cutflow.hh:78
virtual int fillnext(const double weight=1.0, const double fraction=1.0)
Convenience method to fill the next cut step.
Definition Cutflow.hh:85
Log & getLog() const
Get a logger object.
Definition Cutflow.hh:183
void normalizeStep(const std::string &edge, const double norm)
Scale the cutflow weights so that the weight count after cut edge is norm.
Definition Cutflow.hh:115
Cutflow()
Nullary constructor.
Definition Cutflow.hh:37
void normalizeFirst(const double norm)
Alias to scale the cutflow weights so that the weight after the pre-init cut is norm.
Definition Cutflow.hh:125
string str() const
Create a string representation.
Definition Cutflow.hh:130
Cutflow(const std::vector< std::string > &edges, const std::string &path="")
Definition Cutflow.hh:51
Cutflow(const BinningT &binning)
Constructor using binning object.
Definition Cutflow.hh:41
size_t currentIndex() const
Returns current cutflow index for debugging.
Definition Cutflow.hh:105
void scale(const double factor)
Scale the cutflow weights by the given factor.
Definition Cutflow.hh:110
virtual int fillinit(const double weight=1.0, const double fraction=1.0)
Convenience method to fill the pre-cut step.
Definition Cutflow.hh:73
Cutflow(BinningT &&binning)
Constructor using rvalue binning object.
Definition Cutflow.hh:45
virtual int fill(FillType &&coords, const double weight=1.0, const double fraction=1.0)
Fill function with FillType.
Definition Cutflow.hh:57
void print(std::ostream &os) const
Print string representation to a stream.
Definition Cutflow.hh:176
A container for several Cutflow objects, with some convenient batch access.
Definition Cutflow.hh:293
string str() const
Create a string representation.
Definition Cutflow.hh:510
double integralError(const bool includeOverflows=true) const noexcept
Get the total volume error of the histogram group.
Definition Cutflow.hh:464
int groupfillnext(const std::vector< bool > &cutresults, const double weight=1.0, const double fraction=1.0)
Method using a vector of cutresults.
Definition Cutflow.hh:359
double effNumEntries(const bool includeOverflows=true) const noexcept
Get the effective number of fills.
Definition Cutflow.hh:429
void reset() noexcept
Reset the histogram.
Definition Cutflow.hh:399
void scaleW(const double scalefactor) noexcept
Rescale as if all fill weights had been different by factor scalefactor.
Definition Cutflow.hh:474
void scale(const double scalefactor) noexcept
Rescale as if all fill weights had been different by factor scalefactor along dimension i.
Definition Cutflow.hh:482
int fillnext(const std::string &grpCoord, const std::vector< bool > &cutresults, const double weight=1.0, const double fraction=1.0)
Method that only fills the next step at coordinate grpCoord using a vector of cutresults.
Definition Cutflow.hh:384
int groupfillnext(const double weight=1.0, const double fraction=1.0)
Short-hand method that assumes the cut result is true.
Definition Cutflow.hh:354
double sumW(const bool includeOverflows=true) const noexcept
Calculates sum of weights in histo group.
Definition Cutflow.hh:439
Cutflows()
Nullary constructor.
Definition Cutflow.hh:305
int groupfillinit(const double weight=1.0, const double fraction=1.0)
Method to fill the pre-cut steps.
Definition Cutflow.hh:333
void normalizeFirst(const double norm)
Alias to scale the cutflow weights so that the weight after the pre-init cut is norm.
Definition Cutflow.hh:500
Cutflows(const std::vector< std::string > &edges)
Constructor using a vector of (outer) edges.
Definition Cutflow.hh:309
int fill(const std::string &grpCoord, const std::string &edge, const double weight=1.0, const double fraction=1.0)
Fill method using the FillType of the underlying FIllableStorage.
Definition Cutflow.hh:323
int fillnext(const std::string &grpCoord, const bool cutresult, const double weight=1.0, const double fraction=1.0)
Method that only fills the next step at coordinate grpCoord if cutresult is true.
Definition Cutflow.hh:376
int fillnext(const std::string &grpCoord, const double weight=1.0, const double fraction=1.0)
Method that only fills the next step at coordinate grpCoord.
Definition Cutflow.hh:371
size_t dim() const noexcept
Total dimension of the object (number of fill axes + filled value).
Definition Cutflow.hh:414
int groupfillnext(const bool cutresult, const double weight=1.0, const double fraction=1.0)
Method to fill the next step if cutresult is true.
Definition Cutflow.hh:343
Cutflows(std::initializer_list< std::string > &&edges)
Constructor using an initializer_set of (outer) edges.
Definition Cutflow.hh:313
double integral(const bool includeOverflows=true) const noexcept
Get the total volume of the histogram group.
Definition Cutflow.hh:459
void print(std::ostream &os) const
Print string representation to a stream.
Definition Cutflow.hh:520
double numEntries(const bool includeOverflows=true) const noexcept
Get the number of fills (fractional fills are possible).
Definition Cutflow.hh:419
size_t fillDim() const noexcept
Fill dimension of the object (number of conent axes + temprary axis).
Definition Cutflow.hh:409
void normalizeStep(const std::string &edge, const double norm)
Definition Cutflow.hh:492
double sumW2(const bool includeOverflows=true) const noexcept
Calculates sum of squared weights in histo group.
Definition Cutflow.hh:449
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition Cutflow.hh:264
int fillnext(const bool cutresult, const double weight=1.0, const double fraction=1.0)
Convenience method to fill the next cut step if cutresult is true.
Definition Cutflow.hh:231
FillCollector(typename YAO::Ptr yao)
Definition Cutflow.hh:211
int fillnext(const std::vector< bool > &cutresults, const double weight=1.0, const double fraction=1.0)
Convenience method to fill the next cut steps from an n-element results vector cutresult.
Definition Cutflow.hh:240
int fillnext(const double weight=1.0, const double fraction=1.0)
Convenience method to fill the next cut step.
Definition Cutflow.hh:236
int fill(const std::string val, const double weight=1.0, const double fraction=1.0)
Fill function using an explicit coordinate.
Definition Cutflow.hh:227
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition Cutflow.hh:220
int fillinit(const double weight=1.0, const double fraction=1.0)
Convenience method to fill the pre-cut step.
Definition Cutflow.hh:254
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition Cutflow.hh:259
Logging system for controlled & formatted writing to stdout.
Definition Logging.hh:10
static Log & getLog(const std::string &name)
Definition RivetYODA.hh:1376
vector< Fill< T > > Fills
A collection of several Fill objects.
Definition RivetYODA.hh:148
#define MSG_WARNING(x)
Warning messages for non-fatal bad things, using MSG_LVL.
Definition Logging.hh:200
Definition LHCbCommon.hh:9
std::shared_ptr< Cutflows > CutflowsPtr
Convenience alias.
Definition Cutflow.hh:531
std::ostream & operator<<(std::ostream &os, const AnalysisInfo &ai)
Stream an AnalysisInfo as a text description.
Definition AnalysisInfo.hh:463
MultiplexPtr< Multiplexer< Cutflow > > CutflowPtr
Convenience alias.
Definition Cutflow.hh:278
STL namespace.
Error for e.g. use of invalid bin ranges.
Definition Exceptions.hh:23