diff --git a/include/Rivet/Makefile.am b/include/Rivet/Makefile.am --- a/include/Rivet/Makefile.am +++ b/include/Rivet/Makefile.am @@ -1,179 +1,180 @@ ## Internal headers - not to be installed nobase_dist_noinst_HEADERS = ## Public headers - to be installed nobase_pkginclude_HEADERS = ## Rivet interface nobase_pkginclude_HEADERS += \ Rivet.hh \ Run.hh \ Event.hh \ ParticleBase.hh \ Particle.fhh Particle.hh \ Jet.fhh Jet.hh \ Projection.fhh Projection.hh \ ProjectionApplier.hh \ ProjectionHandler.hh \ Analysis.hh \ AnalysisHandler.hh \ AnalysisInfo.hh \ AnalysisBuilder.hh \ AnalysisLoader.hh ## Build config stuff nobase_pkginclude_HEADERS += \ Config/RivetCommon.hh \ Config/RivetConfig.hh \ Config/BuildOptions.hh ## Projections nobase_pkginclude_HEADERS += \ Projections/AliceCommon.hh \ Projections/AxesDefinition.hh \ Projections/Beam.hh \ Projections/BeamThrust.hh \ Projections/CentralEtHCM.hh \ Projections/CentralityProjection.hh \ Projections/ChargedFinalState.hh \ Projections/ChargedLeptons.hh \ Projections/ConstLossyFinalState.hh \ Projections/DirectFinalState.hh \ Projections/DISFinalState.hh \ Projections/DISKinematics.hh \ Projections/DISLepton.hh \ Projections/DressedLeptons.hh \ Projections/FastJets.hh \ Projections/FinalPartons.hh \ Projections/FinalState.hh \ Projections/FoxWolframMoments.hh \ Projections/FParameter.hh \ Projections/GeneratedPercentileProjection.hh \ Projections/HadronicFinalState.hh \ Projections/HeavyHadrons.hh \ Projections/Hemispheres.hh \ Projections/IdentifiedFinalState.hh \ Projections/ImpactParameterProjection.hh \ Projections/IndirectFinalState.hh \ Projections/InitialQuarks.hh \ Projections/InvMassFinalState.hh \ Projections/JetAlg.hh \ Projections/JetShape.hh \ Projections/LeadingParticlesFinalState.hh \ Projections/LossyFinalState.hh \ Projections/MergedFinalState.hh \ Projections/MissingMomentum.hh \ Projections/NeutralFinalState.hh \ Projections/NonHadronicFinalState.hh \ Projections/NonPromptFinalState.hh \ Projections/ParisiTensor.hh \ Projections/ParticleFinder.hh \ Projections/PartonicTops.hh \ + Projections/PercentileProjection.hh \ Projections/PrimaryHadrons.hh \ Projections/PrimaryParticles.hh \ Projections/PromptFinalState.hh \ Projections/SingleValueProjection.hh \ Projections/SmearedParticles.hh \ Projections/SmearedJets.hh \ Projections/SmearedMET.hh \ Projections/Sphericity.hh \ Projections/Spherocity.hh \ Projections/TauFinder.hh \ Projections/Thrust.hh \ Projections/TriggerCDFRun0Run1.hh \ Projections/TriggerCDFRun2.hh \ Projections/TriggerUA5.hh \ Projections/UnstableFinalState.hh \ Projections/UserCentEstimate.hh \ Projections/VetoedFinalState.hh \ Projections/VisibleFinalState.hh \ Projections/WFinder.hh \ Projections/ZFinder.hh ## Meta-projection convenience headers nobase_pkginclude_HEADERS += \ Projections/FinalStates.hh \ Projections/Smearing.hh ## Analysis base class headers # TODO: Move to Rivet/AnalysisTools header dir? nobase_pkginclude_HEADERS += \ Analyses/MC_ParticleAnalysis.hh \ Analyses/MC_JetAnalysis.hh \ Analyses/MC_JetSplittings.hh ## Tools nobase_pkginclude_HEADERS += \ Tools/AliceCommon.hh \ Tools/BeamConstraint.hh \ Tools/BinnedHistogram.hh \ Tools/CentralityBinner.hh \ Tools/Cmp.fhh \ Tools/Cmp.hh \ Tools/Cutflow.hh \ Tools/Cuts.fhh \ Tools/Cuts.hh \ Tools/Exceptions.hh \ Tools/JetUtils.hh \ Tools/Logging.hh \ Tools/Random.hh \ Tools/ParticleBaseUtils.hh \ Tools/ParticleIdUtils.hh \ Tools/ParticleUtils.hh \ Tools/ParticleName.hh \ Tools/PrettyPrint.hh \ Tools/RivetPaths.hh \ Tools/RivetSTL.hh \ Tools/RivetFastJet.hh \ Tools/RivetHepMC.hh \ Tools/RivetYODA.hh \ Tools/RivetMT2.hh \ Tools/SmearingFunctions.hh \ Tools/MomentumSmearingFunctions.hh \ Tools/ParticleSmearingFunctions.hh \ Tools/JetSmearingFunctions.hh \ Tools/TypeTraits.hh \ Tools/Utils.hh \ Tools/Nsubjettiness/AxesDefinition.hh \ Tools/Nsubjettiness/ExtraRecombiners.hh \ Tools/Nsubjettiness/MeasureDefinition.hh \ Tools/Nsubjettiness/Njettiness.hh \ Tools/Nsubjettiness/NjettinessPlugin.hh \ Tools/Nsubjettiness/Nsubjettiness.hh \ Tools/Nsubjettiness/TauComponents.hh \ Tools/Nsubjettiness/XConePlugin.hh nobase_dist_noinst_HEADERS += \ Tools/osdir.hh ## Maths nobase_pkginclude_HEADERS += \ Math/Matrices.hh \ Math/Vector3.hh \ Math/VectorN.hh \ Math/MatrixN.hh \ Math/MatrixDiag.hh \ Math/MathHeader.hh \ Math/Vectors.hh \ Math/LorentzTrans.hh \ Math/Matrix3.hh \ Math/MathUtils.hh \ Math/Vector4.hh \ Math/Math.hh \ Math/Units.hh \ Math/Constants.hh \ Math/eigen/util.h \ Math/eigen/regressioninternal.h \ Math/eigen/regression.h \ Math/eigen/vector.h \ Math/eigen/ludecompositionbase.h \ Math/eigen/ludecomposition.h \ Math/eigen/linearsolver.h \ Math/eigen/linearsolverbase.h \ Math/eigen/matrix.h \ Math/eigen/vectorbase.h \ Math/eigen/projective.h \ Math/eigen/matrixbase.h diff --git a/include/Rivet/Projections/PercentileProjection.hh b/include/Rivet/Projections/PercentileProjection.hh new file mode 100644 --- /dev/null +++ b/include/Rivet/Projections/PercentileProjection.hh @@ -0,0 +1,138 @@ +// -*- C++ -*- +#ifndef RIVET_PERCENTILEPROJECTION_HH +#define RIVET_PERCENTILEPROJECTION_HH + +#include "Rivet/Projections/SingleValueProjection.hh" +#include "Rivet/Tools/RivetYODA.hh" +#include + +namespace Rivet { + +/** + @brief class for projections that reports the percentile for a + given SingleValueProjection when initialized with a Histo1D of the + distribution in the SingleValueProjection. + + @author Leif Lönnblad + +*/ +class PercentileProjection : public SingleValueProjection { + +public: + + // Constructor taking a SingleValueProjection and a calibration + // histogram. If increasing it means that low values corresponds to + // lower percentiles. + PercentileProjection(const SingleValueProjection & sv, Histo1DPtr calhist, + bool increasing = false) + : _calhist("EMPTY"), _increasing(increasing) { + declare(sv, "OBSERVABLE"); + if ( !calhist ) return; + MSG_INFO("Constructing PercentileProjection from " << calhist->path()); + _calhist = calhist->path(); + int N = calhist->numBins(); + double sum = calhist->sumW(); + + if ( increasing ) { + double acc = calhist->underflow().sumW(); + _table.insert(make_pair(calhist->bin(0).xEdges().first, 100.0*acc/sum)); + for ( int i = 0; i < N; ++i ) { + acc += calhist->bin(i).sumW(); + _table.insert(make_pair(calhist->bin(i).xEdges().second, 100.0*acc/sum)); + } + } else { + double acc = calhist->overflow().sumW(); + _table.insert(make_pair(calhist->bin(N - 1).xEdges().second, 100.0*acc/sum)); + for ( int i = N - 1; i >= 0; --i ) { + acc += calhist->bin(i).sumW(); + _table.insert(make_pair(calhist->bin(i).xEdges().first, 100.0*acc/sum)); + } + } + } + + // Constructor taking a SingleValueProjection and a calibration + // histogram. If increasing it means that low values corresponds to + // lower percentiles. + PercentileProjection(const SingleValueProjection & sv, Scatter2DPtr calscat, + bool increasing = false) + : _calhist("EMPTY"), _increasing(increasing) { + declare(sv, "OBSERVABLE"); + + if ( !calscat ) return; + MSG_INFO("Constructing PercentileProjection from " << calscat->path()); + _calhist = calscat->path(); + int N = calscat->numPoints(); + double sum = 0.0; + for ( const auto & p : calscat->points() ) sum += p.y(); + + double acc = 0.0; + if ( increasing ) { + _table.insert(make_pair(calscat->point(0).xMin(), 100.0*acc/sum)); + for ( int i = 0; i < N; ++i ) { + acc += calscat->point(i).y(); + _table.insert(make_pair(calscat->point(i).xMax(), 100.0*acc/sum)); + } + } else { + _table.insert(make_pair(calscat->point(N - 1).xMax(), 100.0*acc/sum)); + for ( int i = N - 1; i >= 0; --i ) { + acc += calscat->point(i).y(); + _table.insert(make_pair(calscat->point(i).xMin(), 100.0*acc/sum)); + } + } + } + + DEFAULT_RIVET_PROJ_CLONE(PercentileProjection); + + // The projection function takes the assigned SingeValueProjection + // and sets the value of this projection to the corresponding + // percentile. If no calibration has been provided, -1 will be + // returned. If values are outside of the calibration histogram, 0 + // or 100 will be returned. + void project(const Event& e) { + clear(); + if ( _table.empty() ) return; + double obs = apply(e, "OBSERVABLE")(); + double pcnt = lookup(obs); + if ( pcnt >= 0.0 ) set(pcnt); + } + + + // Standard comparison function. + int compare(const Projection& p) const { + const PercentileProjection pp = + dynamic_cast(p); + return mkNamedPCmp(p, "OBSERVABLE") || cmp(_increasing,pp._increasing) || + cmp(_calhist, pp._calhist); + } + +private: + + // The (interpolated) lookup table + double lookup(double obs) const { + auto low = _table.upper_bound(obs); + if ( low == _table.end() ) return _increasing? 100.0: 0.0; + if ( low == _table.begin() ) return _increasing? 0.0: 100.0; + auto high = low--; + return low->second + (obs - low->first)*(high->second - low->second)/ + (high->first - low->first); + } + + // Astring identifying the calibration histogram. + string _calhist; + + // A lookup table to find (by interpolation) the percentile given + // the value of the underlying SingleValueProjection. + map _table; + + // A flag to say whether the distribution should be integrated from + // below or above. + bool _increasing; + +}; + + + + +} + +#endif