From e23b01f0d0b58b9a6f09afeb0aeee3f3996aa45e Mon Sep 17 00:00:00 2001
From: Aravindhan Venkateswaran <aravindhan.venkateswaran@cern.ch>
Date: Fri, 14 Jul 2023 19:39:06 +0200
Subject: [PATCH] New line for B -> Tau nu

---
 .../StrippingRD/StrippingB2TauNu.py           | 207 ++++++++++++++++++
 .../StrippingRD/__init__.py                   |   3 +-
 2 files changed, 209 insertions(+), 1 deletion(-)
 create mode 100644 Phys/StrippingSelections/python/StrippingSelections/StrippingRD/StrippingB2TauNu.py

diff --git a/Phys/StrippingSelections/python/StrippingSelections/StrippingRD/StrippingB2TauNu.py b/Phys/StrippingSelections/python/StrippingSelections/StrippingRD/StrippingB2TauNu.py
new file mode 100644
index 000000000..65af88015
--- /dev/null
+++ b/Phys/StrippingSelections/python/StrippingSelections/StrippingRD/StrippingB2TauNu.py
@@ -0,0 +1,207 @@
+###############################################################################
+# (c) Copyright 2000-2019 CERN for the benefit of the LHCb Collaboration      #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+from StandardParticles import StdLooseAllPhotons
+from StandardParticles import StdLooseKaons, StdNoPIDsKaons
+from StandardParticles import StdNoPIDsPions, StdLoosePions
+from StrippingUtils.Utils import LineBuilder
+from StrippingConf.StrippingLine import StrippingLine
+from PhysSelPython.Wrappers import Selection, DataOnDemand, SimpleSelection, PassThroughSelection
+from GaudiConfUtils.ConfigurableGenerators import FilterDesktop, CombineParticles, OfflineVertexFitter, DaVinci__N3BodyDecays
+from GaudiConfUtils.ConfigurableGenerators import AddRelatedInfo
+from Configurables import RelInfoConeVariables, RelInfoVertexIsolation
+from Gaudi.Configuration import *
+__author__ = ['F. Blanc', "A. Venkateswaran"]
+__date__ = '13/07/2023'
+__version__ = '$Revision: 0.1$'
+
+# Stripping line for B->tau nu
+
+from GaudiKernel.SystemOfUnits import MeV
+from GaudiKernel.SystemOfUnits import mm
+"""
+  B->TauNu
+"""
+__all__ = ('B2TauNuConf', 'getRelInfoB2TauNu', 'default_config')
+
+default_config = {
+    'NAME': 'B2TauNu',
+    'BUILDERTYPE': 'B2TauNuConf',
+    'WGs': ['RD'],
+    'CONFIG': {
+        'SpdMult': '600',
+        #
+        'FDZ_MIN_B': 10,
+        'FDZ_MAX_B': 100,
+        'PT_MIN_B': 2500 * MeV,
+        'P_MIN_B': 10000 * MeV,
+        'FDCHI2_MIN_B': 16,
+        'VTXCHI2_MAX_B': 6,
+        'BPVDIRA_MIN_B': 0.9,
+        'MASS_MIN_pipipi': 400 * MeV,
+        'MASS_MAX_pipipi': 2100 * MeV,
+        'MVIS_MIN_B': 500 * MeV,
+        'MVIS_MAX_B': 1900 * MeV,
+        'CORRM_MIN_B': 1900 * MeV,
+        'CORRM_MAX_B': 10000 * MeV,
+        #
+        'COMB_PT': 800 * MeV,
+        'COMB_NUMPT': 1000 * MeV,
+        'COMB_MAXDOCA': 0.2 * mm,
+        #
+        'PT_Pion': 250 * MeV,
+        'P_Pion': 1000 * MeV,
+        'IPCHI2_Tr': 16,
+        'TRACKCHI2_Tr': 4,
+        'TRGHOPROB_Tr': 0.4,
+        'PROBNNPI_Pion': 0.55,
+        #
+        'B2TauNu_LineNoPrescale': 1,
+        'B2TauNu_LinePrescale': 0.1,
+        'B2TauNu_LinePostscale': 1,
+        #
+        'B2TauNu_HLTSelection': "HLT_PASS_RE('Hlt1(Two)?Track.*Decision')"
+    },
+    'STREAMS': ['Bhadron']
+}
+
+
+class B2TauNuConf(LineBuilder):
+    """
+      Builder for B->TauNu
+    """
+
+    __configuration_keys__ = default_config['CONFIG'].keys()
+
+    def __init__(self, name, config):
+
+        LineBuilder.__init__(self, name, config)
+
+        trackCuts = "(MIPCHI2DV(PRIMARY) > %(IPCHI2_Tr)s) & (TRCHI2DOF < %(TRACKCHI2_Tr)s) & (TRGHOSTPROB < %(TRGHOPROB_Tr)s)" % config
+        trackCuts += " & (PT > %(PT_Pion)s) & (P > %(P_Pion)s)" % config
+        PionCuts = trackCuts + " & (PROBNNpi > %(PROBNNPI_Pion)s)" % config
+
+        self.FilterSPD = {
+            'Code':
+            " ( recSummary(LHCb.RecSummary.nSPDhits,'Raw/Spd/Digits') < %(SpdMult)s )"
+            % config,
+            'Preambulo': [
+                "from LoKiNumbers.decorators import *",
+                "from LoKiCore.basic import LHCb"
+                ]
+            }
+
+        self.selPions = SimpleSelection(
+            "Pions" + name, FilterDesktop, [StdLoosePions], Code=PionCuts)
+        self.selTracks = SimpleSelection(
+            "Tracks" + name, FilterDesktop, [StdNoPIDsPions], Code=trackCuts)
+
+        self.selB2TauNu = self._makeB2TauNu(name, self.selPions, config)
+        self.selB2TauNuNoPID = self._makeB2TauNu(name + "NoPID", self.selTracks, config)
+        self.selB2TauNuSS = self._makeB2TauNu(name + "SS", self.selPions, config, SS=True)
+
+        # Finished making selections build and register lines
+
+        self.B2TauNu_Line = self._makeLine("B2TauNuLine",
+                                           self.selB2TauNu, config)
+        self.B2TauNuNoPID_Line = self._makeLine("B2TauNuNoPIDLine",
+                                                self.selB2TauNuNoPID, config, PreScale=True)
+        self.B2TauNuSS_Line = self._makeLine("B2TauNuSSLine",
+                                             self.selB2TauNuSS, config)
+
+# Make B candidate selection
+
+    def _makeB2TauNu(self, name, tracks, config, SS=False):
+
+        combcut = "(APT>%(COMB_PT)s) & (AMAXDOCA('')<%(COMB_MAXDOCA)s) & (ANUM(PT > %(COMB_NUMPT)s) >= 1)" % config
+        combcut += " & (in_range ( %(MASS_MIN_pipipi)s, AM, %(MASS_MAX_pipipi)s ) )" % config
+
+        mothercut = "( BPVVDCHI2 > %(FDCHI2_MIN_B)s ) & ( BPVVDZ > %(FDZ_MIN_B)s*mm ) & ( BPVVDZ < %(FDZ_MAX_B)s*mm )" % config
+        mothercut += " & (PT > %(PT_MIN_B)s) & (P > %(P_MIN_B)s) & (M > %(MVIS_MIN_B)s) & (M < %(MVIS_MAX_B)s) " % config
+        mothercut += " & (VFASPF(VCHI2) < %(VTXCHI2_MAX_B)s) & (BPVDIRA > %(BPVDIRA_MIN_B)s )" % config
+        mothercut += " & (BPVCORRM > %(CORRM_MIN_B)s ) & (BPVCORRM < %(CORRM_MAX_B)s ) " % config
+
+        descriptors = ["[B+ -> pi+ pi- pi+]cc"]
+        if SS:
+            descriptors = ["[B+ -> pi+ pi+ pi+]cc"]
+
+        Combine = DaVinci__N3BodyDecays(
+            DecayDescriptors=descriptors,
+            Combination12Cut="AM < 1800",
+            CombinationCut=combcut,
+            MotherCut=mothercut)
+
+        presel = Selection(name, Algorithm=Combine, RequiredSelections=[tracks])
+
+        # determine vertex isolation variables, and add them to the candidate for further selection
+        tool          = RelInfoVertexIsolation('TauIsoInfo')
+        algo          = AddRelatedInfo()
+        algo.Inputs   = [presel.outputLocation()]
+        algo.Location = 'Iso'
+        algo.Tool     = tool.getFullName()
+        tau_withinfo  = PassThroughSelection(name+'TauInfo', Algorithm=algo, RequiredSelection=presel)
+        loc  = presel.outputLocation().replace('/Particles', '/Iso')
+        # apply selection based on isolation variables
+        sel = SimpleSelection(name+"IsoFilter",
+                              FilterDesktop,
+                              [tau_withinfo],
+                              Code="RELINFO('"+loc+"', 'VTXISODCHI2ONETRACK', 100000.) >25")
+
+        return sel
+
+# Helpers to make lines
+
+    def _makeLine(self, name, sel, config, PreScale=False):
+
+        pscale = config['B2TauNu_LineNoPrescale']
+        if PreScale:
+            pscale = config['B2TauNu_LinePrescale']
+
+        line = StrippingLine(
+            name,
+            prescale=pscale,
+            postscale=config['B2TauNu_LinePostscale'],
+            # MDSTFlag = False,
+            FILTER=self.FilterSPD,
+            HLT1=config['B2TauNu_HLTSelection'],
+            RelatedInfoTools=getRelInfoB2TauNu(),
+            selection=sel,
+            MaxCandidates=50)
+        self.registerLine(line)
+        return line
+
+# Related Info
+def getRelInfoB2TauNu():
+
+    relInfo = []
+    for coneAngle in [0.5, 0.8, 1.0, 1.3, 1.5]:
+        conestr = str(coneAngle).replace('.', '')
+        relInfo += [{
+            "Type":
+            "RelInfoConeVariables",
+            "IgnoreUnmatchedDescriptors":
+            True,
+            "ConeAngle":
+            coneAngle,
+            "Location":
+            "VertexConeInfo",
+            "Variables": [
+                          'CONEANGLE', 'CONEMULT', 'CONEPASYM', 'CONEPTASYM',
+                          'CONEDELTAETA'
+                          ],
+            "DaughterLocations": {
+                                  "^[Beauty -> X+ X- X+]CC": 'P2ConeVar%s_B' % conestr
+                                  }
+            }]
+    relInfo += [{
+        "Type": "RelInfoVertexIsolation",
+        "Location": "VertexIsoInfo"
+        }]
+    return relInfo
diff --git a/Phys/StrippingSelections/python/StrippingSelections/StrippingRD/__init__.py b/Phys/StrippingSelections/python/StrippingSelections/StrippingRD/__init__.py
index d17a0859b..04d4bf3cd 100644
--- a/Phys/StrippingSelections/python/StrippingSelections/StrippingRD/__init__.py
+++ b/Phys/StrippingSelections/python/StrippingSelections/StrippingRD/__init__.py
@@ -31,7 +31,8 @@ _selections = ('StrippingRareBaryonicMuMu',
                'StrippingB2KstTauTau', 
                'StrippingS2Hyperons',
                'StrippingB2XTauTau.py',
-               'StrippingB2STauTauInclusive.py'
+               'StrippingB2STauTauInclusive.py',
+               'StrippingB2TauNu.py'
         )
 
 for _sel in _selections :
-- 
GitLab