From 063d1dad05b4a7fe87d4bca7f85bc81d41bc90fd Mon Sep 17 00:00:00 2001
From: Yi Jiang <y.jiang@cern.ch>
Date: Mon, 27 Jan 2025 05:55:03 +0100
Subject: [PATCH 1/2] add B -> D(*s) D(*s) phi data

---
 Bs2DDphi_Run12/dv_tupling.py | 229 +++++++++++++++++++++++++++++++++++
 Bs2DDphi_Run12/info.yaml     |  31 +++++
 2 files changed, 260 insertions(+)
 create mode 100644 Bs2DDphi_Run12/dv_tupling.py
 create mode 100644 Bs2DDphi_Run12/info.yaml

diff --git a/Bs2DDphi_Run12/dv_tupling.py b/Bs2DDphi_Run12/dv_tupling.py
new file mode 100644
index 0000000000..6851372fa0
--- /dev/null
+++ b/Bs2DDphi_Run12/dv_tupling.py
@@ -0,0 +1,229 @@
+
+###
+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 DecayTreeTuple, LoKi__Hybrid__TupleTool, TupleToolDecay, TupleToolTrigger, TupleToolTISTOS, TupleToolTagging
+from Configurables import FitDecayTrees, TupleToolGeometry
+from Configurables import DecayTreeTuple, LoKi__Hybrid__TupleTool, TupleToolDecay, TupleToolTrigger, TupleToolTISTOS, TupleToolTagging, TupleToolRecoStats
+from Configurables import FitDecayTrees, TupleToolGeometry
+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, StdLoosePhotons as gamma,  StdLooseKsLL as KS_LL,  StdLooseKsDD as KS_DD, StdAllNoPIDsKaons as Kpi, StdAllNoPIDspions as pipm
+
+
+lines = [ 'B2DDphi_B2DDPhiLine','B2DDphi_B2DsDsPhiLine','B2DDphi_B2DstDpPhiLine','B2DDphi_B2DstDstPhiLine']
+
+#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]) +")")
+#make the candidates
+
+# KFromB = FilterInTrees('KFromB', Code="('K+'==ABSID)")
+# selKFromB = Selection("selKFromB",
+#         Algorithm = KFromB,
+#         RequiredSelections = [DataOnDemand("/Phys/{}/Particles".format(lines[0]))])
+
+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 = 200
+    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, location, d1, d2):
+    ret = DecayTreeTuple( name )
+    ret.Inputs = [ location ]
+    ret.TupleName = "DecayTree"
+    if d1 == "D":
+        d1_d = "^(D+ -> ^K- ^pi+ ^pi+)"
+        d1_n = ["D1_K", "D1_pi1", "D1_pi2"]
+    elif d1 == "Dst":
+        d1_d = "^(D*(2010)+ -> ^([D0]CC -> ^K- ^pi+) ^pi+)"
+        d1_n = ["D1_D", "D1_D_K", "D1_D_pi", "D1_pi"]
+    elif d1 == "Ds":
+        d1_d = "^(D_s+ -> ^K- ^K+ ^pi+)"
+        d1_n = ["D1_K1", "D1_K2", "D1_pi"]
+    if d2 == "D":
+        d2_d = "^(D- -> ^K+ ^pi- ^pi-)"
+        d2_n = ["D2_K", "D2_pi1", "D2_pi2"]
+    elif d2 == "Dst":
+        d2_d = "^(D*(2010)- -> ^([D~0]CC -> ^K+ ^pi-) ^pi-)"
+        d2_n = ["D2_D", "D2_D_K", "D2_D_pi", "D2_pi"]
+    elif d2 == "Ds":
+        d2_d = "^(D_s- -> ^K+ ^K- ^pi-)"
+        d2_n = ["D2_K1", "D2_K2", "D2_pi"]
+    decay_temp = " [B_s0]CC -> {} {} ^K+ ^K- ".format(d1_d, d2_d)
+    if d1 == d2:
+        decay_temp = "^( " + decay_temp + " )"
+    else:
+        decay_temp = "^[ " + decay_temp + " ]CC"
+    names = ['B','D1'] + d1_n + ["D2"]+ d2_n + ["Kp", "Km"]
+    decay_temp = decay_temp.replace("^", "{{{}}}").format(*names)
+
+    ret.Decay = decay_temp.format(**{k: "^" for k in names})
+    ret.addBranches({k1: decay_temp.format(**{k2: "^" if k2 == k1 else "" for k2 in names}) for k1 in names})
+    for part in names:
+        ret.addTupleTool(TupleToolDecay, name = part)
+    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",
+        }
+    ret.B.addTool(LoKi_Lb)
+    ret.B.ToolList+=["LoKi::Hybrid::TupleTool/LoKi_Lb"]
+    if False:
+       tagtuple = ret.B.addTool(TupleToolTagging, name="B0Tag")
+       ret.B.ToolList+=["TupleToolTagging/B0Tag"]
+       tagtuple.UseFTfromDST = True  # tell TTT to read the FT info from the dst
+       tagtuple.ActiveTaggerTypes = [
+          "OSCharm",
+          "OSElectron",
+          "OSElectronLatest",
+          "OSKaon",
+          "OSKaonLatest",
+          "OSMuon",
+          "OSMuonLatest",
+          "OSVtxCh",
+          "SSKaon",
+          "SSKaonLatest",
+          "SSPion",
+          "SSProton",
+       ]
+       tagtuple.OutputLevel = 6
+
+    #DTF
+    extra_mass = []
+    d_m = []
+    if d1 == "D" or d2 == "D":
+        d_m.append("D+")
+    if d1 == "Ds" or d2 == "Ds":
+        d_m.append("D_s+")
+    if d1 == "Dst" or d2 == "Dst":
+        d_m.append("D0")
+        extra_mass.append("D*(2010)+")
+    make_dtf(ret, "PV", [], True)
+    make_dtf(ret, "PVALL", ["B_s0"] + d_m + extra_mass, True)
+    make_dtf(ret, "PVDau", d_m + extra_mass, True)
+    if len(extra_mass) > 0:
+        make_dtf(ret, "PVDauD0", d_m, True)
+    make_dtf(ret, "NOPV", [], False)
+    return ret
+
+
+dtts = []
+for idx, (d1, d2) in enumerate([["D", "D"], ["Ds", "Ds"], ["Dst", "D"], ["Dst", "Dst"]]):
+    name = "Bs2{}{}Phi".format(d1, d2)
+    location = "/Phys/{}/Particles".format(lines[idx])
+    dtts.append(make_tuple(name, location, d1, d2))
+
+
+if False:
+    from Configurables import PrintDecayTree, PrintDecayTreeTool
+    tree = PrintDecayTree("PrintFoundBs")
+    tree.Inputs = [ SeqB2DDK.outputLocation() ]
+    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/Bs2DDphi_Run12/info.yaml b/Bs2DDphi_Run12/info.yaml
new file mode 100644
index 0000000000..c60e47097b
--- /dev/null
+++ b/Bs2DDphi_Run12/info.yaml
@@ -0,0 +1,31 @@
+defaults:
+    application: DaVinci/v46r11
+    wg: B2OC
+    automatically_configure: yes
+    turbo: no
+    inform:
+        - y.jiang@cern.ch
+
+# Real data (collision)
+{%- set collision_datasets2 = [
+    ('11', '3500', '14',  '21r1'),
+    ('12', '4000', '14',  '21'),
+    ('15', '6500', '15a', '24r2'),
+    ('16', '6500', '16',  '28r2'),
+    ('17', '6500', '17',  '29r2'),
+    ('18', '6500', '18',  '34'),
+]%}
+
+{%- for year, beam, reco, strip in collision_datasets2 %}
+  {%- for polarity in ['MagDown','MagUp'] %}
+20{{year}}_{{polarity}}_collision_Bs2DDPhi:
+    input:
+        bk_query: /LHCb/Collision{{year}}/Beam{{beam}}GeV-VeloClosed-{{polarity}}/Real Data/Reco{{reco}}/Stripping{{strip}}/90000000/BHADRON.MDST
+        n_test_lfns: 1
+    options:
+        - dv_tupling.py
+    output: Bs2DDPhi.ROOT
+    root_in_tes: /Event/Bhadron
+  {%- endfor %}
+{%- endfor %}
+
-- 
GitLab


