diff --git a/Hlt/Hlt1Conf/options/hlt1_example_muon_lines.py b/Hlt/Hlt1Conf/options/hlt1_example_muon_lines.py new file mode 100644 index 0000000000000000000000000000000000000000..e33ca4837697dacf0c8f5615b43df7cd3a3128b1 --- /dev/null +++ b/Hlt/Hlt1Conf/options/hlt1_example_muon_lines.py @@ -0,0 +1,221 @@ +############################################################################### +# (c) Copyright 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 __future__ import absolute_import, division, print_function +import math +from collections import namedtuple + +InputSample = namedtuple('InputSample', ['tfdb', 'ftdec_v', 'multi_threading']) + +from GaudiKernel.SystemOfUnits import mm, MeV, GeV + +from PyConf import ( + configurable, ) +from Hlt1Conf.lines import ( + require_all, + require_any, + TrackV1FilterWithPVs, + TrackCombinerWithPVs, +) + +from Hlt1Conf.reconstruction import ( + gec, + RawData, + FilterEmptyPVs, + make_velo_tracks, + make_VeloUT_tracks, + make_IPselectedTracks, + make_forward_tracks, + make_muonmatchvelout_tracks, + make_param_forward_fitted_tracks, + make_pvs, + EmptyFilter, + VeloUTTracking, + SciFiTrackForwarding, + convert_tracksUT_to_v2tracks, + convert_IPselectedTracks_to_v2tracks, +) + +from PyConf.components import Algorithm +from PyConf.environment import EverythingHandler + +from PyConf.Algorithms import FTRawBankDecoder + + +def patch_hybrid_tool(): + """Remove Hybrid modules that require a DVAlgorithm. + + Some modules import functors that depend on the DVAlgorithm context being + available. The LoKi::Hybrid::Tool tool loads these modules by default, but + we don't want nor need them, so remove them from the default list. + """ + # List of modules we will delete from the default list + dv_modules = ["LoKiPhys.decorators", "LoKiArrayFunctors.decorators"] + + from Configurables import LoKi__Hybrid__Tool + factory = LoKi__Hybrid__Tool("HybridFactory") + for m in dv_modules: + del factory.Modules[factory.Modules.index(m)] + # Add the Track functors as we'll need most of these + # It can be important to include this in the Modules, otherwise the functor + # context patching might not be applied in time (e.g. if a Track functor is + # imported and instantiated in the preamble) + factory.Modules.append('LoKiTrack.decorators') + + +@configurable +def single_muon_line(code='TrALL', + make_input_tracks=make_param_forward_fitted_tracks, + make_pvs=make_pvs): + + return TrackV1FilterWithPVs( + Code=code, Input=make_input_tracks(), InputVertices=make_pvs()).Output + + +@configurable +def dimuon_line( + daughter_cuts='TrALL', + CombinationCut=None, + VertexCut='VALL', + combiner_preamble=[ + "from LoKiPhys.decorators import RV_MASS, RV_PT, VCHI2PDOF, VX, VY" + ], + make_input_tracks=make_param_forward_fitted_tracks, + make_pvs=make_pvs): + + pvs = make_pvs() + + daughters = TrackV1FilterWithPVs( + Code=daughter_cuts, Input=make_input_tracks(), + InputVertices=pvs).Output + + return TrackCombinerWithPVs( + NBodies=2, + Preamble=combiner_preamble, + CombinationCut=CombinationCut, + VertexCut=VertexCut, + InputTracks=daughters, + InputVertices=pvs).OutputVertices + + +#sample = InputSample('MiniBrunel_2018_MinBias_FTv4_MDF', ftdec_v=4, multi_threading=True) +sample = InputSample( + 'upgrade-magup-sim10-up01-34112106-xdigi', + ftdec_v=6, + multi_threading=False) # KS0 -> mu+ mu- upgrade MC + +with FTRawBankDecoder.bind(DecodingVersion=sample.ftdec_v): + + gec = gec(FTDecodingVersion=sample.ftdec_v) + + NoPVFilter = FilterEmptyPVs() + # + # Configuration of muon lines + # + single_muon_cuts = require_all( + 'TrPT > {min_pt}', + 'TrP > {min_p}', + 'TrCHI2PDOF < {max_chi2pdof}', + 'TrMINIPCHI2 > {min_ipchi2}', + ) + dimuon_lines_dc = single_muon_cuts + dimuon_lines_cc = require_all( + 'RV_PT > {min_vertex_pt}', + "RV_MASS('mu+', 'mu-') > {min_vertex_mass}", + ) + dimuon_lines_vc = require_all( + 'VCHI2PDOF < {max_vertex_chi2pdof}', + '(VX**2 + VY**2) > {min_vertex_rho2}', + ) + + with make_forward_tracks.bind(make_tracks=make_muonmatchvelout_tracks): + + with make_VeloUT_tracks.bind(make_velo_tracks=make_velo_tracks), \ + convert_IPselectedTracks_to_v2tracks.bind(make_tracks=make_velo_tracks): + single_muon = single_muon_line( + code=single_muon_cuts.format( + min_pt=1.5 * GeV, + min_p=3 * GeV, + min_ipchi2=0, + max_chi2pdof=3)) + + dimuon = dimuon_line( + daughter_cuts=dimuon_lines_dc.format( + min_pt=250 * MeV, + min_p=3 * GeV, + min_ipchi2=0, + max_chi2pdof=3), + CombinationCut=dimuon_lines_cc.format( + min_vertex_pt=0 * MeV, min_vertex_mass=220 * MeV), + VertexCut=dimuon_lines_vc.format( + max_vertex_chi2pdof=25, + min_vertex_rho2=0 * mm * mm, + )) + + with VeloUTTracking.bind( + name='VeloUTDetached', + minPT=80 * MeV, + minPTFinal=80 * MeV, + minMomentumFinal=2.5 * GeV), \ + SciFiTrackForwarding.bind( + name='ForwardTrackingDetached', + MinPt=80, + PreSelectionPT=0.): + with make_IPselectedTracks.bind(ip_cut=10 * mm): + single_muon_detached = single_muon_line( + code=single_muon_cuts.format( + min_pt=80 * MeV, + min_p=3 * GeV, + min_ipchi2=100, + max_chi2pdof=3)) + with make_IPselectedTracks.bind(ip_cut=0.4 * mm): + dimuon_detached = dimuon_line( + daughter_cuts=dimuon_lines_dc.format( + min_pt=80 * MeV, + min_p=3 * GeV, + min_ipchi2=9, + max_chi2pdof=4), + CombinationCut=dimuon_lines_cc.format( + min_vertex_pt=0 * MeV, min_vertex_mass=220 * MeV), + VertexCut=dimuon_lines_vc.format( + max_vertex_chi2pdof=25, + min_vertex_rho2=0 * mm * mm, + )) + + # + # Register the lines + # + if sample.multi_threading: + mt_opts = dict(threadPoolSize=5, nEventSlots=4) + else: + mt_opts = dict(threadPoolSize=1, nEventSlots=1) + + env = EverythingHandler(evtMax=1000, debug=True, **mt_opts) + env.registerLine( + 'single_muon', + algs=[ + gec, NoPVFilter, + EmptyFilter(InputLocation=make_velo_tracks()), single_muon + ]) + env.registerLine( + 'single_muon_detached', algs=[gec, NoPVFilter, single_muon_detached]) + env.registerLine( + 'dimuon', algs=[gec, NoPVFilter, + EmptyFilter(InputLocation=dimuon)]) + env.registerLine( + 'dimuon_detached', + algs=[gec, NoPVFilter, + EmptyFilter(InputLocation=dimuon_detached)]) + + env.setupInputFromTestFileDB(sample.tfdb) + env.configure() + #env.plotDataFlow() # only if you have graphivz available + +patch_hybrid_tool() diff --git a/Hlt/Hlt1Conf/python/Hlt1Conf/reconstruction.py b/Hlt/Hlt1Conf/python/Hlt1Conf/reconstruction.py index 08a988ad245c427aae2c1805b048d6471429d96e..8486a0b55cc58aa5f2dba94ed09fb3bf7773d96b 100644 --- a/Hlt/Hlt1Conf/python/Hlt1Conf/reconstruction.py +++ b/Hlt/Hlt1Conf/python/Hlt1Conf/reconstruction.py @@ -42,6 +42,8 @@ from PyConf.Algorithms import ( TrackBeamLineVertexFinderSoA, SciFiTrackForwardingStoreHit, VeloKalman, + MuonRawToHits, + MuonMatchVeloUTSoA, ) from GaudiKernel.SystemOfUnits import mm, MeV @@ -167,6 +169,11 @@ def convert_tracksVP_to_v2tracks( HitsLocation=hits).OutputTracksLocation +@configurable +def make_Muon_hits(raw=RawData): + return MuonRawToHits(RawEventLocation=raw().RawEvent).HitContainer + + @configurable def convert_IPselectedTracks_to_v2tracks(make_tracks=make_IPselectedTracks, make_hits=make_velo_hits): @@ -188,6 +195,36 @@ def convert_tracksUT_to_v2tracks( @configurable +def make_muonmatchvelout_tracks(make_velout_tracks=make_VeloUT_tracks, + make_muon_hits=make_Muon_hits): + + tracks = MuonMatchVeloUTSoA( + InputTracks=make_velout_tracks(), + InputMuonHits=make_muon_hits()).OutputTracks + return tracks + + +@configurable +def make_param_forward_fitted_tracks(make_tracks=make_forward_tracks, + convertToSelection=True): + + from Configurables import TrackMasterExtrapolator, SimplifiedMaterialLocator + materiallocator = Tool(SimplifiedMaterialLocator) + extrapolator = Tool( + TrackMasterExtrapolator, + MaterialLocator=materiallocator, + ApplyMultScattCorr=True, + ApplyEnergyLossCorr=False, + ApplyElectronEnergyLossCorr=True) + + fitted_tracks = ParamForwardFit( + InputName=make_tracks(), Extrapolator=extrapolator).OutputName + # fitted_tracks = ParamForwardFit(InputName = make_tracks()).OutputName + if not convertToSelection: + return fitted_tracks + return SelTrackV1(Input=fitted_tracks).Output + + def convert_tracksFT_to_v2tracks( make_velout_tracks=convert_tracksUT_to_v2tracks, make_forward_tracks=make_forward_tracks): @@ -220,8 +257,7 @@ def convert_fitted_tracks_to_v2tracks( @configurable -def make_param_forward_fitted_tracks( - make_tracks=convert_fitted_tracks_to_v2tracks): +def make_param_forward_fitted_tracks(make_tracks=convert_tracksFT_to_v2tracks): track_v1 = fromV2TrackV1TrackVector( InputTracksName=make_tracks()).OutputTracksName return TrackV1Selection(Input=track_v1).Output diff --git a/Hlt/Hlt1Conf/tests/qmtest/test_hlt1_example_muon_lines.qmt b/Hlt/Hlt1Conf/tests/qmtest/test_hlt1_example_muon_lines.qmt new file mode 100644 index 0000000000000000000000000000000000000000..98cb7bdd300acdf1a24be3c9139d98a53b28fdc9 --- /dev/null +++ b/Hlt/Hlt1Conf/tests/qmtest/test_hlt1_example_muon_lines.qmt @@ -0,0 +1,42 @@ + + + + +gaudirun.py + + $HLT1CONFROOT/options/hlt1_example_muon_lines.py + --output=hlt1_example_muon_lines.opts.py + --all-opt + + +from Configurables import HiveDataBrokerSvc +HiveDataBrokerSvc().OutputLevel = 5 + +true + + +countErrorLines({"FATAL": 0, "ERROR": 0, "WARNING": 0}) + +# test that at least one event fires +import re +m = re.search('NONLAZY_OR: hlt_decision .*Sum=(\d+)', stdout) +if m: + result['hlt_decision_sum'] = result.Quote(m.group(1)) + if int(m.group(1)) < 1: + causes.append('no positive decisions found') +else: + causes.append('hlt_decision counter not found') + + +