KaliVeda
Toolkit for HIC analysis
Loading...
Searching...
No Matches
KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins > Class Template Reference

Detailed Description

template<int NPart, typename ParticleClass, typename ParticleInfoStruct, int NumBins = 1>
class KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >

Generic event mixing algorithm for N-particle correlation studies.

Template Parameters
NPartnumber of particles to correlate = 2, 3, 4, ...
ParticleClassclass used to represent particles as passed via iterators to ProcessEvent()
ParticleInfoStructuser-provided structure which will be used to store any required information on each particle to be used in the event mixing
NumBinsnumber 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 \(N\)-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 \(N\)-particle correlation functions using an event mixing technique. Given events containing \(N\) particle types A, type B, type C, ..., it is assumed the user wants to construct some quantity which can be calculated from the properties of any multiplet of particles (A,B,C,...), using both correlated and uncorrelated (mixed) sets of particles. The algorithm requires the user to provide:

  • iterators to perform loops over the different types of particles in each event;
  • functions to treat each correlated and uncorrelated multiplet of particles (A,B,C,...)

For each analysed event, the function for correlated particles will be called for each multiplet in the event, and then each previous event stored in buffers will be used to generate uncorrelated multiplets 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.

Defining storage for particle properties to be used in event mixing buffers

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 (this is the same type as the template parameter ParticleType - 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:

struct azimuthal_cor
{
double phi;
azimuthal_cor(const KVNucleus& nuc) : phi{nuc.GetPhi()} {} // ParticleType=KVNucleus
};
Description of properties and kinematics of atomic nuclei.
Definition KVNucleus.h:126

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:

struct azimuthal_cor
{
double phi;
int det_index;
azimuthal_cor(const KVReconstructedNucleus& nuc)
: phi{nuc.GetPhi()}, det_index{nuc.GetStoppingDetector()->GetIndex()} {} // ParticleType=KVReconstructedNucleus
};
Nuclei reconstructed from data measured by a detector array .

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:

struct my_nucleus
{
KVNucleus nuc;
my_nucleus(const KVReconstructedNucleus& n)
{
nuc.SetZandA(n.GetZ(),n.GetA());
nuc.SetMomentum(n.GetMomentum()); // this is momentum in whatever 'default' frame is defined for n
}
};
void SetZandA(Int_t z, Int_t a)
Set atomic number and mass number.
void SetMomentum(const TVector3 *v)
Definition KVParticle.h:542
const Int_t n

In all cases, your class/struct needs to have a default constructor, default copy constructor, and default move constructor: just add them as shown:

struct my_part_struct
{
// add compiler-generated default constructors
my_part_struct() = default;
my_part_struct(const azimuthal_cor&) = default;
my_part_struct(azimuthal_cor&&) = default;
};

Using the event mixer in data analysis

Once the class/struct for particle info storage is defined, the event mixer can be declared as a member variable of your analysis class, as in this example for 2-body azimuthal correlations calculated for experimental data:

struct azimuthal_cor { ... };
Generic event mixing algorithm for N-particle correlation studies.

The 4 template parameters are:

  • the number of particles to correlate in each event;
  • the class used to represent the particles in the data being analysed;
  • the user's particle storage class;
  • the number of different classes/bins that events are sorted into (default=1: no binning).

The constructor optionally takes an argument defining the buffer depth to use for the mixing (if not given, default value 10 events is used).

In your event by event analysis, you need to call the ProcessEvent() method, providing the required iterators and functions to treat each multiplet 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):

event_mixer.ProcessEvent(bin,CorrelatedFunction,UnCorrelatedFunction,IterA,IterB,IterC,...);
void ProcessEvent(int bin_number, TreatCorFunc TreatCor, TreatNCorFunc TreatNCor, const part_iterator &iter_part, part_iterator_list... part_iterators)

User-provided iterators for each particle type

The 'iterators' IterA, IterB, etc. 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(auto& p : X){ ... }
#define X(type, name)

For example, if the particles in your event are stored in a std::vector, X would be a reference to the vector:

std::vector<KVNucleus> my_event;
for(auto& n : my_event){ ... loop over particles in event ... }
event_mixer.ProcessEvent(bin, CorFunc, UnCorFunc, my_event, ...);

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:

for(auto& n : EventOKIterator(GetEvent())) { ... loop over 'OK' particles of event, 'n' is a KVNucleus& ... }
for(auto& p : ReconEventIterator(GetEvent(),
{"alpha",[](const KVReconstructedNucleus* x){ return x->IsAMeasured() && x->IsIsotope(2,4); }})
)
{ ... loop over isotopically-identified alpha particles of event, 'p' is a KVReconstructedNucleus& ... }
Class for iterating over "OK" nuclei in events accessed through base pointer/reference.
Wrapper class for iterating over nuclei in KVReconstructedEvent accessed through base pointer or refe...
Double_t x[n]
TArc a

