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
+ 626
18
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 urllib.request import DataHandler
from Gaudi.Configuration import INFO, VERBOSE
from Functors.grammar import BoundFunctor
from PyConf.Algorithms import SubstitutePIDAlg_Particles
import Functors as F
import re
class SubstitutePID:
"""
SubstitutePID is an DaVinci python tool which can configure easily the PID substitution
for DaVinci and create functors to access the necesary information.
The substitution syntax is the following:
' Old_PID{{New_PID}} '
Args:
Input (DataHandle): the Input data handle (TES).
Substitutions (list): substitution rules, using the substitution syntax.
Name (str): Name of the substitution algorithm, will printed in the Gaudi.
OutputLevel (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 subtituted 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,
Input: DataHandler,
Substitutions: list,
Name='',
OutputLevel=INFO):
# Check
if not Substitutions:
raise ValueError("The 'Substitutions' rules can't be empty.")
for Subs in Substitutions:
if Subs.lower().find(']cc'):
raise ValueError(
"The '[]cc' syntax is not yet supported in the SubstitutePID tool. "
)
# Basic
self.OutputLevel = OutputLevel
# Extend subsitituions
SubstitutionMap = self._GetSubsitutionMap(Substitutions)
# Find all possible decays
decays = []
for decay_descriptor, subsituted_pid in SubstitutionMap.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
if Name == '':
self.Algorithm = SubstitutePIDAlg_Particles(
Input=Input,
Decays=decays,
Substitute=SubstitutionMap,
OutputLevel=OutputLevel)
else:
self.Algorithm = SubstitutePIDAlg_Particles(
name=Name,
Input=Input,
Decays=decays,
Substitute=SubstitutionMap,
OutputLevel=OutputLevel)
# 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 _GetSubsitutionMap(self, Subsitutions: list):
if self.OutputLevel <= VERBOSE:
print("==============================")
print(
"SubstitutePID will extend the substitution rules to the following substitution map:"
)
print("{")
# Compile the regex
find_subs = re.compile(r'{{(.*?)}}')
SubstitutionMap = {}
for Subsitution in Subsitutions:
if self.OutputLevel <= VERBOSE:
print("SubstitutePID: ", Subsitution)
# Find the targets
targets = find_subs.findall(Subsitution)
pos = 0
for target in targets:
# Find target
target_full = '{{' + target + '}}'
target_start = Subsitution.find(target_full, pos + 1)
target_end = target_start + len(target_full)
pos = target_end
# Find origin
origin_start = max(
Subsitution.rfind(' ', 0, target_start) + 1, 0)
if Subsitution[origin_start] == '(':
origin_start += 1
origin_end = target_start
origin = Subsitution[origin_start:origin_end]
# Extend substitution rule
add_hat = Subsitution[
0:origin_start] + '^' + origin + Subsitution[target_end:]
remove_else = find_subs.sub('', add_hat)
SubstitutionMap[remove_else] = target
if self.OutputLevel <= VERBOSE:
for key, value in SubstitutionMap.items():
print(f"\t '{key}' : '{value}',")
if self.OutputLevel <= VERBOSE:
print("}")
print("==============================")
return SubstitutionMap
Loading