1#ifndef RIVET_Cutflow_HH
2#define RIVET_Cutflow_HH
4#include "Rivet/Tools/HistoGroup.hh"
5#include "Rivet/Tools/RivetYODA.hh"
6#include "Rivet/Tools/Utils.hh"
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);
26 class Cutflow :
public YODA::BinnedHisto<std::string> {
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=;
38 : BaseT(), icurr(0) { }
42 : BaseT(binning), icurr(0) { }
46 : BaseT(
std::move(binning)), icurr(0) { }
51 Cutflow(
const std::vector<std::string>& edges,
const std::string& path =
"")
52 : BaseT(
std::vector<
std::string>{
""} + edges, path), icurr(0) { }
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);
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);
73 virtual int fillinit(
const double weight = 1.0,
const double fraction = 1.0) {
74 return fill(
""s, weight, fraction);
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);
85 virtual int fillnext(
const double weight = 1.0,
const double fraction = 1.0) {
86 return fillnext(
true, weight, fraction);
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() +
"')");
97 for (
size_t i = 0; i < cutresults.size(); ++i) {
98 if (!cutresults[i])
return 0;
111 BaseT::scaleW(factor);
116 const auto& b = BaseT::binAt(edge);
118 MSG_WARNING(
"Failed to scale Cutflow " << BaseT::path() <<
" as bin " << edge <<
" is empty");
121 scale(norm / b.sumW());
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();
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);
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";
147 const double wtot = BaseT::bin(1).sumW();
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);
155 ss2 << fixed << setprecision(1) << bin.sumW();
156 const string weightstr = ss2.str();
158 ss2 << fixed << setprecision(1) << bin.effNumEntries();
159 const string countstr = ss2.str();
161 ss2 << fixed << setprecision(3) << pcttot <<
"%";
162 const string pcttotstr = ss2.str();
164 ss2 << fixed << setprecision(3) << pctinc <<
"%";
165 const string pctincstr = ss2.str();
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);
176 void print(std::ostream& os)
const {
177 os <<
str() << std::flush;
197 using Ptr = shared_ptr<FillCollector<YAO>>;
198 using YAO::operator=;
212 : YAO(yao->binning()) {
213 YAO::setPath(yao->path());
220 int fill(
typename YAO::FillType&& fillCoords,
const double weight = 1.0,
const double fraction = 1.0) {
222 YAO::icurr = YAO::_binning.globalIndexAt(fillCoords);
223 _fills.insert(_fills.end(), {std::move(fillCoords), weight});
224 return (
int)YAO::icurr;
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);
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);
236 int fillnext(
const double weight = 1.0,
const double fraction = 1.0) {
237 return fillnext(
true, weight, fraction);
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() +
"')");
247 for (
size_t i = 0; i < cutresults.size(); ++i) {
248 if (!cutresults[i])
return 0;
251 return (
int)YAO::icurr;
254 int fillinit(
const double weight = 1.0,
const double fraction = 1.0) {
255 return fill(
""s, weight, fraction);
282 return os << cf.
str();
286 return os << cf->str();
293 class Cutflows :
public YODA::FillableStorage<2, CutflowPtr, std::string>,
public YODA::Fillable {
296 using BaseT = YODA::FillableStorage<2, CutflowPtr, std::string>;
298 using BinT = YODA::Bin<1, BinContentT, BaseT::BinningT>;
299 using FillDim = std::integral_constant<size_t, 2>;
306 : BaseT(groupAdapter<FillDim{}, BinContentT,
std::string>) { }
310 : BaseT(YODA::Axis<
std::string>(edges), groupAdapter<FillDim{}, BinContentT,
std::string>) { }
313 Cutflows(std::initializer_list<std::string>&& edges)
314 : BaseT(YODA::Axis<
std::string>(
std::move(edges)),
315 groupAdapter<FillDim{}, BinContentT,
std::string>) { }
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;
329 return cfl->fill({edge}, weight, fraction);
335 for (
auto& cfl : BaseT::bins()) {
336 if (!cfl.get())
continue;
337 pass &= cfl->fillinit(weight, fraction);
343 int groupfillnext(
const bool cutresult,
const double weight = 1.0,
const double fraction = 1.0) {
344 if (!cutresult)
return 0;
346 for (
auto& cfl : BaseT::bins()) {
347 if (!cfl.get())
continue;
348 pass &= cfl->fillnext(cutresult, weight, fraction);
360 const double weight = 1.0,
361 const double fraction = 1.0) {
363 for (
auto& cfl : BaseT::bins()) {
364 if (!cfl.get())
continue;
365 pass &= cfl->fillnext(cutresults, weight, fraction);
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);
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);
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);
414 size_t dim() const noexcept {
419 double numEntries(
const bool includeOverflows =
true) const noexcept {
421 for (
const auto& cfl : BaseT::bins(includeOverflows)) {
422 if (!cfl.get())
continue;
423 n += cfl->numEntries(includeOverflows);
431 for (
const auto& cfl : BaseT::bins(includeOverflows)) {
432 if (!cfl.get())
continue;
433 n += cfl->effNumEntries(includeOverflows);
439 double sumW(
const bool includeOverflows =
true) const noexcept {
441 for (
const auto& cfl : BaseT::bins(includeOverflows)) {
442 if (!cfl.get())
continue;
443 sumw += cfl->sumW(includeOverflows);
449 double sumW2(
const bool includeOverflows =
true) const noexcept {
451 for (
const auto& cfl : BaseT::bins(includeOverflows)) {
452 if (!cfl.get())
continue;
453 sumw2 += cfl->sumW2(includeOverflows);
459 double integral(
const bool includeOverflows =
true) const noexcept {
460 return sumW(includeOverflows);
465 return sqrt(
sumW2(includeOverflows));
474 void scaleW(
const double scalefactor)
noexcept {
475 for (
auto& cfl : BaseT::bins(
true,
true)) {
476 if (!cfl.get())
continue;
477 cfl->scaleW(scalefactor);
482 void scale(
const double scalefactor)
noexcept {
483 for (
auto& cfl : BaseT::bins(
true,
true)) {
484 if (!cfl.get())
continue;
485 cfl->scale(scalefactor);
493 for (
auto& cfl : BaseT::bins(
true,
true)) {
494 if (!cfl.get())
continue;
495 if (cfl->binAt(edge).sumW() != 0.) cfl->normalizeStep(edge, norm);
511 std::stringstream ss;
512 for (
auto& cf : BaseT::bins(
true,
true)) {
513 if (!cf.get())
continue;
520 void print(std::ostream& os)
const {
521 os <<
str() << std::flush;
535 return os << cfs.
str();
540 return os << cfs->str();
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
Error for e.g. use of invalid bin ranges.
Definition Exceptions.hh:23