From 4087330c7823dbde8e753386848f513350cbc0c4 Mon Sep 17 00:00:00 2001
From: Yi Jiang <y.jiang@cern.ch>
Date: Mon, 23 Dec 2024 04:41:37 +0100
Subject: [PATCH] add B2Dst0Dst0K_run12

---
 B2Dst0Dst0K_Run12/dv_tupling.py | 332 ++++++++++++++++++++++++++++++++
 B2Dst0Dst0K_Run12/info.yaml     |  31 +++
 2 files changed, 363 insertions(+)
 create mode 100644 B2Dst0Dst0K_Run12/dv_tupling.py
 create mode 100644 B2Dst0Dst0K_Run12/info.yaml

diff --git a/B2Dst0Dst0K_Run12/dv_tupling.py b/B2Dst0Dst0K_Run12/dv_tupling.py
new file mode 100644
index 0000000000..046bc56c5d
--- /dev/null
+++ b/B2Dst0Dst0K_Run12/dv_tupling.py
@@ -0,0 +1,332 @@
+
+###
+from Gaudi.Configuration import *
+from Configurables import GaudiSequencer
+from Configurables import DaVinci
+from Configurables import  DecayTreeTuple, CheckPV, SubstitutePID, SubPIDMMFilter, FilterInTrees
+from PhysSelPython.Wrappers import AutomaticData, Selection, SelectionSequence, DataOnDemand, MergedSelection
+from Configurables import   CombineParticles, FilterDesktop,  OfflineVertexFitter
+from Configurables import FitDecayTrees, TupleToolGeometry
+from Configurables import DecayTreeTuple, LoKi__Hybrid__TupleTool, TupleToolDecay, TupleToolTrigger, TupleToolTISTOS, TupleToolTagging, TupleToolRecoStats, TupleToolPi0Info, TupleToolPhotonInfo
+from Configurables import LoKi__Hybrid__TupleTool as LoKiTupleTool
+from Configurables import TupleToolDecayTreeFitter
+from Configurables import LoKi__Hybrid__EvtTupleTool as LoKiTool
+from Configurables import CondDB
+from Configurables import TupleToolMCTruth, TupleToolMCBackgroundInfo 
+from Configurables import LoKi__Hybrid__DictOfFunctors
+from Configurables import LoKi__Hybrid__Dict2Tuple
+from Configurables import LoKi__Hybrid__DTFDict
+
+from StandardParticles import StdLooseResolvedPi0 as pi0, StdAllNoPIDsPions as pip, StdAllNoPIDsKaons as Km, StdLoosePhotons as gamma
+from StandardParticles import StdLooseKsDD as KSDD, StdLooseKsLL as KSLL
+# lines = [ 'B02DstD0KBeauty2CharmLine',
+#         'B02DstD0KD02K3PiBeauty2CharmLine',
+#        'B02DstD0KDstarD02K3PiBeauty2CharmLine', 
+#        'B02DstD0KDstarD02K3PiD02K3PiBeauty2CharmLine']
+lines = ['InclusiveDoubleDLine']
+
+#hlt filters
+from PhysConf.Filters import LoKi_Filters
+fltrs = LoKi_Filters(STRIP_Code = "("+"|".join(["HLT_PASS_RE('Stripping{}Decision')".format(line) for line in lines]) + ")")
+
+# _Dst = FilterInTrees('dst_in_line', Code="('D*(2010)+' == ABSID)")
+_D0 = FilterInTrees('d0_in_line', Code="('D0' == ABSID)")
+_K = FilterInTrees('K_in_line', Code="('K+' == ABSID)")
+_Dst0 = CombineParticles('comb_Dst0',
+        DecayDescriptor="[D*(2007)0 -> D0 pi0]cc",
+        CombinationCut="(ADAMASS('D*(2007)0') < 600*MeV)",
+        MotherCut="(M-MAXTREE(ABSID=='D0',M) < 300*MeV)",
+        DaughtersCuts   = {
+        'D0': "ALL", # DaughtCutpi,
+        'gamma': "ALL", # DaughtCutpi
+        },
+        ReFitPVs        = True)
+_Dst0_gamma = CombineParticles('comb_Dst0_gamma',
+        DecayDescriptor="[D*(2007)0 -> D0 gamma]cc",
+        CombinationCut="(ADAMASS('D*(2007)0') < 600*MeV)",
+        MotherCut="(M-MAXTREE(ABSID=='D0',M) < 300*MeV)",
+        DaughtersCuts   = {
+        'D0': "ALL", # DaughtCutpi,
+        'gamma': "ALL", # DaughtCutpi
+        },
+        ReFitPVs        = True)
+
+_Dst = CombineParticles('comb_Dst',
+        DecayDescriptors=["D*(2010)+ -> D0 pi+", "D*(2010)- -> D~0 pi-"],
+        CombinationCut="(ADAMASS('D*(2010)+') < 600*MeV) & (ADOCA(1,2)<0.5*mm)",
+        MotherCut="(VFASPF(VCHI2/VDOF)<10) & (BPVVDCHI2>36) & (BPVDIRA>0) & (M-MAXTREE(ABSID=='D0',M) < 200*MeV)",
+        DaughtersCuts   = {
+        'D0': "ALL", # DaughtCutpi,
+        'pi+': "ALL", # DaughtCutpi
+        },
+        ReFitPVs        = True)
+_Bp =  CombineParticles('comb_bp',
+        DecayDescriptors=["B- -> D*(2007)0 D*(2007)~0 K-", "B+ -> D*(2007)~0 D*(2007)0 K+"],
+                       CombinationCut="(AM<6000*MeV)",
+                       MotherCut="(VFASPF(VCHI2/VDOF)<10) & (INTREE(HASTRACK & (P>10000*MeV) & (PT>1700*MeV) & (TRCHI2DOF<4.) & (MIPCHI2DV(PRIMARY)>16) & (MIPDV(PRIMARY)>0.1*mm))) & (NINTREE((ISBASIC & HASTRACK & (TRCHI2DOF<4.) & (PT > 500*MeV) & (P > 5000*MeV))|((ABSID=='KS0') & (PT > 500*MeV) & (P > 5000*MeV) & (BPVVDCHI2 > 1000))) > 1) & (BPVLTIME()>0.2*ps) & (BPVIPCHI2()<25) & (BPVDIRA>0.999)",
+                       DaughtersCuts   = {
+        # 'D*(20)0': "ALL", # DaughtCutpi,
+        'D*(2007)0': "ALL", # DaughtCutpi
+        'K-': "ALL"},
+    ReFitPVs        = True)
+_B0 =  CombineParticles('comb_b0',
+        DecayDescriptors=["B0 -> D*(2007)0 D*(2007)~0 KS0"],
+                       CombinationCut="(AM<6000*MeV)",
+                       MotherCut="(VFASPF(VCHI2/VDOF)<10) & (INTREE(HASTRACK & (P>10000*MeV) & (PT>1700*MeV) & (TRCHI2DOF<4.) & (MIPCHI2DV(PRIMARY)>16) & (MIPDV(PRIMARY)>0.1*mm))) & (NINTREE((ISBASIC & HASTRACK & (TRCHI2DOF<4.) & (PT > 500*MeV) & (P > 5000*MeV))|((ABSID=='KS0') & (PT > 500*MeV) & (P > 5000*MeV) & (BPVVDCHI2 > 1000))) > 1) & (BPVLTIME()>0.2*ps) & (BPVIPCHI2()<25) & (BPVDIRA>0.999)",
+                       DaughtersCuts   = {
+       #  'D*(2010)+': "ALL", # DaughtCutpi,
+        'D*(2007)0': "ALL", # DaughtCutpi
+        'KS0': "ALL"},
+    ReFitPVs        = True)
+
+line_loc = "/Event/CharmCompleteEvent/Phys/{}/Particles".format(lines[0])
+line_data = DataOnDemand(line_loc)
+name = "B2Dst0Dst0K"
+sel_D0 = Selection(name+"_D0",
+                            Algorithm=_D0,
+                            RequiredSelections=[line_data])
+sel_Dst = Selection(name+"_Dst",
+                            Algorithm=_Dst,
+                            RequiredSelections=[sel_D0, pip])
+
+sel_Dst0_gamma = Selection(name+"_Dst0_gamma",
+                            Algorithm=_Dst0_gamma,
+                            RequiredSelections=[sel_D0, gamma])
+sel_Dst0 = Selection(name+"_Dst0",
+                            Algorithm=_Dst0,
+                            RequiredSelections=[sel_D0, pi0])
+
+sel_all_dst = MergedSelection("all_dst0", [sel_Dst0, sel_Dst0_gamma])
+
+sel_B0DD = Selection(name +"_B0DD",
+                            Algorithm=_B0,
+                            RequiredSelections=[sel_all_dst, KSDD])
+sel_B0LL = Selection(name +"_B0LL",
+                            Algorithm=_B0,
+                            RequiredSelections=[sel_all_dst, KSLL])
+sel_Bp = Selection(name +"_Bp",
+                            Algorithm=_Bp,
+                            RequiredSelections=[sel_all_dst, Km])
+#
+seqs = []
+
+##DecayTree
+from DecayTreeTuple.Configuration import *
+#Dm Dsp pi pi
+def make_dtf(dtt,  name, mass_constains, pv):
+    tup1 = dtt.B.addTupleTool(LoKi__Hybrid__Dict2Tuple, name + "FitTupTuple")
+    tup1.NumVar = 300
+    tup2 = tup1.addTool(LoKi__Hybrid__DTFDict, name + "FitTup")
+    tup1.Source = "LoKi::Hybrid::DTFDict/"+name+"FitTup"
+    tup2.constrainToOriginVertex = pv
+    tup2.daughtersToConstrain = mass_constains # [ "D-", "D_s+", "B0", "phi(1020)"]
+    tup3 = tup2.addTool(LoKi__Hybrid__DictOfFunctors, name+"FitTupdict")
+    tup2.Source = "LoKi::Hybrid::DictOfFunctors/"+name+"FitTupdict"
+    tup3.Variables = {}
+    for branch, decaychain in dtt.Branches.items():
+        for var in ['E','PX','PY','PZ','PT','ETA','M','ID']:
+            if branch == 'B':
+                tup3.Variables.update( {"{}_{}".format(branch, var): var})
+            else:
+                tup3.Variables.update( {"{}_{}".format(branch, var): "CHILD({},'{}')".format(var, decaychain)})
+
+# tuple.setDescriptorTemplate("${B}[B0 -> ${D1}(D- -> ${D1_K}K+ ${D1_pi1}pi- ${D1_pi2}pi-) ${D2}(D_s+ -> ${D2_K1}K- ${D2_K2}K+ ${D2_pi}pi+) ${phi}(phi(1020) -> ${K1}K+ ${K2}K-)]CC")
+#add tools
+triglist = [
+        "L0DiMuonDecision","L0ElectronDecision","L0ElectronHiDecision",
+        "L0HadronDecision","L0MuonDecision",
+        "L0PhotonDecision","L0HadronDecision",
+        "Hlt1TrackAllL0Decision","Hlt1TrackMVADecision","Hlt1TwoTrackMVADecision",
+        "Hlt2Topo2BodyBBDTDecision","Hlt2Topo3BodyBBDTDecision","Hlt2Topo4BodyBBDTDecision","Hlt2IncPhiDecision","Hlt2PhiIncPhiDecision",
+        "Hlt2Topo2BodyDecision","Hlt2Topo3BodyDecision","Hlt2Topo4BodyDecision"
+    ]
+tistos = TupleToolTISTOS('tistos')
+tistos.VerboseL0   = True
+tistos.VerboseHlt1 = True
+tistos.VerboseHlt2 = True
+tistos.TriggerList = triglist[:]
+
+tupletools = ["TupleToolGeometry",
+        "TupleToolKinematic",
+        "TupleToolEventInfo",
+        "TupleToolPid",
+        "TupleToolTrackInfo",
+        "TupleToolRecoStats",
+       # "TupleToolMCTruth",
+       # "TupleToolMCBackgroundInfo"
+        ]
+
+
+
+def make_tuple(name, dst0, dst0bar, d1, d2, K):
+    if K == "Km":
+        sel_B = sel_Bp
+    else:
+        if K == "KSDD":
+             sel_B = sel_B0DD
+        else:
+             sel_B = sel_B0LL
+    seq = SelectionSequence(name+'_seq', TopSelection=sel_B)
+    
+    ret = DecayTreeTuple( name )
+    ret.Inputs = [ seq.outputLocation() ]
+    ret.TupleName = "DecayTree" 
+    if d1 == "":
+        d1_d = "^K- ^pi+"
+        d1_n = ["D1_D_K", "D1_D_pi"]
+    else:
+        d1_d = "^K- ^pi+ ^pi+ ^pi-"
+        d1_n = ["D1_D_K", "D1_D_pi1", "D1_D_pi2", "D1_D_pi3"]
+    if d2  == "":
+        d2_d = "^K+ ^pi-"
+        d2_n = ["D2_D_K", "D2_D_pi"]
+    else:
+        d2_d = "^K+ ^pi- ^pi- ^pi+"
+        d2_n = ["D2_D_K", "D2_D_pi1", "D2_D_pi2", "D2_D_pi3"]
+    if "gamma" in dst0:
+        dst0_d = "^gamma"
+        dst0_n = ["D2_gamma"]
+    else:
+        dst0_d= "^(pi0 -> ^gamma ^gamma)"
+        dst0_n = ["D2_pi0", "D2_pi0_gamma1", "D2_pi0_gamma2"]
+    if "gamma" in dst0bar:
+        dst0bar_d = "^gamma"
+        dst0bar_n = ["D1_gamma"]
+    else:
+        dst0bar_d = "^(pi0 -> ^gamma ^gamma)"
+        dst0bar_n = ["D1_pi0", "D1_pi0_gamma1", "D1_pi0_gamma2"]
+    if K == "Km":
+        k_d = "^K-"
+        b_d = "B-"
+        k_n = ["K"]
+        decay_temp = "^[ {} -> ^(D*(2007)0 -> ^(D0 -> {}) {}) ^(D*(2007)~0 -> ^(D~0 -> {}) {}) {} ]CC".format(b_d, d1_d, dst0bar_d, d2_d, dst0_d, k_d)
+    else:
+        k_d = "^(KS0 -> ^pi+ ^pi-)"
+        b_d = "B0"
+        k_n = ["K", "K_pip", "K_pim"]
+        decay_temp = "^({} -> ^(D*(2007)0 -> ^(D0 -> {}) {}) ^(D*(2007)~0 -> ^(D~0 -> {}) {}) {})".format(b_d, d1_d, dst0bar_d, d2_d, dst0_d, k_d)
+    names = ['B','D1','D1_D'] + d1_n + dst0bar_n +  ['D2', 'D2_D'] + d2_n + dst0_n + k_n
+    decay_temp = decay_temp.replace("^", "{{{}}}").format(*names)
+    # print(name, decay_temp)
+    
+    ret.Decay = decay_temp.format(**{k: "^" for k in names})
+    decay_node_map = {k1: decay_temp.format(**{k2: "^" if k2 == k1 else "" for k2 in names}) for k1 in names}
+    # print(decay_node_map)
+    ret.addBranches(decay_node_map)
+    for part in names:
+        tool = ret.addTupleTool(TupleToolDecay, name = part)
+        if part == "D2_pi0":
+            tool.addTupleTool(TupleToolPi0Info, name="TupleToolPi0Info")
+        if part == "D1_pi0":
+            tool.addTupleTool(TupleToolPi0Info, name="TupleToolPi0Info")
+        if "gamma" in part:
+            tool.addTupleTool(TupleToolPi0Info, name="TupleToolPhotonInfo")
+    ret.ToolList+=tupletools
+    ret.B.ToolList = [ "TupleToolPropertime" ]
+    #TISTOS
+    ret.B.addTool(tistos)
+    ret.B.ToolList+=["TupleToolTISTOS/tistos"]
+    #loki
+    ret.ReFitPVs = True
+    LoKi_Lb=LoKi__Hybrid__TupleTool("LoKi_Lb")
+    LoKi_Lb.Variables =  {
+        "ETA"                  : "ETA",
+        "Y"                    : "Y",
+        "LOKI_DTF_CTAU"        : "DTF_CTAU( 0, True )",
+        "LOKI_DTF_CHI2NDOF"    : "DTF_CHI2NDOF( True )",
+        "LOKI_DTF_CTAUERR"     : "DTF_CTAUERR( 0, True )",
+        "FDCHI2_BPV"            : "BPVVDCHI2",
+        "FD_BPV"                : "BPVVD",
+        "IPCHI2_BPV"            : "BPVIPCHI2()",
+        }
+    ret.B.addTool(LoKi_Lb)
+    ret.B.ToolList+=["LoKi::Hybrid::TupleTool/LoKi_Lb"]
+
+    extra_mass = []
+    if "KS" in K:
+        extra_mass.append("KS0")
+        tagtuple = ret.B.addTool(TupleToolTagging, name="B0Tag")
+        ret.B.ToolList+=["TupleToolTagging/B0Tag"]
+        from FlavourTagging.Tunings import applyTuning, BTaggingTool
+        btagtool = tagtuple.addTool(BTaggingTool, name = "MyBTaggingTool2")
+        applyTuning(btagtool, tuning_version="Summer2017Optimisation_v4_Run2")
+        tagtuple.TaggingToolName = btagtool.getFullName()
+
+    #DTF
+    make_dtf(ret, "PV", [], True)
+    if "gamma" not in dst0:
+        make_dtf(ret, "PVALLpi0", ["D0", "D*(2007)0", "pi0", "B0"]+extra_mass, True)
+    
+        make_dtf(ret, "PVDaupi0", ["D0", "D*(2007)0", "pi0"] + extra_mass, True)
+    make_dtf(ret, "PVALL", ["D0", "D*(2007)0", "B0"]+extra_mass, True)
+    make_dtf(ret, "PVDau", ["D0", "D*(2007)0"]+extra_mass, True)
+    make_dtf(ret, "PVDauD0", ["D0", "K-"], True)
+    make_dtf(ret, "NOPV", [], False)
+    return seq, ret
+
+
+dtts = []
+
+idx = { ("", ""): 0,
+        ("", "_K3pi"): 1,
+        ("_K3pi", ""): 2,
+        ("_K3pi", "_K3pi"): 3,
+    }
+
+
+for d1, d2 in [("","")]: # , ("", "_K3pi"), ("_K3pi", ""), ("_K3pi", "_K3pi")]:
+    for dst0 in ["", "_gamma"]:
+        for dst0bar in ["", "_gamma"]:
+            for k in ["Km", "KSDD", "KSLL"]:
+                name = "B2Dst0{}{}Dst0{}{}{}".format(d1, dst0bar, d2, dst0, k)
+                seq, dtt = make_tuple(name, dst0, dst0bar, d1, d2, k)
+                seqs.append(seq)
+                dtts.append(dtt)
+
+if False:
+    from Configurables import PrintDecayTree, PrintDecayTreeTool
+    tree = PrintDecayTree("PrintFoundBs")
+    tree.Inputs = seqs[-1].outputLocations() #[ "/Event/CharmCompleteEvent/Phys/{}/Particles".format(lines[0]) ]
+    tree.addTool( PrintDecayTreeTool, name = "PrintDecay" )
+    tree.PrintDecay.Information = "Name M P Px Py Pz Pt chi2"
+    DaVinci().MoniSequence += [ tree ]
+
+
+
+tuples = dtts
+
+
+from Configurables import CheckPV
+checkpv = CheckPV()
+from Configurables import TrackScaleState as SCALER
+scaler = SCALER('Scaler')
+from Configurables import TrackSmearState as SMEAR
+smear = SMEAR('Smear')
+
+###davinci
+DaVinci().EvtMax = -1                       # Number of events
+DaVinci().Simulation   = False
+DaVinci().Lumi = not DaVinci().Simulation
+DaVinci().EventPreFilters = fltrs.filters('Filter')
+DaVinci().UserAlgorithms = [ checkpv]
+if(DaVinci().Simulation == False):
+    DaVinci().UserAlgorithms += [scaler];
+else:
+    DaVinci().UserAlgorithms += [smear]
+DaVinci().UserAlgorithms += seqs + tuples
+
+#DaVinci().TupleFile = "B02DmDspipi.root"
+DaVinci().PrintFreq = 1000
+#locationRoot = "/Event/CharmCompleteEvent"
+#DaVinci().RootInTES = locationRoot
+# DaVinci().InputType = 'DST'
+
+########################################################################
+MessageSvc().Format = "% F%60W%S%7W%R%T %0W%M"
+from Configurables import  DaVinciInit, GetIntegratedLuminosity
+# DaVinciInit().OutputLevel = 6
+# MessageSvc().OutputLevel                  = 6
+GetIntegratedLuminosity().OutputLevel       = INFO
+ToolSvc().OutputLevel                     = 6
+NTupleSvc().OutputLevel                   = 6
+
diff --git a/B2Dst0Dst0K_Run12/info.yaml b/B2Dst0Dst0K_Run12/info.yaml
new file mode 100644
index 0000000000..1a697be00d
--- /dev/null
+++ b/B2Dst0Dst0K_Run12/info.yaml
@@ -0,0 +1,31 @@
+defaults:
+    application: DaVinci/v46r11
+    wg: B2OC
+    automatically_configure: yes
+    turbo: no
+    inform:
+        - y.jiang@cern.ch
+          # root_in_tes: /Event/Bhadron 
+
+# Real data (collision)
+{%- set collision_datasets2 = [
+    ('11', '3500', '14',  '21r1p2'),
+    ('12', '4000', '14',  '21r0p2'),
+    ('15', '6500', '15a', '24r2'),
+    ('16', '6500', '16',  '28r2'),
+    ('17', '6500', '17',  '29r2p1'),
+    ('18', '6500', '18',  '34r0p1'),
+]%}
+
+{%- for year, beam, reco, strip in collision_datasets2 %}
+  {%- for polarity in ['MagDown','MagUp'] %}
+20{{year}}_{{polarity}}_collision_B2Dst0Dst0K:
+    input:
+        bk_query: /LHCb/Collision{{year}}/Beam{{beam}}GeV-VeloClosed-{{polarity}}/Real Data/Reco{{reco}}/Stripping{{strip}}/90000000/CHARMCOMPLETEEVENT.DST
+        n_test_lfns: 1
+    options:
+        - dv_tupling.py
+    output: B2Dst0Dst0K.ROOT
+  {%- endfor %}
+{%- endfor %}
+
-- 
GitLab