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