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));
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(); }
265 return os << cf.
str();
269 return os << cf->str();
276 class Cutflows :
public YODA::FillableStorage<2, CutflowPtr, std::string>,
277 public YODA::Fillable {
280 using BaseT = YODA::FillableStorage<2, CutflowPtr, std::string>;
282 using BinT = YODA::Bin<1, BinContentT, BaseT::BinningT>;
283 using FillDim = std::integral_constant<size_t, 2>;
293 : BaseT(YODA::Axis<
std::string>(edges), groupAdapter<FillDim{},
BinContentT,
std::string>) { }
296 Cutflows(std::initializer_list<std::string>&& edges)
297 : BaseT(YODA::Axis<
std::string>(
std::move(edges)), groupAdapter<FillDim{},
BinContentT,
std::string>) { }
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;
308 return cfl->fill({edge}, weight, fraction);
314 for (
auto& cfl : BaseT::bins()) {
315 if (!cfl.get())
continue;
316 pass &= cfl->fillinit(weight, fraction);
322 int groupfillnext(
const bool cutresult,
const double weight = 1.0,
const double fraction = 1.0) {
323 if (!cutresult)
return 0;
325 for (
auto& cfl : BaseT::bins()) {
326 if (!cfl.get())
continue;
327 pass &= cfl->fillnext(cutresult, weight, fraction);
338 int groupfillnext(
const std::vector<bool>& cutresults,
const double weight = 1.0,
const double fraction = 1.0) {
340 for (
auto& cfl : BaseT::bins()) {
341 if (!cfl.get())
continue;
342 pass &= cfl->fillnext(cutresults, weight, fraction);
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);
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);
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);
371 void reset() noexcept { BaseT::reset(); }
379 size_t fillDim() const noexcept {
return FillDim{}; }
385 double numEntries(
const bool includeOverflows=
true) const noexcept {
387 for (
const auto& cfl : BaseT::bins(includeOverflows)) {
388 if (!cfl.get())
continue;
389 n += cfl->numEntries(includeOverflows);
397 for (
const auto& cfl : BaseT::bins(includeOverflows)) {
398 if (!cfl.get())
continue;
399 n += cfl->effNumEntries(includeOverflows);
405 double sumW(
const bool includeOverflows=
true) const noexcept {
407 for (
const auto& cfl : BaseT::bins(includeOverflows)) {
408 if (!cfl.get())
continue;
409 sumw += cfl->sumW(includeOverflows);
415 double sumW2(
const bool includeOverflows=
true) const noexcept {
417 for (
const auto& cfl : BaseT::bins(includeOverflows)) {
418 if (!cfl.get())
continue;
419 sumw2 += cfl->sumW2(includeOverflows);
425 double integral(
const bool includeOverflows=
true) const noexcept {
426 return sumW(includeOverflows);
431 return sqrt(
sumW2(includeOverflows));
440 void scaleW(
const double scalefactor)
noexcept {
441 for (
auto& cfl : BaseT::bins(
true,
true)) {
442 if (!cfl.get())
continue;
443 cfl->scaleW(scalefactor);
448 void scale(
const double scalefactor)
noexcept {
449 for (
auto& cfl : BaseT::bins(
true,
true)) {
450 if (!cfl.get())
continue;
451 cfl->scale(scalefactor);
459 for (
auto& cfl : BaseT::bins(
true,
true)) {
460 if (!cfl.get())
continue;
461 if (cfl->binAt(edge).sumW() != 0.) cfl->normalizeStep(edge, norm);
477 std::stringstream ss;
478 for (
auto& cf : BaseT::bins(
true,
true)) {
479 if (!cf.get())
continue;
486 void print(std::ostream& os)
const {
487 os <<
str() << std::flush;
502 return os << cfs.
str();
507 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: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
Error for e.g. use of invalid bin ranges.
Definition Exceptions.hh:22