From a116dd157510fd6ab196b8b8d8aa776e820d7427 Mon Sep 17 00:00:00 2001
From: Yi Jiang <y.jiang@cern.ch>
Date: Tue, 28 Jan 2025 04:45:58 +0100
Subject: [PATCH 2/2] add more cuts to reduce output size

---
 Bs2DDphi_Run12/dv_tupling.py | 67 ++++++++++++++++++++++++++++++++----
 1 file changed, 61 insertions(+), 6 deletions(-)

diff --git a/Bs2DDphi_Run12/dv_tupling.py b/Bs2DDphi_Run12/dv_tupling.py
index 6851372fa0..238042ac36 100644
--- a/Bs2DDphi_Run12/dv_tupling.py
+++ b/Bs2DDphi_Run12/dv_tupling.py
@@ -27,7 +27,44 @@ from PhysConf.Filters import LoKi_Filters
 fltrs = LoKi_Filters(STRIP_Code = "("+"|".join(["HLT_PASS_RE('Stripping{}Decision')".format(line) for line in lines]) +")")
 #make the candidates
 
-# KFromB = FilterInTrees('KFromB', Code="('K+'==ABSID)")
+KFromB = FilterInTrees('KFromB', Code="('K+'==ABSID)")
+DFromB = FilterInTrees('DFromB', Code="('D+'==ABSID)|('D_s+'==ABSID)|('D*(2010)+'==ABSID)")
+
+_phi =  CombineParticles('comb_phi',
+        DecayDescriptors=["phi(1020) -> K+ K-"],
+                       CombinationCut="(AM<1100*MeV) & (ADOCACHI2CUT(30, ''))",
+                       MotherCut="(VFASPF(VCHI2) < 25.0)",
+                       DaughtersCuts   = {'K+': "ALL",'K-': "ALL"},
+        ReFitPVs        = True)
+
+combine_b = {"DD":
+    CombineParticles('comb_B1',
+        DecayDescriptors=["B_s0 -> D+ D- phi(1020)"],
+                       CombinationCut="(AM<5800*MeV)",
+                       MotherCut="(VFASPF(VCHI2/VDOF) < 15) & (BPVDIRA > 0.999) & (BPVLTIME() > 0.2*ps)",
+                       DaughtersCuts   = {'D+': "ALL",'D-': "ALL", "phi(1020)": "ALL"},
+        ReFitPVs        = True),
+    "DsDs":   CombineParticles('comb_B2',
+        DecayDescriptors=["B_s0 -> D_s+ D_s- phi(1020)"],
+                       CombinationCut="(AM<5800*MeV)",
+                       MotherCut="(VFASPF(VCHI2/VDOF) < 15) & (BPVDIRA > 0.999) & (BPVLTIME() > 0.2*ps)",
+                       DaughtersCuts   = {'D_s+': "ALL",'D_s-': "ALL", "phi(1020)": "ALL"},
+        ReFitPVs        = True),
+    "DstD":CombineParticles('comb_B3',
+        DecayDescriptors=["[B_s0 -> D*(2010)+ D- phi(1020)]cc"],
+                       CombinationCut="(AM<5800*MeV)",
+                       MotherCut="(VFASPF(VCHI2/VDOF) < 15) & (BPVDIRA > 0.999) & (BPVLTIME() > 0.2*ps)",
+                       DaughtersCuts   = {'D*(2010)+': "ALL",'D-': "ALL", "phi(1020)": "ALL"},
+        ReFitPVs        = True),
+    "DstDst": CombineParticles('comb_B4',
+        DecayDescriptors=["B_s0 -> D*(2010)+ D*(2010)- phi(1020)"],
+                       CombinationCut="(AM<5800*MeV)",
+                       MotherCut="(VFASPF(VCHI2/VDOF) < 15) & (BPVDIRA > 0.999) & (BPVLTIME() > 0.2*ps)",
+                       DaughtersCuts   = {'D*(2010)+': "ALL",'D*(2010)-': "ALL", "phi(1020)": "ALL"},
+        ReFitPVs        = True)
+}
+
+
 # selKFromB = Selection("selKFromB",
 #         Algorithm = KFromB,
 #         RequiredSelections = [DataOnDemand("/Phys/{}/Particles".format(lines[0]))])
