File indexing completed on 2025-04-19 09:06:49
0001
0002 #ifndef RIVET_PERCENTILEPROJECTION_HH
0003 #define RIVET_PERCENTILEPROJECTION_HH
0004
0005 #include "Rivet/Projections/SingleValueProjection.hh"
0006 #include "Rivet/Tools/RivetYODA.hh"
0007 #include <map>
0008
0009 namespace Rivet {
0010
0011 enum class PercentileOrder { INCREASING, DECREASING };
0012
0013
0014
0015
0016
0017
0018
0019 class PercentileProjection : public SingleValueProjection {
0020 public:
0021
0022 using SingleValueProjection::operator =;
0023
0024
0025
0026
0027
0028
0029 PercentileProjection(const SingleValueProjection & sv, const Histo1D& calhist,
0030 PercentileOrder pctorder=PercentileOrder::DECREASING)
0031 : _calhist("EMPTY"),
0032 _increasing(pctorder == PercentileOrder::INCREASING)
0033 {
0034 setName("PercentileProjection");
0035 declare(sv, "OBSERVABLE");
0036
0037 MSG_DEBUG("Constructing PercentileProjection from " << calhist.path());
0038 _calhist = calhist.path();
0039 int N = calhist.numBins();
0040 double sum = calhist.sumW();
0041 if ( _increasing ) {
0042 double acc = 0.0;
0043 for (int i = 0; i <= N; ++i) {
0044 acc += calhist.bin(i).sumW();
0045 _table.insert(make_pair(calhist.bin(i).xMax(), 100.0*acc/sum));
0046 }
0047 }
0048 else {
0049 double acc = 0.0;
0050 for (int i = N+1; i > 0; --i) {
0051 acc += calhist.bin(i).sumW();
0052 _table.insert(make_pair(calhist.bin(i).xMin(), 100.0*acc/sum));
0053 }
0054 }
0055 if (getLog().isActive(Log::DEBUG)) {
0056 MSG_DEBUG("Mapping from observable to percentile:");
0057 for (auto p : _table) {
0058 std::cout << std::setw(16) << p.first << " -> "
0059 << std::setw(16) << p.second << "%" << std::endl;
0060 if (not _increasing and p.second <= 0) break;
0061 if (_increasing and p.second >= 100) break;
0062 }
0063 }
0064 }
0065
0066
0067
0068
0069
0070 PercentileProjection(const SingleValueProjection & sv, const Estimate1D& calest,
0071 PercentileOrder pctorder=PercentileOrder::DECREASING)
0072 : _calhist("EMPTY"),
0073 _increasing(pctorder == PercentileOrder::INCREASING)
0074 {
0075 declare(sv, "OBSERVABLE");
0076
0077
0078 MSG_DEBUG("Constructing PercentileProjection from " << calest.path());
0079 _calhist = calest.path();
0080 int N = calest.numBins();
0081 double sum = 0.0;
0082 for (const auto &b : calest.bins() ) sum += b.val();
0083
0084 double acc = 0.0;
0085 if ( _increasing ) {
0086 _table.insert(make_pair(calest.bin(1).xMin(), 100.0*acc/sum));
0087 for ( int i = 0; i < N; ++i ) {
0088 acc += calest.bin(i+1).val();
0089 _table.insert(make_pair(calest.bin(i+1).xMax(), 100.0*acc/sum));
0090 }
0091 }
0092 else {
0093 _table.insert(make_pair(calest.bin(N).xMax(), 100.0*acc/sum));
0094 for (int i = N - 1; i >= 0; --i) {
0095 acc += calest.bin(i+1).val();
0096 _table.insert(make_pair(calest.bin(i+1).xMin(), 100.0*acc/sum));
0097 }
0098 }
0099 }
0100
0101
0102 RIVET_DEFAULT_PROJ_CLONE(PercentileProjection);
0103
0104
0105 using Projection::operator =;
0106
0107
0108
0109
0110
0111
0112
0113 void project(const Event& e) {
0114 clear();
0115 if ( _table.empty() ) return;
0116 auto& pobs = apply<SingleValueProjection>(e, "OBSERVABLE");
0117 double obs = pobs();
0118 double pcnt = lookup(obs);
0119 if ( pcnt >= 0.0 ) setValue(pcnt);
0120 MSG_DEBUG("Observable(" << pobs.name() << ")="
0121 << std::setw(16) << obs
0122 << "-> Percentile=" << std::setw(16) << pcnt << "%");
0123 }
0124
0125
0126 CmpState compare(const Projection& p) const {
0127 const PercentileProjection pp = dynamic_cast<const PercentileProjection&>(p);
0128 return mkNamedPCmp(p, "OBSERVABLE") ||
0129 cmp(_increasing, pp._increasing) ||
0130 cmp(_calhist, pp._calhist);
0131 }
0132
0133
0134 protected:
0135
0136
0137 double lookup(double obs) const {
0138 auto low = _table.upper_bound(obs);
0139 if ( low == _table.end() ) return _increasing? 100.0: 0.0;
0140 if ( low == _table.begin() ) return _increasing? 0.0: 100.0;
0141 auto high = low--;
0142 return low->second + (obs - low->first)*(high->second - low->second)/
0143 (high->first - low->first);
0144 }
0145
0146
0147 string _calhist;
0148
0149
0150
0151 map<double,double> _table;
0152
0153
0154
0155 bool _increasing;
0156
0157 };
0158
0159
0160 }
0161
0162 #endif