KaliVeda
Toolkit for HIC analysis
|
Generic event mixing algorithm for two-particle correlation studies.
ParticleInfoStruct | user-provided structure which will be used to store any required information on each particle to be used in the event mixing |
NumBins | number of different event classes to be treated separately in the event mixing |
This class is a generic implementation of the event mixing technique used to estimate the uncorrelated background for two-particle correlation functions. Events belonging to different user-defined event classes can be treated separately at the same time.
The generic problem adressed here is the construction of 2-particle correlation functions using an event mixing technique. Given events containing particles of type A and particles type B, it is assumed the user wants to construct some quantity which can be calculated from the properties of any pair (A,B), using both correlated and uncorrelated (mixed) pairs. The algorithm requires the user to provide:
For each analysed event, the function for correlated pairs will be called for each pair in the event, and then each previous event stored in buffers will be used to generate uncorrelated pairs for which the corresponding function will be called. The particles of each type of the \(N\) previous events (by default \(N=10\): can be changed with an argument to the class constructor) are kept in memory: decorrelating begins when each buffer is full, after this each new event which is added causes the previous 'oldest' event in the same buffer to be discarded.
The user must define a class/struct which will be used to store any necessary information on each particle in the buffers used in the event mixing. This struct must define a constructor whose single argument is compatible with whatever type of reference to the particles in the event is returned by the iterators provided by the user (see ProcessEvent() method below). In the case of events stored in KVEvent (or derived) objects, this class/struct must have a constructor which can be called with a reference to a KVNucleus object (or derived class) and which will extract and store the required information.
Here are some examples:
This could be used for azimuthal correlations, supposing that all is required is the azimuthal angle of each particle.
In experimental cases (i.e. analysing reconstructed data), you probably need to store some information on which detector was hit by the particle, in order to avoid generating uncorrelated pairs which could not exist experimentally. For example:
If more detailed informations on each particle are required, the most simple (but not the most lightweight in terms of memory) way may be to store the informations in a KVNucleus object in your structure. In this case, rather than trying to do a direct 'copy' of the nucleus passed to the constructor (especially when dealing with KVReconstructedNucleus objects), you should use the appropriate 'Set' methods of KVNucleus in order to copy the required characteristics for each nucleus. In this example, we show the minimum required in order to keep all kinematic information (in a given reference frame - not all frames can be copied) on each nucleus:
In all cases, your class/struct needs to have a default constructor, default copy constructor, and default move constructor: just add them as shown:
Once the class/struct for particle info storage is defined, the event mixer can be declared as a member variable of your analysis class:
The 2 template parameters are:
The constructor optionally takes an argument defining the number of events to use for the mixing (if not given, default value 10 is used).
In your event by event analysis, you need to call the ProcessEvent() method, providing the required iterators and functions to treat each pair of particles, along with the 'bin' number corresponding to the class of the current event (e.g. events could be classed according to total multiplicity into bins of centrality - it is up to you how you sort your events):
The 'iterators' IterA and IterB are not in fact strictly iterators: they are any expression which can be used on the right-hand side of a range-for loop, i.e. 'X' in the following pseudo-code:
For example, if the particles in your event are stored in a std::vector, X would be a reference to the vector:
KaliVeda provides a wide range of pseudo-iterators for KVEvent to be used in range-for loops, which are commonly used in KVEventSelector analysis classes:
Therefore to use KVEventMixer in a KVEventSelector analysis class, IterA and IterB will probably be one of these pseudo-iterators, as in this (incomplete) example for correlating \(\alpha\)-particles and deuterons:
Finally you have to provide two functions in order to treat each pair of correlated and uncorrelated particles. This is conveniently done using lambda functions. Each function takes three arguments, the 'bin' corresponding to the event class (this is the value passed as first argumet to ProcessEvent) and then one argument for each particle in the pair, with a slight signature difference between correlated and uncorrelated pairs:
void(int, IteratorReferenceType, IteratorReferenceType)
void(int, IteratorReferenceType, ParticleInfoStruct&)
where IteratorReferenceType
refers to the type of reference to the particles in the event returned by the pseudo-iterators given as 2nd and 3rd argument:
and ParticleInfoStruct
is the structure you provided to store the informations on particles from different events for the decorrelation.
The correlated pair function CorrelatedPairFunction will be called for every pair of particles (A,B) generated by coupling every A particle in the event with every B particle. If A and B particles are in fact of the same type, it is the user's responsibility to avoid correlating each particle with itself in the given CorrelatedPairFunction (e.g. by comparing the memory address of each particle object).
The uncorrelated pair function UnCorrelatedPairFunction will be called for every pair generated by coupling:
All will hopefully become clear with a full example. Let us assume that in your experimental data analysis you want to calculate azimuthal correlations for alpha particles for different bins in centrality, using the azimuthal_cor
structure we presented above to store relevant informations ( \(\phi\) angle and detector index for each \(\alpha\)-particle).
Declaration and initialisation of the structure and the event mixing object as member variables of the analysis class (we only specify the parts of the code concerning the event mixing):
Next, the use of the event mixing object in the event by event analysis:
Things to note in this example:
if(&alpha == &other_alpha) return;
)Definition at line 264 of file KVEventMixer.h.
#include <KVEventMixer.h>
Classes | |
struct | bin_data |
struct | event |
Public Member Functions | |
KVEventMixer (typename std::deque< event >::size_type number_of_events_to_mix=10) | |
template<typename TreatCorPairFunc , typename TreatNCorPairFunc , typename partA_iterator , typename partB_iterator > | |
void | ProcessEvent (int bin_number, partA_iterator iter_A, partB_iterator iter_B, TreatCorPairFunc TreatCorPair, TreatNCorPairFunc TreatNCorPair) |
Event-by-event processing function. | |
Private Attributes | |
bin_data | bins [NumBins] |
std::deque< event >::size_type | decor_events = 10 |
|
inline |
ParticleInfoStruct | user-provided structure which will be used to store any required information on each particle to be used in the event mixing |
NumBins | number of different event classes to be treated separately in the event mixing [default:1] |
number_of_events_to_mix | number of previous events to store in order to do event mixing [default:10] |
Definition at line 296 of file KVEventMixer.h.
|
inline |
Event-by-event processing function.
bin_number | user-defined 'event class number'; particles from different classes are not mixed |
iter_A | iterator over particle type A |
iter_B | iterator over particle type B |
TreatCorPair | function called for each pair of (A,B) particles from the same event |
TreatNCorPair | function called for each pair of (A,B) particles built from different events |
In your event by event analysis, you need to call the ProcessEvent() method, providing the required iterators and functions to treat each pair of particles, along with the 'bin' number corresponding to the class of the current event (e.g. events could be classed according to total multiplicity into bins of centrality - it is up to you how you sort your events):
The 'iterators' IterA and IterB are not in fact strictly iterators: they are any expression which can be used on the right-hand side of a range-for loop, i.e. 'X' in the following pseudo-code:
For example, if the particles in your event are stored in a std::vector, X would be a reference to the vector:
KaliVeda provides a wide range of pseudo-iterators for KVEvent to be used in range-for loops, which are commonly used in KVEventSelector analysis classes:
Therefore to use KVEventMixer in a KVEventSelector analysis class, IterA and IterB will probably be one of these pseudo-iterators, as in this (incomplete) example for correlating \(\alpha\)-particles and deuterons:
Finally you have to provide two functions in order to treat each pair of correlated and uncorrelated particles. This is conveniently done using lambda functions. Each function takes three arguments, the 'bin' corresponding to the event class (this is the value passed as first argumet to ProcessEvent) and then one argument for each particle in the pair, with a slight signature difference between correlated and uncorrelated pairs:
void(int, IteratorReferenceType, IteratorReferenceType)
void(int, IteratorReferenceType, ParticleInfoStruct&)
where IteratorReferenceType
refers to the type of reference to the particles in the event returned by the pseudo-iterators given as 2nd and 3rd argument:
and ParticleInfoStruct
is the structure you provided to store the informations on particles from different events for the decorrelation.
The correlated pair function CorrelatedPairFunction will be called for every pair of particles (A,B) generated by coupling every A particle in the event with every B particle. If A and B particles are in fact of the same type, it is the user's responsibility to avoid correlating each particle with itself in the given CorrelatedPairFunction (e.g. by comparing the memory address of each particle object).
The uncorrelated pair function UnCorrelatedPairFunction will be called for every pair generated by coupling:
Definition at line 379 of file KVEventMixer.h.
|
private |
Definition at line 285 of file KVEventMixer.h.
|
private |
Definition at line 288 of file KVEventMixer.h.