2.2. Particle Identification =============================== Data access and PID selection can be done at once in this concept. You can ask the analysis object ``PndAnalysis`` to return list of particles fulfilling certain PID criteria. (You can find example code in **tut_ana_pid.C/tut_ana.C** in the tutorial directory.) 2.2.1. Set Mass Hypothesis only -------------------------------- In this example we need muon candidates (when no charge is mentioned, I always mean particles and anti-particles) to reconstruct the *J/psi -> mu+ mu- decay*. The ``pbarpSystem`` then is reconstructed from a *J/psi* candidate and two oppositely charged pion candidates. When we want to do a very unbiased analysis without any PID, we would request all charged candidates, which were reconstructed in the event. Requesting lists is done via the ``PndAnalysis::FillList`` method and looks e.g. like this:: RhoCandList allCharged; // *** a list container which will be filled with particle candidates ... // event loop while ( theAnalysis->GetEvent() ) { theAnalysis->FillList(allCharged,"Charged"); // *** here the list is requested ... The parameter ``allCharged`` is an object of class ``RhoCandList`` (for info on Rho interfaces please take look at http://panda-wiki.gsi.de/cgi-bin/view/Computing/PandaRootAnalysisJuly13) - a container for the particle class ``RhoCandidate`` - and the keyword ``Charged`` requests all charged particle candidates. If we wanted to request all positively or negatively charged particles, we could use the keywords ``Plus`` or ``Minus`` instead. Since neither a particle type is known nor requested, the energy component of the 4-vectors of all particles in the list will be set to a value corresponding to a certain default particle mass, usually the rest mass of a charged pion. An alternative approach might be more useful in cases, where we don't want to use PID, but want to set all candidates to a certain mass hypothesis. The keywords here are a concatenation of the particle's type keywords - ``Electron, Muon, Pion, Kaon`` or ``Proton`` - followed by the keyword ``All`` (There is in addition a special list for electrons available corrected for bremsstrahlung: ``ElectronBrem``). If appending another ``Plus`` or ``Minus`` we can request a list with all positively and negatively charged particles with electron mass hypothesis by this code:: RhoCandList allMuonsPlus, allMuonsMinus; ... theAnalysis->FillList( allMuonsPlus, "MuonAllPlus"); theAnalysis->FillList( allMuonsMinus, "MuonAllMinus"); Since ``All`` is the default selection criterion the even more compact keywords ``MuonPlus`` and ``MuonMinus`` do the same. 2.2.2. Various PID Criteria ---------------------------- When we actually want to use some PID information, we can replace the keyword ``All`` by different criteria. These are defined by certain requirements on the identification probability *P* (next chapter will say more about how this *P* is obtained). The available keywords are (for the time being): * All - *P ≥ 0.0* required * VeryLoose - *P ≥ 0.0* required * Loose - *P ≥ 0.25* required * Tight - *P ≥ 0.5* required * VeryTight - *P ≥ 0.9* required * Best - accept as type *i*, if *P*\ :sub:`i` > *P*\ :sub:`j` for all *j!=i* * 0.XY - arbitrary cut *P ≥ 0.XY*, where X and Y are digits [0, 1, ... 9] The thresholds for the default criteria can actually be set via the parameter database, but this shall not be discuss here any further. Please note, that in the moment the criterion ``VeryLoose`` does the same as ``All`` (which is not really reasonable) - this might be changed in the future. When we want to work e.g. with pion candidates fulfilling tight PID criteria, we would write:: RhoCandList tightPionsCharged, tightPionsPlus, tightPionsMinus; ... // ... in event loop ... theAnalysis->FillList( tightPionsCharged, "PionTight"); theAnalysis->FillList( tightPionsPlus, "PionTightPlus"); theAnalysis->FillList( tightPionsMinus, "PionTightMinus"); If none of the available default criteria suits our needs, we can apply our own cut on *P* with:: theAnalysis->FillList( myPionsPlus, "PionPlus0.45"); theAnalysis->FillList( myPionsMinus, "PionMinus0.1"); 2.2.3. PID Algorithms ---------------------- The selection criteria described above require some certain value of the PID probabilities *P*\ :sub:`i` for all five particle types *i* ∈ (*e, mu, pi, K, p*). These probability values are computed by various PID classifier tasks during the PID reconstruction stage based on responses of the various PID detectors. The corresponding source code in the class ``PndMasterPidTask`` (https://subversion.gsi.de/trac/fairroot/browser/pandaroot/trunk/PndTools/master/PndMasterPidTask.cxx) looks like:: ... this->Add(new PndPidIdealAssociatorTask()); // "PidAlgoIdealCharged", "PidAlgoIdealNeutral" this->Add(new PndPidMvdAssociatorTask()); // "PidAlgoMvd" this->Add(new PndPidMdtHCAssociatorTask()); // "PidAlgoMdtHardCuts" this->Add(new PndPidDrcAssociatorTask()); // "PidAlgoDrc" this->Add(new PndPidDiscAssociatorTask()); // "PidAlgoDisc" this->Add(new PndPidSttAssociatorTask()); // "PidAlgoStt" this->Add(new PndPidEmcBayesAssociatorTask()); // "PidAlgoEmcBayes" this->Add(new PndPidSciTAssociatorTask()); // "PidAlgoSciT" this->Add(new PndPidRichAssociatorTask()); // "PidAlgoRich" As you can see at the moment there are nine different algorithms running, where each determines a set of five probabilities (*P*\ :sub:`e`, *P*\ :sub:`mu`, *P*\ :sub:`pi`, *P*\ :sub:`K`, *P*\ :sub:`p`) for every particle in the event (only charged particles up to now) based on the available PID information like e.g. EMC cluster energy *E*\ :sub:`EMC`, momentum *p*, energy loss *dE/dx*, cherenkov angle *theta*\ :sub:`C` etc. These values are stored for each event. In order to perform PID selection based on a particular algorithms, the name can be specified as a third parameter in the ``FillList`` method. This looks e.g. like:: // ... in event loop ... theAnalysis->FillList( looseElectrons, "ElectronLoose", "PidAlgoEmcBayes"); theAnalysis->FillList( tightKaonsPlus, "KaonTightPlus", "PidAlgoDrc"); The algorithm ``PidAlgoIdealCharged`` sets ideal PID probabilities in the sense, that the true particle species gets *P=1*, the others *P=0*. Note: This is **not** the same as requesting the MC truth object, since it only checks the particle species, not the charge. It can happen, that the reco object has the opposite charge of the true particle from simulation due to misreconstruction. In this case the the reco particle selected with !PidAlgoIdealCharge nevertheless is accepted. If you want to make sure, that a particle has been reconstructed and identified correctly, better use ``RhoCandidate::GetMcTruth()`` (see below). There is even the possibility to combine the information of various algorithms with:: theAnalysis->FillList( eLoose, "ElectronLoose", "PidAlgoEmcBayes;PidAlgoDrc;PidAlgoStt"); In this case the probabilities for PID selection are achieved by multiplying the probability values of the chosen algorithms, i.e. *P*\ :sub:`e` = *P*\ :sub:`e,1` × *P*\ :sub:`e,2` × *P*\ :sub:`e,2`, etc. 2.2.4. Stand-alone PID Selector --------------------------------- Besides using the ``PndAnalysis::FillList`` syntax for PID selection, it is also possible to instantiate stand-alone PID selectors, i.e. you can start with a list of charged particles and uses a PID selector to select a particle type based on a certain PID algorithm and selection criterion. In order to understand the mechanism it might help to take a look to some technical details. As describe above, during the PID stage of the simulation, certain PID algorithm task can be appended to the reconstruction sequence, where each computes a set of probability values (*P*\ :sub:`e`, *P*\ :sub:`mu`, *P*\ :sub:`pi`, *P*\ :sub:`K`, *P*\ :sub:`p`) for each track in each event. Since we don't know yet how many algorithms will be invented in the future, these values are not part of the **PndPidCandidate**, they are stored in separate **TClonesArrays**. In order to transfer the probability values or even combination of values (usually given by the product of the probabilities) a class called *PndAnaPi*d*Combiner* is used. After configuring it to read in the probability set of the desired algorithms, it is used to copy the values to a **RhoCandidate** or even all candidates in a **RhoCandList**. After this step, an object called **PndAnaPidSelector** can be used to select particles based on the current probability values. Altogether, an example looks like this:: PndAnaPidCombiner pidComb("PidComb"); // *** the PidCombiner pidComb.SetTcaNames("PidAlgoDrc;PidAlgoStt"); // *** configure it to read in values from PidAlgoDrc and PidAlgoStt and combine them PndAnaPidSelector kaonSel("KaonSelector"); // *** the PidSelector kaonSel.SetSelection("KaonTightPlus"); // *** set type of particles to be selected ... // ... in event loop ... theAnalysis->FillList( charged, "Charged"); // *** we start with charged candidates pidComb.Apply(charged); // *** here the probabilities are copied to RhoCandidates kaonSel.Select(charged, kplus); // *** perform selection This actually looks a bit complicated for the time being, so there might be an improvement in the interface later. However all kinds of standard selection can be performed with the ``PndAnalysis::FillList`` method, which is a quite comfortable way.