Therefore to use KVEventMixer in a KVEventSelector analysis class, IterA, IterB, ... will probably be one of these pseudo-iterators, as in this (incomplete) example for correlating \(\alpha\)-particles and deuterons:

event_mixer.ProcessEvent(bin,
CorFunc, UnCorFunc,
ReconEventIterator(GetEvent(),
{"alpha",[](const KVReconstructedNucleus* x){ return x->IsAMeasured() && x->IsIsotope(2,4); }}),
ReconEventIterator(GetEvent(),
{"deuton",[](const KVReconstructedNucleus* x){ return x->IsAMeasured() && x->IsIsotope(1,2); }})
);

User-provided functions for correlated and uncorrelated particles

Finally you have to provide two functions in order to treat each set of correlated and uncorrelated particles. This is conveniently done using lambda functions, but any callable can be used.

Both functions receive as first argument the 'bin' corresponding to the event class (this is the value passed as first argumet to ProcessEvent). For correlated particles, the multiplet of \(N\) correlated particles are passed in a vector:

// CorFunc signature:
void(int bin_number, KVRefVec<ParticleType>& particles)
Vector of references to objects.
Definition KVRefVec.h:24
void(off) SmallVectorTemplateBase< T

KVRefVec<T> behaves like a std::vector of references to T objects: given a vector KVRefVec<T> o;, o[i] is a T& reference.

The correlated function CorFunc will be called for every set of particles (A,B,C,...) generated by coupling all possible combinations of the \(N\) different types of particles in the event. If 2 or more of the particle types are in fact the same, so that two or more particles to correlate may in fact be the same physical particle, it is the user's responsibility to avoid correlating each particle with itself in the given CorFunc (e.g. by comparing the memory address of each particle object).

For uncorrelated particles, we pass to the user's function a reference to a particle in the current event and \(N-1\) references to the other particles taken from previous events in the buffers:

// UnCorFunc signature:
void(int bin_number, ParticleType& part, KVRefVec<ParticleInfoStruct>& buffer_particles)

The particles of each type are taken from the buffers of \(N\) previous events; note that in the buffers for different particles, there may be particles of different types from the same event. If you want to avoid using particles from the same event, you could (as in order to avoid particles hitting the same detector in different events) store in the ParticleInfoStruct the event number for each particle, and then check that all buffer particles are from different events in you UnCorFunc function.

Examples
ExampleAnalysis_KVEventMixerN_2Body.cpp, and ExampleAnalysis_KVEventMixerN_3Body.cpp.

Definition at line 200 of file KVEventMixerN.h.

#include <KVEventMixerN.h>

Classes

struct  bin_data
 
struct  event
 

Public Member Functions

 KVEventMixerN (typename event_buffer::size_type number_of_events_to_mix=10)
 vector of references to particles from buffers for decorrelation
 
template<typename TreatNCorFunc , typename part_iterator , typename... part_iterator_list>
void decorrelate (int part_index, TreatNCorFunc TreatNCor, part_iterator &iter_part, part_iterator_list... part_iterators)
 
template<typename TreatNCorFunc >
void decorrelate (int, TreatNCorFunc)
 
template<typename part_iterator , typename... part_iterator_list>
void fill_all_particle_buffers (int part_index, part_iterator &iter_part, part_iterator_list... part_iterators)
 
void fill_all_particle_buffers (int)
 
template<typename TreatCorFunc , typename part_iterator , typename... part_iterator_list>
void process_event (int part_index, TreatCorFunc TreatCor, part_iterator &iter_part, part_iterator_list... part_iterators)
 
template<typename TreatCorFunc >
void process_event (int, TreatCorFunc TreatCor)
 
template<typename TreatCorFunc , typename TreatNCorFunc , typename part_iterator , typename... part_iterator_list>
void ProcessEvent (int bin_number, TreatCorFunc TreatCor, TreatNCorFunc TreatNCor, const part_iterator &iter_part, part_iterator_list... part_iterators)
 
template<typename TreatNCorFunc >
void recursive_decorrelation (ParticleClass &part, int part_index, int decor_index, int decor_vec_index, TreatNCorFunc TreatNCor)
 

Private Types

using event_buffer = std::deque< event >
 

Private Attributes

bin_data bins [NumBins]
 
std::array< bool, NPart > buffer_ready
 
std::array< bool, NPart > can_decorrelate
 
KVRefVec< ParticleClass > correlated_particles {NPart}
 
int current_bin_number
 number of events used for decorrelation (event mixing)
 
event_buffer::size_type decor_events = 10
 
std::array< bool, NPart > mult_fixed
 particle multiplicities for event being treated by ProcessEvent
 
std::array< int, NPart > n_part
 bin number passed in current call to ProcessEvent
 
KVRefVec< ParticleInfoStruct > uncorrelated_particles {NPart - 1}
 vector of references to particles in current event
 

