Source code for skim.WGs.taupair

#!/usr/bin/env python3

##########################################################################
# basf2 (Belle II Analysis Software Framework)                           #
# Author: The Belle II Collaboration                                     #
#                                                                        #
# See git log for contributors and copyright holders.                    #
# This file is licensed under LGPL-3.0, see LICENSE.md.                  #
##########################################################################

""" Skim list building functions for tau-pair analyses """

import modularAnalysis as ma
from skim.standardlists.lightmesons import (loadStdAllF_0, loadStdAllKstar0,
                                            loadStdAllPhi, loadStdAllRho0)
from skim import BaseSkim, fancy_skim_header
from stdCharged import stdE, stdK, stdMu, stdPi, stdPr
from stdPhotons import stdPhotons
from variables import variables as vm
from stdV0s import stdKshorts
import variables.collections as vc
import variables.utils as vu

__liaison__ = "Kenji Inami <kenji.inami@desy.de>"
_VALIDATION_SAMPLE = "mdst14.root"


[docs] def tauskim_particle_selection(label, path): # Track trackCuts = "-3.0 < dz < 3.0 and dr < 1.0" ma.cutAndCopyList(f"pi+:{label}", "pi+:all", trackCuts, path=path) # pi0 gammaDetectorLocation = { "FWD": "clusterReg == 1", "BRL": "clusterReg == 2", "BWD": "clusterReg == 3" } gammaForPi0lists = [] for g in gammaDetectorLocation.keys(): gammaForPi0Cuts = gammaDetectorLocation[g] gammaForPi0Cuts += ' and abs(clusterTiming) < 200' gammaForPi0Cuts += ' and thetaInCDCAcceptance' gammaForPi0Cuts += ' and clusterNHits > 1.5' gammaForPi0 = f'gamma:looseForPi0{label}{g}' gammaForPi0lists.append(gammaForPi0) ma.cutAndCopyLists(gammaForPi0, 'gamma:all', gammaForPi0Cuts, path=path) # -# -- -- cos of opening angle between the photons vm.addAlias( 'cosAngle2Photons', 'formula((daughter(0, px) * daughter(1, px) + ' 'daughter(0, py) * daughter(1, py) + ' 'daughter(0, pz) * daughter(1, pz) ) / daughter(0, p) / daughter(1, p) )') vm.addAlias('leadingclusterE', 'formula(max(daughter(0, clusterE),daughter(1, clusterE)))') vm.addAlias('subleadingclusterE', 'formula(min(daughter(0, clusterE),daughter(1, clusterE)))') # Determine pi0 reco for individual Detector Parts Pi0CutLabel = ["leadingclusterE", "subleadingclusterE", "cosAngle2Photons", "p"] Pi0CutValue = { "FWD,FWD": [0.5625, 0.1625, 0.9458, 0.9444], "BRL,BRL": [0.4125, 0.0625, 0.8875, 0.6333], "BWD,BWD": [0.4125, 0.1125, 0.8708, 0.6111], "BRL,FWD": [0.3625, 0.0875, 0.8875, 0.5889], "BRL,BWD": [0.3625, 0.0875, 0.8875, 0.5889] } Pi0lists = [] for cut in Pi0CutValue.keys(): gammalists = cut.split(",") CurrentPi0List = f'pi0:fromLooseGammas{label}{gammalists[0]}{gammalists[1]}' Pi0lists.append(CurrentPi0List) Pi0Cut = '0.115 < M < 0.152' for i, c in enumerate(Pi0CutLabel): Pi0Cut += f' and {c} > {Pi0CutValue[cut][i]}' ma.reconstructDecay(f'{CurrentPi0List} -> gamma:looseForPi0{label}{gammalists[0]} gamma:looseForPi0{label}{gammalists[1]}', Pi0Cut, path=path) ma.copyLists(f'pi0:{label}', Pi0lists, path=path) ma.cutAndCopyList(f'gamma:pi0_{label}', 'gamma:all', f'isDescendantOfList(pi0:{label}) == 1', path=path) # gamma gammaCuts = 'E > 0.2' gammaCuts += ' and abs(clusterTiming) < 200' gammaCuts += ' and thetaInCDCAcceptance' gammaCuts += ' and clusterNHits > 1.5' gammaCuts += f' and isDescendantOfList(pi0:{label}) == 0' ma.cutAndCopyList(f'gamma:nonpi0_{label}', 'gamma:all', gammaCuts, path=path) ma.copyLists(f'gamma:{label}', [f'gamma:pi0_{label}', f'gamma:nonpi0_{label}'], path=path)
[docs] @fancy_skim_header class TauLFV(BaseSkim): """ **Channel**: :math:`\\tau \\to l \\gamma, lll, l \\pi^0, l \\eta, l \\eta', l K_S, l f_0, l V^0, lhh, llp, phh, \\lambda\\pi` **Output particle lists**: ``e+:taulfv, mu+:taulfv, pi+:taulfv, K+:taulfv, p+:taulfv``, ``gamma:taulfv, pi0:taulfv, K_S0:taulfv, eta:taulfv, eta':taulfv``, ``omega:taulfv, Lambda0:taulfv_p, Lambda0:taulfv_antip`` **Criteria for 1 prong final states**: Number of good tracks < 5, :math:`1.0 < M < 2.0` GeV, :math:`-1.5 < \\Delta E < 0.5` GeV **Criteria for >1 prong final states**: Number of good tracks < 7, :math:`1.4 < M < 2.0` GeV, :math:`-1.0 < \\Delta E < 0.5` GeV """ __authors__ = ["Kenji Inami"] __description__ = "Skim for Tau LFV decays." __contact__ = __liaison__ __category__ = "physics, tau" ApplyHLTHadronCut = False produce_on_tau_samples = False # retention is too high on taupair validation_sample = _VALIDATION_SAMPLE
[docs] def load_standard_lists(self, path): stdE("all", path=path) stdK("all", path=path) stdMu("all", path=path) stdPi("all", path=path) stdPr("all", path=path) stdPhotons("all", path=path) loadStdAllRho0(path=path) loadStdAllKstar0(path=path) loadStdAllPhi(path=path) loadStdAllF_0(path=path)
[docs] def build_lists(self, path): # particle selection trackCuts = "-3.0 < dz < 3.0 and dr < 1.0" ma.cutAndCopyList("e+:taulfv", "e+:all", trackCuts, path=path) ma.cutAndCopyList("mu+:taulfv", "mu+:all", trackCuts, path=path) ma.cutAndCopyList("pi+:taulfv", "pi+:all", trackCuts, path=path) ma.cutAndCopyList("K+:taulfv", "K+:all", trackCuts, path=path) ma.cutAndCopyList("p+:taulfv", "p+:all", trackCuts, path=path) ma.reconstructDecay("K_S0:taulfv -> pi+:all pi-:all", "0.3 < M < 0.7", path=path) gammaCuts = "E > 0.20 and clusterNHits > 1.5 and thetaInCDCAcceptance" ma.cutAndCopyList("gamma:taulfv", "gamma:all", gammaCuts, path=path) gammaLooseCuts = "E > 0.1 and thetaInCDCAcceptance and clusterNHits > 1.5" ma.cutAndCopyLists("gamma:taulfvloose", "gamma:all", gammaLooseCuts, path=path) # pi0 ma.reconstructDecay("pi0:taulfv -> gamma:taulfvloose gamma:taulfvloose", "0.115 < M < 0.152", path=path) # eta ma.reconstructDecay("eta:taulfv1 -> gamma:taulfvloose gamma:taulfvloose", "0.4 < M < 0.6", path=path) ma.reconstructDecay("eta:taulfv2 -> pi0:taulfv pi-:all pi+:all", "0.4 < M < 0.6", path=path) ma.copyLists("eta:taulfv", ["eta:taulfv1", "eta:taulfv2"], path=path) # eta' ma.reconstructDecay("eta':taulfv1 -> pi+:all pi-:all gamma:taulfvloose", "0.8 < M < 1.1", path=path) ma.reconstructDecay("eta':taulfv2 -> pi+:all pi-:all eta:taulfv", "0.8 < M < 1.1", path=path) ma.copyLists("eta':taulfv", ["eta':taulfv1", "eta':taulfv2"], path=path) # omega ma.reconstructDecay("omega:taulfv -> pi0:taulfv pi-:all pi+:all", "0.73 < M < 0.83", path=path) # Lambda0 ma.reconstructDecay("Lambda0:taulfv_p -> p+:all pi-:all", "0.9 < M < 1.3", path=path) ma.reconstructDecay("Lambda0:taulfv_antip -> anti-p-:all pi+:all", "0.9 < M < 1.3", path=path) # event selection # vm.addAlias("netChargeLFV", "formula(countInList(pi+:taulfv, charge == 1) - countInList(pi+:taulfv, charge == -1))") tauLFVCuts1 = "nParticlesInList(pi+:taulfv) < 5 and 1.0 < M < 2.0 and -1.5 < deltaE < 0.5" tauLFVCuts3 = "nParticlesInList(pi+:taulfv) < 7 and 1.4 < M < 2.0 and -1.0 < deltaE < 0.5" tau_lgamma_Channels = ["e+:taulfv gamma:taulfv", "mu+:taulfv gamma:taulfv" ] tau_lll_Channels = ["e+:taulfv e+:taulfv e-:taulfv", "mu+:taulfv mu+:taulfv mu-:taulfv", "mu+:taulfv e+:taulfv e-:taulfv", "e+:taulfv mu+:taulfv mu-:taulfv", "e+:taulfv e+:taulfv mu-:taulfv", "mu+:taulfv mu+:taulfv e-:taulfv" ] tau_lP01_Channels = ["e+:taulfv pi0:taulfv", "mu+:taulfv pi0:taulfv", "e+:taulfv eta:taulfv1", "mu+:taulfv eta:taulfv1" ] tau_lP03_Channels = ["e+:taulfv eta:taulfv2", "mu+:taulfv eta:taulfv2", "e+:taulfv eta':taulfv", "mu+:taulfv eta':taulfv", "e+:taulfv K_S0:taulfv", "mu+:taulfv K_S0:taulfv" ] tau_lS0_Channels = ["e+:taulfv f_0:all", "mu+:taulfv f_0:all" ] tau_lV0_Channels = ["e+:taulfv rho0:all", "mu+:taulfv rho0:all", "e+:taulfv K*0:all", "mu+:taulfv K*0:all", "e+:taulfv anti-K*0:all", "mu+:taulfv anti-K*0:all", "e+:taulfv phi:all", "mu+:taulfv phi:all", "e+:taulfv omega:taulfv", "mu+:taulfv omega:taulfv" ] tau_lhh_Channels = ["e+:taulfv pi-:taulfv pi+:taulfv", "mu+:taulfv pi-:taulfv pi+:taulfv", "e-:taulfv pi+:taulfv pi+:taulfv", "mu-:taulfv pi+:taulfv pi+:taulfv", "e+:taulfv K-:taulfv K+:taulfv", "mu+:taulfv K-:taulfv K+:taulfv", "e-:taulfv K+:taulfv K+:taulfv", "mu-:taulfv K+:taulfv K+:taulfv", "e+:taulfv K-:taulfv pi+:taulfv", "mu+:taulfv K-:taulfv pi+:taulfv", "e-:taulfv K+:taulfv pi+:taulfv", "mu-:taulfv K+:taulfv pi+:taulfv", "e+:taulfv K_S0:taulfv K_S0:taulfv", "mu+:taulfv K_S0:taulfv K_S0:taulfv" ] tau_bnv_Channels = ["mu+:taulfv mu+:taulfv anti-p-:taulfv", "mu-:taulfv mu+:taulfv p+:taulfv", "anti-p-:taulfv pi+:taulfv pi+:taulfv", "p+:taulfv pi-:taulfv pi+:taulfv", "anti-p-:taulfv pi+:taulfv K+:taulfv", "p+:taulfv pi-:taulfv K+:taulfv", "Lambda0:taulfv_p pi+:taulfv", "Lambda0:taulfv_antip pi+:taulfv" ] tau_lgamma_list = [] for chID, channel in enumerate(tau_lgamma_Channels): ma.reconstructDecay("tau+:LFV_lgamma" + str(chID) + " -> " + channel, tauLFVCuts1, chID, path=path) tau_lgamma_list.append("tau+:LFV_lgamma" + str(chID)) tau_lll_list = [] for chID, channel in enumerate(tau_lll_Channels): ma.reconstructDecay("tau+:LFV_lll" + str(chID) + " -> " + channel, tauLFVCuts3, chID, path=path) tau_lll_list.append("tau+:LFV_lll" + str(chID)) tau_lP0_list = [] for chID, channel in enumerate(tau_lP01_Channels): ma.reconstructDecay("tau+:LFV_lP01" + str(chID) + " -> " + channel, tauLFVCuts1, chID, path=path) tau_lP0_list.append("tau+:LFV_lP01" + str(chID)) for chID, channel in enumerate(tau_lP03_Channels): ma.reconstructDecay("tau+:LFV_lP03" + str(chID) + " -> " + channel, tauLFVCuts3, chID, path=path) tau_lP0_list.append("tau+:LFV_lP03" + str(chID)) tau_lS0_list = [] for chID, channel in enumerate(tau_lS0_Channels): ma.reconstructDecay("tau+:LFV_lS0" + str(chID) + " -> " + channel, tauLFVCuts3, chID, path=path) tau_lS0_list.append("tau+:LFV_lS0" + str(chID)) tau_lV0_list = [] for chID, channel in enumerate(tau_lV0_Channels): ma.reconstructDecay("tau+:LFV_lV0" + str(chID) + " -> " + channel, tauLFVCuts3, chID, path=path) tau_lV0_list.append("tau+:LFV_lV0" + str(chID)) tau_lhh_list = [] for chID, channel in enumerate(tau_lhh_Channels): ma.reconstructDecay("tau+:LFV_lhh" + str(chID) + " -> " + channel, tauLFVCuts3, chID, path=path) tau_lhh_list.append("tau+:LFV_lhh" + str(chID)) tau_bnv_list = [] for chID, channel in enumerate(tau_bnv_Channels): ma.reconstructDecay("tau+:LFV_bnv" + str(chID) + " -> " + channel, tauLFVCuts3, chID, path=path) tau_bnv_list.append("tau+:LFV_bnv" + str(chID)) return tau_lgamma_list + tau_lll_list + tau_lP0_list + tau_lS0_list + tau_lV0_list + tau_lhh_list + tau_bnv_list
[docs] def validation_histograms(self, path): # NOTE: the validation package is not part of the light releases, so this import # must be made here rather than at the top of the file. from validation_tools.metadata import create_validation_histograms ma.copyLists('tau+:LFV', self.SkimLists, path=path) # add contact information to histogram contact = "kenji@hepl.phys.nagoya-u.ac.jp" # the variables that are printed out are: M, deltaE create_validation_histograms( rootfile=f'{self}_Validation.root', particlelist='tau+:LFV', variables_1d=[ ('M', 100, 1.00, 2.00, '', contact, '', ''), ('deltaE', 120, -1.6, 0.6, '', contact, '', '')], variables_2d=[('M', 50, 1.00, 2.00, 'deltaE', 60, -1.6, 0.6, '', contact, '', '')], path=path)
[docs] @fancy_skim_header class TauGeneric(BaseSkim): """ **Channel**: :math:`e^+ e^- \\to \\tau^+ \\tau^-` **Criteria**: Ntrk = 2 1. Number of good tracks = 2, net charge < 2 2. ``visibleEnergyOfEventCMS < 10 GeV and E_ECLtrk < 6 GeV`` and ``missingMomentumOfEvent_theta < 2.6180`` 3. ``visibleEnergyOfEventCMS > 3 GeV or max P_t > 1 GeV`` 4. max. opening angle < 178 deg. Ntrk = 3,4 1. Number of good tracks = 3 or 4, net charge < 2 2. ``visibleEnergyOfEventCMS < 10.5 GeV and E_ECLtrk < 6 GeV`` 3. ``visibleEnergyOfEventCMS > 3 GeV or max P_t > 1 GeV`` 4. max. opening angle < 178 deg. 5. Event divided by thrust axis; No. good tracks in tag side = 1 or 3 6. ``M_tag < 1.8 GeV`` and ``M_sig < 2.3 GeV`` Ntrk = 5,6 1. Number of good tracks = 5 or 6, net charge < 2 2. Event divided by thrust axis; No. good tracks in tag side = 1 or 3 3. ``M_tag < 1.8 GeV`` and ``M_sig < 2.3 GeV`` """ __authors__ = ["Kenji Inami"] __description__ = "Skim for Tau generic decays." __contact__ = __liaison__ __category__ = "physics, tau" ApplyHLTHadronCut = False produce_on_tau_samples = False # retention is too high on taupair validation_sample = _VALIDATION_SAMPLE
[docs] def load_standard_lists(self, path): stdPi("all", path=path) stdPhotons("all", path=path)
[docs] def additional_setup(self, path): """ Set particle lists and variables for TauGeneric skim. **Output particle lists**: * ``pi+:tauskim, pi0:tauskim, gamma:pi0_tauskim, gamma:nonpi0_tauskim, gamma:tauskim, pi+:S1/S2, pi0:S1/S2, gamma:S1/S2`` **Variables**: * ``nGoodTracks``: number of good tracks in an event * ``netCharge``: total net charge of good tracks * ``nTracksS1/nTracksS2:`` number of good tracks in each hemisphere ``S1/S2`` divided by thrust axis * ``invMS1/invMS2``: invariant mass of particles in each hemisphere * ``maxPt``: maximum Pt amoung good tracks * ``E_ECLtrk``: total ECL energy of good tracks """ tauskim_particle_selection("tauskim", path) # Get EventShape variables ma.buildEventShape(["pi+:tauskim", "gamma:tauskim"], allMoments=False, foxWolfram=False, cleoCones=False, sphericity=False, jets=False, path=path) ma.buildEventKinematics(["pi+:tauskim", "gamma:tauskim"], path=path) # Split in signal and tag ma.cutAndCopyList("pi+:S1", "pi+:tauskim", "cosToThrustOfEvent > 0", path=path) ma.cutAndCopyList("pi+:S2", "pi+:tauskim", "cosToThrustOfEvent < 0", path=path) ma.cutAndCopyList("pi0:S1", "pi0:tauskim", "cosToThrustOfEvent > 0", path=path) ma.cutAndCopyList("pi0:S2", "pi0:tauskim", "cosToThrustOfEvent < 0", path=path) ma.cutAndCopyList("gamma:S1", "gamma:tauskim", "cosToThrustOfEvent > 0", path=path) ma.cutAndCopyList("gamma:S2", "gamma:tauskim", "cosToThrustOfEvent < 0", path=path) vm.addAlias("nGoodTracks", "nParticlesInList(pi+:tauskim)") vm.addAlias("netCharge", "formula(countInList(pi+:tauskim, charge == 1) - countInList(pi+:tauskim, charge == -1))") vm.addAlias("nTracksS1", "nParticlesInList(pi+:S1)") vm.addAlias("nTracksS2", "nParticlesInList(pi+:S2)") vm.addAlias("invMS1", "invMassInLists(pi+:S1, pi0:S1, gamma:S1)") vm.addAlias("invMS2", "invMassInLists(pi+:S2, pi0:S2, gamma:S2)") # vm.addAlias("Evis", "visibleEnergyOfEventCMS") vm.addAlias("maxPt", "maxPtInList(pi+:tauskim)") vm.addAlias("E_ECLtrk", "formula(totalECLEnergyOfParticlesInList(pi+:tauskim))") vm.addAlias("maxOp", "useCMSFrame(maxOpeningAngleInList(pi+:tauskim))")
[docs] def build_lists(self, path): # reconstruct with each Ntrk case ma.reconstructDecay('tau+:g2 -> pi+:S1', 'nGoodTracks == 2 and -2 < netCharge <2', path=path) ma.reconstructDecay('tau+:g34 -> pi+:S1', '[nGoodTracks == 3 or nGoodTracks == 4] and -2 < netCharge <2', path=path) ma.reconstructDecay('tau+:g56 -> pi+:S1', '[nGoodTracks == 5 or nGoodTracks == 6] and -2 < netCharge <2', path=path) # Selection criteria # Ntrk=2 ma.applyCuts('tau+:g2', 'visibleEnergyOfEventCMS < 10', path=path) ma.applyCuts('tau+:g2', 'E_ECLtrk < 6', path=path) ma.applyCuts('tau+:g2', 'missingMomentumOfEvent_theta < 2.6180', path=path) ma.applyCuts('tau+:g2', 'visibleEnergyOfEventCMS > 3 or maxPt > 1', path=path) ma.applyCuts('tau+:g2', 'maxOp < 3.106686', path=path) # Ntrk=3,4 ma.applyCuts('tau+:g34', 'visibleEnergyOfEventCMS < 10.5', path=path) ma.applyCuts('tau+:g34', 'E_ECLtrk < 6', path=path) ma.applyCuts('tau+:g34', 'visibleEnergyOfEventCMS > 3 or maxPt > 1', path=path) ma.applyCuts('tau+:g34', 'maxOp < 3.106686', path=path) ma.applyCuts('tau+:g34', '[[ nTracksS1 == 1 or nTracksS1 == 3 ] and invMS1 < 1.8 and invMS2 < 2.3 ] or ' '[[ nTracksS2 == 1 or nTracksS2 == 3 ] and invMS2 < 1.8 and invMS1 < 2.3 ]', path=path) # Ntrk=5,6 ma.applyCuts('tau+:g56', '[[ nTracksS1 == 1 or nTracksS1 == 3 ] and invMS1 < 1.8 and invMS2 < 2.3 ] or ' '[[ nTracksS2 == 1 or nTracksS2 == 3 ] and invMS2 < 1.8 and invMS1 < 2.3 ]', path=path) # For skimming, the important thing is if the final particleList is empty or not. return ['tau+:g2', 'tau+:g34', 'tau+:g56']
[docs] def validation_histograms(self, path): # NOTE: the validation package is not part of the light releases, so this import # must be made here rather than at the top of the file. from validation_tools.metadata import create_validation_histograms vm.addAlias('Theta_miss', 'formula(missingMomentumOfEvent_theta*180/3.14159)') # add contact information to histogram contact = "kenji@hepl.phys.nagoya-u.ac.jp" ma.copyLists('tau+:generic', self.SkimLists, path=path) path = self.skim_event_cuts(cut='nParticlesInList(tau+:generic) > 0', path=path) create_validation_histograms( rootfile=f'{self}_Validation.root', particlelist='', variables_1d=[ ('nGoodTracks', 7, 1, 8, '', contact, '', ''), ('visibleEnergyOfEventCMS', 40, 0, 12, '', contact, '', ''), ('E_ECLtrk', 70, 0, 7, '', contact, '', ''), ('maxPt', 30, 0, 6, '', contact, '', ''), ('invMS1', 60, 0, 3, '', contact, '', '', '', ''), ('invMS2', 60, 0, 3, '', contact, '', ''), ('Theta_miss', 30, 0, 180, '', contact, '', '')], variables_2d=[('invMS1', 30, 0, 3, 'invMS2', 30, 0, 3, '', contact, '', '')], path=path)
[docs] @fancy_skim_header class TauThrust(BaseSkim): """ **Channel**: :math:`e^+ e^- \\to \\tau^+ \\tau^-` **Criteria**: * ``1 < No. good tracks < 7`` * ``net charge == 0`` * Event divided by thrust axis; select 1x1, 1x3, 1x5, 3x3 topology * ``0.8 < thrust`` * ``visibleEnergyOfEventCMS < 10.4 GeV`` * For 1x1 topology, ``thrust < 0.99`` * For 1x1 topology, ``1.5 < visibleEnergyOfEventCMS`` """ __authors__ = ["Ami Rostomyan", "Kenji Inami"] __description__ = "Skim for Tau decays using thrust." __contact__ = __liaison__ __category__ = "physics, tau" ApplyHLTHadronCut = False produce_on_tau_samples = False # retention is too high on taupair validation_sample = _VALIDATION_SAMPLE
[docs] def load_standard_lists(self, path): stdPi("all", path=path) stdPhotons("all", path=path)
[docs] def additional_setup(self, path): """ Set particle lists and variables for TauThrust skim. **Constructed particle lists**: * ``pi+:thrust, pi0:thust, gamma:pi0_thrust, gamma:nonpi0_thrust, gamma:thrust, pi+:thrustS1/thrustS2`` **Variables**: * ``nGoodTracksThrust``: number of good tracks in an event * ``netChargeThrust``: total net charge of good tracks * ``nTracksS1Thrust/nTracksS2Thrust``: number of good tracks in each hemisphere S1/S2 divided by thrust axis """ tauskim_particle_selection("thrust", path) # Get EventShape variables ma.buildEventShape(['pi+:thrust', 'gamma:thrust'], allMoments=False, foxWolfram=False, cleoCones=False, sphericity=False, jets=False, path=path) ma.buildEventKinematics(['pi+:thrust', 'gamma:thrust'], path=path) # Split in signal and tag ma.cutAndCopyList('pi+:thrustS1', 'pi+:thrust', 'cosToThrustOfEvent > 0', path=path) ma.cutAndCopyList('pi+:thrustS2', 'pi+:thrust', 'cosToThrustOfEvent < 0', path=path) vm.addAlias('nGoodTracksThrust', 'nParticlesInList(pi+:thrust)') vm.addAlias('netChargeThrust', 'formula(countInList(pi+:thrust, charge == 1) - countInList(pi+:thrust, charge == -1))') vm.addAlias('nTracksS1Thrust', 'nParticlesInList(pi+:thrustS1)') vm.addAlias('nTracksS2Thrust', 'nParticlesInList(pi+:thrustS2)')
[docs] def build_lists(self, path): ma.reconstructDecay("tau+:thrust -> pi+:thrustS1", "", path=path) eventParticle = ["tau+:thrust"] # Selection criteria ma.applyCuts("tau+:thrust", "1 < nGoodTracksThrust < 7", path=path) # cut1 ma.applyCuts("tau+:thrust", "netChargeThrust == 0", path=path) # cut2 topologyCuts = "[nTracksS1Thrust == 1 and nTracksS2Thrust == 1]" # 1x1 topologyCuts += " or [nTracksS1Thrust == 1 and nTracksS2Thrust == 3]"\ " or [nTracksS1Thrust == 3 and nTracksS2Thrust == 1]" # 1x3, 3x1 topologyCuts += " or [nTracksS1Thrust == 1 and nTracksS2Thrust == 5]"\ " or [nTracksS1Thrust == 5 and nTracksS2Thrust == 1]" # 1x5, 5x1 topologyCuts += " or [nTracksS1Thrust == 3 and nTracksS2Thrust == 3]" # 3x3 ma.applyCuts("tau+:thrust", topologyCuts, path=path) # cut3 ma.applyCuts("tau+:thrust", "0.8 < thrust", path=path) # cut4 ma.applyCuts("tau+:thrust", "visibleEnergyOfEventCMS < 10.4", path=path) # cut5 # cut for 1x1 topology ma.applyCuts("tau+:thrust", "thrust < 0.99 or nGoodTracksThrust!=2", path=path) ma.applyCuts("tau+:thrust", "1.5 < visibleEnergyOfEventCMS or nGoodTracksThrust!=2", path=path) return eventParticle
[docs] def validation_histograms(self, path): # NOTE: the validation package is not part of the light releases, so this import # must be made here rather than at the top of the file. from validation_tools.metadata import create_validation_histograms path = self.skim_event_cuts(cut='nParticlesInList(tau+:thrust) > 0', path=path) create_validation_histograms( rootfile=f'{self}_Validation.root', particlelist='', variables_1d=[ ('nGoodTracksThrust', 7, 1, 8, '', self.__contact__, '', ''), ('visibleEnergyOfEventCMS', 40, 0, 12, '', self.__contact__, '', ''), ('thrust', 50, 0.8, 1, '', self.__contact__, '', '')], path=path)
############################################################
[docs] @fancy_skim_header class TauKshort(BaseSkim): """ **Channel**: :math:`e^+ e^- \\to \\tau^+ \\tau^-, \\tau \\to K_s \\pi X` **Criteria**: * ``nAlltracks < 7`` * ``0.9 < thrust < 0.995`` * ``2.5 < visibleEnergyOfEventCMS < 10 GeV`` * ``0.2 < track_kshort_pt < 4.5`` * ``max(kshort_track1_pt,kshort_track2_pt) > 0.25`` * ``track_kshort_significanceOfDistance > 3`` """ __authors__ = ["Paolo Leo", "Kenji Inami"] __description__ = "Skim for Tau decays with Kshort." __contact__ = __liaison__ __category__ = "physics, tau" ApplyHLTHadronCut = False produce_on_tau_samples = False # retention is too high on taupair validation_sample = _VALIDATION_SAMPLE
[docs] def load_standard_lists(self, path): stdPi("all", path=path) stdPhotons("all", path=path) # if arg_dataORmc == 'mc': # stdKshorts(prioritiseV0=True, fitter='TreeFit', path=main, updateAllDaughters=True) # if arg_dataORmc == 'data': # stdKshorts(prioritiseV0=True, fitter='TreeFit', path=main, updateAllDaughters=False) stdKshorts(path=path)
[docs] def additional_setup(self, path): """ Set particle lists and variables for TauKshort skim. **Constructed particle lists**: * ``pi+:tauKs, pi0:tauKs, gamma:pi0_tauKs, gamma:nonpi0_tauKs, gamma:tauKs, pi+:tauKsS1/tauKsS2`` **Variables**: """ tauskim_particle_selection("tauKs", path)
[docs] def build_lists(self, path): vm.addAlias('nAllTracksTauKs', 'nParticlesInList(pi+:all)') ma.cutAndCopyLists('K_S0:tauKs_merged', 'K_S0:merged', 'significanceOfDistance > 3', path=path) ma.cutAndCopyLists('pi+:tauKs_kshort', 'pi+:all', 'isDescendantOfList(K_S0:tauKs_merged) == 1', path=path) ma.cutAndCopyLists('pi+:tauKs_notKs', 'pi+:tauKs', 'isDescendantOfList(K_S0:tauKs_merged) == 0', path=path) ma.copyLists('pi+:tauKs_used', ['pi+:tauKs_kshort', 'pi+:tauKs_notKs'], path=path) vm.addAlias('netChargeTauKs', 'formula(countInList(pi+:tauKs_used, charge == 1) - countInList(pi+:tauKs_used, charge == -1))') # Get EventShape variables ma.buildEventShape( ['pi+:tauKs_notKs', 'pi+:tauKs_kshort', 'gamma:tauKs'], allMoments=False, foxWolfram=False, cleoCones=False, sphericity=False, jets=False, path=path) ma.buildEventKinematics( ['pi+:tauKs_notKs', 'pi+:tauKs_kshort', 'gamma:tauKs'], path=path) # reconstruct ma.reconstructDecay('tau+:tauKs_kshort -> K_S0:tauKs_merged pi+:tauKs_notKs', '', path=path) ma.reconstructDecay('tau-:tauKs_1prong -> pi-:tauKs', '', path=path) ma.reconstructDecay('vpho:tauKs -> tau+:tauKs_kshort tau-:tauKs_1prong', '', path=path) # Cut on events requiring opposite hemispheres vm.addAlias('prod1', 'formula(daughter(0, daughter(0, cosToThrustOfEvent))*daughter(1, daughter(0,cosToThrustOfEvent)))') vm.addAlias('prod2', 'formula(daughter(0, daughter(1, cosToThrustOfEvent))*daughter(1, daughter(0,cosToThrustOfEvent)))') ma.applyCuts('vpho:tauKs', 'prod1 < 0 and prod2 < 0', path=path) evP = 'vpho:tauKs' ma.applyCuts(evP, 'nAllTracksTauKs < 7', path=path) # cut0 ma.applyCuts(evP, '0.9 < thrust < 0.995', path=path) # cut1 ma.applyCuts(evP, '2.5 < visibleEnergyOfEventCMS < 10', path=path) # cut2 #### commonVariables = vc.kinematics kshortVariables = ['flightDistance', 'significanceOfDistance', 'daughter1DecayAngle', 'daughter2DecayAngle'] vu.create_aliases_for_selected(list_of_variables=commonVariables + kshortVariables, decay_string='vpho -> [tau+ -> ^K_S0 ^pi+] [tau- -> ^pi-]', prefix=['track_kshort', 'track_pi_kshort', 'track_1prong']) vu.create_aliases_for_selected(list_of_variables=commonVariables, decay_string='vpho -> [tau+ -> [K_S0 -> ^pi+ ^pi-] pi+] tau-', prefix=['kshort_track1', 'kshort_track2']) #### ma.applyCuts(evP, '0.2 < track_kshort_pt < 4.5', path=path) # cut3 ma.applyCuts(evP, 'max(kshort_track1_pt, kshort_track2_pt) > 0.25', path=path) # cut4 ma.applyCuts(evP, 'track_kshort_significanceOfDistance > 3', path=path) # cut5 return [evP]
[docs] def validation_histograms(self, path): # NOTE: the validation package is not part of the light releases, so this import # must be made here rather than at the top of the file. from validation_tools.metadata import create_validation_histograms contact = "kenji@hepl.phys.nagoya-u.ac.jp" evP = 'vpho:tauKs' ma.rankByHighest(particleList=evP, variable='p', numBest=1, path=path) # ma.fillParticleListsFromMC([('K_S0:gen','')],path=path) # vm.addAlias('nKsMC', 'nParticlesInList(K_S0:gen)') create_validation_histograms( rootfile=f'{self}_Validation.root', particlelist=evP, variables_1d=[ # ('nKsMC',5,0,5,'', contact, '', ''), ('nAllTracksTauKs', 7, 1, 8, '', contact, '', ''), ('netChargeTauKs', 7, -3, 4, '', contact, '', ''), ('visibleEnergyOfEventCMS', 40, 0, 12, '', contact, '', ''), ('thrust', 50, 0.75, 1, '', contact, '', '')], path=path)