@@ -82,8 +119,22 @@ tupletools = ["TupleToolGeometry",
 
 
 def make_tuple(name, location, d1, d2):
+    data_in_line = DataOnDemand(location)
+    sel_k = Selection( name+"_K",
+            Algorithm          = KFromB ,
+            RequiredSelections = [ data_in_line ] )
+    sel_d = Selection( name+"_D",
+            Algorithm          = DFromB ,
+            RequiredSelections = [ data_in_line ] )
+    sel_phi = Selection( name+"_phi",
+            Algorithm          = _phi ,
+            RequiredSelections = [sel_k ] )
+    sel_b = Selection( name+"_B",
+            Algorithm          = combine_b[d1+d2] ,
+            RequiredSelections = [sel_d, sel_phi ] )
+    seq = SelectionSequence("Seq" +name, TopSelection = sel_b)
     ret = DecayTreeTuple( name )
-    ret.Inputs = [ location ]
+    ret.Inputs = [seq.outputLocation() ]
     ret.TupleName = "DecayTree"
     if d1 == "D":
         d1_d = "^(D+ -> ^K- ^pi+ ^pi+)"
@@ -103,12 +154,12 @@ def make_tuple(name, location, d1, d2):
     elif d2 == "Ds":
         d2_d = "^(D_s- -> ^K+ ^K- ^pi-)"
         d2_n = ["D2_K1", "D2_K2", "D2_pi"]
-    decay_temp = " [B_s0]CC -> {} {} ^K+ ^K- ".format(d1_d, d2_d)
+    decay_temp = " [B_s0]CC -> {} {} ^(phi(1020) -> ^K+ ^K-) ".format(d1_d, d2_d)
     if d1 == d2:
         decay_temp = "^( " + decay_temp + " )"
     else:
         decay_temp = "^[ " + decay_temp + " ]CC"
-    names = ['B','D1'] + d1_n + ["D2"]+ d2_n + ["Kp", "Km"]
+    names = ['B','D1'] + d1_n + ["D2"]+ d2_n + ["phi", "Kp", "Km"]
     decay_temp = decay_temp.replace("^", "{{{}}}").format(*names)
 
     ret.Decay = decay_temp.format(**{k: "^" for k in names})
@@ -166,18 +217,22 @@ def make_tuple(name, location, d1, d2):
         extra_mass.append("D*(2010)+")
     make_dtf(ret, "PV", [], True)
     make_dtf(ret, "PVALL", ["B_s0"] + d_m + extra_mass, True)
+    make_dtf(ret, "PVALLphi", ["B_s0", "phi(1020)"] + d_m + extra_mass, True)
     make_dtf(ret, "PVDau", d_m + extra_mass, True)
+    make_dtf(ret, "PVDauphi", ["phi(1020)"] + d_m + extra_mass, True)
     if len(extra_mass) > 0:
         make_dtf(ret, "PVDauD0", d_m, True)
     make_dtf(ret, "NOPV", [], False)
-    return ret
+    return seq, ret
 
 
 dtts = []
 for idx, (d1, d2) in enumerate([["D", "D"], ["Ds", "Ds"], ["Dst", "D"], ["Dst", "Dst"]]):
     name = "Bs2{}{}Phi".format(d1, d2)
     location = "/Phys/{}/Particles".format(lines[idx])
-    dtts.append(make_tuple(name, location, d1, d2))
+    seq, tup = make_tuple(name, location, d1, d2)
+    seqs.append(seq)
+    dtts.append(tup)
 
 
 if False:
-- 
GitLab