diff --git a/lbtopktautau/2016_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py b/lbtopktautau/2016_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py new file mode 100644 index 0000000000000000000000000000000000000000..847e245ef96d6dd97e0d8f15b4016ca17a0b14a2 --- /dev/null +++ b/lbtopktautau/2016_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py @@ -0,0 +1,652 @@ + +########################################################## +# AUTOMATICALLY GENERATED FILE IN ganga_options_generic.py +simulation = False +noPID = False +no_restrip = False +stripping_stream = 'Semileptonic' +stripping_line = 'B2XTauTauLeptonic_Lb2pK_Mu_ReversePIDmu_line' +decay = '(( Lambda_b0 -> ^(D0 -> ^mu+ ^mu-) ^(Lambda(1520)0 -> ^p+ ^K-) )) || (( Lambda_b~0 -> ^(D0 -> ^mu- ^mu+) ^(Lambda(1520)~0 -> ^p~- ^K+) )) ' +branches = {'mother': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'jpsi': '(( Lambda_b0 -> ^(D0 -> mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> ^(D0 -> mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'd1': '(( Lambda_b0 -> (D0 -> ^mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> ^mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'd2': '(( Lambda_b0 -> (D0 -> mu+ ^mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- ^mu+) (Lambda(1520)~0 -> p~- K+) ))', 'inter': '(( Lambda_b0 -> (D0 -> mu+ mu-) ^(Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) ^(Lambda(1520)~0 -> p~- K+) ))', 'h1': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> ^p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> ^p~- K+) ))', 'h2': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> p+ ^K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> p~- ^K+) ))'} +year = '2016' +mcdecay = 'N/A' +# END AUTOMATICALLY GENERATED FILE IN ganga_options_generic.py +# From here on, the file dv_options_generic.py will be used +# (Stripping will be added first for the lb2pkemu line) +########################################################### + +try: + simulation = simulation + noPID = noPID + no_restrip = no_restrip + stripping_stream = stripping_stream + stripping_line = stripping_line + decay = decay + branches = branches + year = year + mcdecay = mcdecay + +except NameError as error: + raise RuntimeError("""{error} - most likely due to incorrect usage; don't run this file directly. + The variables 'simulation', 'noPID', 'stripping_line', 'decay', 'branches', 'year', 'mcdecay' have to + be specified first. Correct usage is to run 'ganga_options_generic.py'""") + +# don't use f-strings as not supported pre python 3.6! +print("Simulation = {0}".format(simulation)) +print("noPID = {0}".format(noPID)) +print("no_restrip = {0}".format(no_restrip)) +print("year = {0}".format(year)) +print("mcdecay descriptor = {0}".format(mcdecay)) +print("stripping stream = {0}".format(stripping_stream)) +print("stripping line = {0}".format(stripping_line)) +print("decay = {0}".format(decay)) +print("branches = {0}".format(branches)) + + +from Gaudi.Configuration import * +from LHCbKernel.Configuration import * +from DaVinci.Configuration import * +from DecayTreeTuple.Configuration import * + +from Configurables import DaVinci, DecayTreeTuple, MCDecayTreeTuple +from Configurables import TupleToolTISTOS +from Configurables import EventNodeKiller, ProcStatusCheck +from Configurables import LoKi__HDRFilter + +from StrippingConf.Configuration import StrippingConf, StrippingStream +from StrippingSettings.Utils import strippingConfiguration +from StrippingArchive.Utils import buildStreams +from StrippingArchive import strippingArchive + +############################################## + +print("\n## Determined stripping line to be: \n ===>", stripping_line) + +print("\n## config determined") +print("\n===> stream = ", stripping_stream) +print("\n===> line = ", stripping_line) +print("\n===> decay = ", decay) +print("\n===> branches = ", branches) +################################# +# ## Stream and stripping line ### +stream = stripping_stream +line = stripping_line + +########################### +# ## Restripping process ### + +# In the case that we are dealing with simulation, we may need to restrip due to the fact +# that the stripping version for the simulation is different (older) than that of the +# stripping line + +# In the case that we remove the PID requirements, this changes the restripping process +# since we edit the config file to remove these requirements + +if simulation == True: + if no_restrip == False: + event_node_killer = EventNodeKiller('StripKiller') + event_node_killer.Nodes = ['/Event/AllStreams', '/Event/Strip'] + #################### + if noPID == False: # conventional restrip + if year == '2016': + strip = 'stripping28r2p2' + elif year == '2017': + strip = 'stripping29r2p3' + elif year == '2018': + strip = 'stripping34r0p3' + + streams = buildStreams(stripping=strippingConfiguration(strip), + archive=strippingArchive(strip)) + + custom_stream = StrippingStream('AllStreams') + custom_line = 'Stripping'+line + + for stream in streams: + for sline in stream.lines: + if sline.name() == custom_line: + custom_stream.appendLines([sline]) + ##################### + else: # remove PID requirements and restrip + # in this case we need to edit the config to remove PID requirements + # different stripping versions for different years + if year == '2016': + from StrippingArchive.Stripping28r2p2.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder + from StrippingArchive.Stripping28r2p2.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config + elif year == '2017': + from StrippingArchive.Stripping29r2p3.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder + from StrippingArchive.Stripping29r2p3.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config + elif year == '2018': + from StrippingArchive.Stripping34r0p3.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder + from StrippingArchive.Stripping34r0p3.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config + + # print the unedited config file + print("OLD CONFIG below") + print(config['CONFIG']) + print("OLD CONFIG above") + + # edit the config + config1 = config['CONFIG'] + config1['MuonPID'] = -1001 + config1['ElectronPID'] = -1001 + config1['UseNoPIDsHadrons'] = True + + # then print the edited config file + print("NEW CONFIG below") + print(config1) + print("NEW CONFIG above") + + lb = builder('B2XTauTauLeptonic', config1) + custom_stream = StrippingStream('MyStream') + # Now we have the stream and the line and can add the lines to the stream + target_line = 'Stripping' + line + for sline in lb.lines(): + if sline.name() == target_line: + custom_stream.appendLines([sline]) + ####################### + filterBadEvents = ProcStatusCheck() + sc = StrippingConf(Streams=[custom_stream], + MaxCandidates=10000, + AcceptBadEvents=False, + BadEventSelection=filterBadEvents) + + ### Fill tuple with DecayTreeTuple ### + dtt = DecayTreeTuple('DecayTreeTuple') + dtt.Inputs = ['/Event/Phys/{0}/Particles'.format(line)] + else: # no restrip + ### Fill tuple with DecayTreeTuple ### + dtt = DecayTreeTuple('DecayTreeTuple') + dtt.Inputs = ['/Event/{0}/Phys/{1}/Particles'.format(stream,line)] + +else: # data rather than simulation + ### Fill tuple with DecayTreeTuple ### + dtt = DecayTreeTuple('DecayTreeTuple') + dtt.Inputs = ['/Event/{0}/Phys/{1}/Particles'.format(stream,line)] +######################################## +# ## Define decay and create branches ### +dtt.Decay = decay +dtt.addBranches(branches) + +###################### +# ## Add tupletools ### +# # Generic tupletools ## +dtt.ToolList = [] #reset toollist to add verbose to geometry/kinematic + +SubMassTool = dtt.addTupleTool('TupleToolSubMass') + +# +# will create Sum_{p=2,max) C(N,p) new entries in the nTuple called [head]_M[ij...] +# Particle daughters are sorted by PID at each branch of the tree (cc-independant) +# +#**** Substitution property +# +# usage : TupleTool.Substitution += ["pi+ => K+"] TupleTool.Substitution += ["K+ => pi+"] +# produce alternative mass with substituted PID pi<->K (cc is assumed) +# +#-change only one pion (K) at once in case of several pion (K) in the decay tree (producing separate output par pion (K) ) +# +#**** DoubleSubstitution property +# +# usage : TupleTool.DoubleSubstitution += ["K+/pi- => pi+/K-"] TupleTool.DoubleSubstitution += ["K+/K-" => pi+/pi-"] +# change all [K+pi-]cc ([K+K-]cc) pairs to (pi+K-)cc ([pi+pi-]cc) +# change only one pair at once in case of several pairs in the decay tree (producing separate output per pair) +# +# "/" separator is not mandatory : K+pi- syntax is allowed (just a bit slower to parse) + + +GeometryTool = dtt.addTupleTool('TupleToolGeometry') #Fill geometry related information for DecayTreeTuple +GeometryTool.Verbose=True +# head_MINIP : minimum impact parameter on any PV +# head_MINIPCHI2 : minimum chi2 IP on all PVs +# head_ENDVERTEX_[X|Y|Z] : decay vertex position for composite particles +# head_ENDVERTEX_[X|Y|Z]ERR : decay vertex position error estimate for composite particles +# head_ENDVERTEX_CHI2 : decay vertex chi2 +# head_ENDVERTEX_NDOF : decay vertex nDoF +# head_OWNPV_[X|Y|Z] : related primary vertex position +# head_OWNPV_[X|Y|Z]ERR : related primary vertex position error estimate for composite particles +# head_OWNPV_CHI2 : related primary vertex chi2 +# head_OWNPV_NDOF : related primary vertex nDoF +# head_IP_OWNPV : impact parameter with respect to the PhysDesktop::relatedVertex() considered particle +# head_IPCHI2_OWNPV : impact parameter chi2 with respect to the relatedVertex() considered particle +# head_FD_OWNPV : flight distance of composite particle wrt. the relatedVertex() considered particle +# head_FDCHI2_OWNPV : flight distance significance in units of chi2 wrt. the relatedVertex() considered particle +# head_DIRA_OWNPV : direction angle wrt. the PhysDesktop::relatedVertex() considered particle + +# Verbose being true gives: +# head_TOPPV_[X|Y|Z] : PhysDesktop::relatedVertex() of the top of decay chain position +# head_TOPPV_[X|Y|Z]ERR : PhysDesktop::relatedVertex() of the top of decay chain position error estimate +# head_TOPPV_CHI2 : PhysDesktop::relatedVertex() of the top of decay chain chi2 +# head_TOPPV_NDOF : PhysDesktop::relatedVertex() of the top of decay chain nDoF +# head_IP_TOPPV : impact parameter with respect to the PhysDesktop::relatedVertex() of the top of decay chain +# head_IPCHI2_TOPPV : impact parameter chi2 with respect to the relatedVertex() of the top of decay chain +# head_FD_TOPPV : flight distance of composite particle wrt. the relatedVertex() of the top of decay chain +# head_FDCHI2_TOPPV : flight distance significance in units of chi2 wrt. the PhysDesktop::relatedVertex() of the top of decay chain +# head_DIRA_TOPPV : direction angle wrt. the relatedVertex() of the top of decay chain +# head_ORIVX_[X|Y|Z] : ancestor's related primary vertex position (when applicable) +# head_ORIVX_[X|Y|Z]ERR : ancestor's related primary vertex position error estimate (when applicable) +# head_ORIVX_CHI2 : ancestor's related primary vertex chi2 (when applicable) +# head_ORIVX_NDOF : ancestor's related primary vertex nDoF (when applicable) +# head_IP_ORIVX : impact parameter with respect to the ancestor's vertex (when applicable) +# head_IPCHI2_ORIVX : impact parameter chi2 with respect to the ancestor's vertex (when applicable) +# head_FD_ORIVX : flight distance of composite particle wrt. the ancestor's vertex (when applicable) +# head_FDCHI2_ORIVX : flight distance significance in units of chi2 wrt. ancestor's vertex (when applicable) +# head_DIRA_ORIVX : direction angle wrt. ancestor's vertex (when applicable) + +KinematicTool = dtt.addTupleTool('TupleToolKinematic') #Fill kinematic information for DecayTreeTuple +KinematicTool.Verbose=True +# head_P : momentum's amplitude +# head_PT : transverse momentum +# head_P[E|X|Y|Z] : four vector momentum +# head_MM : measured mass (or assigned mass in case of 'basic' particle +# head_M : mass calculated from momentum four-vector +# head_MMERR : error on the measured mass (only for non-basic parts) + +# Verbose being true gives: +# head_REFP[X|Y|Z]: one point the particle momentum extrapolation goes through +# head_PreFitMass: Mass of 4-vectors of daughters, not yet extrapolated to the head decay vertex (only for composites). +# This is the quantity used in ADAMASS or AM in CombineParticles.CombinationCut +# prefix_AtVtx_P[X|Y|Z]: momentum information of basic particles at origin vertex position + +TrackInfoTool = dtt.addTupleTool('TupleToolTrackInfo') #Fill track information for DecayTreeTuple +TrackInfoTool.Verbose=True +# X_TRACK_CHI2NDOF : track chi2/ndof +# X_TRACK_TYPE : track type +# X_TRACK_PCHI2 : track Chi2 probability +# X_TRACK_GhostProb : Ghost probability (run NeuralNetTmva to fill it) +# X_TRACK_CloneDist : Only available for 2009 data + +# Verbose being true gives: +# X_TRACK_CHI2 : track chi2 +# X_TRACK_NDOF : track ndof +# X_TRACK_VeloCHI2NDOF : Track fit velo chi2/nDoF +# X_TRACK_TCHI2NDOF : Track fit T chi2/nDoF +# X_TRACK_VELO_UTID : hopefully unique double constructed from multiplying all Velo hit IDs +# X_TRACK_TT_UTID : hopefully unique double constructed from multiplying all TT hit IDs +# X_TRACK_IT_UTID : hopefully unique double constructed from multiplying all IT hit IDs +# X_TRACK_OT_UTID : hopefully unique double constructed from multiplying all OT hit IDs +# X_TRACK_VP_UTID : hopefully unique double constructed from multiplying all VP hit IDs +# X_TRACK_UT_UTID : hopefully unique double constructed from multiplying all UT hit IDs +# X_TRACK_FT_UTID : hopefully unique double constructed from multiplying all FT hit IDs +# X_TRACK_nVeloHits : Number of Velo hits on the track +# X_TRACK_nVeloRHits : Number of Velo R hits on the track +# X_TRACK_nVeloPhiHits : Number of Velo phi hits on the track +# X_TRACK_nVeloPileUpHits : Number of Velo pile-up hits on the track +# X_TRACK_nTTHits : Number of TT hits on the track +# X_TRACK_nITHits : Number of IT hits on the track +# X_TRACK_nOTHits : Number of OT hits on the track +# X_TRACK_nVPHits : Number of VP hits on the track +# X_TRACK_nUTHits : Number of UT hits on the track +# X_TRACK_nFTHits : Number of FT hits on the track +# X_TRACK_FirstMeasurementX: x position of state at 'FirstMeasurement' +# X_TRACK_FirstMeasurementY: y position of state at 'FirstMeasurement' +# X_TRACK_FirstMeasurementZ: z position of state at 'FirstMeasurement' +# X_TRACK_History: Algorithm which the track was made with +# X_TRACK_qOverp : q/p of state at 'FirstMeasurement' +# X_TRACK_Tx : x slope of state at 'FirstMeasurement' +# X_TRACK_Ty : y slope of state at 'FirstMeasurement' + +EventInfoTool = dtt.addTupleTool('TupleToolEventInfo') #Event and Run number for DecayTreeTuple +EventInfoTool.Verbose=True +# runNumber: well, the run number +# eventNumber: +# BCID and BC type +# Odin and Hlt TCKs +# GPS time +# If the property Mu is given it will fill the Mu of the run. A working dictionary can be +# found at https://twiki.cern.ch/twiki/bin/view/LHCb/NuMuPileUp + +# if Verbose is on, also gps time in year,month,day,hour,min,second Note that months are +# numbered [0-11]. That's a convention. Sorry. + +PropertimeTool = dtt.addTupleTool('TupleToolPropertime') #Fills the propertime for DecayTreeTuple +# PropertimeTool.Verbose=True +# head_TAU +# head_TAUERR +# head_TAUCHI2 + +RecoStatsTool = dtt.addTupleTool('TupleToolRecoStats') #Fills Reco stats, from RecSummary. +# RecoStatsTool.Verbose=True + +PidTool = dtt.addTupleTool('TupleToolPid') #DLL and PID information to be stored in a Tuple +# PidTool.Verbose=True +# head_ID : particleID().pid(); +# For the long lived particles (isBasicParticle()). +# head_PIDe : LHCb::ProtoParticle::CombDLLe +# head_PIDmu : LHCb::ProtoParticle::CombDLLmu +# head_PIDK : LHCb::ProtoParticle::CombDLLk +# head_PIDp : LHCb::ProtoParticle::CombDLLp + +ANNPIDTool = dtt.addTupleTool('TupleToolANNPID') #ProbNN values for "Electron", "Muon", "Pion", "Kaon", "Proton", "Ghost" +# ANNPIDTool.Verbose=True + +AnglesTool = dtt.addTupleTool('TupleToolAngles') #Fill MC Particle with decay angle in mother frame +# AnglesTool.Verbose=True +# head_CosTheta : angle in mother's frame +# if WRTMother is false, will calculate angle in frame of top of tree + +PrimariesTool = dtt.addTupleTool('TupleToolPrimaries') #Primary vertices properties for DecayTreeTuple +# PrimariesTool.Verbose=True +# coordinates PVX, PVY, PVZ +# errors PVXERR, PVYERR, PVZERR +# vertex chi2 PVCHI +# vertex ndf PVNDOF +# Nb of tracks used to do the vertex PVNTRACKS + +## Isolation variables ## + +# cone isolation # +ConeIsoTool = dtt.addTupleTool('TupleToolConeIsolation') +# choose cones to have a deltaR of 0.5, 0.7, 0.9 radians +ConeIsoTool.MinConeSize = 0.6 +ConeIsoTool.MaxConeSize = 0.6 +# ConeIsoTool.SizeStep = 0.2 +# Fill asymmetry, delta, and component variables +# ConeIsoTool.FillAsymmetry = True +# ConeIsoTool.FillDeltas = True +# ConeIsoTool.FillComponents = True + + +# head_cc: charged cone +# head_nc: neutral cone + +# head_XX_mult : number of objects inside the cone +# head_XX_sPT : scalar-summed pT of the objects inside the cone +# head_XX_vPT : vector-summed pT of the objects inside the cone +# head_XX_P : x, y and z components of the cone momentum +# head_XX_asy_P : momentum asymmetry between the head and the cone defined as (head_P - head_XX_P) / (head_P + head_XX_P) +# head_XX_asy_P : x, y, z and transverse components of the momentum asymmetry +# head_XX_deltaEta : difference in eta between the head and the cone +# head_XX_deltaPhi : difference in phi between the head and the cone +# head_XX_IT : transverse isolation of the head in the cone, defined as head_PT / (head_P + head_XX_P)_T +# head_IT : transverse isolation of the head in the charged and neutral cones, defined as head_PT / (head_P + head_cc_P + head_nc_P)_T +# head_cc_maxPt_Q : charge of the max-pT object in the charged cone +# head_XX_maxPt_P : x, y, z (and e) components of the max-pT object momentum in the cone +# head_MasshPi0: invariant mass of the seed-Pi0 combinations +# head_Pi0_DeltaR: DeltaR between the seed and the pi0 directions +# head_Pi0_E, head_Pi0_PX, head_Pi0_PY, head_Pi0_PZ: four momentum of the pi0 +# head_Pi0_M: invariant mass of the pi0 +# head_Pi0Ph1_CL, head_Pi0Ph2_CL: confidence levels of the (photon) pi0 daughters + +# track isolation # +TrackIsoTool = dtt.addTupleTool('TupleToolTrackIsolation') +# choose cones to have a deltaR of 0.5, 0.7, 0.9 radians +TrackIsoTool.MinConeAngle = 0.6 +TrackIsoTool.MaxConeAngle = 0.6 +# TrackIsoTool.StepSize = 0.2 +# fill asymmetry and DeltaAngles variables +TrackIsoTool.FillAsymmetry = True +# TrackIsoTool.FillDeltaAngles = True + +# Open up a cone around head, exclude all tracks that are in the decay descriptor +# (i.e. that belong to the decay you are looking for), build the variables with +# the remaining tracks. + +# head_cmult : Number of tracks inside cone. +# head_cp : Summed p inside cone +# head_cpt : Summed pt inside cone +# head_cpx : Summed px inside cone +# head_cpy : Summed py inside cone +# head_cpz : Summed pz inside cone + +# If Verbose, or other flags are set: + +# Asymmetry variables + +# head_pasy : (head_P - head_cp)/(head_P + head_cp) +# head_ptasy : (head_PT - head_cpt)/(head_PT + head_cpt) +# head_pxasy : (head_Px - head_cpx)/(head_Px + head_cpx) +# head_pyasy : (head_Py - head_cpy)/(head_Py + head_cpy) +# head_pzasy : (head_Pz - head_cpz)/(head_Pz + head_cpz) Delta angle variables +# head_DeltaEta : Difference in eta between summed tracks and head +# head_DeltaPhi : Difference in phi between summed tracks and head + + +# MinConeAngle: Set the minimal deltaR of the cone (default = 0.5), in radians +# MaxConeAngle: Set the maximum deltaR of the cone (default = 1.0), in radians +# StepSize: Set the step of deltaR between two iterations (default = 0.1), in radians +# TrackType: Set the type of tracks which are considered inside the cone (default = 3) +# FillAsymmetry: Flag to fill the asymmetry variables (default = false) +# FillDeltaAngles: Flag to fill the delta angle variables (default = false) + +# vertex isolation # +VtxIsoTool = dtt.addTupleTool('TupleToolVtxIsoln') + +# head_NOPARTWITHINDCHI2WDW : no. of non-signal particles that when added to vertex give delta chi2 < specified window +# head_NOPARTWITHINCHI2WDW : no. of non-signal particles that when added to vertex give chi2 < specified window +# head_SMALLESTCHI2: chi2 of smallest chi2 combination with any of the input Particles +# head_SMALLESTDELTACHI2: delta chi2 of smallest delta chi2 combination with any of the input Particles +#### updates: +# (head)_NumVtxWithinChi2WindowOneTrack: number of particles that generate a vertex within a chi2 window +# (head)_SmallestDeltaChi2OneTrack: smallest delta chi2 when adding one track +# (head)_SmallestDeltaChi2MassOneTrack: mass of the candidate with the smallest delta chi2 +# (head)_SmallestDeltaChi2TwoTracks: smallest delta chi2 when adding one track to the combination +# that has the smallest delta chi2 when adding one track +# (head)_SmallestDeltaChi2MassTwoTracks: mass of the candidate with the smallest delta chi2 when adding +# one track to the combination that has the smallest delta chi2 when adding one track + +## Hybrid tupletool ## +all_hybrid = dtt.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_All') +all_hybrid.Variables = { + 'ETA' : "ETA", #pseudorapidity + 'PHI' : "PHI", #asimuthal angle + 'MINIPCHI2' : "MIPCHI2DV(PRIMARY)", + #The special version of LoKi::Particles::MinImpParChi2 functor which gets all the primary + #vertices from desktop. + 'MINIP' : "MIPDV(PRIMARY)", + #The special version of LoKi::Particles::MinImpPar functor which gets all the primary + #vertices from desktop. + 'IPCHI2_OWNPV' : "BPVIPCHI2()", + #The special "context-dependent" version of LoKi::Particles::ImpParChi2 functor which gets + #the related primary vertex from IPhysDesktop tool + 'IP_OWNPV' : "BPVIP()", + #The special "context-dependent" version of LoKi::Particles::ImpPar functor which gets the + #related primary vertex from IPhysDesktop tool. + 'DIRA_OWNPV' : "BPVDIRA", + 'ghost' : "TRGHP", #simple evaluator of "ghost probability" + 'TrackCHI2DOF' : 'TRCHI2DOF', + 'FD_CHI2' : "BPVVDCHI2", + #BPV = Adaptor to "best-primary-vertex", VDCHI2 = Evaluator of the chi2 of GEOMETRY distance + #between the particle "endVertex" and "the vertex". + 'VCHI2DOF' : 'VFASPF(VCHI2/VDOF)', + # #Decay tree fitter functions: + # 'DTF_CHI2NDOF' : "DTF_CHI2NDOF( True )", + # #Simple evaluator of $\chi^2$ per degree of freedom for the decay tree fit. + # 'DTF_VCHI2NDOF' : "DTF_FUN ( VFASPF(VCHI2/VDOF) , True )", + # #VCHI2 = evaluator of the Chi2 of the vertex / VDOF = evaluator of the number of degrees + # #of freedom for the vertex + # 'DTF_MASS_JpsiConstr' : "DTF_FUN ( M , True , 'J/psi(1S)' )" , + # 'DTF_MASS' : "DTF_FUN ( M , True )" , + # 'DTF_CTAU"' : "DTF_CTAU( 0, True )", + # #Evaluate $c\tau$ for the dauthter particle in the decay tree. + # 'DTF_CTAUS' : "DTF_CTAUSIGNIFICANCE( 0, True )" + # #Evaluate $ \frac{c\tau}{\sigma \left( c\tau\right) } $ for the dauthter particle + # #in the decay tree. +} + +lb_hybrid = dtt.mother.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_Lb') +lb_hybrid.Variables = { + 'DOCAjpsiinter' : "DOCA(1,2)", + 'DOCAmotherjpsi' : "DOCA(0,1)", + 'DOCAmotherinter' : "DOCA(0,2)", + 'DOCAjpsiinterCHI2' : "DOCACHI2(1,2)", + 'DOCAmotherjpsiCHI2' : "DOCACHI2(0,1)", + 'DOCAmotherinterCHI2' : "DOCACHI2(0,2)" +} +jpsi_hybrid = dtt.jpsi.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_jpsi') +jpsi_hybrid.Variables = { + 'DOCAd1d2' : "DOCA(1,2)", + 'DOCAjpsid1' : "DOCA(0,1)", + 'DOCAjpsid2' : "DOCA(0,2)", + 'DOCAd1d2CHI2' : "DOCACHI2(1,2)", + 'DOCAjpsid1CHI2' : "DOCACHI2(0,1)", + 'DOCAjpsid2CHI2' : "DOCACHI2(0,2)" +} +inter_hybrid = dtt.inter.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_inter') +inter_hybrid.Variables = { + #note that the end vertex of the intermediate hadron is also the end vertex of the lb + 'DOCAh1h2' : "DOCA(1,2)", + 'DOCAmotherh1' : "DOCA(0,1)", + 'DOCAmotherh2' : "DOCA(0,2)", + 'DOCAh1h2CHI2' : "DOCACHI2(1,2)", + 'DOCAmotherh1CHI2' : "DOCACHI2(0,1)", + 'DOCAmotherh2CHI2' : "DOCACHI2(0,2)" +} + +################ +### Triggers ### +# Add trigger list # + +L0Triggers = ['L0MuonDecision','L0DiMuonDecision','L0HadronDecision'] +Hlt1Triggers = [# muon lines + 'Hlt1TrackMuonDecision','Hlt1SingleMuonNoIPDecision','Hlt1SingleMuonHighPTDecision', + # dimuon lines + 'Hlt1DiMuonHighMassDecision','Hlt1DiMuonLowMassDecision', + # MVA lines + 'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision','Hlt1TrackMuonMVADecision', + 'Hlt1TwoTrackMVALooseDecision','Hlt1TwoTrackMVADecision' + ] +Hlt2Triggers = [# topo lines + 'Hlt2Topo2BodyDecision','Hlt2Topo3BodyDecision','Hlt2Topo4BodyDecision', + 'Hlt2TopoMu2BodyDecision','Hlt2TopoMu3BodyDecision','Hlt2TopoMu4BodyDecision', + 'Hlt2TopoMuMu2BodyDecision','Hlt2TopoMuMu3BodyDecision','Hlt2TopoMuMu4BodyDecision', + # muon lines + 'Hlt2SingleMuonDecision','Hlt2SingleMuonHighPTDecision','Hlt2SingleMuonLowPTDecision', + 'Hlt2SingleMuonRareDecision','Hlt2SingleMuonVHighPTDecision', + # dimuon lines + 'Hlt2DiMuonDecision','Hlt2DiMuonJPsiDecision','Hlt2DiMuonDetachedDecision', + 'Hlt2DiMuonDetachedHeavyDecision','Hlt2DiMuonDetachedJPsiDecision', + 'Hlt2DiMuonDetachedPsi2SDecision','Hlt2DiMuonSoftDecision' + ] +# Electrons in Sel +if '_E_' in stripping_line or '_MuE_' in stripping_line or '_EPi_' in stripping_line: + L0Triggers += ["L0ElectronDecision","L0ElectronHiDecision","L0PhotonDecision","L0PhotonHiDecision"] + Hlt1Triggers += ["Hlt1SingleElectronNoIPDecision"] + Hlt2Triggers += ["Hlt2TopoE2BodyDecision","Hlt2TopoE3BodyDecision","Hlt2TopoE4BodyDecision", + "Hlt2TopoEE2BodyDecision","Hlt2TopoEE3BodyDecision","Hlt2TopoEE4BodyDecision", + "Hlt2TopoMuE2BodyDecision","Hlt2TopoMuE3BodyDecision","Hlt2TopoMuE4BodyDecision" + ] + +AllTriggers = L0Triggers + Hlt1Triggers + Hlt2Triggers + +MuonTriggers = [# L0 + 'L0MuonDecision', + # Hlt1 + 'Hlt1TrackMuonDecision','Hlt1SingleMuonNoIPDecision','Hlt1SingleMuonHighPTDecision', + 'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision','Hlt1TrackMuonMVADecision', + # Hlt2 + 'Hlt2SingleMuonDecision','Hlt2SingleMuonHighPTDecision', + 'Hlt2SingleMuonLowPTDecision','Hlt2SingleMuonRareDecision','Hlt2SingleMuonVHighPTDecision' + ] +HadronTriggers = [# L0 + 'L0HadronDecision', + # Hlt1 + 'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision' + ] +ElectronTriggers = [# L0 + "L0ElectronDecision","L0ElectronHiDecision","L0PhotonDecision","L0PhotonHiDecision", + # Hlt1 + "Hlt1SingleElectronNoIPDecision","Hlt1TrackMVADecision"] + +# TupleToolTISTOS # +# It saves the trigger TIS/TOS decisions for each particle for each Hlt Selection +dtt.mother.ToolList += [ "TupleToolTISTOS" ] +dtt.mother.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" ) +dtt.mother.TupleToolTISTOS.Verbose = True +dtt.mother.TupleToolTISTOS.TriggerList = AllTriggers +dtt.d2.ToolList += [ "TupleToolTISTOS" ] +dtt.d2.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" ) +dtt.d2.TupleToolTISTOS.Verbose = True +dtt.d2.TupleToolTISTOS.TriggerList = HadronTriggers +dtt.d1.ToolList += [ "TupleToolTISTOS" ] +dtt.d1.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" ) +dtt.d1.TupleToolTISTOS.Verbose = True +dtt.d1.TupleToolTISTOS.TriggerList = HadronTriggers +dtt.h1.ToolList += [ "TupleToolTISTOS" ] +dtt.h1.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" ) +dtt.h1.TupleToolTISTOS.Verbose = True +if '_Mu_' in stripping_line or '_MuE_' in stripping_line or '_MuPi_' in stripping_line: + dtt.h1.TupleToolTISTOS.TriggerList = MuonTriggers +elif '_EPi_' in stripping_line: + dtt.h1.TupleToolTISTOS.TriggerList = ElectronTriggers +elif '_PiPi_' in stripping_line: + dtt.h1.TupleToolTISTOS.TriggerList = HadronTriggers +# else: # TODO remove +# print('LOCAL: ERROR WITH h1 TRIGGER ASSIGNMENT') + +dtt.h2.ToolList += [ "TupleToolTISTOS" ] +dtt.h2.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" ) +dtt.h2.TupleToolTISTOS.Verbose = True +if '_E_' in stripping_line or '_MuE_' in stripping_line: + dtt.h2.TupleToolTISTOS.TriggerList = ElectronTriggers +elif '_EPi_' in stripping_line or '_PiPi_' in stripping_line: + dtt.h2.TupleToolTISTOS.TriggerList = HadronTriggers + +## MC truth value tupletools ## +if simulation == True: + MCTruthTool = dtt.addTupleTool('TupleToolMCTruth') #Fill MC truth info if a link is present + # head_TRUEID : true pid + MCTruthTool.ToolList = [ + "MCTupleToolKinematic", + # head_TRUEP[E|X|Y|Z] : true four vector momentum + # head_TRUEPT : true transverse momentum, PT + # head_TRUEORIGINVERTEX_[X|Y|Z] : position of the true origin vertex. + # head_TRUEENDVERTEX_[X|Y|Z] : position of the true end vertex (the first one) + # head_TRUEISSTABLE : MCAssociate has no daughters. + # head_TRUETAU : true propertime + "MCTupleToolHierarchy", + # head_MC_MOTHER_ID : true mc mother ID + # head_MC_MOTHER_KEY : true mc mother key + # head_MC_GD_MOTHER_ID : grand mother ID + # head_MC_GD_MOTHER_KEY : grand mother key + # head_MC_GD_GD_MOTHER_ID : grand grand mother ID + # head_MC_GD_GD_MOTHER_KEY : grand grand mother key + ] + + ## Hybrid tupletool ## + hybrid_mc_dtt = dtt.addTupleTool('LoKi::Hybrid::MCTupleTool/LoKi_All_MC') + hybrid_mc_dtt.Variables = { + 'MCETA' : "MCETA", #pseudorapidity + 'MCPHI' : "MCPHI", #asimuthal angle + } + + MCBackgroundInfoTool = dtt.addTupleTool('TupleToolMCBackgroundInfo') #Fill the info from IBackgroundCategory. + # head_BKGCAT : category + + # add mcdecaytreetuple + + def Make_MCTuple(decay): + MCTuple = MCDecayTreeTuple("MCDecayTreeTuple") + + MCTuple.Decay = decay + MCTuple.setDescriptorTemplate( decay ) + MCTuple.ToolList = [ + "MCTupleToolKinematic" + , "MCTupleToolHierarchy" + , "MCTupleToolAngles" + , "MCTupleToolPID" + , "TupleToolEventInfo" + , "TupleToolRecoStats" + ] + ## Hybrid tupletool ## + hybrid_mc_mcdtt = MCTuple.addTupleTool('LoKi::Hybrid::MCTupleTool/LoKi_All_MC') + hybrid_mc_mcdtt.Variables = { + 'MCETA' : "MCETA", #pseudorapidity + 'MCPHI' : "MCPHI", #asimuthal angle + } + return MCTuple + + + MCTuple = Make_MCTuple(mcdecay) + +######################### +# ## Configure DaVinci ### +from Configurables import GaudiSequencer +MySequencer = GaudiSequencer('Sequence') +if simulation == True: + MySequencer.Members = [event_node_killer, sc.sequence(), dtt, MCTuple] + # MySequencer.Members = [event_node_killer, sc.sequence(),dtt] +else: + MySequencer.Members = [dtt] + +DaVinci().UserAlgorithms += [MySequencer] +DaVinci().EvtMax = -1 +DaVinci().PrintFreq = 1000 diff --git a/lbtopktautau/2017_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py b/lbtopktautau/2017_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py new file mode 100644 index 0000000000000000000000000000000000000000..5cc09245ec15ed5cd864399a75181b07820090fa --- /dev/null +++ b/lbtopktautau/2017_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py @@ -0,0 +1,652 @@ + +########################################################## +# AUTOMATICALLY GENERATED FILE IN ganga_options_generic.py +simulation = False +noPID = False +no_restrip = False +stripping_stream = 'Semileptonic' +stripping_line = 'B2XTauTauLeptonic_Lb2pK_Mu_ReversePIDmu_line' +decay = '(( Lambda_b0 -> ^(D0 -> ^mu+ ^mu-) ^(Lambda(1520)0 -> ^p+ ^K-) )) || (( Lambda_b~0 -> ^(D0 -> ^mu- ^mu+) ^(Lambda(1520)~0 -> ^p~- ^K+) )) ' +branches = {'mother': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'jpsi': '(( Lambda_b0 -> ^(D0 -> mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> ^(D0 -> mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'd1': '(( Lambda_b0 -> (D0 -> ^mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> ^mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'd2': '(( Lambda_b0 -> (D0 -> mu+ ^mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- ^mu+) (Lambda(1520)~0 -> p~- K+) ))', 'inter': '(( Lambda_b0 -> (D0 -> mu+ mu-) ^(Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) ^(Lambda(1520)~0 -> p~- K+) ))', 'h1': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> ^p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> ^p~- K+) ))', 'h2': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> p+ ^K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> p~- ^K+) ))'} +year = '2017' +mcdecay = 'N/A' +# END AUTOMATICALLY GENERATED FILE IN ganga_options_generic.py +# From here on, the file dv_options_generic.py will be used +# (Stripping will be added first for the lb2pkemu line) +########################################################### + +try: + simulation = simulation + noPID = noPID + no_restrip = no_restrip + stripping_stream = stripping_stream + stripping_line = stripping_line + decay = decay + branches = branches + year = year + mcdecay = mcdecay + +except NameError as error: + raise RuntimeError("""{error} - most likely due to incorrect usage; don't run this file directly. + The variables 'simulation', 'noPID', 'stripping_line', 'decay', 'branches', 'year', 'mcdecay' have to + be specified first. Correct usage is to run 'ganga_options_generic.py'""") + +# don't use f-strings as not supported pre python 3.6! +print("Simulation = {0}".format(simulation)) +print("noPID = {0}".format(noPID)) +print("no_restrip = {0}".format(no_restrip)) +print("year = {0}".format(year)) +print("mcdecay descriptor = {0}".format(mcdecay)) +print("stripping stream = {0}".format(stripping_stream)) +print("stripping line = {0}".format(stripping_line)) +print("decay = {0}".format(decay)) +print("branches = {0}".format(branches)) + + +from Gaudi.Configuration import * +from LHCbKernel.Configuration import * +from DaVinci.Configuration import * +from DecayTreeTuple.Configuration import * + +from Configurables import DaVinci, DecayTreeTuple, MCDecayTreeTuple +from Configurables import TupleToolTISTOS +from Configurables import EventNodeKiller, ProcStatusCheck +from Configurables import LoKi__HDRFilter + +from StrippingConf.Configuration import StrippingConf, StrippingStream +from StrippingSettings.Utils import strippingConfiguration +from StrippingArchive.Utils import buildStreams +from StrippingArchive import strippingArchive + +############################################## + +print("\n## Determined stripping line to be: \n ===>", stripping_line) + +print("\n## config determined") +print("\n===> stream = ", stripping_stream) +print("\n===> line = ", stripping_line) +print("\n===> decay = ", decay) +print("\n===> branches = ", branches) +################################# +# ## Stream and stripping line ### +stream = stripping_stream +line = stripping_line + +########################### +# ## Restripping process ### + +# In the case that we are dealing with simulation, we may need to restrip due to the fact +# that the stripping version for the simulation is different (older) than that of the +# stripping line + +# In the case that we remove the PID requirements, this changes the restripping process +# since we edit the config file to remove these requirements + +if simulation == True: + if no_restrip == False: + event_node_killer = EventNodeKiller('StripKiller') + event_node_killer.Nodes = ['/Event/AllStreams', '/Event/Strip'] + #################### + if noPID == False: # conventional restrip + if year == '2016': + strip = 'stripping28r2p2' + elif year == '2017': + strip = 'stripping29r2p3' + elif year == '2018': + strip = 'stripping34r0p3' + + streams = buildStreams(stripping=strippingConfiguration(strip), + archive=strippingArchive(strip)) + + custom_stream = StrippingStream('AllStreams') + custom_line = 'Stripping'+line + + for stream in streams: + for sline in stream.lines: + if sline.name() == custom_line: + custom_stream.appendLines([sline]) + ##################### + else: # remove PID requirements and restrip + # in this case we need to edit the config to remove PID requirements + # different stripping versions for different years + if year == '2016': + from StrippingArchive.Stripping28r2p2.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder + from StrippingArchive.Stripping28r2p2.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config + elif year == '2017': + from StrippingArchive.Stripping29r2p3.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder + from StrippingArchive.Stripping29r2p3.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config + elif year == '2018': + from StrippingArchive.Stripping34r0p3.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder + from StrippingArchive.Stripping34r0p3.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config + + # print the unedited config file + print("OLD CONFIG below") + print(config['CONFIG']) + print("OLD CONFIG above") + + # edit the config + config1 = config['CONFIG'] + config1['MuonPID'] = -1001 + config1['ElectronPID'] = -1001 + config1['UseNoPIDsHadrons'] = True + + # then print the edited config file + print("NEW CONFIG below") + print(config1) + print("NEW CONFIG above") + + lb = builder('B2XTauTauLeptonic', config1) + custom_stream = StrippingStream('MyStream') + # Now we have the stream and the line and can add the lines to the stream + target_line = 'Stripping' + line + for sline in lb.lines(): + if sline.name() == target_line: + custom_stream.appendLines([sline]) + ####################### + filterBadEvents = ProcStatusCheck() + sc = StrippingConf(Streams=[custom_stream], + MaxCandidates=10000, + AcceptBadEvents=False, + BadEventSelection=filterBadEvents) + + ### Fill tuple with DecayTreeTuple ### + dtt = DecayTreeTuple('DecayTreeTuple') + dtt.Inputs = ['/Event/Phys/{0}/Particles'.format(line)] + else: # no restrip + ### Fill tuple with DecayTreeTuple ### + dtt = DecayTreeTuple('DecayTreeTuple') + dtt.Inputs = ['/Event/{0}/Phys/{1}/Particles'.format(stream,line)] + +else: # data rather than simulation + ### Fill tuple with DecayTreeTuple ### + dtt = DecayTreeTuple('DecayTreeTuple') + dtt.Inputs = ['/Event/{0}/Phys/{1}/Particles'.format(stream,line)] +######################################## +# ## Define decay and create branches ### +dtt.Decay = decay +dtt.addBranches(branches) + +###################### +# ## Add tupletools ### +# # Generic tupletools ## +dtt.ToolList = [] #reset toollist to add verbose to geometry/kinematic + +SubMassTool = dtt.addTupleTool('TupleToolSubMass') + +# +# will create Sum_{p=2,max) C(N,p) new entries in the nTuple called [head]_M[ij...] +# Particle daughters are sorted by PID at each branch of the tree (cc-independant) +# +#**** Substitution property +# +# usage : TupleTool.Substitution += ["pi+ => K+"] TupleTool.Substitution += ["K+ => pi+"] +# produce alternative mass with substituted PID pi<->K (cc is assumed) +# +#-change only one pion (K) at once in case of several pion (K) in the decay tree (producing separate output par pion (K) ) +# +#**** DoubleSubstitution property +# +# usage : TupleTool.DoubleSubstitution += ["K+/pi- => pi+/K-"] TupleTool.DoubleSubstitution += ["K+/K-" => pi+/pi-"] +# change all [K+pi-]cc ([K+K-]cc) pairs to (pi+K-)cc ([pi+pi-]cc) +# change only one pair at once in case of several pairs in the decay tree (producing separate output per pair) +# +# "/" separator is not mandatory : K+pi- syntax is allowed (just a bit slower to parse) + + +GeometryTool = dtt.addTupleTool('TupleToolGeometry') #Fill geometry related information for DecayTreeTuple +GeometryTool.Verbose=True +# head_MINIP : minimum impact parameter on any PV +# head_MINIPCHI2 : minimum chi2 IP on all PVs +# head_ENDVERTEX_[X|Y|Z] : decay vertex position for composite particles +# head_ENDVERTEX_[X|Y|Z]ERR : decay vertex position error estimate for composite particles +# head_ENDVERTEX_CHI2 : decay vertex chi2 +# head_ENDVERTEX_NDOF : decay vertex nDoF +# head_OWNPV_[X|Y|Z] : related primary vertex position +# head_OWNPV_[X|Y|Z]ERR : related primary vertex position error estimate for composite particles +# head_OWNPV_CHI2 : related primary vertex chi2 +# head_OWNPV_NDOF : related primary vertex nDoF +# head_IP_OWNPV : impact parameter with respect to the PhysDesktop::relatedVertex() considered particle +# head_IPCHI2_OWNPV : impact parameter chi2 with respect to the relatedVertex() considered particle +# head_FD_OWNPV : flight distance of composite particle wrt. the relatedVertex() considered particle +# head_FDCHI2_OWNPV : flight distance significance in units of chi2 wrt. the relatedVertex() considered particle +# head_DIRA_OWNPV : direction angle wrt. the PhysDesktop::relatedVertex() considered particle + +# Verbose being true gives: +# head_TOPPV_[X|Y|Z] : PhysDesktop::relatedVertex() of the top of decay chain position +# head_TOPPV_[X|Y|Z]ERR : PhysDesktop::relatedVertex() of the top of decay chain position error estimate +# head_TOPPV_CHI2 : PhysDesktop::relatedVertex() of the top of decay chain chi2 +# head_TOPPV_NDOF : PhysDesktop::relatedVertex() of the top of decay chain nDoF +# head_IP_TOPPV : impact parameter with respect to the PhysDesktop::relatedVertex() of the top of decay chain +# head_IPCHI2_TOPPV : impact parameter chi2 with respect to the relatedVertex() of the top of decay chain +# head_FD_TOPPV : flight distance of composite particle wrt. the relatedVertex() of the top of decay chain +# head_FDCHI2_TOPPV : flight distance significance in units of chi2 wrt. the PhysDesktop::relatedVertex() of the top of decay chain +# head_DIRA_TOPPV : direction angle wrt. the relatedVertex() of the top of decay chain +# head_ORIVX_[X|Y|Z] : ancestor's related primary vertex position (when applicable) +# head_ORIVX_[X|Y|Z]ERR : ancestor's related primary vertex position error estimate (when applicable) +# head_ORIVX_CHI2 : ancestor's related primary vertex chi2 (when applicable) +# head_ORIVX_NDOF : ancestor's related primary vertex nDoF (when applicable) +# head_IP_ORIVX : impact parameter with respect to the ancestor's vertex (when applicable) +# head_IPCHI2_ORIVX : impact parameter chi2 with respect to the ancestor's vertex (when applicable) +# head_FD_ORIVX : flight distance of composite particle wrt. the ancestor's vertex (when applicable) +# head_FDCHI2_ORIVX : flight distance significance in units of chi2 wrt. ancestor's vertex (when applicable) +# head_DIRA_ORIVX : direction angle wrt. ancestor's vertex (when applicable) + +KinematicTool = dtt.addTupleTool('TupleToolKinematic') #Fill kinematic information for DecayTreeTuple +KinematicTool.Verbose=True +# head_P : momentum's amplitude +# head_PT : transverse momentum +# head_P[E|X|Y|Z] : four vector momentum +# head_MM : measured mass (or assigned mass in case of 'basic' particle +# head_M : mass calculated from momentum four-vector +# head_MMERR : error on the measured mass (only for non-basic parts) + +# Verbose being true gives: +# head_REFP[X|Y|Z]: one point the particle momentum extrapolation goes through +# head_PreFitMass: Mass of 4-vectors of daughters, not yet extrapolated to the head decay vertex (only for composites). +# This is the quantity used in ADAMASS or AM in CombineParticles.CombinationCut +# prefix_AtVtx_P[X|Y|Z]: momentum information of basic particles at origin vertex position + +TrackInfoTool = dtt.addTupleTool('TupleToolTrackInfo') #Fill track information for DecayTreeTuple +TrackInfoTool.Verbose=True +# X_TRACK_CHI2NDOF : track chi2/ndof +# X_TRACK_TYPE : track type +# X_TRACK_PCHI2 : track Chi2 probability +# X_TRACK_GhostProb : Ghost probability (run NeuralNetTmva to fill it) +# X_TRACK_CloneDist : Only available for 2009 data + +# Verbose being true gives: +# X_TRACK_CHI2 : track chi2 +# X_TRACK_NDOF : track ndof +# X_TRACK_VeloCHI2NDOF : Track fit velo chi2/nDoF +# X_TRACK_TCHI2NDOF : Track fit T chi2/nDoF +# X_TRACK_VELO_UTID : hopefully unique double constructed from multiplying all Velo hit IDs +# X_TRACK_TT_UTID : hopefully unique double constructed from multiplying all TT hit IDs +# X_TRACK_IT_UTID : hopefully unique double constructed from multiplying all IT hit IDs +# X_TRACK_OT_UTID : hopefully unique double constructed from multiplying all OT hit IDs +# X_TRACK_VP_UTID : hopefully unique double constructed from multiplying all VP hit IDs +# X_TRACK_UT_UTID : hopefully unique double constructed from multiplying all UT hit IDs +# X_TRACK_FT_UTID : hopefully unique double constructed from multiplying all FT hit IDs +# X_TRACK_nVeloHits : Number of Velo hits on the track +# X_TRACK_nVeloRHits : Number of Velo R hits on the track +# X_TRACK_nVeloPhiHits : Number of Velo phi hits on the track +# X_TRACK_nVeloPileUpHits : Number of Velo pile-up hits on the track +# X_TRACK_nTTHits : Number of TT hits on the track +# X_TRACK_nITHits : Number of IT hits on the track +# X_TRACK_nOTHits : Number of OT hits on the track +# X_TRACK_nVPHits : Number of VP hits on the track +# X_TRACK_nUTHits : Number of UT hits on the track +# X_TRACK_nFTHits : Number of FT hits on the track +# X_TRACK_FirstMeasurementX: x position of state at 'FirstMeasurement' +# X_TRACK_FirstMeasurementY: y position of state at 'FirstMeasurement' +# X_TRACK_FirstMeasurementZ: z position of state at 'FirstMeasurement' +# X_TRACK_History: Algorithm which the track was made with +# X_TRACK_qOverp : q/p of state at 'FirstMeasurement' +# X_TRACK_Tx : x slope of state at 'FirstMeasurement' +# X_TRACK_Ty : y slope of state at 'FirstMeasurement' + +EventInfoTool = dtt.addTupleTool('TupleToolEventInfo') #Event and Run number for DecayTreeTuple +EventInfoTool.Verbose=True +# runNumber: well, the run number +# eventNumber: +# BCID and BC type +# Odin and Hlt TCKs +# GPS time +# If the property Mu is given it will fill the Mu of the run. A working dictionary can be +# found at https://twiki.cern.ch/twiki/bin/view/LHCb/NuMuPileUp + +# if Verbose is on, also gps time in year,month,day,hour,min,second Note that months are +# numbered [0-11]. That's a convention. Sorry. + +PropertimeTool = dtt.addTupleTool('TupleToolPropertime') #Fills the propertime for DecayTreeTuple +# PropertimeTool.Verbose=True +# head_TAU +# head_TAUERR +# head_TAUCHI2 + +RecoStatsTool = dtt.addTupleTool('TupleToolRecoStats') #Fills Reco stats, from RecSummary. +# RecoStatsTool.Verbose=True + +PidTool = dtt.addTupleTool('TupleToolPid') #DLL and PID information to be stored in a Tuple +# PidTool.Verbose=True +# head_ID : particleID().pid(); +# For the long lived particles (isBasicParticle()). +# head_PIDe : LHCb::ProtoParticle::CombDLLe +# head_PIDmu : LHCb::ProtoParticle::CombDLLmu +# head_PIDK : LHCb::ProtoParticle::CombDLLk +# head_PIDp : LHCb::ProtoParticle::CombDLLp + +ANNPIDTool = dtt.addTupleTool('TupleToolANNPID') #ProbNN values for "Electron", "Muon", "Pion", "Kaon", "Proton", "Ghost" +# ANNPIDTool.Verbose=True + +AnglesTool = dtt.addTupleTool('TupleToolAngles') #Fill MC Particle with decay angle in mother frame +# AnglesTool.Verbose=True +# head_CosTheta : angle in mother's frame +# if WRTMother is false, will calculate angle in frame of top of tree + +PrimariesTool = dtt.addTupleTool('TupleToolPrimaries') #Primary vertices properties for DecayTreeTuple +# PrimariesTool.Verbose=True +# coordinates PVX, PVY, PVZ +# errors PVXERR, PVYERR, PVZERR +# vertex chi2 PVCHI +# vertex ndf PVNDOF +# Nb of tracks used to do the vertex PVNTRACKS + +## Isolation variables ## + +# cone isolation # +ConeIsoTool = dtt.addTupleTool('TupleToolConeIsolation') +# choose cones to have a deltaR of 0.5, 0.7, 0.9 radians +ConeIsoTool.MinConeSize = 0.6 +ConeIsoTool.MaxConeSize = 0.6 +# ConeIsoTool.SizeStep = 0.2 +# Fill asymmetry, delta, and component variables +# ConeIsoTool.FillAsymmetry = True +# ConeIsoTool.FillDeltas = True +# ConeIsoTool.FillComponents = True + + +# head_cc: charged cone +# head_nc: neutral cone + +# head_XX_mult : number of objects inside the cone +# head_XX_sPT : scalar-summed pT of the objects inside the cone +# head_XX_vPT : vector-summed pT of the objects inside the cone +# head_XX_P : x, y and z components of the cone momentum +# head_XX_asy_P : momentum asymmetry between the head and the cone defined as (head_P - head_XX_P) / (head_P + head_XX_P) +# head_XX_asy_P : x, y, z and transverse components of the momentum asymmetry +# head_XX_deltaEta : difference in eta between the head and the cone +# head_XX_deltaPhi : difference in phi between the head and the cone +# head_XX_IT : transverse isolation of the head in the cone, defined as head_PT / (head_P + head_XX_P)_T +# head_IT : transverse isolation of the head in the charged and neutral cones, defined as head_PT / (head_P + head_cc_P + head_nc_P)_T +# head_cc_maxPt_Q : charge of the max-pT object in the charged cone +# head_XX_maxPt_P : x, y, z (and e) components of the max-pT object momentum in the cone +# head_MasshPi0: invariant mass of the seed-Pi0 combinations +# head_Pi0_DeltaR: DeltaR between the seed and the pi0 directions +# head_Pi0_E, head_Pi0_PX, head_Pi0_PY, head_Pi0_PZ: four momentum of the pi0 +# head_Pi0_M: invariant mass of the pi0 +# head_Pi0Ph1_CL, head_Pi0Ph2_CL: confidence levels of the (photon) pi0 daughters + +# track isolation # +TrackIsoTool = dtt.addTupleTool('TupleToolTrackIsolation') +# choose cones to have a deltaR of 0.5, 0.7, 0.9 radians +TrackIsoTool.MinConeAngle = 0.6 +TrackIsoTool.MaxConeAngle = 0.6 +# TrackIsoTool.StepSize = 0.2 +# fill asymmetry and DeltaAngles variables +TrackIsoTool.FillAsymmetry = True +# TrackIsoTool.FillDeltaAngles = True + +# Open up a cone around head, exclude all tracks that are in the decay descriptor +# (i.e. that belong to the decay you are looking for), build the variables with +# the remaining tracks. + +# head_cmult : Number of tracks inside cone. +# head_cp : Summed p inside cone +# head_cpt : Summed pt inside cone +# head_cpx : Summed px inside cone +# head_cpy : Summed py inside cone +# head_cpz : Summed pz inside cone + +# If Verbose, or other flags are set: + +# Asymmetry variables + +# head_pasy : (head_P - head_cp)/(head_P + head_cp) +# head_ptasy : (head_PT - head_cpt)/(head_PT + head_cpt) +# head_pxasy : (head_Px - head_cpx)/(head_Px + head_cpx) +# head_pyasy : (head_Py - head_cpy)/(head_Py + head_cpy) +# head_pzasy : (head_Pz - head_cpz)/(head_Pz + head_cpz) Delta angle variables +# head_DeltaEta : Difference in eta between summed tracks and head +# head_DeltaPhi : Difference in phi between summed tracks and head + + +# MinConeAngle: Set the minimal deltaR of the cone (default = 0.5), in radians +# MaxConeAngle: Set the maximum deltaR of the cone (default = 1.0), in radians +# StepSize: Set the step of deltaR between two iterations (default = 0.1), in radians +# TrackType: Set the type of tracks which are considered inside the cone (default = 3) +# FillAsymmetry: Flag to fill the asymmetry variables (default = false) +# FillDeltaAngles: Flag to fill the delta angle variables (default = false) + +# vertex isolation # +VtxIsoTool = dtt.addTupleTool('TupleToolVtxIsoln') + +# head_NOPARTWITHINDCHI2WDW : no. of non-signal particles that when added to vertex give delta chi2 < specified window +# head_NOPARTWITHINCHI2WDW : no. of non-signal particles that when added to vertex give chi2 < specified window +# head_SMALLESTCHI2: chi2 of smallest chi2 combination with any of the input Particles +# head_SMALLESTDELTACHI2: delta chi2 of smallest delta chi2 combination with any of the input Particles +#### updates: +# (head)_NumVtxWithinChi2WindowOneTrack: number of particles that generate a vertex within a chi2 window +# (head)_SmallestDeltaChi2OneTrack: smallest delta chi2 when adding one track +# (head)_SmallestDeltaChi2MassOneTrack: mass of the candidate with the smallest delta chi2 +# (head)_SmallestDeltaChi2TwoTracks: smallest delta chi2 when adding one track to the combination +# that has the smallest delta chi2 when adding one track +# (head)_SmallestDeltaChi2MassTwoTracks: mass of the candidate with the smallest delta chi2 when adding +# one track to the combination that has the smallest delta chi2 when adding one track + +## Hybrid tupletool ## +all_hybrid = dtt.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_All') +all_hybrid.Variables = { + 'ETA' : "ETA", #pseudorapidity + 'PHI' : "PHI", #asimuthal angle + 'MINIPCHI2' : "MIPCHI2DV(PRIMARY)", + #The special version of LoKi::Particles::MinImpParChi2 functor which gets all the primary + #vertices from desktop. + 'MINIP' : "MIPDV(PRIMARY)", + #The special version of LoKi::Particles::MinImpPar functor which gets all the primary + #vertices from desktop. + 'IPCHI2_OWNPV' : "BPVIPCHI2()", + #The special "context-dependent" version of LoKi::Particles::ImpParChi2 functor which gets + #the related primary vertex from IPhysDesktop tool + 'IP_OWNPV' : "BPVIP()", + #The special "context-dependent" version of LoKi::Particles::ImpPar functor which gets the + #related primary vertex from IPhysDesktop tool. + 'DIRA_OWNPV' : "BPVDIRA", + 'ghost' : "TRGHP", #simple evaluator of "ghost probability" + 'TrackCHI2DOF' : 'TRCHI2DOF', + 'FD_CHI2' : "BPVVDCHI2", + #BPV = Adaptor to "best-primary-vertex", VDCHI2 = Evaluator of the chi2 of GEOMETRY distance + #between the particle "endVertex" and "the vertex". + 'VCHI2DOF' : 'VFASPF(VCHI2/VDOF)', + # #Decay tree fitter functions: + # 'DTF_CHI2NDOF' : "DTF_CHI2NDOF( True )", + # #Simple evaluator of $\chi^2$ per degree of freedom for the decay tree fit. + # 'DTF_VCHI2NDOF' : "DTF_FUN ( VFASPF(VCHI2/VDOF) , True )", + # #VCHI2 = evaluator of the Chi2 of the vertex / VDOF = evaluator of the number of degrees + # #of freedom for the vertex + # 'DTF_MASS_JpsiConstr' : "DTF_FUN ( M , True , 'J/psi(1S)' )" , + # 'DTF_MASS' : "DTF_FUN ( M , True )" , + # 'DTF_CTAU"' : "DTF_CTAU( 0, True )", + # #Evaluate $c\tau$ for the dauthter particle in the decay tree. + # 'DTF_CTAUS' : "DTF_CTAUSIGNIFICANCE( 0, True )" + # #Evaluate $ \frac{c\tau}{\sigma \left( c\tau\right) } $ for the dauthter particle + # #in the decay tree. +} + +lb_hybrid = dtt.mother.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_Lb') +lb_hybrid.Variables = { + 'DOCAjpsiinter' : "DOCA(1,2)", + 'DOCAmotherjpsi' : "DOCA(0,1)", + 'DOCAmotherinter' : "DOCA(0,2)", + 'DOCAjpsiinterCHI2' : "DOCACHI2(1,2)", + 'DOCAmotherjpsiCHI2' : "DOCACHI2(0,1)", + 'DOCAmotherinterCHI2' : "DOCACHI2(0,2)" +} +jpsi_hybrid = dtt.jpsi.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_jpsi') +jpsi_hybrid.Variables = { + 'DOCAd1d2' : "DOCA(1,2)", + 'DOCAjpsid1' : "DOCA(0,1)", + 'DOCAjpsid2' : "DOCA(0,2)", + 'DOCAd1d2CHI2' : "DOCACHI2(1,2)", + 'DOCAjpsid1CHI2' : "DOCACHI2(0,1)", + 'DOCAjpsid2CHI2' : "DOCACHI2(0,2)" +} +inter_hybrid = dtt.inter.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_inter') +inter_hybrid.Variables = { + #note that the end vertex of the intermediate hadron is also the end vertex of the lb + 'DOCAh1h2' : "DOCA(1,2)", + 'DOCAmotherh1' : "DOCA(0,1)", + 'DOCAmotherh2' : "DOCA(0,2)", + 'DOCAh1h2CHI2' : "DOCACHI2(1,2)", + 'DOCAmotherh1CHI2' : "DOCACHI2(0,1)", + 'DOCAmotherh2CHI2' : "DOCACHI2(0,2)" +} + +################ +### Triggers ### +# Add trigger list # + +L0Triggers = ['L0MuonDecision','L0DiMuonDecision','L0HadronDecision'] +Hlt1Triggers = [# muon lines + 'Hlt1TrackMuonDecision','Hlt1SingleMuonNoIPDecision','Hlt1SingleMuonHighPTDecision', + # dimuon lines + 'Hlt1DiMuonHighMassDecision','Hlt1DiMuonLowMassDecision', + # MVA lines + 'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision','Hlt1TrackMuonMVADecision', + 'Hlt1TwoTrackMVALooseDecision','Hlt1TwoTrackMVADecision' + ] +Hlt2Triggers = [# topo lines + 'Hlt2Topo2BodyDecision','Hlt2Topo3BodyDecision','Hlt2Topo4BodyDecision', + 'Hlt2TopoMu2BodyDecision','Hlt2TopoMu3BodyDecision','Hlt2TopoMu4BodyDecision', + 'Hlt2TopoMuMu2BodyDecision','Hlt2TopoMuMu3BodyDecision','Hlt2TopoMuMu4BodyDecision', + # muon lines + 'Hlt2SingleMuonDecision','Hlt2SingleMuonHighPTDecision','Hlt2SingleMuonLowPTDecision', + 'Hlt2SingleMuonRareDecision','Hlt2SingleMuonVHighPTDecision', + # dimuon lines + 'Hlt2DiMuonDecision','Hlt2DiMuonJPsiDecision','Hlt2DiMuonDetachedDecision', + 'Hlt2DiMuonDetachedHeavyDecision','Hlt2DiMuonDetachedJPsiDecision', + 'Hlt2DiMuonDetachedPsi2SDecision','Hlt2DiMuonSoftDecision' + ] +# Electrons in Sel +if '_E_' in stripping_line or '_MuE_' in stripping_line or '_EPi_' in stripping_line: + L0Triggers += ["L0ElectronDecision","L0ElectronHiDecision","L0PhotonDecision","L0PhotonHiDecision"] + Hlt1Triggers += ["Hlt1SingleElectronNoIPDecision"] + Hlt2Triggers += ["Hlt2TopoE2BodyDecision","Hlt2TopoE3BodyDecision","Hlt2TopoE4BodyDecision", + "Hlt2TopoEE2BodyDecision","Hlt2TopoEE3BodyDecision","Hlt2TopoEE4BodyDecision", + "Hlt2TopoMuE2BodyDecision","Hlt2TopoMuE3BodyDecision","Hlt2TopoMuE4BodyDecision" + ] + +AllTriggers = L0Triggers + Hlt1Triggers + Hlt2Triggers + +MuonTriggers = [# L0 + 'L0MuonDecision', + # Hlt1 + 'Hlt1TrackMuonDecision','Hlt1SingleMuonNoIPDecision','Hlt1SingleMuonHighPTDecision', + 'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision','Hlt1TrackMuonMVADecision', + # Hlt2 + 'Hlt2SingleMuonDecision','Hlt2SingleMuonHighPTDecision', + 'Hlt2SingleMuonLowPTDecision','Hlt2SingleMuonRareDecision','Hlt2SingleMuonVHighPTDecision' + ] +HadronTriggers = [# L0 + 'L0HadronDecision', + # Hlt1 + 'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision' + ] +ElectronTriggers = [# L0 + "L0ElectronDecision","L0ElectronHiDecision","L0PhotonDecision","L0PhotonHiDecision", + # Hlt1 + "Hlt1SingleElectronNoIPDecision","Hlt1TrackMVADecision"] + +# TupleToolTISTOS # +# It saves the trigger TIS/TOS decisions for each particle for each Hlt Selection +dtt.mother.ToolList += [ "TupleToolTISTOS" ] +dtt.mother.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" ) +dtt.mother.TupleToolTISTOS.Verbose = True +dtt.mother.TupleToolTISTOS.TriggerList = AllTriggers +dtt.d2.ToolList += [ "TupleToolTISTOS" ] +dtt.d2.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" ) +dtt.d2.TupleToolTISTOS.Verbose = True +dtt.d2.TupleToolTISTOS.TriggerList = HadronTriggers +dtt.d1.ToolList += [ "TupleToolTISTOS" ] +dtt.d1.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" ) +dtt.d1.TupleToolTISTOS.Verbose = True +dtt.d1.TupleToolTISTOS.TriggerList = HadronTriggers +dtt.h1.ToolList += [ "TupleToolTISTOS" ] +dtt.h1.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" ) +dtt.h1.TupleToolTISTOS.Verbose = True +if '_Mu_' in stripping_line or '_MuE_' in stripping_line or '_MuPi_' in stripping_line: + dtt.h1.TupleToolTISTOS.TriggerList = MuonTriggers +elif '_EPi_' in stripping_line: + dtt.h1.TupleToolTISTOS.TriggerList = ElectronTriggers +elif '_PiPi_' in stripping_line: + dtt.h1.TupleToolTISTOS.TriggerList = HadronTriggers +# else: # TODO remove +# print('LOCAL: ERROR WITH h1 TRIGGER ASSIGNMENT') + +dtt.h2.ToolList += [ "TupleToolTISTOS" ] +dtt.h2.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" ) +dtt.h2.TupleToolTISTOS.Verbose = True +if '_E_' in stripping_line or '_MuE_' in stripping_line: + dtt.h2.TupleToolTISTOS.TriggerList = ElectronTriggers +elif '_EPi_' in stripping_line or '_PiPi_' in stripping_line: + dtt.h2.TupleToolTISTOS.TriggerList = HadronTriggers + +## MC truth value tupletools ## +if simulation == True: + MCTruthTool = dtt.addTupleTool('TupleToolMCTruth') #Fill MC truth info if a link is present + # head_TRUEID : true pid + MCTruthTool.ToolList = [ + "MCTupleToolKinematic", + # head_TRUEP[E|X|Y|Z] : true four vector momentum + # head_TRUEPT : true transverse momentum, PT + # head_TRUEORIGINVERTEX_[X|Y|Z] : position of the true origin vertex. + # head_TRUEENDVERTEX_[X|Y|Z] : position of the true end vertex (the first one) + # head_TRUEISSTABLE : MCAssociate has no daughters. + # head_TRUETAU : true propertime + "MCTupleToolHierarchy", + # head_MC_MOTHER_ID : true mc mother ID + # head_MC_MOTHER_KEY : true mc mother key + # head_MC_GD_MOTHER_ID : grand mother ID + # head_MC_GD_MOTHER_KEY : grand mother key + # head_MC_GD_GD_MOTHER_ID : grand grand mother ID + # head_MC_GD_GD_MOTHER_KEY : grand grand mother key + ] + + ## Hybrid tupletool ## + hybrid_mc_dtt = dtt.addTupleTool('LoKi::Hybrid::MCTupleTool/LoKi_All_MC') + hybrid_mc_dtt.Variables = { + 'MCETA' : "MCETA", #pseudorapidity + 'MCPHI' : "MCPHI", #asimuthal angle + } + + MCBackgroundInfoTool = dtt.addTupleTool('TupleToolMCBackgroundInfo') #Fill the info from IBackgroundCategory. + # head_BKGCAT : category + + # add mcdecaytreetuple + + def Make_MCTuple(decay): + MCTuple = MCDecayTreeTuple("MCDecayTreeTuple") + + MCTuple.Decay = decay + MCTuple.setDescriptorTemplate( decay ) + MCTuple.ToolList = [ + "MCTupleToolKinematic" + , "MCTupleToolHierarchy" + , "MCTupleToolAngles" + , "MCTupleToolPID" + , "TupleToolEventInfo" + , "TupleToolRecoStats" + ] + ## Hybrid tupletool ## + hybrid_mc_mcdtt = MCTuple.addTupleTool('LoKi::Hybrid::MCTupleTool/LoKi_All_MC') + hybrid_mc_mcdtt.Variables = { + 'MCETA' : "MCETA", #pseudorapidity + 'MCPHI' : "MCPHI", #asimuthal angle + } + return MCTuple + + + MCTuple = Make_MCTuple(mcdecay) + +######################### +# ## Configure DaVinci ### +from Configurables import GaudiSequencer +MySequencer = GaudiSequencer('Sequence') +if simulation == True: + MySequencer.Members = [event_node_killer, sc.sequence(), dtt, MCTuple] + # MySequencer.Members = [event_node_killer, sc.sequence(),dtt] +else: + MySequencer.Members = [dtt] + +DaVinci().UserAlgorithms += [MySequencer] +DaVinci().EvtMax = -1 +DaVinci().PrintFreq = 1000 diff --git a/lbtopktautau/2018_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py b/lbtopktautau/2018_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py new file mode 100644 index 0000000000000000000000000000000000000000..5b0c6f08fe070f6570cb427a450259e3e11de665 --- /dev/null +++ b/lbtopktautau/2018_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py @@ -0,0 +1,652 @@ + +########################################################## +# AUTOMATICALLY GENERATED FILE IN ganga_options_generic.py +simulation = False +noPID = False +no_restrip = False +stripping_stream = 'Semileptonic' +stripping_line = 'B2XTauTauLeptonic_Lb2pK_Mu_ReversePIDmu_line' +decay = '(( Lambda_b0 -> ^(D0 -> ^mu+ ^mu-) ^(Lambda(1520)0 -> ^p+ ^K-) )) || (( Lambda_b~0 -> ^(D0 -> ^mu- ^mu+) ^(Lambda(1520)~0 -> ^p~- ^K+) )) ' +branches = {'mother': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'jpsi': '(( Lambda_b0 -> ^(D0 -> mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> ^(D0 -> mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'd1': '(( Lambda_b0 -> (D0 -> ^mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> ^mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'd2': '(( Lambda_b0 -> (D0 -> mu+ ^mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- ^mu+) (Lambda(1520)~0 -> p~- K+) ))', 'inter': '(( Lambda_b0 -> (D0 -> mu+ mu-) ^(Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) ^(Lambda(1520)~0 -> p~- K+) ))', 'h1': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> ^p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> ^p~- K+) ))', 'h2': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> p+ ^K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> p~- ^K+) ))'} +year = '2018' +mcdecay = 'N/A' +# END AUTOMATICALLY GENERATED FILE IN ganga_options_generic.py +# From here on, the file dv_options_generic.py will be used +# (Stripping will be added first for the lb2pkemu line) +########################################################### + +try: + simulation = simulation + noPID = noPID + no_restrip = no_restrip + stripping_stream = stripping_stream + stripping_line = stripping_line + decay = decay + branches = branches + year = year + mcdecay = mcdecay + +except NameError as error: + raise RuntimeError("""{error} - most likely due to incorrect usage; don't run this file directly. + The variables 'simulation', 'noPID', 'stripping_line', 'decay', 'branches', 'year', 'mcdecay' have to + be specified first. Correct usage is to run 'ganga_options_generic.py'""") + +# don't use f-strings as not supported pre python 3.6! +print("Simulation = {0}".format(simulation)) +print("noPID = {0}".format(noPID)) +print("no_restrip = {0}".format(no_restrip)) +print("year = {0}".format(year)) +print("mcdecay descriptor = {0}".format(mcdecay)) +print("stripping stream = {0}".format(stripping_stream)) +print("stripping line = {0}".format(stripping_line)) +print("decay = {0}".format(decay)) +print("branches = {0}".format(branches)) + + +from Gaudi.Configuration import * +from LHCbKernel.Configuration import * +from DaVinci.Configuration import * +from DecayTreeTuple.Configuration import * + +from Configurables import DaVinci, DecayTreeTuple, MCDecayTreeTuple +from Configurables import TupleToolTISTOS +from Configurables import EventNodeKiller, ProcStatusCheck +from Configurables import LoKi__HDRFilter + +from StrippingConf.Configuration import StrippingConf, StrippingStream +from StrippingSettings.Utils import strippingConfiguration +from StrippingArchive.Utils import buildStreams +from StrippingArchive import strippingArchive + +############################################## + +print("\n## Determined stripping line to be: \n ===>", stripping_line) + +print("\n## config determined") +print("\n===> stream = ", stripping_stream) +print("\n===> line = ", stripping_line) +print("\n===> decay = ", decay) +print("\n===> branches = ", branches) +################################# +# ## Stream and stripping line ### +stream = stripping_stream +line = stripping_line + +########################### +# ## Restripping process ### + +# In the case that we are dealing with simulation, we may need to restrip due to the fact +# that the stripping version for the simulation is different (older) than that of the +# stripping line + +# In the case that we remove the PID requirements, this changes the restripping process +# since we edit the config file to remove these requirements + +if simulation == True: + if no_restrip == False: + event_node_killer = EventNodeKiller('StripKiller') + event_node_killer.Nodes = ['/Event/AllStreams', '/Event/Strip'] + #################### + if noPID == False: # conventional restrip + if year == '2016': + strip = 'stripping28r2p2' + elif year == '2017': + strip = 'stripping29r2p3' + elif year == '2018': + strip = 'stripping34r0p3' + + streams = buildStreams(stripping=strippingConfiguration(strip), + archive=strippingArchive(strip)) + + custom_stream = StrippingStream('AllStreams') + custom_line = 'Stripping'+line + + for stream in streams: + for sline in stream.lines: + if sline.name() == custom_line: + custom_stream.appendLines([sline]) + ##################### + else: # remove PID requirements and restrip + # in this case we need to edit the config to remove PID requirements + # different stripping versions for different years + if year == '2016': + from StrippingArchive.Stripping28r2p2.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder + from StrippingArchive.Stripping28r2p2.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config + elif year == '2017': + from StrippingArchive.Stripping29r2p3.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder + from StrippingArchive.Stripping29r2p3.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config + elif year == '2018': + from StrippingArchive.Stripping34r0p3.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder + from StrippingArchive.Stripping34r0p3.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config + + # print the unedited config file + print("OLD CONFIG below") + print(config['CONFIG']) + print("OLD CONFIG above") + + # edit the config + config1 = config['CONFIG'] + config1['MuonPID'] = -1001 + config1['ElectronPID'] = -1001 + config1['UseNoPIDsHadrons'] = True + + # then print the edited config file + print("NEW CONFIG below") + print(config1) + print("NEW CONFIG above") + + lb = builder('B2XTauTauLeptonic', config1) + custom_stream = StrippingStream('MyStream') + # Now we have the stream and the line and can add the lines to the stream + target_line = 'Stripping' + line + for sline in lb.lines(): + if sline.name() == target_line: + custom_stream.appendLines([sline]) + ####################### + filterBadEvents = ProcStatusCheck() + sc = StrippingConf(Streams=[custom_stream], + MaxCandidates=10000, + AcceptBadEvents=False, + BadEventSelection=filterBadEvents) + + ### Fill tuple with DecayTreeTuple ### + dtt = DecayTreeTuple('DecayTreeTuple') + dtt.Inputs = ['/Event/Phys/{0}/Particles'.format(line)] + else: # no restrip + ### Fill tuple with DecayTreeTuple ### + dtt = DecayTreeTuple('DecayTreeTuple') + dtt.Inputs = ['/Event/{0}/Phys/{1}/Particles'.format(stream,line)] + +else: # data rather than simulation + ### Fill tuple with DecayTreeTuple ### + dtt = DecayTreeTuple('DecayTreeTuple') + dtt.Inputs = ['/Event/{0}/Phys/{1}/Particles'.format(stream,line)] +######################################## +# ## Define decay and create branches ### +dtt.Decay = decay +dtt.addBranches(branches) + +###################### +# ## Add tupletools ### +# # Generic tupletools ## +dtt.ToolList = [] #reset toollist to add verbose to geometry/kinematic + +SubMassTool = dtt.addTupleTool('TupleToolSubMass') + +# +# will create Sum_{p=2,max) C(N,p) new entries in the nTuple called [head]_M[ij...] +# Particle daughters are sorted by PID at each branch of the tree (cc-independant) +# +#**** Substitution property +# +# usage : TupleTool.Substitution += ["pi+ => K+"] TupleTool.Substitution += ["K+ => pi+"] +# produce alternative mass with substituted PID pi<->K (cc is assumed) +# +#-change only one pion (K) at once in case of several pion (K) in the decay tree (producing separate output par pion (K) ) +# +#**** DoubleSubstitution property +# +# usage : TupleTool.DoubleSubstitution += ["K+/pi- => pi+/K-"] TupleTool.DoubleSubstitution += ["K+/K-" => pi+/pi-"] +# change all [K+pi-]cc ([K+K-]cc) pairs to (pi+K-)cc ([pi+pi-]cc) +# change only one pair at once in case of several pairs in the decay tree (producing separate output per pair) +# +# "/" separator is not mandatory : K+pi- syntax is allowed (just a bit slower to parse) + + +GeometryTool = dtt.addTupleTool('TupleToolGeometry') #Fill geometry related information for DecayTreeTuple +GeometryTool.Verbose=True +# head_MINIP : minimum impact parameter on any PV +# head_MINIPCHI2 : minimum chi2 IP on all PVs +# head_ENDVERTEX_[X|Y|Z] : decay vertex position for composite particles +# head_ENDVERTEX_[X|Y|Z]ERR : decay vertex position error estimate for composite particles +# head_ENDVERTEX_CHI2 : decay vertex chi2 +# head_ENDVERTEX_NDOF : decay vertex nDoF +# head_OWNPV_[X|Y|Z] : related primary vertex position +# head_OWNPV_[X|Y|Z]ERR : related primary vertex position error estimate for composite particles +# head_OWNPV_CHI2 : related primary vertex chi2 +# head_OWNPV_NDOF : related primary vertex nDoF +# head_IP_OWNPV : impact parameter with respect to the PhysDesktop::relatedVertex() considered particle +# head_IPCHI2_OWNPV : impact parameter chi2 with respect to the relatedVertex() considered particle +# head_FD_OWNPV : flight distance of composite particle wrt. the relatedVertex() considered particle +# head_FDCHI2_OWNPV : flight distance significance in units of chi2 wrt. the relatedVertex() considered particle +# head_DIRA_OWNPV : direction angle wrt. the PhysDesktop::relatedVertex() considered particle + +# Verbose being true gives: +# head_TOPPV_[X|Y|Z] : PhysDesktop::relatedVertex() of the top of decay chain position +# head_TOPPV_[X|Y|Z]ERR : PhysDesktop::relatedVertex() of the top of decay chain position error estimate +# head_TOPPV_CHI2 : PhysDesktop::relatedVertex() of the top of decay chain chi2 +# head_TOPPV_NDOF : PhysDesktop::relatedVertex() of the top of decay chain nDoF +# head_IP_TOPPV : impact parameter with respect to the PhysDesktop::relatedVertex() of the top of decay chain +# head_IPCHI2_TOPPV : impact parameter chi2 with respect to the relatedVertex() of the top of decay chain +# head_FD_TOPPV : flight distance of composite particle wrt. the relatedVertex() of the top of decay chain +# head_FDCHI2_TOPPV : flight distance significance in units of chi2 wrt. the PhysDesktop::relatedVertex() of the top of decay chain +# head_DIRA_TOPPV : direction angle wrt. the relatedVertex() of the top of decay chain +# head_ORIVX_[X|Y|Z] : ancestor's related primary vertex position (when applicable) +# head_ORIVX_[X|Y|Z]ERR : ancestor's related primary vertex position error estimate (when applicable) +# head_ORIVX_CHI2 : ancestor's related primary vertex chi2 (when applicable) +# head_ORIVX_NDOF : ancestor's related primary vertex nDoF (when applicable) +# head_IP_ORIVX : impact parameter with respect to the ancestor's vertex (when applicable) +# head_IPCHI2_ORIVX : impact parameter chi2 with respect to the ancestor's vertex (when applicable) +# head_FD_ORIVX : flight distance of composite particle wrt. the ancestor's vertex (when applicable) +# head_FDCHI2_ORIVX : flight distance significance in units of chi2 wrt. ancestor's vertex (when applicable) +# head_DIRA_ORIVX : direction angle wrt. ancestor's vertex (when applicable) + +KinematicTool = dtt.addTupleTool('TupleToolKinematic') #Fill kinematic information for DecayTreeTuple +KinematicTool.Verbose=True +# head_P : momentum's amplitude +# head_PT : transverse momentum +# head_P[E|X|Y|Z] : four vector momentum +# head_MM : measured mass (or assigned mass in case of 'basic' particle +# head_M : mass calculated from momentum four-vector +# head_MMERR : error on the measured mass (only for non-basic parts) + +# Verbose being true gives: +# head_REFP[X|Y|Z]: one point the particle momentum extrapolation goes through +# head_PreFitMass: Mass of 4-vectors of daughters, not yet extrapolated to the head decay vertex (only for composites). +# This is the quantity used in ADAMASS or AM in CombineParticles.CombinationCut +# prefix_AtVtx_P[X|Y|Z]: momentum information of basic particles at origin vertex position + +TrackInfoTool = dtt.addTupleTool('TupleToolTrackInfo') #Fill track information for DecayTreeTuple +TrackInfoTool.Verbose=True +# X_TRACK_CHI2NDOF : track chi2/ndof +# X_TRACK_TYPE : track type +# X_TRACK_PCHI2 : track Chi2 probability +# X_TRACK_GhostProb : Ghost probability (run NeuralNetTmva to fill it) +# X_TRACK_CloneDist : Only available for 2009 data + +# Verbose being true gives: +# X_TRACK_CHI2 : track chi2 +# X_TRACK_NDOF : track ndof +# X_TRACK_VeloCHI2NDOF : Track fit velo chi2/nDoF +# X_TRACK_TCHI2NDOF : Track fit T chi2/nDoF +# X_TRACK_VELO_UTID : hopefully unique double constructed from multiplying all Velo hit IDs +# X_TRACK_TT_UTID : hopefully unique double constructed from multiplying all TT hit IDs +# X_TRACK_IT_UTID : hopefully unique double constructed from multiplying all IT hit IDs +# X_TRACK_OT_UTID : hopefully unique double constructed from multiplying all OT hit IDs +# X_TRACK_VP_UTID : hopefully unique double constructed from multiplying all VP hit IDs +# X_TRACK_UT_UTID : hopefully unique double constructed from multiplying all UT hit IDs +# X_TRACK_FT_UTID : hopefully unique double constructed from multiplying all FT hit IDs +# X_TRACK_nVeloHits : Number of Velo hits on the track +# X_TRACK_nVeloRHits : Number of Velo R hits on the track +# X_TRACK_nVeloPhiHits : Number of Velo phi hits on the track +# X_TRACK_nVeloPileUpHits : Number of Velo pile-up hits on the track +# X_TRACK_nTTHits : Number of TT hits on the track +# X_TRACK_nITHits : Number of IT hits on the track +# X_TRACK_nOTHits : Number of OT hits on the track +# X_TRACK_nVPHits : Number of VP hits on the track +# X_TRACK_nUTHits : Number of UT hits on the track +# X_TRACK_nFTHits : Number of FT hits on the track +# X_TRACK_FirstMeasurementX: x position of state at 'FirstMeasurement' +# X_TRACK_FirstMeasurementY: y position of state at 'FirstMeasurement' +# X_TRACK_FirstMeasurementZ: z position of state at 'FirstMeasurement' +# X_TRACK_History: Algorithm which the track was made with +# X_TRACK_qOverp : q/p of state at 'FirstMeasurement' +# X_TRACK_Tx : x slope of state at 'FirstMeasurement' +# X_TRACK_Ty : y slope of state at 'FirstMeasurement' + +EventInfoTool = dtt.addTupleTool('TupleToolEventInfo') #Event and Run number for DecayTreeTuple +EventInfoTool.Verbose=True +# runNumber: well, the run number +# eventNumber: +# BCID and BC type +# Odin and Hlt TCKs +# GPS time +# If the property Mu is given it will fill the Mu of the run. A working dictionary can be +# found at https://twiki.cern.ch/twiki/bin/view/LHCb/NuMuPileUp + +# if Verbose is on, also gps time in year,month,day,hour,min,second Note that months are +# numbered [0-11]. That's a convention. Sorry. + +PropertimeTool = dtt.addTupleTool('TupleToolPropertime') #Fills the propertime for DecayTreeTuple +# PropertimeTool.Verbose=True +# head_TAU +# head_TAUERR +# head_TAUCHI2 + +RecoStatsTool = dtt.addTupleTool('TupleToolRecoStats') #Fills Reco stats, from RecSummary. +# RecoStatsTool.Verbose=True + +PidTool = dtt.addTupleTool('TupleToolPid') #DLL and PID information to be stored in a Tuple +# PidTool.Verbose=True +# head_ID : particleID().pid(); +# For the long lived particles (isBasicParticle()). +# head_PIDe : LHCb::ProtoParticle::CombDLLe +# head_PIDmu : LHCb::ProtoParticle::CombDLLmu +# head_PIDK : LHCb::ProtoParticle::CombDLLk +# head_PIDp : LHCb::ProtoParticle::CombDLLp + +ANNPIDTool = dtt.addTupleTool('TupleToolANNPID') #ProbNN values for "Electron", "Muon", "Pion", "Kaon", "Proton", "Ghost" +# ANNPIDTool.Verbose=True + +AnglesTool = dtt.addTupleTool('TupleToolAngles') #Fill MC Particle with decay angle in mother frame +# AnglesTool.Verbose=True +# head_CosTheta : angle in mother's frame +# if WRTMother is false, will calculate angle in frame of top of tree + +PrimariesTool = dtt.addTupleTool('TupleToolPrimaries') #Primary vertices properties for DecayTreeTuple +# PrimariesTool.Verbose=True +# coordinates PVX, PVY, PVZ +# errors PVXERR, PVYERR, PVZERR +# vertex chi2 PVCHI +# vertex ndf PVNDOF +# Nb of tracks used to do the vertex PVNTRACKS + +## Isolation variables ## + +# cone isolation # +ConeIsoTool = dtt.addTupleTool('TupleToolConeIsolation') +# choose cones to have a deltaR of 0.5, 0.7, 0.9 radians +ConeIsoTool.MinConeSize = 0.6 +ConeIsoTool.MaxConeSize = 0.6 +# ConeIsoTool.SizeStep = 0.2 +# Fill asymmetry, delta, and component variables +# ConeIsoTool.FillAsymmetry = True +# ConeIsoTool.FillDeltas = True +# ConeIsoTool.FillComponents = True + + +# head_cc: charged cone +# head_nc: neutral cone + +# head_XX_mult : number of objects inside the cone +# head_XX_sPT : scalar-summed pT of the objects inside the cone +# head_XX_vPT : vector-summed pT of the objects inside the cone +# head_XX_P : x, y and z components of the cone momentum +# head_XX_asy_P : momentum asymmetry between the head and the cone defined as (head_P - head_XX_P) / (head_P + head_XX_P) +# head_XX_asy_P : x, y, z and transverse components of the momentum asymmetry +# head_XX_deltaEta : difference in eta between the head and the cone +# head_XX_deltaPhi : difference in phi between the head and the cone +# head_XX_IT : transverse isolation of the head in the cone, defined as head_PT / (head_P + head_XX_P)_T +# head_IT : transverse isolation of the head in the charged and neutral cones, defined as head_PT / (head_P + head_cc_P + head_nc_P)_T +# head_cc_maxPt_Q : charge of the max-pT object in the charged cone +# head_XX_maxPt_P : x, y, z (and e) components of the max-pT object momentum in the cone +# head_MasshPi0: invariant mass of the seed-Pi0 combinations +# head_Pi0_DeltaR: DeltaR between the seed and the pi0 directions +# head_Pi0_E, head_Pi0_PX, head_Pi0_PY, head_Pi0_PZ: four momentum of the pi0 +# head_Pi0_M: invariant mass of the pi0 +# head_Pi0Ph1_CL, head_Pi0Ph2_CL: confidence levels of the (photon) pi0 daughters + +# track isolation # +TrackIsoTool = dtt.addTupleTool('TupleToolTrackIsolation') +# choose cones to have a deltaR of 0.5, 0.7, 0.9 radians +TrackIsoTool.MinConeAngle = 0.6 +TrackIsoTool.MaxConeAngle = 0.6 +# TrackIsoTool.StepSize = 0.2 +# fill asymmetry and DeltaAngles variables +TrackIsoTool.FillAsymmetry = True +# TrackIsoTool.FillDeltaAngles = True + +# Open up a cone around head, exclude all tracks that are in the decay descriptor +# (i.e. that belong to the decay you are looking for), build the variables with +# the remaining tracks. + +# head_cmult : Number of tracks inside cone. +# head_cp : Summed p inside cone +# head_cpt : Summed pt inside cone +# head_cpx : Summed px inside cone +# head_cpy : Summed py inside cone +# head_cpz : Summed pz inside cone + +# If Verbose, or other flags are set: + +# Asymmetry variables + +# head_pasy : (head_P - head_cp)/(head_P + head_cp) +# head_ptasy : (head_PT - head_cpt)/(head_PT + head_cpt) +# head_pxasy : (head_Px - head_cpx)/(head_Px + head_cpx) +# head_pyasy : (head_Py - head_cpy)/(head_Py + head_cpy) +# head_pzasy : (head_Pz - head_cpz)/(head_Pz + head_cpz) Delta angle variables +# head_DeltaEta : Difference in eta between summed tracks and head +# head_DeltaPhi : Difference in phi between summed tracks and head + + +# MinConeAngle: Set the minimal deltaR of the cone (default = 0.5), in radians +# MaxConeAngle: Set the maximum deltaR of the cone (default = 1.0), in radians +# StepSize: Set the step of deltaR between two iterations (default = 0.1), in radians +# TrackType: Set the type of tracks which are considered inside the cone (default = 3) +# FillAsymmetry: Flag to fill the asymmetry variables (default = false) +# FillDeltaAngles: Flag to fill the delta angle variables (default = false) + +# vertex isolation # +VtxIsoTool = dtt.addTupleTool('TupleToolVtxIsoln') + +# head_NOPARTWITHINDCHI2WDW : no. of non-signal particles that when added to vertex give delta chi2 < specified window +# head_NOPARTWITHINCHI2WDW : no. of non-signal particles that when added to vertex give chi2 < specified window +# head_SMALLESTCHI2: chi2 of smallest chi2 combination with any of the input Particles +# head_SMALLESTDELTACHI2: delta chi2 of smallest delta chi2 combination with any of the input Particles +#### updates: +# (head)_NumVtxWithinChi2WindowOneTrack: number of particles that generate a vertex within a chi2 window +# (head)_SmallestDeltaChi2OneTrack: smallest delta chi2 when adding one track +# (head)_SmallestDeltaChi2MassOneTrack: mass of the candidate with the smallest delta chi2 +# (head)_SmallestDeltaChi2TwoTracks: smallest delta chi2 when adding one track to the combination +# that has the smallest delta chi2 when adding one track +# (head)_SmallestDeltaChi2MassTwoTracks: mass of the candidate with the smallest delta chi2 when adding +# one track to the combination that has the smallest delta chi2 when adding one track + +## Hybrid tupletool ## +all_hybrid = dtt.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_All') +all_hybrid.Variables = { + 'ETA' : "ETA", #pseudorapidity + 'PHI' : "PHI", #asimuthal angle + 'MINIPCHI2' : "MIPCHI2DV(PRIMARY)", + #The special version of LoKi::Particles::MinImpParChi2 functor which gets all the primary + #vertices from desktop. + 'MINIP' : "MIPDV(PRIMARY)", + #The special version of LoKi::Particles::MinImpPar functor which gets all the primary + #vertices from desktop. + 'IPCHI2_OWNPV' : "BPVIPCHI2()", + #The special "context-dependent" version of LoKi::Particles::ImpParChi2 functor which gets + #the related primary vertex from IPhysDesktop tool + 'IP_OWNPV' : "BPVIP()", + #The special "context-dependent" version of LoKi::Particles::ImpPar functor which gets the + #related primary vertex from IPhysDesktop tool. + 'DIRA_OWNPV' : "BPVDIRA", + 'ghost' : "TRGHP", #simple evaluator of "ghost probability" + 'TrackCHI2DOF' : 'TRCHI2DOF', + 'FD_CHI2' : "BPVVDCHI2", + #BPV = Adaptor to "best-primary-vertex", VDCHI2 = Evaluator of the chi2 of GEOMETRY distance + #between the particle "endVertex" and "the vertex". + 'VCHI2DOF' : 'VFASPF(VCHI2/VDOF)', + # #Decay tree fitter functions: + # 'DTF_CHI2NDOF' : "DTF_CHI2NDOF( True )", + # #Simple evaluator of $\chi^2$ per degree of freedom for the decay tree fit. + # 'DTF_VCHI2NDOF' : "DTF_FUN ( VFASPF(VCHI2/VDOF) , True )", + # #VCHI2 = evaluator of the Chi2 of the vertex / VDOF = evaluator of the number of degrees + # #of freedom for the vertex + # 'DTF_MASS_JpsiConstr' : "DTF_FUN ( M , True , 'J/psi(1S)' )" , + # 'DTF_MASS' : "DTF_FUN ( M , True )" , + # 'DTF_CTAU"' : "DTF_CTAU( 0, True )", + # #Evaluate $c\tau$ for the dauthter particle in the decay tree. + # 'DTF_CTAUS' : "DTF_CTAUSIGNIFICANCE( 0, True )" + # #Evaluate $ \frac{c\tau}{\sigma \left( c\tau\right) } $ for the dauthter particle + # #in the decay tree. +} + +lb_hybrid = dtt.mother.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_Lb') +lb_hybrid.Variables = { + 'DOCAjpsiinter' : "DOCA(1,2)", + 'DOCAmotherjpsi' : "DOCA(0,1)", + 'DOCAmotherinter' : "DOCA(0,2)", + 'DOCAjpsiinterCHI2' : "DOCACHI2(1,2)", + 'DOCAmotherjpsiCHI2' : "DOCACHI2(0,1)", + 'DOCAmotherinterCHI2' : "DOCACHI2(0,2)" +} +jpsi_hybrid = dtt.jpsi.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_jpsi') +jpsi_hybrid.Variables = { + 'DOCAd1d2' : "DOCA(1,2)", + 'DOCAjpsid1' : "DOCA(0,1)", + 'DOCAjpsid2' : "DOCA(0,2)", + 'DOCAd1d2CHI2' : "DOCACHI2(1,2)", + 'DOCAjpsid1CHI2' : "DOCACHI2(0,1)", + 'DOCAjpsid2CHI2' : "DOCACHI2(0,2)" +} +inter_hybrid = dtt.inter.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_inter') +inter_hybrid.Variables = { + #note that the end vertex of the intermediate hadron is also the end vertex of the lb + 'DOCAh1h2' : "DOCA(1,2)", + 'DOCAmotherh1' : "DOCA(0,1)", + 'DOCAmotherh2' : "DOCA(0,2)", + 'DOCAh1h2CHI2' : "DOCACHI2(1,2)", + 'DOCAmotherh1CHI2' : "DOCACHI2(0,1)", + 'DOCAmotherh2CHI2' : "DOCACHI2(0,2)" +} + +################ +### Triggers ### +# Add trigger list # + +L0Triggers = ['L0MuonDecision','L0DiMuonDecision','L0HadronDecision'] +Hlt1Triggers = [# muon lines + 'Hlt1TrackMuonDecision','Hlt1SingleMuonNoIPDecision','Hlt1SingleMuonHighPTDecision', + # dimuon lines + 'Hlt1DiMuonHighMassDecision','Hlt1DiMuonLowMassDecision', + # MVA lines + 'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision','Hlt1TrackMuonMVADecision', + 'Hlt1TwoTrackMVALooseDecision','Hlt1TwoTrackMVADecision' + ] +Hlt2Triggers = [# topo lines + 'Hlt2Topo2BodyDecision','Hlt2Topo3BodyDecision','Hlt2Topo4BodyDecision', + 'Hlt2TopoMu2BodyDecision','Hlt2TopoMu3BodyDecision','Hlt2TopoMu4BodyDecision', + 'Hlt2TopoMuMu2BodyDecision','Hlt2TopoMuMu3BodyDecision','Hlt2TopoMuMu4BodyDecision', + # muon lines + 'Hlt2SingleMuonDecision','Hlt2SingleMuonHighPTDecision','Hlt2SingleMuonLowPTDecision', + 'Hlt2SingleMuonRareDecision','Hlt2SingleMuonVHighPTDecision', + # dimuon lines + 'Hlt2DiMuonDecision','Hlt2DiMuonJPsiDecision','Hlt2DiMuonDetachedDecision', + 'Hlt2DiMuonDetachedHeavyDecision','Hlt2DiMuonDetachedJPsiDecision', + 'Hlt2DiMuonDetachedPsi2SDecision','Hlt2DiMuonSoftDecision' + ] +# Electrons in Sel +if '_E_' in stripping_line or '_MuE_' in stripping_line or '_EPi_' in stripping_line: + L0Triggers += ["L0ElectronDecision","L0ElectronHiDecision","L0PhotonDecision","L0PhotonHiDecision"] + Hlt1Triggers += ["Hlt1SingleElectronNoIPDecision"] + Hlt2Triggers += ["Hlt2TopoE2BodyDecision","Hlt2TopoE3BodyDecision","Hlt2TopoE4BodyDecision", + "Hlt2TopoEE2BodyDecision","Hlt2TopoEE3BodyDecision","Hlt2TopoEE4BodyDecision", + "Hlt2TopoMuE2BodyDecision","Hlt2TopoMuE3BodyDecision","Hlt2TopoMuE4BodyDecision" + ] + +AllTriggers = L0Triggers + Hlt1Triggers + Hlt2Triggers + +MuonTriggers = [# L0 + 'L0MuonDecision', + # Hlt1 + 'Hlt1TrackMuonDecision','Hlt1SingleMuonNoIPDecision','Hlt1SingleMuonHighPTDecision', + 'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision','Hlt1TrackMuonMVADecision', + # Hlt2 + 'Hlt2SingleMuonDecision','Hlt2SingleMuonHighPTDecision', + 'Hlt2SingleMuonLowPTDecision','Hlt2SingleMuonRareDecision','Hlt2SingleMuonVHighPTDecision' + ] +HadronTriggers = [# L0 + 'L0HadronDecision', + # Hlt1 + 'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision' + ] +ElectronTriggers = [# L0 + "L0ElectronDecision","L0ElectronHiDecision","L0PhotonDecision","L0PhotonHiDecision", + # Hlt1 + "Hlt1SingleElectronNoIPDecision","Hlt1TrackMVADecision"] + +# TupleToolTISTOS # +# It saves the trigger TIS/TOS decisions for each particle for each Hlt Selection +dtt.mother.ToolList += [ "TupleToolTISTOS" ] +dtt.mother.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" ) +dtt.mother.TupleToolTISTOS.Verbose = True +dtt.mother.TupleToolTISTOS.TriggerList = AllTriggers +dtt.d2.ToolList += [ "TupleToolTISTOS" ] +dtt.d2.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" ) +dtt.d2.TupleToolTISTOS.Verbose = True +dtt.d2.TupleToolTISTOS.TriggerList = HadronTriggers +dtt.d1.ToolList += [ "TupleToolTISTOS" ] +dtt.d1.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" ) +dtt.d1.TupleToolTISTOS.Verbose = True +dtt.d1.TupleToolTISTOS.TriggerList = HadronTriggers +dtt.h1.ToolList += [ "TupleToolTISTOS" ] +dtt.h1.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" ) +dtt.h1.TupleToolTISTOS.Verbose = True +if '_Mu_' in stripping_line or '_MuE_' in stripping_line or '_MuPi_' in stripping_line: + dtt.h1.TupleToolTISTOS.TriggerList = MuonTriggers +elif '_EPi_' in stripping_line: + dtt.h1.TupleToolTISTOS.TriggerList = ElectronTriggers +elif '_PiPi_' in stripping_line: + dtt.h1.TupleToolTISTOS.TriggerList = HadronTriggers +# else: # TODO remove +# print('LOCAL: ERROR WITH h1 TRIGGER ASSIGNMENT') + +dtt.h2.ToolList += [ "TupleToolTISTOS" ] +dtt.h2.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" ) +dtt.h2.TupleToolTISTOS.Verbose = True +if '_E_' in stripping_line or '_MuE_' in stripping_line: + dtt.h2.TupleToolTISTOS.TriggerList = ElectronTriggers +elif '_EPi_' in stripping_line or '_PiPi_' in stripping_line: + dtt.h2.TupleToolTISTOS.TriggerList = HadronTriggers + +## MC truth value tupletools ## +if simulation == True: + MCTruthTool = dtt.addTupleTool('TupleToolMCTruth') #Fill MC truth info if a link is present + # head_TRUEID : true pid + MCTruthTool.ToolList = [ + "MCTupleToolKinematic", + # head_TRUEP[E|X|Y|Z] : true four vector momentum + # head_TRUEPT : true transverse momentum, PT + # head_TRUEORIGINVERTEX_[X|Y|Z] : position of the true origin vertex. + # head_TRUEENDVERTEX_[X|Y|Z] : position of the true end vertex (the first one) + # head_TRUEISSTABLE : MCAssociate has no daughters. + # head_TRUETAU : true propertime + "MCTupleToolHierarchy", + # head_MC_MOTHER_ID : true mc mother ID + # head_MC_MOTHER_KEY : true mc mother key + # head_MC_GD_MOTHER_ID : grand mother ID + # head_MC_GD_MOTHER_KEY : grand mother key + # head_MC_GD_GD_MOTHER_ID : grand grand mother ID + # head_MC_GD_GD_MOTHER_KEY : grand grand mother key + ] + + ## Hybrid tupletool ## + hybrid_mc_dtt = dtt.addTupleTool('LoKi::Hybrid::MCTupleTool/LoKi_All_MC') + hybrid_mc_dtt.Variables = { + 'MCETA' : "MCETA", #pseudorapidity + 'MCPHI' : "MCPHI", #asimuthal angle + } + + MCBackgroundInfoTool = dtt.addTupleTool('TupleToolMCBackgroundInfo') #Fill the info from IBackgroundCategory. + # head_BKGCAT : category + + # add mcdecaytreetuple + + def Make_MCTuple(decay): + MCTuple = MCDecayTreeTuple("MCDecayTreeTuple") + + MCTuple.Decay = decay + MCTuple.setDescriptorTemplate( decay ) + MCTuple.ToolList = [ + "MCTupleToolKinematic" + , "MCTupleToolHierarchy" + , "MCTupleToolAngles" + , "MCTupleToolPID" + , "TupleToolEventInfo" + , "TupleToolRecoStats" + ] + ## Hybrid tupletool ## + hybrid_mc_mcdtt = MCTuple.addTupleTool('LoKi::Hybrid::MCTupleTool/LoKi_All_MC') + hybrid_mc_mcdtt.Variables = { + 'MCETA' : "MCETA", #pseudorapidity + 'MCPHI' : "MCPHI", #asimuthal angle + } + return MCTuple + + + MCTuple = Make_MCTuple(mcdecay) + +######################### +# ## Configure DaVinci ### +from Configurables import GaudiSequencer +MySequencer = GaudiSequencer('Sequence') +if simulation == True: + MySequencer.Members = [event_node_killer, sc.sequence(), dtt, MCTuple] + # MySequencer.Members = [event_node_killer, sc.sequence(),dtt] +else: + MySequencer.Members = [dtt] + +DaVinci().UserAlgorithms += [MySequencer] +DaVinci().EvtMax = -1 +DaVinci().PrintFreq = 1000 diff --git a/lbtopktautau/info.yaml b/lbtopktautau/info.yaml new file mode 100644 index 0000000000000000000000000000000000000000..602080acb4bbe23128b3cd39759a35cbf1660c9e --- /dev/null +++ b/lbtopktautau/info.yaml @@ -0,0 +1,43 @@ +defaults: + wg: RD + output: ntuples.root + inform: + - lmadhanm@hep.phy.cam.ac.uk + - joshua.james.bex@cern.ch + automatically_configure: 'True' +MD_2016_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu: + application: DaVinci/v46r5 + input: + bk_query: /LHCb/Collision16/Beam6500GeV-VeloClosed-MagDown/Real Data/Reco16/Stripping28r2p2/90000000/SEMILEPTONIC.DST + options: + - 2016_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py +MU_2016_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu: + application: DaVinci/v46r5 + input: + bk_query: /LHCb/Collision16/Beam6500GeV-VeloClosed-MagUp/Real Data/Reco16/Stripping28r2p2/90000000/SEMILEPTONIC.DST + options: + - 2016_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py +MD_2017_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu: + application: DaVinci/v46r5 + input: + bk_query: /LHCb/Collision17/Beam6500GeV-VeloClosed-MagDown/Real Data/Reco17/Stripping29r2p3/90000000/SEMILEPTONIC.DST + options: + - 2017_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py +MU_2017_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu: + application: DaVinci/v46r5 + input: + bk_query: /LHCb/Collision17/Beam6500GeV-VeloClosed-MagUp/Real Data/Reco17/Stripping29r2p3/90000000/SEMILEPTONIC.DST + options: + - 2017_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py +MD_2018_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu: + application: DaVinci/v46r5 + input: + bk_query: /LHCb/Collision18/Beam6500GeV-VeloClosed-MagDown/Real Data/Reco18/Stripping34r0p3/90000000/SEMILEPTONIC.DST + options: + - 2018_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py +MU_2018_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu: + application: DaVinci/v46r5 + input: + bk_query: /LHCb/Collision18/Beam6500GeV-VeloClosed-MagUp/Real Data/Reco18/Stripping34r0p3/90000000/SEMILEPTONIC.DST + options: + - 2018_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py