Skip to content
Snippets Groups Projects

New PID Substitution DaVinci Tool

Merged Jiahui Zhuo requested to merge jzhuo_SubsPID into master
Compare and
7 files
+ 637
7
Compare changes
  • Side-by-side
  • Inline
Files
7
###############################################################################
# (c) Copyright 2022 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 PyConf.dataflow import DataHandle
from Gaudi.Configuration import INFO, DEBUG, VERBOSE, ALL
from Functors.grammar import BoundFunctor
from PyConf.Algorithms import SubstitutePIDAlg_Particles
import Functors as F
import re
class SubstitutePID:
"""
Python tool to help with the configuration of the PID substitution `SubstitutePIDAlg_Particles`
and the creation of functors to access the necessary information.
.. note::
You can configure the mass hypothesis subsitution using the following syntax:
' Old_PID{{New_PID}} '
The '[]cc' syntax is not yet supported in the SubstitutePID tool, you have to
specify the substitution rule explicitly for each cc case.
e.g.
'[B+ -> K+ K+ K-{{pi-}}]cc' => ['B+ -> K+ K+ K-{{pi-}}', 'B- -> K- K- K+{{pi+}}']
Args:
name (str): name of the substitution algorithm, will printed in the Gaudi.
substitutions (list): substitution rules, using the substitution syntax.
input (DataHandle): the input data handle (TES)
output_level (int, optional): standard Gaudi Algorithm OutputLevel.
Example:
# Create the tool
Subs_PhiG = SubstitutePID(
name = 'Subs_PhiG',
input = B_Data,
substitutions = [
'B0{{B_s0}} -> ( K*(892)0{{phi(1020)}} -> K+ K- ) gamma'
]
)
Subs_KstG = SubstitutePID(
name = 'Subs_KstG',
input = B_Data,
substitutions = [
'B0 -> ( K*(892)0 -> K+ K-{{pi-}} ) gamma'
]
)
# Get the energy of the substituted particle
allvariables['ENERGY'] = F.ENERGY
allvariables['PhiG_ENERGY'] = Subs_PhiG.get_info( F.ENERGY )
allvariables['KstG_ENERGY'] = Subs_KstG.get_info( F.ENERGY )
"""
def __init__(self,
name: str,
input: DataHandle,
substitutions: list,
output_level=INFO):
# Check
if not substitutions:
raise ValueError("The 'substitutions' rules can't be empty.")
for Subs in substitutions:
if Subs.lower().find(']cc') != -1:
raise ValueError(
"The '[]cc' syntax is not yet supported in the SubstitutePID tool. "
"You have to specify the substitution rule explicitly for each cc case."
)
# Extend subsitituions
subsitution_map = self._get_subsitution_map(substitutions,
output_level)
# Find all possible decays
decays = []
for decay_descriptor, _ in subsitution_map.items():
simple_descriptor = decay_descriptor.replace('^', ' ')
repeated = False
for decay in decays:
if decay.replace(' ', '') == simple_descriptor.replace(
' ', ''):
repeated = True
break
if not repeated:
decays.append(simple_descriptor)
# Create gaudi algorithm
self.Algorithm = SubstitutePIDAlg_Particles(
name=name,
Input=input,
Decays=decays,
Substitute=subsitution_map,
OutputLevel=output_level)
# Store the algorithm result
self.AllParticles = self.Algorithm.AllParticles
self.Particles = self.Algorithm.Particles
self.Relation = self.Algorithm.Relation
def get_info(self, Functor: BoundFunctor):
"""
Apply a specified functor to the result particle of substitution
Args:
Functor (BoundFunctor): the functor to be applied
Return:
BoundFunctor: result functor
Example:
variables['SUBS_CHI2DOF'] = Subs.get_info(F.CHI2DOF)
"""
return F.MAP_INPUT(Functor, self.Relation)
def _get_subsitution_map(self, substitutions: list, output_level):
if output_level in {DEBUG, VERBOSE, ALL}:
print("==============================")
print(
"SubstitutePID will extend the substitution rules to the following substitution map:"
)
print("{")
# Compile the regex
find_subs = re.compile(r'{{(.*?)}}')
substitution_map = {}
for substitution in substitutions:
# Find the targets
targets = find_subs.findall(substitution)
pos = 0
for target in targets:
# Find target
target_full = '{{' + target + '}}'
target_start = substitution.find(target_full, pos + 1)
target_end = target_start + len(target_full)
pos = target_end
# Find origin
origin_start = max(
substitution.rfind(' ', 0, target_start) + 1, 0)
if substitution[origin_start] == '(':
origin_start += 1
origin_end = target_start
origin = substitution[origin_start:origin_end]
# Extend substitution rule
add_hat = substitution[
0:origin_start] + '^' + origin + substitution[target_end:]
remove_else = find_subs.sub('', add_hat)
substitution_map[remove_else] = target
if output_level in {DEBUG, VERBOSE, ALL}:
for key, value in substitution_map.items():
print(f"\t '{key}' : '{value}',")
if output_level in {DEBUG, VERBOSE, ALL}:
print("}")
print("==============================")
return substitution_map
Loading