2.3. Combinatorics

Basic combinatorics can be performed fairly simple with the objects RhoCandList and RhoCandidate. After using the PndAnalysis::FillList method, you start your analysis code with a couple of filled lists. (Example code in macro tut_ana_comb.C/tut_ana.C in the tutorial directory.)

In our example, we start with muons and anti-muons, selected with loose criterion using the combination =PidAlgoMdtHardCuts;PidAlgoMvd;PidAlgoStt;PidAlgoDrc= (not necessarily the best for this purpose, just exemplarily):

RhoCandList muplus, muminus, jpsi;
...
  // ... in event loop ...
  theAnalysis->FillList(muplus, "MuonLoosePlus","PidAlgoMdtHardCuts;PidAlgoMvd;PidAlgoStt;PidAlgoDrc");
  theAnalysis->FillList(muminus, "MuonLooseMinus","PidAlgoMdtHardCuts;PidAlgoMvd;PidAlgoStt;PidAlgoDrc");

In order to fill the list named jpsi with J/psi -> mu+ mu- candidates based on the RhoCandidate::Combine method, we could use a classical nested loop like this:

// clean jpsi list and fill it with mu+ mu- combinations
jpsi.Cleanup();

for (j=0;j<muplus.GetLength();++j)
  for (k=0;k<muminus.GetLength();++k)
  {
    RhoCandidate *combCand = muplus[j]->Combine(muminus[k]);
    // ... some computation or checks ...
    jpsi.Append(combCand);
  }

The advantage of coding like this is, that certain operations can be done in between, before actually appending the candidate to the list. When you really just want to do simple combinatorics, the complete routine from above can be short-cutted by using RhoCandList::Combine to:

jpsi.Combine(muplus,muminus);

In order to reduce combinatorics, a cut on the invariant mass can be applied very easily by defining a mass selector with:

                                                          center of selection window
                                                                         v
RhoMassParticleSelector *jpsiMassSel=new RhoMassParticleSelector("jpsi",3.096,1.0);
                                                                               ^
                                                                     full width of window

someplace outside of the event loop and applying it to a list with:

jpsi.Select(jpsiMassSel);

For the complete combinatorics for our decay tree psi(2S) -> J/psi pi+ pi- -> mu+ mu- pi+ pi- only the following lines of code are necessary:

...
// ... in event loop ...
theAnalysis->FillList(muplus, "MuonAllPlus");
theAnalysis->FillList(muminus, "MuonAllMinus");
theAnalysis->FillList(piplus, "PionAllPlus");
theAnalysis->FillList(piminus, "PionAllMinus");

jpsi.Combine(muplus, muminus);
jpsi.Select(jpsiMassSel);
psi.Combine(jpsi,piplus,piminus);

(When you are wondering, why no PID algorithm is specified: Since we want to select all particles and just set the mass hypothesis, we don’t care in this case.)

This kind of doing combinatorics with RhoCandList::Combine avoids double counting (which easily happens when doing combinatorics with indistinguishable particles, e.g. forming gamma gamma combinations) and overlaps (which means, that a certain reconstructed particle appears more than once in a composite candidate with e.g. different mass hypotheses).

The results for the combinatorics for the J/psi and the psi(2S) with no PID requirement look like this:

J/psi mass with no PID psi(2S) with no PID

The same spectra with tight PID applied look like this:

J/psi with tight PID psi(2S) with tight PID

You can see in particular in the left plot, that the wrong combinations of J/psi based on pion tracks at low invariant masses are significantly suppressed.