2#ifndef RIVET_EventMixingFinalState_HH
3#define RIVET_EventMixingFinalState_HH
5#include "Rivet/Projection.hh"
6#include "Rivet/Projections/ParticleFinder.hh"
7#include "Rivet/Tools/Random.hh"
34 template <
class RandomAccessIterator,
35 class WeightIterator,
class RandomNumberGenerator>
36 void weighted_shuffle(RandomAccessIterator first, RandomAccessIterator last,
37 WeightIterator fw, WeightIterator lw, RandomNumberGenerator& g) {
38 while(first != last && fw != lw) {
39 std::discrete_distribution<int> weightDist(fw, lw);
40 int i = weightDist(g);
42 std::iter_swap(first, next(first, i));
43 std::iter_swap(fw, next(fw, i));
50 typedef pair<Particles, double> MixEvent;
51 typedef map<double, std::deque<MixEvent> > MixMap;
70 size_t nMixIn,
double oMin,
double oMax,
double deltao,
71 const size_t defaultIdx) : nMix(nMixIn), unitWeights(
true) {
77 MSG_WARNING(
"EventMixing is not fully validated. Use with caution.");
79 _defaultWeightIdx = defaultIdx;
81 for(
double o = oMin; o < oMax; o+=deltao )
82 mixEvents[o] = std::deque<MixEvent>();
89 bool hasMixingEvents()
const {
90 MixMap::const_iterator mixItr = mixEvents.lower_bound(
mObs);
91 if(mixItr == mixEvents.end() || mixItr->second.size() < nMix + 1)
97 vector<MixEvent> getMixingEvents()
const {
98 if (!hasMixingEvents())
99 return vector<MixEvent>();
100 MixMap::const_iterator mixItr = mixEvents.lower_bound(
mObs);
101 return vector<MixEvent>(mixItr->second.begin(), mixItr->second.end() - 1);
106 virtual const Particles particles()
const {
108 if (!hasMixingEvents())
111 MixMap::const_iterator mixItr = mixEvents.lower_bound(
mObs);
112 vector<MixEvent> mixEvents(mixItr->second.begin(), mixItr->second.end() - 1);
115 vector<double> weights;
117 for (
size_t i = 0; i < mixEvents.size(); ++i)
118 pSize+=mixEvents[i].first.size();
119 mixParticles.reserve(pSize);
120 weights.reserve(pSize);
122 for (
size_t i = 0; i < mixEvents.size(); ++i) {
123 mixParticles.insert(mixParticles.end(), mixEvents[i].first.begin(), mixEvents[i].first.end());
124 vector<double> tmp(mixEvents[i].first.size(), mixEvents[i].second);
125 weights.insert(weights.end(), tmp.begin(), tmp.end());
132 std::shuffle(mixParticles.begin(), mixParticles.end(),
rng());
135 weighted_shuffle(mixParticles.begin(), mixParticles.end(), weights.begin(), weights.end(),
rng());
136 Particles tmp = vector<Particle>(mixParticles.begin(), mixParticles.begin() +
size_t(ceil(mixParticles.size() / 2)));
146 virtual void calculateMixingObs(
const Projection* mProj) = 0;
151 const Projection* mixObsProjPtr = &applyProjection<Projection>(e,
"OBS");
152 calculateMixingObs(mixObsProjPtr);
153 MixMap::iterator mixItr = mixEvents.lower_bound(
mObs);
154 if (mixItr == mixEvents.end()){
156 MSG_DEBUG(
"Mixing observable out of bounds.");
160 mixItr->second.push_back(make_pair(mix,e.
weights()[_defaultWeightIdx]));
162 if (unitWeights && e.
weights()[_defaultWeightIdx] != 1.0 ) {
166 if (mixItr->second.size() > nMix + 1)
167 mixItr->second.pop_front();
192 size_t _defaultWeightIdx;
201 const ParticleFinder& mix,
size_t nMixIn,
double oMin,
double oMax,
202 double deltao,
const size_t defaultIdx) :
203 EventMixingBase(mixObsProj, mix, nMixIn, oMin, oMax, deltao, defaultIdx) {
204 setName(
"EventMixingFinalState");
212 virtual void calculateMixingObs(
const Projection* mProj) {
224 const ParticleFinder& mix,
size_t nMixIn,
double oMin,
double oMax,
225 double deltao,
const size_t defaultIdx) :
226 EventMixingBase(mixObsProj, mix, nMixIn, oMin, oMax, deltao, defaultIdx) {
227 setName(
"EventMixingCentrality");
234 virtual void calculateMixingObs(
const Projection* mProj) {
Used together with the percentile-based analysis objects Percentile and PercentileXaxis.
Definition: CentralityProjection.hh:26
Definition: EventMixingFinalState.hh:66
void project(const Event &e)
Perform the projection on the Event.
Definition: EventMixingFinalState.hh:150
double mObs
The mixing observable of the current event.
Definition: EventMixingFinalState.hh:178
CmpState compare(const Projection &p) const
Compare with other projections.
Definition: EventMixingFinalState.hh:172
Definition: EventMixingFinalState.hh:220
Definition: EventMixingFinalState.hh:198
Representation of a HepMC event, and enabler of Projection caching.
Definition: Event.hh:22
std::valarray< double > weights() const
The generation weights associated with the event.
Base class for projections which return subsets of an event's particles.
Definition: ParticleFinder.hh:11
virtual const Particles & particles() const
Get the particles in no particular order, with no cuts.
Definition: ParticleFinder.hh:49
Specialised vector of Particle objects.
Definition: Particle.hh:25
const PROJ & declare(const PROJ &proj, const std::string &name)
Register a contained projection (user-facing version)
Definition: ProjectionApplier.hh:170
Base class for all Rivet projections.
Definition: Projection.hh:29
void setName(const std::string &name)
Used by derived classes to set their name.
Definition: Projection.hh:142
Cmp< Projection > mkNamedPCmp(const Projection &otherparent, const std::string &pname) const
#define MSG_DEBUG(x)
Debug messaging, not enabled by default, using MSG_LVL.
Definition: Logging.hh:195
#define MSG_WARNING(x)
Warning messages for non-fatal bad things, using MSG_LVL.
Definition: Logging.hh:200
double p(const ParticleBase &p)
Unbound function access to p.
Definition: ParticleBaseUtils.hh:653
Definition: MC_Cent_pPb.hh:10
std::mt19937 & rng()
Return a thread-safe random number generator (mainly for internal use)