From fb81c0140a765b6dfc08c5acf402b3be4140234a Mon Sep 17 00:00:00 2001
From: Yi Jiang <y.jiang@cern.ch>
Date: Fri, 22 Nov 2024 17:06:07 +0100
Subject: [PATCH] add B0 -> D*0 D0 KS

---
 B02Dst0D0KS_Run12/dv_tupling.py | 244 ++++++++++++++++++++++++++++++++
 B02Dst0D0KS_Run12/info.yaml     |  30 ++++
 2 files changed, 274 insertions(+)
 create mode 100644 B02Dst0D0KS_Run12/dv_tupling.py
 create mode 100644 B02Dst0D0KS_Run12/info.yaml

diff --git a/B02Dst0D0KS_Run12/dv_tupling.py b/B02Dst0D0KS_Run12/dv_tupling.py
new file mode 100644
index 0000000000..a5621bc973
--- /dev/null
+++ b/B02Dst0D0KS_Run12/dv_tupling.py
@@ -0,0 +1,244 @@
+
+###
+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
+
+
+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]) +")")
+#make the candidates
+
+DFromB = FilterInTrees('DFromB', Code="('D0'==ABSID)")
+selDFromB = Selection("selDFromB",
+        Algorithm = DFromB,
+        RequiredSelections = [DataOnDemand("/Event/CharmCompleteEvent/Phys/{}/Particles".format(lines[0]))])
+
+# KFromB = FilterInTrees('KFromB', Code="('K+'==ABSID)")
+# selKFromB = Selection("selKFromB",
+#         Algorithm = KFromB,
+#         RequiredSelections = [DataOnDemand("/Phys/{}/Particles".format(lines[0]))])
+
+# pi0 = DataOnDemand(Location = "/Event/Phys/StdLooseResolvedPi0/Particles")
+# gamma  = DataOnDemand(Location = "/Event/Phys/StdLoosePhotons/Particles")
+
+
+_dst = CombineParticles( "_Dst",
+    DecayDescriptor = "[D*(2007)0 -> D0 pi0]cc",
+    CombinationCut = "(ADAMASS('D*(2007)0') < 600*MeV)",
+    MotherCut       = "(M-MAXTREE(ABSID=='D0',M) < 200*MeV)",
+    DaughtersCuts   = {
+        'D0': "ALL",
+        'pi0': "ALL"
+        },
+    ReFitPVs        = True )
+dst = Selection( "Dst",
+    Algorithm          = _dst,
+    RequiredSelections = [selDFromB, pi0] ) 
+
+_dst2 = CombineParticles( "_Dst2",
+    DecayDescriptor = "[D*(2007)0 -> D0 gamma]cc",
+    CombinationCut = "(AALL)",
+    MotherCut       = "(M-MAXTREE(ABSID=='D0',M) < 200*MeV)",
+    DaughtersCuts   = {
+        'D0': "ALL",
+        'gamma': "ALL"
+        },
+    ReFitPVs        = True )
+dst2 = Selection( "Dst2",
+    Algorithm          = _dst2,
+    RequiredSelections = [selDFromB, gamma] )
+
+_B2DDK = CombineParticles( "_B2Dst0D0K",
+    DecayDescriptors = ["[B0 -> D*(2007)0 D~0 KS0]cc", "[B~0 -> D*(2007)~0 D0 KS0]cc"],
+    CombinationCut = "((AM<7000*MeV) & (AM>4750*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))",
+    ReFitPVs        = True )
+
+all_dst = MergedSelection("all_dst0", [dst, dst2])
+
+B2DDK  = Selection( "B2Dst0D0KSLL",
+    Algorithm          = _B2DDK ,
+    RequiredSelections = [ all_dst, selDFromB,  KS_LL] )
+
+B2DDK2  = Selection( "B2Dst0D0KSDD",
+    Algorithm          = _B2DDK ,
+    RequiredSelections = [ all_dst, selDFromB,  KS_DD] )
+
+
+### Gaudi sequence
+SeqB2DDK = SelectionSequence("SeqB2Dst0D0KLL", TopSelection = B2DDK)
+SeqB2DDK2 = SelectionSequence("SeqB2Dst0D0KDD", TopSelection = B2DDK2)
+seq = SeqB2DDK.sequence()
+seq2 = SeqB2DDK2.sequence()
+
+##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, dst0, cc=False):
+    ret = DecayTreeTuple( name )
+    ret.Inputs = [ location ]
+    ret.TupleName = "DecayTree"
+
+    D1 = "^K- ^pi+"
+    D2 = "^K+ ^pi-"
+    bar1, bar2 = "", "~"
+    decay_temp = "^[ [B0]CC -> ^(D*(2007)"+bar1+"0 -> ^(D"+bar1+"0 -> "+D1+") "
+    if "pi0" in dst0:
+        decay_temp += "^(pi0 -> ^gamma ^gamma)" # .replace("^", "{{{}}}").format(*dst)
+    else:
+        decay_temp += "^gamma" # .replace("^", "{{{}}}").format(*dst)
+    decay_temp += ") ^(D"+bar2+"0 -> "+D2+") ^(KS0 -> ^pi+ ^pi-) ]CC"
+    names = ['B','D1','D1_D', 'D1_D_K', 'D1_D_pi'] + dst0 + [ 'D2', 'D2_K', 'D2_pi', 'K', "K_pip", "K_pim"]
+    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"]
+
+
+    #DTF
+    extra_mass = []
+    if "pi0" in dst0:
+        extra_mass = ["pi0"]
+    make_dtf(ret, "PVALL", ["D*(2007)0", "D0", "B0", "KS0"] + extra_mass, True)
+    make_dtf(ret, "PV", [], True)
+    make_dtf(ret, "PVDau", ["D*(2007)0", "D0", "KS0"] + extra_mass, True)
+    make_dtf(ret, "NOPV", [], False)
+    return ret
+
+
+dtt1 = make_tuple("B02Dst0D0KSLL", SeqB2DDK.outputLocation(), ["pi0", "gamma1", "gamma2"])
+dtt2 = make_tuple("B02Dst0_gammaD0KSLL",SeqB2DDK.outputLocation(), ["gamma"])
+dtt3 = make_tuple("B02Dst0D0KSDD", SeqB2DDK2.outputLocation(), ["pi0", "gamma1", "gamma2"])
+dtt4 = make_tuple("B02Dst0_gammaD0KSDD",SeqB2DDK2.outputLocation(), ["gamma"])
+
+
+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 = [dtt1, dtt2, dtt3, dtt4]
+
+
+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, seq, seq2 ] + tuples
+if(DaVinci().Simulation == False):
+    DaVinci().UserAlgorithms += [scaler];
+else:
+    DaVinci().UserAlgorithms += [smear]
+
+#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/B02Dst0D0KS_Run12/info.yaml b/B02Dst0D0KS_Run12/info.yaml
new file mode 100644
index 0000000000..02d84ec368
--- /dev/null
+++ b/B02Dst0D0KS_Run12/info.yaml
@@ -0,0 +1,30 @@
+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',  '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_B02Dst0D0KS:
+    input:
+        bk_query: /LHCb/Collision{{year}}/Beam{{beam}}GeV-VeloClosed-{{polarity}}/Real Data/Reco{{reco}}/Stripping{{strip}}/90000000/CHARMCOMPLETEEVENT.DST
+        n_test_lfns: 3
+    options:
+        - dv_tupling.py
+    output: B02Dst0D0KS.ROOT
+  {%- endfor %}
+{%- endfor %}
+
-- 
GitLab