diff --git a/D02HH/README.md b/D02HH/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b7b157c17a275286683249503e547dfaaa6e6d4f --- /dev/null +++ b/D02HH/README.md @@ -0,0 +1,14 @@ +# AnalysisProductions options for $` D^{0}\rightarrow h^+ h^- `$ + +The options contained in this directory generate the NTuples for the simulation +of prompt $` D^{\ast+} \rightarrow (D^{0}\rightarrow h^+ h^-) \pi^{+}_{tag} `$ +decays (for both standard and LTUNB triggers), +with $` h^+ h^- = K^- \pi^+,\; K^+ K^-,\; \pi^+ \pi^-,\; K^+ \pi^- `$. + +General features: + * `DecayTreeFitter` algorithm applied to the $` D^{\ast+} `$ decay chain + w/ the PV constraint, w/ and w/o the $` D^{0} `$ mass constraint; + * combination of the RS prompt sample with a `PersistReco` muon to be used + as proxy for secondary decays; + * momentum scaling of all particles, except the persisted muons of the prompt + sample. diff --git a/D02HH/info.yaml b/D02HH/info.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a40dfdae45a86f4314910f1838bbb6e93067d9c3 --- /dev/null +++ b/D02HH/info.yaml @@ -0,0 +1,54 @@ +checks: + RSdeltaM: + type: range + tree_pattern: RS_DT_Tuple/RS_DT + expression: B_DTF_Dst_M-B_DTF_D0_M + limits: + min: 139 + max: 155 + n_bins: 100 + WSdeltaM: + type: range + tree_pattern: WS_DT_Tuple/WS_DT + expression: B_DTF_Dst_M-B_DTF_D0_M + limits: + min: 139 + max: 155 + n_bins: 100 + +defaults: + application: DaVinci/v46r3 + automatically_configure: yes + turbo: yes + options: + - make_ntuples.py + output: CHARM_D02HH_DVNTUPLE.ROOT + wg: Charm + inform: + - aodhan.burke@cern.ch + + +{% for polarity in ["MagDown", "MagUp"] %} + +D02HH_2016_{{polarity}}_11774014: + checks: + - RSdeltaM + - WSdeltaM + input: + bk_query: "/MC/2016/Beam6500GeV-2016-{{polarity}}-Nu1.6-25ns-Pythia8/Sim09l-ReDecay01/Trig0x6139160F/Reco16/Turbo03a/Stripping28r2NoPrescalingFlagged/Turbo03aFiltered/11774014/D02HH.HLTFILTER.MDST" + +D02HH_2017_{{polarity}}_11774014: + checks: + - RSdeltaM + - WSdeltaM + input: + bk_query: "/MC/2017/Beam6500GeV-2017-{{polarity}}-Nu1.6-25ns-Pythia8/Sim09l-ReDecay01/Trig0x62661709/Reco17/Turbo04a-WithTurcal/Stripping29r2NoPrescalingFlagged/Turbo04aFiltered/11774014/D02HH.HLTFILTER.MDST" + +D02HH_2018_{{polarity}}_11774014: + checks: + - RSdeltaM + - WSdeltaM + input: + bk_query: "/MC/2018/Beam6500GeV-2018-{{polarity}}-Nu1.6-25ns-Pythia8/Sim09l-ReDecay01/Trig0x617d18a4/Reco18/Turbo05-WithTurcal/Stripping34NoPrescalingFlagged/Turbo05Filtered/11774014/D02HH.HLTFILTER.MDST" + +{% endfor %} diff --git a/D02HH/make_ntuples.py b/D02HH/make_ntuples.py new file mode 100644 index 0000000000000000000000000000000000000000..f04177b869c7526ae5afffe7ec0ea20888117d7d --- /dev/null +++ b/D02HH/make_ntuples.py @@ -0,0 +1,473 @@ + + + + +from copy import copy + +from Configurables import ( + DaVinci, + GaudiSequencer, + ChargedProtoANNPIDConf, + LoKi__Hybrid__Dict2Tuple, + LoKi__Hybrid__DictOfFunctors) +from Configurables import LoKi__Hybrid__DTFDict as DTFDict +from Configurables import DecayTreeTuple +from DecayTreeTuple.Configuration import * + +from PhysConf.Selections import (AutomaticData, MomentumScaling, + RebuildSelection, SelectionSequence, + CombineSelection) +from PhysConf.Filters import LoKi_Filters +from StandardParticles import StdAllLooseMuons +from TeslaTools import TeslaTruthUtils + + +DaVinci().Turbo = True +if DaVinci().Simulation or DaVinci().DataType == "2015" or DaVinci().DataType == "2016": + DaVinci().RootInTES = '/Event/Turbo' +else: + DaVinci().RootInTES = "/Event/Charmtwobody/Turbo" + + +# prompt +hh_keys = { + 'KK': 'KmKp', + 'PP': 'PimPip', + 'RS': 'KmPip', + 'WS': 'KpPim' +} +# semi-leptonic +hh_keys_SL = { + 'KK_SL': 'KmKp', + 'PP_SL': 'PimPip', + 'KP_SL': 'KmPip' +} +# doubly-tagged +hh_keys_DT = { + 'KK_DT' : 'KmKp', + 'PP_DT' : 'PimPip', + 'KP_DT' : 'KmPip' +} + + +hlt2_lines = { + '{k}{ltunb}'.format(k=k, ltunb=ltunb): + 'Hlt2CharmHadDstp2D0Pip_D02{hh}{ltunb}Turbo'.format(hh=hh, ltunb=ltunb) + for k, hh in list(hh_keys.items()) + for ltunb in ['', '_LTUNB']} +hlt2_lines.update({ + '{k}'.format(k=k): + 'Hlt2SLB_B2D0Mu_D02{hh}Turbo'.format(hh=hh) + for k, hh in list(hh_keys_SL.items()) +}) +hlt2_lines.update({ + '{k}'.format(k=k): + 'Hlt2SLB_B2DstMu_D02{hh}Turbo'.format(hh=hh) + for k, hh in list(hh_keys_DT.items()) +}) + +# https://twiki.cern.ch/twiki/bin/view/LHCb/RefitTracksFromDST#Momentum_Scale_correction +particles = {k: AutomaticData('{hlt2_line}/Particles'.format(hlt2_line=hlt2_line)) + for k, hlt2_line in list(hlt2_lines.items())} +if not DaVinci().Simulation: + for k in list(particles.keys()): + particles[k] = MomentumScaling( + particles[k], Turbo=True, Year=DaVinci().DataType) + +# make (D*+ mu) combinations (proxy of secondary decays) +muons = RebuildSelection(StdAllLooseMuons) +dst_mu = CombineSelection( + 'DstMu', + inputs=[RebuildSelection(StdAllLooseMuons), particles['RS']], + DecayDescriptors=['[B0 -> D*(2010)+ mu-]cc', + '[B0 -> D*(2010)+ mu+]cc'], + DaughtersCuts={ + 'D*(2010)+': 'ALL', + 'D*(2010)-': 'ALL', + 'mu-': '(PT > 800.0*MeV) & (P > 3.0*GeV) & (TRGHOSTPROB < 0.5) ' + '& (TRCHI2DOF < 5.0) & (MIPCHI2DV(PRIMARY) > 4.0)', + 'mu+': '(PT > 800.0*MeV) & (P > 3.0*GeV) & (TRGHOSTPROB < 0.5) ' + '& (TRCHI2DOF < 5.0) & (MIPCHI2DV(PRIMARY) > 4.0)'}, + CombinationCut='(AM > 2.0*GeV) & (AM < 10.0*GeV)', + MotherCut=('(VFASPF(VCHI2/VDOF) < 25) & (BPVDIRA> 0.999) &' + '(M > 3.0*GeV) & (M < 8.0*GeV)') +) +if DaVinci().DataType == '2015' or DaVinci().DataType == '2016': + dst_mu.InputPrimaryVertices = 'Primary' +if DaVinci().DataType == '2016' and not DaVinci().Simulation: + # https://twiki.cern.ch/twiki/bin/view/LHCb/MakeNTupleFromTurbo#Exact_clones_in_particle_combina + dst_mu.CheckOverlapTool = 'LoKi::CheckOverlap' +dst_mu_sequence = SelectionSequence('DstMuSequence', TopSelection=dst_mu) +particles['Mu'] = dst_mu_sequence + + +tuple_keys = {k:k for k in list(hlt2_lines.keys()) if 'KP' not in k} +tuple_keys.update({ + 'Mu': 'Mu', + 'RS_SL': 'KP_SL', + 'WS_SL': 'KP_SL', + 'RS_DT': 'KP_DT', + 'WS_DT': 'KP_DT' +}) + + +inputs = { k : particles[tuple_keys[k]] for k in tuple_keys.keys() } + + +# https://twiki.cern.ch/twiki/bin/view/LHCb/EnsureProbNNsCalculated +probnn_sequence = {} +for k, v in list(hlt2_lines.items()): + probnn_sequence[k] = GaudiSequencer('{0}_ProbNNSeq'.format(k)) + annpid = ChargedProtoANNPIDConf( + k + 'ProbNNalg', + RecoSequencer=probnn_sequence[k], + ProtoParticlesLocation='{0}/Protos'.format(v) + ) + + +# K- pi+, K+ K-, pi+ pi- are reconstructed only as D0 +# https://gitlab.cern.ch/lhcb/Hlt/blob/2018-patches/Hlt/Hlt2Lines/python/Hlt2Lines +# - CharmHad/D02HHLines.py +# - SLB/Lines.py +decay_descriptors = { + "KK_LTUNB": " ${Dst}[D*(2010)+ -> ${D0}([D0]cc -> ${P1}K+ ${P2}K- ) ${sPi}pi+]CC", + "PP_LTUNB": " ${Dst}[D*(2010)+ -> ${D0}([D0]cc -> ${P1}pi+ ${P2}pi-) ${sPi}pi+]CC", + "RS_LTUNB": " ${Dst}[D*(2010)+ -> ${D0}(D0 -> ${P1}K- ${P2}pi+) ${sPi}pi+]CC", + "WS_LTUNB": " ${Dst}[D*(2010)- -> ${D0}(D0 -> ${P1}K- ${P2}pi+) ${sPi}pi-]CC", + "KK": " ${Dst}[D*(2010)+ -> ${D0}([D0]cc -> ${P1}K+ ${P2}K- ) ${sPi}pi+]CC", + "PP": " ${Dst}[D*(2010)+ -> ${D0}([D0]cc -> ${P1}pi+ ${P2}pi-) ${sPi}pi+]CC", + "RS": " ${Dst}[D*(2010)+ -> ${D0}(D0 -> ${P1}K- ${P2}pi+) ${sPi}pi+]CC", + "WS": " ${Dst}[D*(2010)- -> ${D0}(D0 -> ${P1}K- ${P2}pi+) ${sPi}pi-]CC", + "Mu": " ${B}[Xb -> ${Dst}(D*(2010)+ -> ${D0}(D0 -> ${P1}K- ${P2}pi+) ${sPi}pi+) ${Mu}[mu-]cc]CC", + "KK_SL": "${B}[Xb -> ${D0}([D0]cc -> ${P1}K+ ${P2}K- ) ${Mu}mu- ]CC", + "PP_SL": "${B}[Xb -> ${D0}([D0]cc -> ${P1}pi+ ${P2}pi-) ${Mu}mu- ]CC", + "RS_SL": "${B}[Xb -> ${D0}(D0 -> ${P1}K- ${P2}pi+) ${Mu}mu- ]CC", + "WS_SL": "${B}[Xb -> ${D0}(D0 -> ${P1}K- ${P2}pi+) ${Mu}mu+ ]CC", + "KK_DT": "${B}[Xb -> ${Dst}(D*(2010)+ -> ${D0}([D0]cc -> ${P1}K+ ${P2}K- ) ${sPi}pi+) ${Mu}[mu-]cc]CC", + "PP_DT": "${B}[Xb -> ${Dst}(D*(2010)+ -> ${D0}([D0]cc -> ${P1}pi+ ${P2}pi-) ${sPi}pi+) ${Mu}[mu-]cc]CC", + "RS_DT": "${B}[Xb -> ${Dst}(D*(2010)+ -> ${D0}(D0 -> ${P1}K- ${P2}pi+) ${sPi}pi+) ${Mu}[mu-]cc]CC", + "WS_DT": "${B}[Xb -> ${Dst}(D*(2010)- -> ${D0}(D0 -> ${P1}K- ${P2}pi+) ${sPi}pi-) ${Mu}[mu+]cc]CC" +} + +decay_descriptors_mc = { + "KK": " ${Dst}[D*(2010)+ => ${D0}([D0]cc => ${P1}K+ ${P2}K- ) ${sPi}pi+]CC", + "PP": " ${Dst}[D*(2010)+ => ${D0}([D0]cc => ${P1}pi+ ${P2}pi-) ${sPi}pi+]CC", + "RS": " ${Dst}[D*(2010)+ => ${D0}(D0 => ${P1}K- ${P2}pi+) ${sPi}pi+]CC", + "RS_Mu": " ${B}[Xb --> ${Dst}(D*(2010)+ => ${D0}(D0 => ${P1}K- ${P2}pi+) ${sPi}pi+) ${Mu}mu- ${Nu}nu_mu~]CC", + "B": "${B}[B0]cc" # to get the B0 decay time +} + + +def AddDTF(dtt, decay_type, constrain_pv=True, constrain_d0_m=False): + # DecayTreeFitter configuration + # https://twiki.cern.ch/twiki/bin/view/LHCb/DaVinciTutorial9b + name = 'DTF{0}{1}'.format('_PV' if constrain_pv else '', + '_D0M' if constrain_d0_m else '') + if decay_type == "P": + DictTuple = dtt.Dst.addTupleTool(LoKi__Hybrid__Dict2Tuple, '{}_DictTuple'.format(name)) + else: + DictTuple = dtt.B.addTupleTool(LoKi__Hybrid__Dict2Tuple, '{}_DictTuple'.format(name)) + DictTuple.addTool(DTFDict, name) + DictTuple.Source = 'LoKi::Hybrid::DTFDict/{}'.format(name) + DictTuple.NumVar = 61 # reserve enough for DT + dtf = getattr(DictTuple, name) + dtf.constrainToOriginVertex = constrain_pv + if constrain_d0_m: + dtf.daughtersToConstrain = ['D0', 'D~0'] + dtf.addTool(LoKi__Hybrid__DictOfFunctors, 'dict') + dtf.Source = 'LoKi::Hybrid::DictOfFunctors/dict' + + variables = {} + if decay_type == "P": + DTFvars = { + "Dst": "{0}", + "D0": "CHILD(1, {0})", + "P1": "CHILD(1, CHILD(1, {0}))", + "P2": "CHILD(1, CHILD(2, {0}))", + "sPi": "CHILD(2, {0})", + } + elif decay_type == "SL": + DTFvars = { + "B": "{0}", + "D0": " CHILD(1, {0})", + "P1": "CHILD(1, CHILD(1, {0}))", + "P2": "CHILD(1, CHILD(2, {0}))", + "Mu": "CHILD(2, {0})", + } + else: + DTFvars = { + "B": "{0}", + "Dst": "CHILD(1, {0})", + "D0": "CHILD(1, CHILD(1, {0}))", + "P1": "CHILD(1, CHILD(1, CHILD(1, {0})))", + "P2": "CHILD(1, CHILD(1, CHILD(2, {0})))", + "sPi": "CHILD(1, CHILD(2, {0}))", + "Mu": "CHILD(2, {0})", + } + for key, string in list(DTFvars.items()): + for var in ["M", "PT", "P", "ETA", "PHI"]: + variables["{0}_{1}".format(key,var)] = string.format(var) + + dtf.dict.Variables = variables + + # the DTF fit is run once for each of the following variable + if decay_type == "P": + Loki_DTF = dtt.Dst.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_{0}'.format(name)) + else: + Loki_DTF = dtt.B.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_{0}'.format(name)) + + if decay_type != "DT": + Loki_DTF.Variables = { + "{0}_D0_CTAU".format(name): "DTF_CTAU(1, {0}{1})".format( + True if constrain_pv else False, + ", strings(['D0', 'D~0'])" if constrain_d0_m else ""), + "{0}_D0_CTAUERR".format(name): "DTF_CTAUERR( 1, {0}{1})".format( + True if constrain_pv else False, + ", strings(['D0', 'D~0'])" if constrain_d0_m else "") + } + else: + Loki_DTF.Variables = { + "{0}_D0_CTAU".format(name): "CHILD(1, DTF_CTAU(1, {0}{1}))".format( + True if constrain_pv else False, + ", strings(['D0', 'D~0'])" if constrain_d0_m else ""), + "{0}_D0_CTAUERR".format(name): "CHILD(1, DTF_CTAUERR( 1, {0}{1}))".format( + True if constrain_pv else False, + ", strings(['D0', 'D~0'])" if constrain_d0_m else "") + } + + Loki_DTF.Variables.update({ + "{0}_CHI2".format(name) : "DTF_CHI2({0}{1})".format(True if constrain_pv else False, ", strings(['D0', 'D~0'])" if constrain_d0_m else ""), + "{0}_NDOF".format(name) : "DTF_NDOF({0}{1})".format(True if constrain_pv else False, ", strings(['D0', 'D~0'])" if constrain_d0_m else ""), + "{0}_CHI2NDOF".format(name) : "DTF_CHI2NDOF({0}{1})".format(True if constrain_pv else False, ", strings(['D0', 'D~0'])" if constrain_d0_m else "") + }) + + return + + +def SetupMCTools(dtt, is_turbo): + dtt.ToolList += ['TupleToolMCTruth', 'TupleToolMCBackgroundInfo'] + mc_tools = ['MCTupleToolPrompt', 'MCTupleToolKinematic', 'MCTupleToolHierarchy'] + # https://twiki.cern.ch/twiki/bin/view/LHCb/MakeNTupleFromTurbo#Monte_Carlo_truth + relations = TeslaTruthUtils.getRelLocs() + [ + TeslaTruthUtils.getRelLoc(''), + 'Relations/Hlt2/Protos/Charged'] # Location of the truth tables for PersistReco objects + TeslaTruthUtils.makeTruth(dtt, relations, mc_tools) + return + + +# see https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/*/src/* +tuple_tools = [ + "TupleToolPropertime", # DecayTreeTuple + "TupleToolEventInfo", # DecayTreeTupleTrigger + "TupleToolBeamSpot", # DecayTreeTuple + "TupleToolPid", # DecayTreeTuple + "TupleToolRecoStats", # DecayTreeTupleReco + "TupleToolMuonPid"] + +trigger_list = [ + "L0B1gasDecision", + "L0B2gasDecision", + "L0DiEMDecision,lowMultDecision", + "L0DiHadron,lowMultDecision", + "L0DiMuonDecision", + "L0DiMuon,lowMultDecision", + "L0ElectronDecision", + "L0Electron,lowMultDecision", + "L0HadronDecision", + "L0JetElDecision", + "L0JetPhDecision", + "L0MuonDecision", + "L0Muon,lowMultDecision", + "L0MuonEWDecision", + "L0PhotonDecision", + "L0Photon,lowMultDecision", + "Hlt1TrackMVADecision", + "Hlt1TrackMVALooseDecision", + "Hlt1TrackMVATightDecision", + "Hlt1TwoTrackMVADecision", + "Hlt1TwoTrackMVALooseDecision", + "Hlt1TwoTrackMVATightDecision", + "Hlt1CalibTrackingKPiDecision", + "Hlt1CalibTrackingKKDecision", + "Hlt1CalibTrackingPiPiDecision"] + +trigger_list_SL_DT = [ + "Hlt1TrackMuonDecision", + "Hlt1TrackMuonMVADecision", + "Hlt1L0AnyDecision", + "Hlt1MBNoBiasDecision", + "Hlt2TopoMu2BodyDecision", + "Hlt2TopoMu3BodyDecision", + "Hlt2TopoMu4BodyDecision", + "Hlt2Topo2BodyDecision", + "Hlt2Topo3BodyDecision", + "Hlt2Topo4BodyDecision", + "Hlt2CharmHadInclDst2PiD02HHXBDTDecision", + "Hlt2SingleMuonDecision"] + + + +loki_vars_dst = { + "DOCACHI2": "DOCACHI2(1,2)", + "DOCA": "DOCA(1,2)"} + +loki_vars_d0 = { + "DOCACHI2": "DOCACHI2(1,2)", + "DOCA": "DOCA(1,2)", + "BPVLTIME": "BPVLTIME()"} + +loki_var ={ + "ETA": "ETA", + "PHI": "PHI"} + + +def MakeTuple(key): + """ Returns a DecayTreeTuple algorithm configured to be run on real data""" + + dtt = DecayTreeTuple("{0}_Tuple".format(key)) + dtt.TupleName = key + dtt.setDescriptorTemplate(decay_descriptors[key]) + dtt.Inputs = [inputs[key].outputLocation()] + if DaVinci().DataType == '2015' or DaVinci().DataType == '2016': + dtt.InputPrimaryVertices = 'Primary' + + dtt.ToolList = copy(tuple_tools) + + # path of header files starts with https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/*/src + dtt.addTupleTool("TupleToolTrackInfo").Verbose = True # DecayTreeTupleReco + dtt.addTupleTool("TupleToolGeometry").Verbose = True # DecayTreeTuple + dtt.addTupleTool("TupleToolKinematic").Verbose = True # DecayTreeTuple + dtt.addTupleTool("TupleToolANNPID").ANNPIDTunes = ["MC15TuneV1"] # DecayTreeTupleANNPID + primTool = dtt.addTupleTool("TupleToolPrimaries") # DecayTreeTuple + primTool.Verbose = True + if DaVinci().DataType == '2015' or DaVinci().DataType == '2016': + primTool.InputLocation = 'Primary' + + # trigger global info for the event - DecayTreeTupleTrigger/src/TupleToolTrigger.h + global_trigger = dtt.addTupleTool("TupleToolTrigger") + global_trigger.VerboseL0 = True + global_trigger.VerboseHlt1 = True + global_trigger.VerboseHlt2 = True + global_trigger.TriggerList = copy(trigger_list) + + # TISTOS - DecayTreeTupleTrigger/src/TupleToolTISTOS.h + tis_tos_tool = dtt.addTupleTool("TupleToolTISTOS") + tis_tos_tool.VerboseL0 = True + tis_tos_tool.VerboseHlt1 = True + tis_tos_tool.VerboseHlt2 = True + tis_tos_tool.FillHlt2 = True + tis_tos_tool.TriggerList = copy(trigger_list) + + LoKi_D0 = dtt.D0.addTupleTool("LoKi::Hybrid::TupleTool/LoKi_D0") + LoKi_D0.Variables = loki_vars_d0 + LoKi_All = dtt.addTupleTool("LoKi::Hybrid::TupleTool/LoKi_ETA_PHI") + LoKi_All.Variables = loki_var + + if not ('SL' in key): + LoKi_DStar = dtt.Dst.addTupleTool("LoKi::Hybrid::TupleTool/LoKi_DStar") + LoKi_DStar.Variables = loki_vars_dst + + # additional info for secondary samples only + if key == 'Mu' or ('SL' in key) or ('DT' in key): + dtt.B.addTupleTool("TupleToolCorrectedMass") # DecayTreeTuple/src/TupleToolCorrectedMass.h + loki_B = dtt.B.addTupleTool("LoKi::Hybrid::TupleTool/LoKi_B") + loki_B.Variables = {"BPVMCORR": "BPVCORRM", + "DOCACHI2": "DOCACHI2(1,2)", + "DOCA": "DOCA(1,2)"} + + if ('SL' in key) or ('DT' in key): + global_trigger.TriggerList += trigger_list_SL_DT + tis_tos_tool.TriggerList += trigger_list_SL_DT + neutrinoTool = dtt.B.addTupleTool("TupleToolNeutrinoReco") + neutrinoTool.Verbose = True + neutrinoTool.MotherMass = 5279.63 + else: + if ('TUNB' in key): + # add prompt Hlt2 line + global_trigger.TriggerList += [ hlt2_lines[key[:2]] + 'Decision' ] + tis_tos_tool.TriggerList += [ hlt2_lines[key[:2]] + 'Decision' ] + else: + # add LTUNB Hlt2 line + if key == 'Mu': + global_trigger.TriggerList += [hlt2_lines['RS_LTUNB'] + 'Decision' ] + tis_tos_tool.TriggerList += [hlt2_lines['RS_LTUNB'] + 'Decision' ] + else: + global_trigger.TriggerList += [hlt2_lines[key+'_LTUNB'] + 'Decision' ] + tis_tos_tool.TriggerList += [hlt2_lines[key+'_LTUNB'] + 'Decision' ] + + type = "P" if 'B' not in list(dtt.Branches.keys()) else ("SL" if "Dst" not in list(dtt.Branches.keys()) else "DT") + AddDTF(dtt, type, constrain_pv=False, constrain_d0_m=False) + AddDTF(dtt, type, constrain_pv=False, constrain_d0_m=True) + AddDTF(dtt, type, constrain_pv=True, constrain_d0_m=False) + AddDTF(dtt, type, constrain_pv=True, constrain_d0_m=True) + + + if DaVinci().Simulation: + SetupMCTools(dtt, DaVinci().Turbo) + + return dtt + + +def MakeTupleMC(key): + """ Returns a MCDecayTreeTuple algorithm configured to be run on simulated + data + """ + + dtt = MCDecayTreeTuple('{0}_MCTuple'.format(key)) + dtt.TupleName = key + dtt.setDescriptorTemplate(decay_descriptors_mc[key]) + dtt.ToolList = [ + "MCTupleToolKinematic", + "TupleToolEventInfo"] + return dtt + + +tuples = [MakeTuple(key) for key in list(tuple_keys.keys())] +if DaVinci().Simulation: + tuples += [MakeTupleMC(key) for key in decay_descriptors_mc.keys()] + + +def MomentumCorrection(is_mc=False): + """ + Returns the momentum scale correction algorithm for data tracks or the + momentum smearing algorithm for MC tracks + """ + if not is_mc: + from Configurables import TrackScaleState as SCALE + scaler = SCALE('StateScale') + return scaler + else: + from Configurables import TrackSmearState as SMEAR + smear = SMEAR('StateSmear') + return smear + return + + +trigger_filter = LoKi_Filters( + HLT1_Code=" HLT_PASS_RE('Hlt1.*TrackMVA.*Decision')" + "| HLT_PASS_RE('Hlt1TrackMuon.*Decision')" + "| HLT_PASS_RE('Hlt1CalibTracking.*Decision')", + HLT2_Code=" HLT_PASS_RE('"+hlt2_lines['KK']+"Decision') " + "| HLT_PASS_RE('"+hlt2_lines['PP']+"Decision') " + "| HLT_PASS_RE('"+hlt2_lines['RS']+"Decision') " + "| HLT_PASS_RE('"+hlt2_lines['WS']+"Decision') " + "| HLT_PASS_RE('"+hlt2_lines['KK_LTUNB']+"Decision') " + "| HLT_PASS_RE('"+hlt2_lines['PP_LTUNB']+"Decision') " + "| HLT_PASS_RE('"+hlt2_lines['RS_LTUNB']+"Decision') " + "| HLT_PASS_RE('"+hlt2_lines['WS_LTUNB']+"Decision') " + "| HLT_PASS_RE('"+hlt2_lines['KK_SL']+"Decision')" + "| HLT_PASS_RE('"+hlt2_lines['PP_SL']+"Decision')" + "| HLT_PASS_RE('"+hlt2_lines['KP_SL']+"Decision')" + "| HLT_PASS_RE('"+hlt2_lines['KK_DT']+"Decision')" + "| HLT_PASS_RE('"+hlt2_lines['PP_DT']+"Decision')" + "| HLT_PASS_RE('"+hlt2_lines['KP_DT']+"Decision')" + ) + + + +DaVinci().EventPreFilters = trigger_filter.filters('TriggerFilter') +DaVinci().UserAlgorithms += [v for v in probnn_sequence.values()] +DaVinci().UserAlgorithms += [MomentumCorrection(DaVinci().Simulation)] +DaVinci().UserAlgorithms += [p for p in particles.values()] +DaVinci().UserAlgorithms += [dst_mu_sequence.sequence()] +DaVinci().UserAlgorithms += tuples