HLT2 trigger line to select D0 to KsKs
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

345 lines
12 KiB

1 year ago
1 year ago
  1. ###############################################################################
  2. # (c) Copyright 2020 CERN for the benefit of the LHCb Collaboration #
  3. # #
  4. # This software is distributed under the terms of the GNU General Public #
  5. # Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". #
  6. # #
  7. # In applying this licence, CERN does not waive the privileges and immunities #
  8. # granted to it by virtue of its status as an Intergovernmental Organization #
  9. # or submit itself to any jurisdiction. #
  10. ###############################################################################
  11. """
  12. Lines to select the decay D*+ -> D0 pi+ with D0 -> KS0 KS0 and KS0 -> pi+ pi-.
  13. The KS0 can be reconstructed either from long, downstream or upstream track, resulting
  14. in the combinations LLLL, LLLD, LLDD, LDDD, DDDD, ULLL, ULDD.
  15. """
  16. import Functors as F
  17. from Functors.math import in_range
  18. from GaudiKernel.SystemOfUnits import MeV, mm, GeV
  19. from Moore.config import register_line_builder
  20. from Moore.lines import Hlt2Line
  21. from RecoConf.reconstruction_objects import make_pvs
  22. from Hlt2Conf.standard_particles import make_down_pions, make_long_pions, make_up_pions
  23. from Hlt2Conf.algorithms import ParticleContainersMerger
  24. from Hlt2Conf.algorithms_thor import (ParticleCombiner, ParticleFilter)
  25. from Hlt2Conf.lines.charm.particle_properties import _KS_M
  26. from Hlt2Conf.lines.charm.prefilters import charm_prefilters
  27. #####################################################################
  28. ### Shortcuts for filters and builders used throughout the module ###
  29. #####################################################################
  30. def make_tagging_pions():
  31. return ParticleFilter(
  32. make_long_pions(),
  33. F.FILTER(F.require_all(F.PT > 200 * MeV, F.P > 1 * GeV)),
  34. )
  35. def _make_long_pions_from_ks():
  36. return ParticleFilter(
  37. make_long_pions(),
  38. F.FILTER(F.MINIPCHI2CUT(IPChi2Cut=36., Vertices=make_pvs())))
  39. def _make_down_pions_from_ks():
  40. return ParticleFilter(
  41. make_down_pions(),
  42. F.FILTER(F.require_all(F.PT > 175 * MeV, F.P > 3000 * MeV)))
  43. def _make_down_pions_from_ks_LD():
  44. return ParticleFilter(
  45. make_down_pions(),
  46. F.FILTER(F.require_all(F.PT > 100 * MeV, F.P > 2000 * MeV)))
  47. def _make_up_pions_from_ks():
  48. return ParticleFilter(
  49. make_up_pions(),
  50. F.FILTER(F.MINIPCHI2CUT(IPChi2Cut=10., Vertices=make_pvs())))
  51. def _make_ll_ks(descriptor="KS0 -> pi+ pi-"):
  52. """Returns maker for KS0 -> pi+ pi- constructed with two long pions."""
  53. return ParticleCombiner(
  54. [_make_long_pions_from_ks(),
  55. _make_long_pions_from_ks()],
  56. DecayDescriptor=descriptor,
  57. name='Charm_D0ToKsKs_Ks_LL_{hash}',
  58. CombinationCut=F.require_all(
  59. in_range(_KS_M - 50 * MeV, F.MASS, _KS_M + 50 * MeV),
  60. F.PT > 450 * MeV,
  61. ),
  62. CompositeCut=F.require_all(
  63. in_range(_KS_M - 30 * MeV, F.MASS, _KS_M + 30 * MeV),
  64. F.CHI2DOF < 7,
  65. in_range(-100 * mm, F.END_VZ, 500 * mm),
  66. F.PT > 500 * MeV,
  67. ),
  68. )
  69. def _make_ll_ks_ULLL(descriptor="KS0 -> pi+ pi-"):
  70. """Returns maker for KS0 -> pi+ pi- constructed with two long pions only for ULLL."""
  71. return ParticleCombiner(
  72. [_make_long_pions_from_ks(),
  73. _make_long_pions_from_ks()],
  74. DecayDescriptor=descriptor,
  75. name='Charm_D0ToKsKs_Ks_LL_ULLL_{hash}',
  76. CombinationCut=F.require_all(
  77. in_range(_KS_M - 50 * MeV, F.MASS, _KS_M + 50 * MeV),
  78. F.PT > 250 * MeV,
  79. ),
  80. CompositeCut=F.require_all(
  81. in_range(_KS_M - 30 * MeV, F.MASS, _KS_M + 30 * MeV),
  82. F.CHI2DOF < 7,
  83. in_range(-100 * mm, F.END_VZ, 500 * mm),
  84. F.PT > 300 * MeV,
  85. ),
  86. )
  87. def _make_ld_ks(descriptor="KS0 -> pi+ pi-"):
  88. """Returns maker for KS0 -> pi+ pi- constructed with a long and downstream pion."""
  89. return ParticleCombiner(
  90. [_make_long_pions_from_ks(),
  91. _make_down_pions_from_ks_LD()],
  92. DecayDescriptor=descriptor,
  93. name='Charm_D0ToKsKs_Ks_LD_{hash}',
  94. CombinationCut=F.require_all(
  95. in_range(_KS_M - 85 * MeV, F.MASS, _KS_M + 85 * MeV),
  96. F.PT > 450 * MeV,
  97. ),
  98. CompositeCut=F.require_all(
  99. in_range(_KS_M - 65 * MeV, F.MASS, _KS_M + 65 * MeV),
  100. F.CHI2DOF < 10,
  101. in_range(50 * mm, F.END_VZ, 500 * mm),
  102. F.PT > 500 * MeV,
  103. ),
  104. )
  105. def _make_dd_ks(descriptor="KS0 -> pi+ pi-"):
  106. """Returns maker for KS0 -> pi+ pi- constructed with two downstream pions."""
  107. return ParticleCombiner(
  108. [_make_down_pions_from_ks(),
  109. _make_down_pions_from_ks()],
  110. DecayDescriptor=descriptor,
  111. name='Charm_D0ToKsKs_Ks_DD_{hash}',
  112. CombinationCut=F.require_all(
  113. in_range(_KS_M - 80 * MeV, F.MASS, _KS_M + 80 * MeV),
  114. F.PT > 450 * MeV,
  115. ),
  116. CompositeCut=F.require_all(
  117. in_range(_KS_M - 60 * MeV, F.MASS, _KS_M + 60 * MeV),
  118. F.CHI2DOF < 10,
  119. in_range(300 * mm, F.END_VZ, 2275 * mm),
  120. F.PT > 500 * MeV,
  121. ),
  122. )
  123. def _make_ul_ks(descriptor="KS0 -> pi+ pi-"):
  124. """Returns maker for KS0 -> pi+ pi- constructed with one long and one upstream pion."""
  125. return ParticleCombiner(
  126. [_make_up_pions_from_ks(),
  127. _make_long_pions_from_ks()],
  128. DecayDescriptor=descriptor,
  129. name='Charm_D0ToKsKs_Ks_UL_{hash}',
  130. CombinationCut=F.require_all(
  131. in_range(_KS_M - 90 * MeV, F.MASS, _KS_M + 90 * MeV),
  132. F.PT > 350 * MeV,
  133. ),
  134. CompositeCut=F.require_all(
  135. in_range(_KS_M - 70 * MeV, F.MASS, _KS_M + 70 * MeV),
  136. F.CHI2DOF < 10,
  137. in_range(-100 * mm, F.END_VZ, 500 * mm),
  138. F.PT > 400 * MeV,
  139. ),
  140. )
  141. def _make_dstars(dzeros, pions, descriptor):
  142. """Returns maker for D*+- -> D0 pi+-."""
  143. return ParticleCombiner(
  144. [dzeros, pions],
  145. DecayDescriptor=descriptor,
  146. name='Charm_D0ToKsKs_Dstars_{hash}',
  147. CombinationCut=F.MASS - F.CHILD(1, F.MASS) < 160 * MeV,
  148. CompositeCut=F.require_all(
  149. F.MASS - F.CHILD(1, F.MASS) < 150 * MeV,
  150. F.CHI2DOF < 25, # fix due to control channel
  151. ),
  152. )
  153. #########################
  154. ### Lines definition ###
  155. #########################
  156. all_lines = {}
  157. @register_line_builder(all_lines)
  158. def dst_to_d0pi_d0toksks_llll(
  159. name="Hlt2Charm_DstpToD0Pip_D0ToKsKs_LLLL"):
  160. pvs = make_pvs()
  161. kshorts = _make_ll_ks()
  162. dzeros = ParticleCombiner(
  163. [kshorts, kshorts],
  164. DecayDescriptor="D0 -> KS0 KS0",
  165. name="Charm_D0ToKsKs_D0ToKsKs_LLLL",
  166. CombinationCut=F.require_all(
  167. in_range(1730 * MeV, F.MASS, 2000 * MeV),
  168. F.SUM(F.PT) > 1500 * MeV,
  169. ),
  170. CompositeCut=F.require_all(
  171. in_range(1775 * MeV, F.MASS, 1955 * MeV),
  172. F.BPVFDCHI2(pvs) > 5,
  173. F.CHI2DOF < 10, # fix
  174. F.BPVDIRA(pvs) > 0.9994,
  175. ),
  176. )
  177. pitag = make_tagging_pions()
  178. dstarp = _make_dstars(dzeros, pitag, "D*(2010)+ -> D0 pi+")
  179. dstarm = _make_dstars(dzeros, pitag, "D*(2010)- -> D0 pi-")
  180. dstars = ParticleContainersMerger([dstarp, dstarm])
  181. return Hlt2Line(
  182. name=name, algs=charm_prefilters() + [kshorts, dzeros, dstars])
  183. @register_line_builder(all_lines)
  184. def dst_to_d0pi_d0toksks_llld_line(
  185. name="Hlt2Charm_DstpToD0Pip_D0ToKsKs_LLLD"):
  186. pvs = make_pvs()
  187. ll_kshorts = _make_ll_ks()
  188. ld_kshorts = _make_ld_ks()
  189. dzeros = ParticleCombiner(
  190. [ll_kshorts, ld_kshorts],
  191. DecayDescriptor="D0 -> KS0 KS0",
  192. name="Charm_D0ToKsKs_D0ToKsKs_LLLD",
  193. AllowDiffInputsForSameIDChildren=True,
  194. CombinationCut=F.require_all(
  195. in_range(1730 * MeV, F.MASS, 2000 * MeV),
  196. F.SUM(F.PT) > 1500 * MeV,
  197. ),
  198. CompositeCut=F.require_all(
  199. in_range(1775 * MeV, F.MASS, 1955 * MeV),
  200. F.CHI2DOF < 10,
  201. F.BPVDIRA(pvs) > 0.9994,
  202. ),
  203. )
  204. pitag = make_tagging_pions()
  205. dstarp = _make_dstars(dzeros, pitag, "D*(2010)+ -> D0 pi+")
  206. dstarm = _make_dstars(dzeros, pitag, "D*(2010)- -> D0 pi-")
  207. dstars = ParticleContainersMerger([dstarp, dstarm])
  208. return Hlt2Line(name=name, algs=charm_prefilters() + [ld_kshorts, dzeros, dstars])
  209. @register_line_builder(all_lines)
  210. def dst_to_d0pi_d0toksks_lldd(
  211. name="Hlt2Charm_DstpToD0Pip_D0ToKsKs_LLDD"):
  212. pvs = make_pvs()
  213. dd_kshorts = _make_dd_ks()
  214. ll_kshorts = _make_ll_ks()
  215. dzeros = ParticleCombiner(
  216. [dd_kshorts, ll_kshorts],
  217. DecayDescriptor="D0 -> KS0 KS0",
  218. AllowDiffInputsForSameIDChildren=True,
  219. name="Charm_D0ToKsKs_D0ToKsKs_LLDD",
  220. CombinationCut=F.require_all(
  221. in_range(1730 * MeV, F.MASS, 2000 * MeV),
  222. F.SUM(F.PT) > 1500 * MeV,
  223. ),
  224. CompositeCut=F.require_all(
  225. in_range(1775 * MeV, F.MASS, 1955 * MeV),
  226. F.CHI2DOF < 10,
  227. F.BPVDIRA(pvs) > 0.9994,
  228. ),
  229. )
  230. pitag = make_tagging_pions()
  231. dstarp = _make_dstars(dzeros, pitag, "D*(2010)+ -> D0 pi+")
  232. dstarm = _make_dstars(dzeros, pitag, "D*(2010)- -> D0 pi-")
  233. dstars = ParticleContainersMerger([dstarp, dstarm])
  234. return Hlt2Line(
  235. name=name, algs=charm_prefilters() + [dd_kshorts, dzeros, dstars])
  236. @register_line_builder(all_lines)
  237. def dst_to_d0pi_d0toksks_dddd(
  238. name="Hlt2Charm_DstpToD0Pip_D0ToKsKs_DDDD"):
  239. pvs = make_pvs()
  240. dd_kshorts = _make_dd_ks()
  241. dzeros = ParticleCombiner(
  242. [dd_kshorts, dd_kshorts],
  243. DecayDescriptor="D0 -> KS0 KS0",
  244. name="Charm_D0ToKsKs_D0ToKsKs_DDDD",
  245. CombinationCut=F.require_all(
  246. in_range(1730 * MeV, F.MASS, 2000 * MeV),
  247. F.SUM(F.PT) > 1500 * MeV,
  248. ),
  249. CompositeCut=F.require_all(
  250. in_range(1775 * MeV, F.MASS, 1955 * MeV),
  251. F.CHI2DOF < 10,
  252. F.BPVDIRA(pvs) > 0.9994,
  253. ),
  254. )
  255. pitag = make_tagging_pions()
  256. dstarp = _make_dstars(dzeros, pitag, "D*(2010)+ -> D0 pi+")
  257. dstarm = _make_dstars(dzeros, pitag, "D*(2010)- -> D0 pi-")
  258. dstars = ParticleContainersMerger([dstarp, dstarm])
  259. return Hlt2Line(
  260. name=name, algs=charm_prefilters() + [dd_kshorts, dzeros, dstars])
  261. @register_line_builder(all_lines)
  262. def dst_to_d0pi_d0toksks_ulll(
  263. name="Hlt2Charm_DstpToD0Pip_D0ToKsKs_ULLL"):
  264. pvs = make_pvs()
  265. ll_kshorts = _make_ll_ks_ULLL()
  266. ul_kshorts = _make_ul_ks()
  267. dzeros = ParticleCombiner(
  268. [ll_kshorts, ul_kshorts],
  269. DecayDescriptor="D0 -> KS0 KS0",
  270. name="Charm_D0ToKsKs_D0ToKsKs_ULLL",
  271. AllowDiffInputsForSameIDChildren=True,
  272. CombinationCut=F.require_all(
  273. in_range(1730 * MeV, F.MASS, 2000 * MeV),
  274. F.SUM(F.PT) > 1500 * MeV,
  275. ),
  276. CompositeCut=F.require_all(
  277. in_range(1775 * MeV, F.MASS, 1955 * MeV),
  278. F.CHI2DOF < 10,
  279. F.BPVDIRA(pvs) > 0.9994,
  280. ),
  281. )
  282. pitag = make_tagging_pions()
  283. dstarp = _make_dstars(dzeros, make_tagging_pions(), "D*(2010)+ -> D0 pi+")
  284. dstarm = _make_dstars(dzeros, make_tagging_pions(), "D*(2010)- -> D0 pi-")
  285. dstars = ParticleContainersMerger([dstarp, dstarm])
  286. return Hlt2Line(
  287. name=name, algs=charm_prefilters() + [ul_kshorts, dzeros, dstars])