1#ifndef RIVET_Cutflow_HH
2#define RIVET_Cutflow_HH
4#include "Rivet/Tools/RivetYODA.hh"
5#include "Rivet/Tools/Utils.hh"
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);
24 class Cutflow :
public YODA::BinnedHisto<std::string> {
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 =;
38 Cutflow(
const BinningT& binning) : BaseT(binning), icurr(0) { }
41 Cutflow(BinningT&& binning) : BaseT(
std::move(binning)), icurr(0) { }
46 Cutflow(
const std::vector<std::string>& edges,
const std::string& path =
"")
47 : BaseT(
std::vector<
std::string>{
""} + edges, path), icurr(0) { }
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);
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);
68 virtual int fillinit(
const double weight=1.0,
const double fraction=1.0) {
69 return fill(
""s, weight, fraction);
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);
80 virtual int fillnext(
const double weight = 1.0,
const double fraction = 1.0) {
81 return fillnext(
true, weight, fraction);
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()+
"')");
89 for (
size_t i = 0; i < cutresults.size(); ++i) {
90 if (!cutresults[i])
return 0;
101 BaseT::scaleW(factor);
106 const auto& b = BaseT::binAt(edge);
108 MSG_WARNING(
"Failed to scale Cutflow " << BaseT::path() <<
" as bin " << edge <<
" is empty");
111 scale(norm/b.sumW());
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();
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);
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";
139 const double wtot = BaseT::bin(1).sumW();
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);
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();
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);
166 void print(std::ostream& os)
const {
167 os <<
str() << std::flush;
188 using Ptr = shared_ptr<FillCollector<YAO>>;
189 using YAO::operator =;
202 YAO::setPath(yao->path());
209 int fill(
typename YAO::FillType&& fillCoords,
210 const double weight=1.0,
const double fraction=1.0) {
212 YAO::icurr = YAO::_binning.globalIndexAt(fillCoords);
213 _fills.insert(_fills.end(), { std::move(fillCoords), weight } );
214 return (
int)YAO::icurr;
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);
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);
226 int fillnext(
const double weight = 1.0,
const double fraction = 1.0) {
227 return fillnext(
true, weight, fraction);
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()+
"')");
234 for (
size_t i = 0; i < cutresults.size(); ++i) {
235 if (!cutresults[i])
return 0;
236 fillnext(weight, fraction);
238 return (
int)YAO::icurr;
241 int fillinit(
const double weight=1.0,
const double fraction=1.0) {
242 return fill(
""s, weight, fraction);
246 void reset() noexcept { _fills.clear(); }
266 return os << cf.
str();
270 return os << cf->str();
277 class Cutflows :
public YODA::FillableStorage<2, CutflowPtr, std::string>,
278 public YODA::Fillable {
281 using BaseT = YODA::FillableStorage<2, CutflowPtr, std::string>;
283 using BinT = YODA::Bin<1, BinContentT, BaseT::BinningT>;
284 using FillDim = std::integral_constant<size_t, 2>;
294 : BaseT(YODA::Axis<
std::string>(edges), groupAdapter<FillDim{},
BinContentT,
std::string>) { }
297 Cutflows(std::initializer_list<std::string>&& edges)
298 : BaseT(YODA::Axis<
std::string>(
std::move(edges)), groupAdapter<FillDim{},
BinContentT,
std::string>) { }
306 int fill(
const std::string& grpCoord,
const std::string& edge,
const double weight = 1.0,
const double fraction = 1.0) {
307 auto& cfl = BaseT::binAt({grpCoord});
308 if (!cfl.raw())
return -1;
309 return cfl->fill({edge}, weight, fraction);
315 for (
auto& cfl : BaseT::bins()) {
316 if (!cfl.get())
continue;
317 pass &= cfl->fillinit(weight, fraction);
323 int groupfillnext(
const bool cutresult,
const double weight = 1.0,
const double fraction = 1.0) {
324 if (!cutresult)
return 0;
326 for (
auto& cfl : BaseT::bins()) {
327 if (!cfl.get())
continue;
328 pass &= cfl->fillnext(cutresult, weight, fraction);
339 int groupfillnext(
const std::vector<bool>& cutresults,
const double weight = 1.0,
const double fraction = 1.0) {
341 for (
auto& cfl : BaseT::bins()) {
342 if (!cfl.get())
continue;
343 pass &= cfl->fillnext(cutresults, weight, fraction);
349 int fillnext(
const std::string& grpCoord,
const double weight=1.0,
const double fraction=1.0) {
350 return BaseT::binAt(grpCoord)->fillnext(weight, fraction);
354 int fillnext(
const std::string& grpCoord,
const bool cutresult,
const double weight=1.0,
const double fraction=1.0) {
355 return BaseT::binAt(grpCoord)->fillnext(cutresult, weight, fraction);
359 int fillnext(
const std::string& grpCoord,
const std::vector<bool>& cutresults,
360 const double weight = 1.0,
const double fraction = 1.0) {
361 return BaseT::binAt(grpCoord)->fillnext(cutresults, weight, fraction);
372 void reset() noexcept { BaseT::reset(); }
380 size_t fillDim() const noexcept {
return FillDim{}; }
386 double numEntries(
const bool includeOverflows=
true) const noexcept {
388 for (
const auto& cfl : BaseT::bins(includeOverflows)) {
389 if (!cfl.get())
continue;
390 n += cfl->numEntries(includeOverflows);
398 for (
const auto& cfl : BaseT::bins(includeOverflows)) {
399 if (!cfl.get())
continue;
400 n += cfl->effNumEntries(includeOverflows);
406 double sumW(
const bool includeOverflows=
true) const noexcept {
408 for (
const auto& cfl : BaseT::bins(includeOverflows)) {
409 if (!cfl.get())
continue;
410 sumw += cfl->sumW(includeOverflows);
416 double sumW2(
const bool includeOverflows=
true) const noexcept {
418 for (
const auto& cfl : BaseT::bins(includeOverflows)) {
419 if (!cfl.get())
continue;
420 sumw2 += cfl->sumW2(includeOverflows);
426 double integral(
const bool includeOverflows=
true) const noexcept {
427 return sumW(includeOverflows);
432 return sqrt(
sumW2(includeOverflows));
441 void scaleW(
const double scalefactor)
noexcept {
442 for (
auto& cfl : BaseT::bins(
true,
true)) {
443 if (!cfl.get())
continue;
444 cfl->scaleW(scalefactor);
449 void scale(
const double scalefactor)
noexcept {
450 for (
auto& cfl : BaseT::bins(
true,
true)) {
451 if (!cfl.get())
continue;
452 cfl->scale(scalefactor);
460 for (
auto& cfl : BaseT::bins(
true,
true)) {
461 if (!cfl.get())
continue;
462 if (cfl->binAt(edge).sumW() != 0.) cfl->normalizeStep(edge, norm);
478 std::stringstream ss;
479 for (
auto& cf : BaseT::bins(
true,
true)) {
480 if (!cf.get())
continue;
487 void print(std::ostream& os)
const {
488 os <<
str() << std::flush;
503 return os << cfs.
str();
508 return os << cfs->str();
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:278
string str() const
Create a string representation.
Definition Cutflow.hh:477
double integralError(const bool includeOverflows=true) const noexcept
Get the total volume error of the histogram group.
Definition Cutflow.hh:431
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:339
double effNumEntries(const bool includeOverflows=true) const noexcept
Get the effective number of fills.
Definition Cutflow.hh:396
void reset() noexcept
Reset the histogram.
Definition Cutflow.hh:372
void scaleW(const double scalefactor) noexcept
Rescale as if all fill weights had been different by factor scalefactor.
Definition Cutflow.hh:441
void scale(const double scalefactor) noexcept
Rescale as if all fill weights had been different by factor scalefactor along dimension i.
Definition Cutflow.hh:449
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:359
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:334
double sumW(const bool includeOverflows=true) const noexcept
Calculates sum of weights in histo group.
Definition Cutflow.hh:406
Cutflows()
Nullary constructor.
Definition Cutflow.hh:290
int groupfillinit(const double weight=1.0, const double fraction=1.0)
Method to fill the pre-cut steps.
Definition Cutflow.hh:313
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:467
Cutflows(const std::vector< std::string > &edges)
Constructor using a vector of (outer) edges.
Definition Cutflow.hh:293
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:306
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:354
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:349
size_t dim() const noexcept
Total dimension of the object (number of fill axes + filled value)
Definition Cutflow.hh:383
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:323
Cutflows(std::initializer_list< std::string > &&edges)
Constructor using an initializer_set of (outer) edges.
Definition Cutflow.hh:297
double integral(const bool includeOverflows=true) const noexcept
Get the total volume of the histogram group.
Definition Cutflow.hh:426
void print(std::ostream &os) const
Print string representation to a stream.
Definition Cutflow.hh:487
double numEntries(const bool includeOverflows=true) const noexcept
Get the number of fills (fractional fills are possible).
Definition Cutflow.hh:386
size_t fillDim() const noexcept
Fill dimension of the object (number of conent axes + temprary axis)
Definition Cutflow.hh:380
void normalizeStep(const std::string &edge, const double norm)
Definition Cutflow.hh:459
double sumW2(const bool includeOverflows=true) const noexcept
Calculates sum of squared weights in histo group.
Definition Cutflow.hh:416
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:262
std::shared_ptr< Cutflows > CutflowsPtr
Convenience alias.
Definition Cutflow.hh:499
Error for e.g. use of invalid bin ranges.
Definition Exceptions.hh:22