rivet is hosted by Hepforge, IPPP Durham
Rivet 4.0.2
Cutflow.hh
1#ifndef RIVET_Cutflow_HH
2#define RIVET_Cutflow_HH
3
4#include "Rivet/Tools/RivetYODA.hh"
5#include "Rivet/Tools/Utils.hh"
6
7#include <iomanip>
8#include <iostream>
9#include <vector>
10#include <sstream>
11#include <string>
12
13namespace Rivet {
14
15 namespace {
16 template<typename T>
17 std::vector<T> operator+(std::vector<T>&& res, const std::vector<T>& vadd) {
18 res.insert(std::end(res), std::begin(vadd), std::end(vadd));
19 return std::move(res);
20 }
21 }
22
24 class Cutflow : public YODA::BinnedHisto<std::string> {
25 public:
26
27 using BaseT = YODA::BinnedHisto<std::string>;
28 using BinningT = BaseT::BinningT;
29 using FillType = BaseT::FillType;
30 using BinType = BaseT::BinT;
31 using Ptr = std::shared_ptr<Cutflow>;
32 using AnalysisObject::operator =;
33
35 Cutflow() : BaseT(), icurr(0) {}
36
38 Cutflow(const BinningT& binning) : BaseT(binning), icurr(0) { }
39
41 Cutflow(BinningT&& binning) : BaseT(std::move(binning)), icurr(0) { }
42
46 Cutflow(const std::vector<std::string>& edges, const std::string& path = "")
47 : BaseT(std::vector<std::string>{""} + edges, path), icurr(0) { }
48
52 virtual int fill(FillType&& coords, const double weight = 1.0, const double fraction = 1.0) {
53 int pos = BaseT::fill(std::move(coords), weight, fraction);
54 icurr = (size_t)pos; // cannot be negative for discrete AOs
55 return pos;
56 }
57
59 //
61 virtual int fill(std::string val, const double weight = 1.0, const double fraction = 1.0) {
62 int pos = BaseT::fill({val}, weight, fraction);
63 icurr = (size_t)pos; // cannot be negative for discrete AOs
64 return pos;
65 }
66
68 virtual int fillinit(const double weight=1.0, const double fraction=1.0) {
69 return fill(""s, weight, fraction);
70 }
71
73 virtual int fillnext(const bool cutresult, const double weight = 1.0, const double fraction = 1.0) {
74 if (!cutresult) return 0;
75 const std::string edge = BaseT::bin(++icurr).xEdge();
76 return fill(edge, weight, fraction);
77 }
78
80 virtual int fillnext(const double weight = 1.0, const double fraction = 1.0) {
81 return fillnext(true, weight, fraction);
82 }
83
85 virtual int fillnext(const std::vector<bool>& cutresults, const double weight = 1.0, const double fraction = 1.0) {
86 if (icurr+cutresults.size() > BaseT::numBins()+1) {
87 throw RangeError("Number of filled cut results needs to match the Cutflow construction (in cutflow '"+BaseT::path()+"')");
88 }
89 for (size_t i = 0; i < cutresults.size(); ++i) {
90 if (!cutresults[i]) return 0;
91 fillnext(weight, fraction); // also incremenrs icurr
92 }
93 return (int)icurr;
94 }
95
97 size_t currentIndex() const { return icurr; }
98
100 void scale(const double factor) {
101 BaseT::scaleW(factor);
102 }
103
105 void normalizeStep(const std::string& edge, const double norm) {
106 const auto& b = BaseT::binAt(edge);
107 if (b.sumW() == 0) {
108 MSG_WARNING("Failed to scale Cutflow " << BaseT::path() << " as bin " << edge << " is empty");
109 return;
110 }
111 scale(norm/b.sumW());
112 }
113
115 void normalizeFirst(const double norm) {
116 normalizeStep(""s, norm);
117 }
118
120 string str() const {
121 using namespace std;
122 stringstream ss;
123 ss << fixed << std::setprecision(1) << BaseT::bin(1).sumW();
124 const size_t weight0len = ss.str().length();
125 ss << fixed << std::setprecision(1) << BaseT::bin(1).effNumEntries();
126 const size_t count0len = ss.str().length();
127 ss.str("");
128 ss << BaseT::path() << " cut-flow:\n";
129 size_t maxnamelen = 0;
130 for (const string& edge : BaseT::xEdges()) {
131 maxnamelen = std::max(edge.length(), maxnamelen);
132 }
133 ss << setw(maxnamelen+5) << "" << " "
134 << setw(weight0len) << right << "Weight" << " "
135 << setw(count0len) << right << "Count" << " "
136 << setw(6) << right << "A_cumu" << " "
137 << setw(6) << right << "A_incr";
138 //for (size_t i = 0; i <= ncuts; ++i) {
139 const double wtot = BaseT::bin(1).sumW();
140 double wlast = wtot;
141 for (const auto& bin : BaseT::bins()) {
142 const size_t i = bin.index();
143 const int pcttot = (wtot == 0) ? -1 : round(100*bin.sumW()/wtot);
144 const int pctinc = (i == 1 || wlast == 0) ? -1 : round(100*bin.sumW()/wlast);
145 wlast = bin.sumW();
146 stringstream ss2;
147 ss2 << fixed << setprecision(1) << bin.sumW();
148 const string weightstr = ss2.str(); ss2.str("");
149 ss2 << fixed << setprecision(1) << bin.effNumEntries();
150 const string countstr = ss2.str(); ss2.str("");
151 ss2 << fixed << setprecision(3) << pcttot << "%";
152 const string pcttotstr = ss2.str(); ss2.str("");
153 ss2 << fixed << setprecision(3) << pctinc << "%";
154 const string pctincstr = ss2.str();
155 ss << "\n"
156 << setw(maxnamelen+5) << left << (i == 1 ? "" : "Pass "+BaseT::bin(i).xEdge()) << " "
157 << setw(weight0len) << right << weightstr << " "
158 << setw(count0len) << right << countstr << " "
159 << setw(6) << right << (pcttot < 0 ? "- " : pcttotstr) << " "
160 << setw(6) << right << (pctinc < 0 ? "- " : pctincstr);
161 }
162 return ss.str();
163 }
164
166 void print(std::ostream& os) const {
167 os << str() << std::flush;
168 }
169
170 protected:
171
173 Log& getLog() const {
174 return Rivet::Log::getLog("Rivet.Cutflow");
175 }
176
177 size_t icurr;
178
179 };
180
181
183 template <>
184 class FillCollector<Cutflow> : public Cutflow {
185 public:
186
187 using YAO = Cutflow;
188 using Ptr = shared_ptr<FillCollector<YAO>>;
189 using YAO::operator =;
190
191 FillCollector() : YAO() { }
192
201 FillCollector(typename YAO::Ptr yao) : YAO(yao->binning()) {
202 YAO::setPath(yao->path());
203 }
204
209 int fill(typename YAO::FillType&& fillCoords,
210 const double weight=1.0, const double fraction=1.0) {
211 (void)fraction; // suppress unused variable warning
212 YAO::icurr = YAO::_binning.globalIndexAt(fillCoords);
213 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
214 return (int)YAO::icurr;
215 }
216
217 int fill(const std::string val, const double weight = 1.0, const double fraction = 1.0) {
218 return fill(typename YAO::FillType{val}, weight, fraction);
219 }
220
221 int fillnext(const bool cutresult, const double weight = 1.0, const double fraction = 1.0) {
222 if (!cutresult) return 0;
223 return fill(YAO::bin(++YAO::icurr).xEdge(), weight, fraction);
224 }
225
226 int fillnext(const double weight = 1.0, const double fraction = 1.0) {
227 return fillnext(true, weight, fraction);
228 }
229
230 int fillnext(const std::vector<bool>& cutresults, const double weight = 1.0, const double fraction = 1.0) {
231 if (YAO::icurr+cutresults.size() > YAO::numBins()+1) {
232 throw RangeError("Number of filled cut results needs to match the Cutflow construction (in cutflow '"+YAO::path()+"')");
233 }
234 for (size_t i = 0; i < cutresults.size(); ++i) {
235 if (!cutresults[i]) return 0;
236 fillnext(weight, fraction);
237 }
238 return (int)YAO::icurr;
239 }
240
241 int fillinit(const double weight=1.0, const double fraction=1.0) {
242 return fill(""s, weight, fraction);
243 }
244
246 void reset() noexcept { _fills.clear(); }
247
249 const Fills<YAO>& fills() const { return _fills; }
250
251 private:
252
253 Fills<YAO> _fills;
254
255 };
256
259
262
264 inline std::ostream& operator << (std::ostream& os, const Cutflow& cf) {
265 return os << cf.str();
266 }
267
268 inline std::ostream& operator << (std::ostream& os, const CutflowPtr& cf) {
269 return os << cf->str();
270 }
271
273
274
276 class Cutflows : public YODA::FillableStorage<2, CutflowPtr, std::string>,
277 public YODA::Fillable {
278 public:
279
280 using BaseT = YODA::FillableStorage<2, CutflowPtr, std::string>;
281 using BinContentT = CutflowPtr;
282 using BinT = YODA::Bin<1, BinContentT, BaseT::BinningT>;
283 using FillDim = std::integral_constant<size_t, 2>;
284
287
289 Cutflows() : BaseT(groupAdapter<FillDim{}, BinContentT, std::string>) { }
290
292 Cutflows(const std::vector<std::string>& edges)
293 : BaseT(YODA::Axis<std::string>(edges), groupAdapter<FillDim{}, BinContentT, std::string>) { }
294
296 Cutflows(std::initializer_list<std::string>&& edges)
297 : BaseT(YODA::Axis<std::string>(std::move(edges)), groupAdapter<FillDim{}, BinContentT, std::string>) { }
298
300
303
305 int fill(const std::string& grpCoord, const std::string& edge, const double weight = 1.0, const double fraction = 1.0) {
306 auto& cfl = BaseT::binAt({grpCoord});
307 if (!cfl.raw()) return -1; // nullptr if bin not booked
308 return cfl->fill({edge}, weight, fraction);
309 }
310
312 int groupfillinit(const double weight=1.0, const double fraction=1.0) {
313 bool pass = true;
314 for (auto& cfl : BaseT::bins()) {
315 if (!cfl.get()) continue;
316 pass &= cfl->fillinit(weight, fraction);
317 }
318 return (int)pass;
319 }
320
322 int groupfillnext(const bool cutresult, const double weight = 1.0, const double fraction = 1.0) {
323 if (!cutresult) return 0;
324 bool pass = true;
325 for (auto& cfl : BaseT::bins()) {
326 if (!cfl.get()) continue;
327 pass &= cfl->fillnext(cutresult, weight, fraction);
328 }
329 return (int)pass;
330 }
331
333 int groupfillnext(const double weight = 1.0, const double fraction = 1.0) {
334 return groupfillnext(true, weight, fraction);
335 }
336
338 int groupfillnext(const std::vector<bool>& cutresults, const double weight = 1.0, const double fraction = 1.0) {
339 bool pass = true;
340 for (auto& cfl : BaseT::bins()) {
341 if (!cfl.get()) continue;
342 pass &= cfl->fillnext(cutresults, weight, fraction);
343 }
344 return (int)pass;
345 }
346
348 int fillnext(const std::string& grpCoord, const double weight=1.0, const double fraction=1.0) {
349 return BaseT::binAt(grpCoord)->fillnext(weight, fraction);
350 }
351
353 int fillnext(const std::string& grpCoord, const bool cutresult, const double weight=1.0, const double fraction=1.0) {
354 return BaseT::binAt(grpCoord)->fillnext(cutresult, weight, fraction);
355 }
356
358 int fillnext(const std::string& grpCoord, const std::vector<bool>& cutresults,
359 const double weight = 1.0, const double fraction = 1.0) {
360 return BaseT::binAt(grpCoord)->fillnext(cutresults, weight, fraction);
361 }
362
364
367
371 void reset() noexcept { BaseT::reset(); }
372
374
377
379 size_t fillDim() const noexcept { return FillDim{}; }
380
382 size_t dim() const noexcept { return fillDim()+1; }
383
385 double numEntries(const bool includeOverflows=true) const noexcept {
386 double n = 0;
387 for (const auto& cfl : BaseT::bins(includeOverflows)) {
388 if (!cfl.get()) continue;
389 n += cfl->numEntries(includeOverflows);
390 }
391 return n;
392 }
393
395 double effNumEntries(const bool includeOverflows=true) const noexcept {
396 double n = 0;
397 for (const auto& cfl : BaseT::bins(includeOverflows)) {
398 if (!cfl.get()) continue;
399 n += cfl->effNumEntries(includeOverflows);
400 }
401 return n;
402 }
403
405 double sumW(const bool includeOverflows=true) const noexcept {
406 double sumw = 0;
407 for (const auto& cfl : BaseT::bins(includeOverflows)) {
408 if (!cfl.get()) continue;
409 sumw += cfl->sumW(includeOverflows);
410 }
411 return sumw;
412 }
413
415 double sumW2(const bool includeOverflows=true) const noexcept {
416 double sumw2 = 0;
417 for (const auto& cfl : BaseT::bins(includeOverflows)) {
418 if (!cfl.get()) continue;
419 sumw2 += cfl->sumW2(includeOverflows);
420 }
421 return sumw2;
422 }
423
425 double integral(const bool includeOverflows=true) const noexcept {
426 return sumW(includeOverflows);
427 }
428
430 double integralError(const bool includeOverflows=true) const noexcept {
431 return sqrt(sumW2(includeOverflows));
432 }
433
435
438
440 void scaleW(const double scalefactor) noexcept {
441 for (auto& cfl : BaseT::bins(true, true)) {
442 if (!cfl.get()) continue;
443 cfl->scaleW(scalefactor);
444 }
445 }
446
448 void scale(const double scalefactor) noexcept {
449 for (auto& cfl : BaseT::bins(true, true)) {
450 if (!cfl.get()) continue;
451 cfl->scale(scalefactor);
452 }
453 }
454
458 void normalizeStep(const std::string& edge, const double norm) {
459 for (auto& cfl : BaseT::bins(true, true)) {
460 if (!cfl.get()) continue;
461 if (cfl->binAt(edge).sumW() != 0.) cfl->normalizeStep(edge, norm);
462 }
463 }
464
466 void normalizeFirst(const double norm) {
467 normalizeStep(""s, norm);
468 }
469
471
474
476 string str() const {
477 std::stringstream ss;
478 for (auto& cf : BaseT::bins(true, true)) {
479 if (!cf.get()) continue;
480 ss << cf << "\n\n";
481 }
482 return ss.str();
483 }
484
486 void print(std::ostream& os) const {
487 os << str() << std::flush;
488 }
489
491
492 };
493
496
498 using CutflowsPtr = std::shared_ptr<Cutflows>;
499
501 inline std::ostream& operator << (std::ostream& os, const Cutflows& cfs) {
502 return os << cfs.str();
503 }
504
506 inline std::ostream& operator << (std::ostream& os, const CutflowsPtr& cfs) {
507 return os << cfs->str();
508 }
509
511
512}
513
514#endif
A tracker of numbers & fractions of events passing sequential cuts.
Definition Cutflow.hh:24
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:61
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:85
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:73
virtual int fillnext(const double weight=1.0, const double fraction=1.0)
Convenience method to fill the next cut step.
Definition Cutflow.hh:80
Log & getLog() const
Get a logger object.
Definition Cutflow.hh:173
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:105
Cutflow()
Nullary constructor.
Definition Cutflow.hh:35
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:115
string str() const
Create a string representation.
Definition Cutflow.hh:120
Cutflow(const std::vector< std::string > &edges, const std::string &path="")
Definition Cutflow.hh:46
Cutflow(const BinningT &binning)
Constructor using binning object.
Definition Cutflow.hh:38
size_t currentIndex() const
Returns current cutflow index for debugging.
Definition Cutflow.hh:97
void scale(const double factor)
Scale the cutflow weights by the given factor.
Definition Cutflow.hh:100
virtual int fillinit(const double weight=1.0, const double fraction=1.0)
Convenience method to fill the pre-cut step.
Definition Cutflow.hh:68
Cutflow(BinningT &&binning)
Constructor using rvalue binning object.
Definition Cutflow.hh:41
virtual int fill(FillType &&coords, const double weight=1.0, const double fraction=1.0)
Fill function with FillType.
Definition Cutflow.hh:52
void print(std::ostream &os) const
Print string representation to a stream.
Definition Cutflow.hh:166
A container for several Cutflow objects, with some convenient batch access.
Definition Cutflow.hh:277
string str() const
Create a string representation.
Definition Cutflow.hh:476
double integralError(const bool includeOverflows=true) const noexcept
Get the total volume error of the histogram group.
Definition Cutflow.hh:430
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:338
double effNumEntries(const bool includeOverflows=true) const noexcept
Get the effective number of fills.
Definition Cutflow.hh:395
void reset() noexcept
Reset the histogram.
Definition Cutflow.hh:371
void scaleW(const double scalefactor) noexcept
Rescale as if all fill weights had been different by factor scalefactor.
Definition Cutflow.hh:440
void scale(const double scalefactor) noexcept
Rescale as if all fill weights had been different by factor scalefactor along dimension i.
Definition Cutflow.hh:448
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:358
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:333
double sumW(const bool includeOverflows=true) const noexcept
Calculates sum of weights in histo group.
Definition Cutflow.hh:405
Cutflows()
Nullary constructor.
Definition Cutflow.hh:289
int groupfillinit(const double weight=1.0, const double fraction=1.0)
Method to fill the pre-cut steps.
Definition Cutflow.hh:312
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:466
Cutflows(const std::vector< std::string > &edges)
Constructor using a vector of (outer) edges.
Definition Cutflow.hh:292
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:305
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:353
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:348
size_t dim() const noexcept
Total dimension of the object (number of fill axes + filled value)
Definition Cutflow.hh:382
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:322
Cutflows(std::initializer_list< std::string > &&edges)
Constructor using an initializer_set of (outer) edges.
Definition Cutflow.hh:296
double integral(const bool includeOverflows=true) const noexcept
Get the total volume of the histogram group.
Definition Cutflow.hh:425
void print(std::ostream &os) const
Print string representation to a stream.
Definition Cutflow.hh:486
double numEntries(const bool includeOverflows=true) const noexcept
Get the number of fills (fractional fills are possible).
Definition Cutflow.hh:385
size_t fillDim() const noexcept
Fill dimension of the object (number of conent axes + temprary axis)
Definition Cutflow.hh:379
void normalizeStep(const std::string &edge, const double norm)
Definition Cutflow.hh:458
double sumW2(const bool includeOverflows=true) const noexcept
Calculates sum of squared weights in histo group.
Definition Cutflow.hh:415
const Fills< YAO > & fills() const
Access the fill info subevent stack.
Definition Cutflow.hh:249
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:221
FillCollector(typename YAO::Ptr yao)
Definition Cutflow.hh:201
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:230
int fillnext(const double weight=1.0, const double fraction=1.0)
Convenience method to fill the next cut step.
Definition Cutflow.hh:226
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:217
int fill(typename YAO::FillType &&fillCoords, const double weight=1.0, const double fraction=1.0)
Definition Cutflow.hh:209
int fillinit(const double weight=1.0, const double fraction=1.0)
Convenience method to fill the pre-cut step.
Definition Cutflow.hh:241
void reset() noexcept
Empty the subevent stack (for start of new event group).
Definition Cutflow.hh:246
FillCollectors which are used to temporarily cache unaggregated fills until collapsed by the Multiple...
Definition RivetYODA.hh:158
Logging system for controlled & formatted writing to stdout.
Definition Logging.hh:10
static Log & getLog(const std::string &name)
Definition RivetYODA.hh:1330
vector< Fill< T > > Fills
A collection of several Fill objects.
Definition RivetYODA.hh:143
#define MSG_WARNING(x)
Warning messages for non-fatal bad things, using MSG_LVL.
Definition Logging.hh:187
Definition MC_CENT_PPB_Projections.hh:10
std::ostream & operator<<(std::ostream &os, const AnalysisInfo &ai)
Stream an AnalysisInfo as a text description.
Definition AnalysisInfo.hh:362
MultiplexPtr< Multiplexer< Cutflow > > CutflowPtr
Convenience alias.
Definition Cutflow.hh:261
std::shared_ptr< Cutflows > CutflowsPtr
Convenience alias.
Definition Cutflow.hh:498
STL namespace.
Error for e.g. use of invalid bin ranges.
Definition Exceptions.hh:22