Member Typedef Documentation

◆ event_buffer

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
using KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::event_buffer = std::deque<event>
private

Definition at line 218 of file KVEventMixerN.h.

Constructor & Destructor Documentation

◆ KVEventMixerN()

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::KVEventMixerN ( typename event_buffer::size_type  number_of_events_to_mix = 10)
inline

vector of references to particles from buffers for decorrelation

Template Parameters
ParticleInfoStructuser-provided structure which will be used to store any required information on each particle to be used in the event mixing
NumBinsnumber of different event classes to be treated separately in the event mixing [default:1]
Parameters
number_of_events_to_mixnumber of previous events to store in order to do event mixing [default:10]

Definition at line 241 of file KVEventMixerN.h.

Member Function Documentation

◆ decorrelate() [1/2]

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
template<typename TreatNCorFunc , typename part_iterator , typename... part_iterator_list>
void KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::decorrelate ( int  part_index,
TreatNCorFunc  TreatNCor,
part_iterator &  iter_part,
part_iterator_list...  part_iterators 
)
inline

Definition at line 334 of file KVEventMixerN.h.

◆ decorrelate() [2/2]

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
template<typename TreatNCorFunc >
void KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::decorrelate ( int  ,
TreatNCorFunc   
)
inline

Definition at line 330 of file KVEventMixerN.h.

◆ fill_all_particle_buffers() [1/2]

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
template<typename part_iterator , typename... part_iterator_list>
void KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::fill_all_particle_buffers ( int  part_index,
part_iterator &  iter_part,
part_iterator_list...  part_iterators 
)
inline

Definition at line 288 of file KVEventMixerN.h.

◆ fill_all_particle_buffers() [2/2]

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
void KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::fill_all_particle_buffers ( int  )
inline

Definition at line 281 of file KVEventMixerN.h.

◆ process_event() [1/2]

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
template<typename TreatCorFunc , typename part_iterator , typename... part_iterator_list>
void KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::process_event ( int  part_index,
TreatCorFunc  TreatCor,
part_iterator &  iter_part,
part_iterator_list...  part_iterators 
)
inline

Definition at line 256 of file KVEventMixerN.h.

◆ process_event() [2/2]

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
template<typename TreatCorFunc >
void KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::process_event ( int  ,
TreatCorFunc  TreatCor 
)
inline

Definition at line 246 of file KVEventMixerN.h.

◆ ProcessEvent()

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
template<typename TreatCorFunc , typename TreatNCorFunc , typename part_iterator , typename... part_iterator_list>
void KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::ProcessEvent ( int  bin_number,
TreatCorFunc  TreatCor,
TreatNCorFunc  TreatNCor,
const part_iterator &  iter_part,
part_iterator_list...  part_iterators 
)
inline

Definition at line 349 of file KVEventMixerN.h.

◆ recursive_decorrelation()

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
template<typename TreatNCorFunc >
void KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::recursive_decorrelation ( ParticleClass &  part,
int  part_index,
int  decor_index,
int  decor_vec_index,
TreatNCorFunc  TreatNCor 
)
inline

Definition at line 309 of file KVEventMixerN.h.

Member Data Documentation

◆ bins

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
bin_data KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::bins[NumBins]
private

Definition at line 222 of file KVEventMixerN.h.

◆ buffer_ready

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
std::array<bool, NPart> KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::buffer_ready
private

Definition at line 229 of file KVEventMixerN.h.

◆ can_decorrelate

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
std::array<bool, NPart> KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::can_decorrelate
private

Definition at line 230 of file KVEventMixerN.h.

◆ correlated_particles

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
KVRefVec<ParticleClass> KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::correlated_particles {NPart}
private

Definition at line 232 of file KVEventMixerN.h.

◆ current_bin_number

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
int KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::current_bin_number
private

number of events used for decorrelation (event mixing)

Definition at line 226 of file KVEventMixerN.h.

◆ decor_events

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
event_buffer::size_type KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::decor_events = 10
private

Definition at line 224 of file KVEventMixerN.h.

◆ mult_fixed

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
std::array<bool, NPart> KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::mult_fixed
private

particle multiplicities for event being treated by ProcessEvent

Definition at line 228 of file KVEventMixerN.h.

◆ n_part

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
std::array<int, NPart> KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::n_part
private

bin number passed in current call to ProcessEvent

Definition at line 227 of file KVEventMixerN.h.

◆ uncorrelated_particles

template<int NPart, typename ParticleClass , typename ParticleInfoStruct , int NumBins = 1>
KVRefVec<ParticleInfoStruct> KVEventMixerN< NPart, ParticleClass, ParticleInfoStruct, NumBins >::uncorrelated_particles {NPart - 1}
private

vector of references to particles in current event

Definition at line 233 of file KVEventMixerN.h.