Rivet  3.1.0
PercentileProjection.hh
1 // -*- C++ -*-
2 #ifndef RIVET_PERCENTILEPROJECTION_HH
3 #define RIVET_PERCENTILEPROJECTION_HH
4 
5 #include "Rivet/Projections/SingleValueProjection.hh"
6 #include "Rivet/Tools/RivetYODA.hh"
7 #include <map>
8 
9 namespace Rivet {
10 
20 public:
21 
27  PercentileProjection(const SingleValueProjection & sv, const Histo1D& calhist,
28  bool increasing = false)
29  : _calhist("EMPTY"), _increasing(increasing) {
30  declare(sv, "OBSERVABLE");
31  //if ( !calhist ) return;
32  MSG_INFO("Constructing PercentileProjection from " << calhist.path());
33  _calhist = calhist.path();
34  int N = calhist.numBins();
35  double sum = calhist.sumW();
36 
37  if ( increasing ) {
38  double acc = calhist.underflow().sumW();
39  _table.insert(make_pair(calhist.bin(0).xEdges().first, 100.0*acc/sum));
40  for ( int i = 0; i < N; ++i ) {
41  acc += calhist.bin(i).sumW();
42  _table.insert(make_pair(calhist.bin(i).xEdges().second, 100.0*acc/sum));
43  }
44  } else {
45  double acc = calhist.overflow().sumW();
46  _table.insert(make_pair(calhist.bin(N - 1).xEdges().second, 100.0*acc/sum));
47  for ( int i = N - 1; i >= 0; --i ) {
48  acc += calhist.bin(i).sumW();
49  _table.insert(make_pair(calhist.bin(i).xEdges().first, 100.0*acc/sum));
50  }
51  }
52  }
53 
54  // Constructor taking a SingleValueProjection and a calibration
55  // histogram. If increasing it means that low values corresponds to
56  // lower percentiles.
57  PercentileProjection(const SingleValueProjection & sv, const Scatter2D& calscat,
58  bool increasing = false)
59  : _calhist("EMPTY"), _increasing(increasing) {
60  declare(sv, "OBSERVABLE");
61 
62  //if ( !calscat ) return;
63  MSG_INFO("Constructing PercentileProjection from " << calscat.path());
64  _calhist = calscat.path();
65  int N = calscat.numPoints();
66  double sum = 0.0;
67  for ( const auto & p : calscat.points() ) sum += p.y();
68 
69  double acc = 0.0;
70  if ( increasing ) {
71  _table.insert(make_pair(calscat.point(0).xMin(), 100.0*acc/sum));
72  for ( int i = 0; i < N; ++i ) {
73  acc += calscat.point(i).y();
74  _table.insert(make_pair(calscat.point(i).xMax(), 100.0*acc/sum));
75  }
76  } else {
77  _table.insert(make_pair(calscat.point(N - 1).xMax(), 100.0*acc/sum));
78  for ( int i = N - 1; i >= 0; --i ) {
79  acc += calscat.point(i).y();
80  _table.insert(make_pair(calscat.point(i).xMin(), 100.0*acc/sum));
81  }
82  }
83  }
84 
85  DEFAULT_RIVET_PROJ_CLONE(PercentileProjection);
86 
87  // The projection function takes the assigned SingeValueProjection
88  // and sets the value of this projection to the corresponding
89  // percentile. If no calibration has been provided, -1 will be
90  // returned. If values are outside of the calibration histogram, 0
91  // or 100 will be returned.
92  void project(const Event& e) {
93  clear();
94  if ( _table.empty() ) return;
95  double obs = apply<SingleValueProjection>(e, "OBSERVABLE")();
96  double pcnt = lookup(obs);
97  if ( pcnt >= 0.0 ) set(pcnt);
98  }
99 
100 
101  // Standard comparison function.
102  CmpState compare(const Projection& p) const {
103  const PercentileProjection pp = dynamic_cast<const PercentileProjection&>(p);
104  return mkNamedPCmp(p, "OBSERVABLE") ||
105  cmp(_increasing, pp._increasing) ||
106  cmp(_calhist, pp._calhist);
107  }
108 
109 private:
110 
111  // The (interpolated) lookup table
112  double lookup(double obs) const {
113  auto low = _table.upper_bound(obs);
114  if ( low == _table.end() ) return _increasing? 100.0: 0.0;
115  if ( low == _table.begin() ) return _increasing? 0.0: 100.0;
116  auto high = low--;
117  return low->second + (obs - low->first)*(high->second - low->second)/
118  (high->first - low->first);
119  }
120 
121  // Astring identifying the calibration histogram.
122  string _calhist;
123 
124  // A lookup table to find (by interpolation) the percentile given
125  // the value of the underlying SingleValueProjection.
126  map<double,double> _table;
127 
128  // A flag to say whether the distribution should be integrated from
129  // below or above.
130  bool _increasing;
131 
132 };
133 
134 
135 
136 
137 }
138 
139 #endif
Definition: MC_Cent_pPb.hh:10
Base class for projections returning a single floating point value.
Definition: SingleValueProjection.hh:17
Representation of a HepMC event, and enabler of Projection caching.
Definition: Event.hh:22
CmpState compare(const Projection &p) const
Definition: PercentileProjection.hh:102
void project(const Event &e)
Definition: PercentileProjection.hh:92
PercentileProjection(const SingleValueProjection &sv, const Histo1D &calhist, bool increasing=false)
Definition: PercentileProjection.hh:27
CONTAINER::value_type sum(const CONTAINER &c)
Generic sum function, adding x for all x in container c.
Definition: Utils.hh:422
const PROJ & declare(const PROJ &proj, const std::string &name)
Register a contained projection (user-facing version)
Definition: ProjectionApplier.hh:160
Cmp< Projection > mkNamedPCmp(const Projection &otherparent, const std::string &pname) const
class for projections that reports the percentile for a given SingleValueProjection when initialized ...
Definition: PercentileProjection.hh:19
Base class for all Rivet projections.
Definition: Projection.hh:29
void clear()
Unset the value.
Definition: SingleValueProjection.hh:54
Cmp< T > cmp(const T &t1, const T &t2)
Global helper function for easy creation of Cmp objects.
Definition: Cmp.hh:255