.. _HowToVeto: How to Veto =========== Introduction ------------ In many physics analyses one of the (final state) particles originates from a specific decay and is not part of the signal decay chain. Such candidates contribute to the background and need to rejected as effectively as possible. Examples: * in studies of radiative B meson or charm decays, such as :math:B^0\to\rho^0\gamma, the photon candidate, which is used in the reconstruction of the :math:B^0 meson may, in reality, originate from the decay of either :math:\pi^0\to\gamma\gamma or :math:\eta\to\gamma\gamma. * in studies of semileptonic B meson or charm decays the lepton sometimes originates from the decay of charmonium, :math:J/\psi for example. To deal with these backgrounds, we construct a veto in order to suppress the background sources. Vetoing comes in two steps: #. calculate or construct some sort of a probability or likelihood that particle :math:X (used in the reconstruction of the signal decay of interest) in reality originates from some other decay, :math:M \to X Y. #. if the calculated probability is larger then some threshold value then we reject X and with it the signal candidate. We veto :math:M. Any veto (:math:\pi^0,\ \eta,\ J/\psi,\ ...) can be fully constructed and configured within the python steering file. Overview of the workflow ------------------------ The analysis of some specific signal side decay with a veto has the following steps. Here we use the worked example of a veto for background photons from a :math:\pi^0\to\gamma\gamma decay but the procedure generalises. #. Reconstruct signal decay candidates * this includes filling of final-state particle lists, making combinations, performing vertex fits, applying cuts, etc... #. Create a :doc:RestOfEvent object for each signal candidate #. Create new basf2.Path to be executed for each :doc:RestOfEvent object in the event (one for each signal candidate) .. warning:: It is important to check if the current :doc:RestOfEvent object is related to a Particle from our signal ParticleList. This is a subtlety, but you may find unrelated :doc:RestOfEvent objects in the DataStore (from some other decay mode). In this case we simply skip the :doc:RestOfEvent by executing a *so called* "dead end" path. #. Fill a ParticleList_ with all (or selected) photons from the :doc:RestOfEvent #. Fill a ParticleList_ with signal photon candidates which is used in the reconstruction of the current signal side candidate (related to current :doc:RestOfEvent) #. Combine the two lists to form pi0 candidates #. Use TMVA or any other method to determine the probability or likelihood that signal photon originates from :math:\pi^0 decay #. Select the best :math:\pi^0 candidate #. Write the probability (or likelihood value) calculated in step iv for the best :math:\pi^0 candidate as extraInfo to the current :math:B^0 candidate #. Continue with signal side reconstruction * continuum suppression, flavour tagging, tag vertex, etc... #. Fill flat ntuple for offline analysis . All analysis actions coloured in blue are executed once per event and all coloured in green are executed once per each :doc:RestOfEvent object in the event. The analysis actions coloured with green together construct a veto. .. seealso:: This is an important usecase of the basf2.Path.for_each functionality. .. _ParticleList: https://software.belle2.org/development/classBelle2_1_1ParticleList.html Examples -------- :math:\pi^0 veto in :math:B^0 \to \rho^0 \gamma decays The code is taken from an existing tutorial: :code:B2A306-B02RhoGamma-withPi0Veto.py 1. The B0 -> rho0 gamma candidates are reconstructed and collected in the ParticleList with name B0. 2. Create :doc:RestOfEvent objects .. code-block:: python import basf2 from modularAnalysis import buildRestOfEvent mymainpath = basf2.Path() buildRestOfEvent('B0', path=mymainpath) 3. Create roe_path in which the veto will be constructed. In addition another dead-end path needs to be created, which will be used in step o) .. code-block:: python roe_path = basf2.Path() deadEndPath = basf2.Path() In next steps the veto is constructed. In this example the veto works in the following way: * combine photon (gamma) used in the reconstruction of the B0 candidate with all other photons found in the event with energy above 50 MeV to form :math:\pi^0 candidates * find best pi0 candidate with invariant mass closest to :math:\pi^0's nominal mass * write value of invariant mass of the best :math:\pi^0 as 'pi0veto' extraInfo o. check if :doc:RestOfEvent is related to any Particle from :code:B0 list .. code-block:: python signalSideParticleFilter('B0', '', roe_path, deadEndPath) 4. fill ParticleList with all photons that have 'E>0.050' from :doc:RestOfEvent (using isInRestOfEvent variable) .. code-block:: python fillParticleList('gamma:roe', 'isInRestOfEvent == 1 and E > 0.050', path=roe_path) 5. fill ParticleList with signal photon candidate which is used in the reconstruction of the current signal side candidate (related to current :doc:RestOfEvent) .. code-block:: python fillSignalSideParticleList('gamma:sig', 'B0 -> rho0 ^gamma', roe_path) 6. combine the two lists to form :math:\pi^0\to\gamma\gamma candidates .. code-block:: python reconstructDecay('pi0:veto -> gamma:sig gamma:roe', '0.080 < M < 0.200', path=roe_path) 7. select the best :math:\pi^0 candidate .. code-block:: python rankByLowest('pi0:veto', 'abs(dM)', 1, path=roe_path) 8. write the probability or likelihood value calculated in step iv) for the best pi0 candidate as extraInfo to the current B0 candidate .. code-block:: python variableToSignalSideExtraInfo('pi0:veto', {'M': 'pi0veto'}, path=roe_path) 9. Connect the roe_path with the main path .. code-block:: python mymainpath.for_each('RestOfEvent', 'RestOfEvents', roe_path) 10. Continue with signal side reconstruction. At this point the B0 candidates have extraInfo(pi0veto) attached. .. code-block:: python printVariableValues('B0', ['pi0veto'], path=mymainpath) If the signal photon candidate could not be paired with any other photon candidate from the :doc:RestOfEvent to form a :math:\pi^0 candidate, then extraInfo(pi0veto) = NaN.