From 20df393f9f9c130b7760109488a6321b4f4fe612 Mon Sep 17 00:00:00 2001 From: Davide Fazzini <davide.fazzini@cern.ch> Date: Mon, 21 Mar 2022 09:15:35 +0100 Subject: [PATCH] Adding qmtest for ParticleTaggerAlg and related functors --- .../option_davinci_tupling_array_taggers.py | 88 +++++++++++++++ .../test_davinci_tupling_array_taggers.qmt | 43 ++++++++ .../test_davinci_tupling_array_taggers.ref | 100 ++++++++++++++++++ .../python/DaVinci/standard_particles.py | 57 ++++++++++ 4 files changed, 288 insertions(+) create mode 100644 DaVinciExamples/python/DaVinciExamples/tupling/option_davinci_tupling_array_taggers.py create mode 100644 DaVinciExamples/tests/qmtest/tupling.qms/test_davinci_tupling_array_taggers.qmt create mode 100644 DaVinciExamples/tests/refs/test_davinci_tupling_array_taggers.ref diff --git a/DaVinciExamples/python/DaVinciExamples/tupling/option_davinci_tupling_array_taggers.py b/DaVinciExamples/python/DaVinciExamples/tupling/option_davinci_tupling_array_taggers.py new file mode 100644 index 000000000..2f05c38f4 --- /dev/null +++ b/DaVinciExamples/python/DaVinciExamples/tupling/option_davinci_tupling_array_taggers.py @@ -0,0 +1,88 @@ +############################################################################### +# (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. # +############################################################################### +""" + Option file for testing the ParticleTaggerAlg algorithm and the related ThOr functors MAP_ARRAY and MAP_RANGE. + The job runs over a spruced sample and retrieves a set of B0 -> Ds K+ candidates. For each candidate the ParticleTaggerAlg + looks at the TES location defined via the 'make_long_pions_from_spruce' function and creates a 'one-to-many' relation map + relating all the available tracks to the B candidate of the events. + Then the MAP_ARRAY functor takes in input this relation map and for each entry stores the output of an external functor (i.e F.P, F.PT) + in a vector via the MAP_RANGE functor. + + This example is meant to be run with + $ ./run davinci run-mc --inputfiledb Spruce_all_lines_dst Phys/DaVinci/options/DaVinciDB-Example.yaml --user_algorithms DaVinciExamples/python/DaVinciExamples/tupling/option_davinci_tupling_array_taggers:main +""" + +import Functors as F +from PyConf.application import make_data_with_FetchDataFromFile +from PyConf.Algorithms import ParticleTaggerAlg, ParticleContainerMerger +from FunTuple import FunctorCollection, FunTuple_Particles as Funtuple +from DaVinci.algorithms import add_filter +from DaVinci.standard_particles import make_long_pions_from_spruce + +bd2dsk_line = "SpruceB2OC_BdToDsmK_DsmToHHH_FEST_Line" +bd2dsk_data = make_data_with_FetchDataFromFile( + f"/Event/Spruce/{bd2dsk_line}/Particles") +pions = make_long_pions_from_spruce() + +tagging_container = ParticleContainerMerger( + InputContainers=[pions]).OutputContainer + +tagAlg = ParticleTaggerAlg( + Input=bd2dsk_data, TaggingContainer=tagging_container, OutputLevel=3) +tagAlg_rels = tagAlg.OutputRelations + +#make collection of functors +variables_B = FunctorCollection({ + 'THOR_MASS': + F.MASS, + "TagTr_P": + F.MAP_INPUT_ARRAY(Functor=F.MAP_RANGE(Functor=F.P), Relations=tagAlg_rels), + "TagTr_PT": + F.MAP_INPUT_ARRAY( + Functor=F.MAP_RANGE(Functor=F.PT), Relations=tagAlg_rels), +}) + +#make collection of functors for Muplus +variables_all = FunctorCollection({ + 'THOR_P': F.P, + 'THOR_PT': F.PT, +}) + +fields = { + 'B0': "[B0 -> D_s- K+]CC", + 'Ds': "[B0 -> ^D_s- K+]CC", + 'Kp': "[B0 -> D_s- ^K+]CC", +} + +variables = { + 'ALL': variables_all, #adds variables to all fields + 'B0': variables_B, +} + +tuple_B0DsK = Funtuple( + name="B0DsK_Tuple", + tuple_name="DecayTree", + fields=fields, + variables=variables, + inputs=bd2dsk_data) + +filter_B0DsK = add_filter("HDRFilter_B0DsK", + f"HLT_PASS('{bd2dsk_line}Decision')") + +from DaVinci import options +options.annsvc_config = 'root://eoslhcb.cern.ch//eos/lhcb/wg/dpa/wp3/tests/spruce_all_lines_realtime.tck.json' +options.histo_file = 'DV-example-tagger-his.root' +options.ntuple_file = 'DV-example-tagger-ntp.root' + + +def main(): + algs = [filter_B0DsK, tuple_B0DsK] + return algs, [] diff --git a/DaVinciExamples/tests/qmtest/tupling.qms/test_davinci_tupling_array_taggers.qmt b/DaVinciExamples/tests/qmtest/tupling.qms/test_davinci_tupling_array_taggers.qmt new file mode 100644 index 000000000..e99775453 --- /dev/null +++ b/DaVinciExamples/tests/qmtest/tupling.qms/test_davinci_tupling_array_taggers.qmt @@ -0,0 +1,43 @@ +<?xml version="1.0" ?> +<!-- +############################################################################### +# (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. # +############################################################################### +--> +<!DOCTYPE extension PUBLIC '-//QM/2.3/Extension//EN' 'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/extension//en.dtd'> +<!-- +####################################################### +# SUMMARY OF THIS TEST +# ................... +# Author: dfazzini +# Purpose: Test for the ParticleTaggerAlg algorithm and the related MAP_ARRAY and MAP_RANGE functors +# Prerequisites: None +# inputfiledb Spruce_all_lines_dst $DAVINCIROOT/options/DaVinciDB-Example.yaml +# user_algorithms ../../python/DaVinciExamples/tupling/option_davinci_tupling_array_taggers:main +####################################################### +--> +<extension class="GaudiTest.GaudiExeTest" kind="test"> + <argument name="program"><text>davinci</text></argument> + <argument name="args"><set> + <text>run-mc</text> + <text>--inputfiledb</text> + <text>Spruce_all_lines_dst</text> + <text>$DAVINCIROOT/options/DaVinciDB-Example.yaml</text> + <text>--user_algorithms</text> + <text>../../python/DaVinciExamples/tupling/option_davinci_tupling_array_taggers:main</text> + </set></argument> + <argument name="reference"><text>../refs/test_davinci_tupling_array_taggers.ref</text></argument> + <argument name="error_reference"><text>../refs/empty.ref</text></argument> + <argument name="validator"><text> +from DaVinciTests.QMTest.DaVinciExclusions import preprocessor +validateWithReference(preproc = preprocessor) +countErrorLines({"FATAL":0, "ERROR":0}) +</text></argument> +</extension> diff --git a/DaVinciExamples/tests/refs/test_davinci_tupling_array_taggers.ref b/DaVinciExamples/tests/refs/test_davinci_tupling_array_taggers.ref new file mode 100644 index 000000000..60a02b2a1 --- /dev/null +++ b/DaVinciExamples/tests/refs/test_davinci_tupling_array_taggers.ref @@ -0,0 +1,100 @@ +INFO No MainOptions specified. DaVinci will import no options file! +INFO User algorithm option_davinci_tupling_array_taggers.main imported successfully! +ApplicationMgr SUCCESS +==================================================================================================================================== +==================================================================================================================================== +ApplicationMgr INFO Application Manager Configured successfully +DetectorPersistencySvc INFO Added successfully Conversion service:XmlCnvSvc +DetectorDataSvc SUCCESS Detector description database: git:/lhcb.xml +NTupleSvc INFO Added stream file:DV-example-tagger-ntp.root as FILE1 +RootHistSvc INFO Writing ROOT histograms to: DV-example-tagger-his.root +HistogramPersistencySvc INFO Added successfully Conversion service:RootHistSvc +FSROutputStreamDstWriter INFO Data source: EventDataSvc output: SVC='Gaudi::RootCnvSvc' +EventClockSvc.FakeEventTime INFO Event times generated from 0 with steps of 0 +Unpacker_PackedChargedProtos.Cha... INFO Using retuned RICH el and mu DLL values in combined DLLs +FunctionalParticleMaker.LoKi::Hy... INFO CUT: ' ( (TrTYPE==3) &TrALL) ' +ApplicationMgr INFO Application Manager Initialized successfully +DeFTDetector INFO Current FT geometry version = 63 +ApplicationMgr INFO Application Manager Started successfully +EventPersistencySvc INFO Added successfully Conversion service:RootCnvSvc +EventSelector SUCCESS Reading Event record 1. Record number within stream 1: 1 +EventPersistencySvc INFO Added successfully Conversion service:LHCb::RawDataCnvSvc +RFileCnv INFO opening Root file "DV-example-tagger-ntp.root" for writing +RCWNTupleCnv INFO Booked TTree with ID: DecayTree "DecayTree" in directory DV-example-tagger-ntp.root:/B0DsK_Tuple +ApplicationMgr INFO Application Manager Stopped successfully +FSROutputStreamDstWriter INFO Set up File Summary Record +FSROutputStreamDstWriter INFO Events output: 1 +B0DsK_Tuple SUCCESS Booked 1 N-Tuples and 0 Event Tag Collections +B0DsK_Tuple SUCCESS List of booked N-Tuples in directory "FILE1/B0DsK_Tuple" +B0DsK_Tuple SUCCESS ID=DecayTree Title="DecayTree" #items=10 {B0_THOR_MASS,indx,B0_TagTr_P[1]/V,B0_TagTr_PT[1]/V,B0_THOR_P,B0_THOR_PT,Ds_THOR_P} +LAZY_AND: DaVinci #=110 Sum=79 Eff=|( 71.81818 +- 4.28949 )%| + NONLAZY_OR: FileSummaryRecords #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + LAZY_AND: GenFSR #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + RecordStream/FSROutputStreamDstWriter #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + NONLAZY_OR: UserAnalysis #=110 Sum=79 Eff=|( 71.81818 +- 4.28949 )%| + LAZY_AND: UserAlgorithms #=110 Sum=79 Eff=|( 71.81818 +- 4.28949 )%| + LHCb__UnpackRawEvent/LHCb__UnpackRawEvent #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + HltPackedDataDecoder/HltPackedDataDecoder #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + UnpackMCParticle/UnpackMCParticle #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + UnpackMCVertex/UnpackMCVertex #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + UnpackTrack/UnpackTracks #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + UnpackRecVertex/UnpackPVs #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + UnpackProtoParticle/UnpackChargedProtos #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + UnpackProtoParticle/UnpackNeutralProtos #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + UnpackCaloHypo/UnpackCaloElectrons #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + UnpackCaloHypo/UnpackCaloPhotons #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + UnpackCaloHypo/UnpackCaloMergedPi0s #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + UnpackCaloHypo/UnpackCaloSplitPhotons #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + MuonPIDUnpacker/UnpackMuonPIDs #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + RichPIDUnpacker/UnpackRichPIDs #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + UnpackParticlesAndVertices/UnpackParticlesAndVertices #=110 Sum=110 Eff=|( 100.0000 +- 0.00000 )%| + LoKi__HDRFilter/HDRFilter_B0DsK #=110 Sum=79 Eff=|( 71.81818 +- 4.28949 )%| + FunTupleBase_Particles/B0DsK_Tuple #=79 Sum=79 Eff=|( 100.0000 +- 0.00000 )%| +ToolSvc INFO Removing all tools created by ToolSvc +RFileCnv INFO dumping contents of /NTUPLES/FILE1 +TFile: name=DV-example-tagger-ntp.root, title=Gaudi Trees, option=CREATE +NTupleSvc INFO NTuples saved successfully +ApplicationMgr INFO Application Manager Finalized successfully +ApplicationMgr INFO Application Manager Terminated successfully +B0DsK_Tuple INFO Number of counters : 7 + | Counter | # | sum | mean/eff^* | rms/err^* | min | max | + | "# events with multiple candidates for field B0"| 64 | + | "# events with multiple candidates for field Ds"| 64 | + | "# events with multiple candidates for field Kp"| 64 | + | "# non-empty events for field B0" | 79 | + | "# non-empty events for field Ds" | 79 | + | "# non-empty events for field Kp" | 79 | + | "# processed events" | 79 | +FunctionalParticleMaker INFO Number of counters : 4 + | Counter | # | sum | mean/eff^* | rms/err^* | min | max | + |*"# passed ProtoParticle filter" | 618 | 618 |( 100.0000 +- 0.000000)% | + |*"# passed Track filter" | 631 | 618 |( 97.93978 +- 0.5654860)% | + | "Nb created anti-particles" | 79 | 307 | 3.8861 | 2.0188 | 2.0000 | 10.000 | + | "Nb created particles" | 79 | 311 | 3.9367 | 2.0459 | 2.0000 | 10.000 | +HDRFilter_B0DsK INFO Number of counters : 1 + | Counter | # | sum | mean/eff^* | rms/err^* | min | max | + |*"#passed" | 110 | 79 |( 71.81818 +- 4.289487)% | +ParticleContainerMerger INFO Number of counters : 2 + | Counter | # | sum | mean/eff^* | rms/err^* | min | max | + | "# input particles" | 79 | 618 | 7.8228 | + | "# output particles" | 618 | 0 | 0.0000 | +ParticleTaggerAlg INFO Number of counters : 3 + | Counter | # | sum | mean/eff^* | rms/err^* | min | max | + | "Events" | 79 | + | "Input Particles" | 79 | 460 | 5.8228 | 13.704 | 1.0000 | 122.00 | + | "Output Particles" | 79 | 618 | 7.8228 | 3.9322 | 4.0000 | 20.000 | +ToolSvc.HltFactory INFO Number of counters : 1 + | Counter | # | sum | mean/eff^* | rms/err^* | min | max | + | "# loaded from PYTHON" | 1 | +ToolSvc.PPFactoryHybridFactory INFO Number of counters : 1 + | Counter | # | sum | mean/eff^* | rms/err^* | min | max | + | "# loaded from PYTHON" | 1 | +ToolSvc.TrackFunctorFactory INFO Number of counters : 1 + | Counter | # | sum | mean/eff^* | rms/err^* | min | max | + | "# loaded from PYTHON" | 1 | +Unpacker_PackedMuonPIDs INFO Number of counters : 1 + | Counter | # | sum | mean/eff^* | rms/err^* | min | max | + | "# UnPackedData" | 79 | 0 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | +Unpacker_PackedRichPIDs INFO Number of counters : 1 + | Counter | # | sum | mean/eff^* | rms/err^* | min | max | + | "# UnPackedData" | 79 | 631 | 7.9873 | 3.9984 | 4.0000 | 20.000 | diff --git a/Phys/DaVinci/python/DaVinci/standard_particles.py b/Phys/DaVinci/python/DaVinci/standard_particles.py index 69e5b1bb1..5af8ab513 100644 --- a/Phys/DaVinci/python/DaVinci/standard_particles.py +++ b/Phys/DaVinci/python/DaVinci/standard_particles.py @@ -635,3 +635,60 @@ def make_mass_constrained_jpsi2mumu(name='MassConstrJpsi2MuMuMaker', ) return ParticleFilter(dimuons, name=name, Code=code) + + +# Temporary function implemented for testing the MAP_ARRAY functor and ParticleTaggerAlg algorithm +# in DaVinciExamples.tupling.test_davinci_tupling_array_taggers.qmt. +# Aim: create long pions particles from Spruce TES location since the standard '/Event/pRec', +# used in all the other make functions, is not available. +# TO BE REMOVED AS SOON AS THIS PYTHON MODULE IS MOVED INTO ANOTHER SHARED REPO OR +# IT'S REDESIGNED SPECIFICALLY FOR DAVINCI. +@configurable +def make_long_pions_from_spruce(stream="/Event/Spruce/HLT2"): + from Configurables import MuonPIDUnpacker, RichPIDUnpacker, UnpackProtoParticle + from PyConf.application import make_data_with_FetchDataFromFile + from PyConf.components import Algorithm, force_location + from PyConf.Tools import (ChargedProtoParticleAddRichInfo, + ChargedProtoParticleAddMuonInfo, + ChargedProtoParticleAddCombineDLLs) + from DaVinci.locations import LocationsUnpackedReco + + # Define a new reco_unpackers taking Spruce locations as input + def reco_unpacker(key, configurable, input_location, **kwargs): + """ + Return a `PyConf.Algorithm` instance that reading from a given input location unpacks a specific reconstructed object, identified by a 'key', to the + forced output location `LocationsUnpackedReco[key]`. + """ + alg = Algorithm( + configurable, + name=f"Unpacker_{key}", + InputName=make_data_with_FetchDataFromFile(input_location), + outputs={ + "OutputName": force_location(LocationsUnpackedReco[key].value) + }, + **kwargs) + return alg + + richPIDs = reco_unpacker("PackedRichPIDs", RichPIDUnpacker, + f"{stream}/pRec/Rich/PIDs") + muonPIDs = reco_unpacker("PackedMuonPIDs", MuonPIDUnpacker, + f"{stream}/pRec/Muon/MuonPID") + + charged_protos = reco_unpacker( + "PackedChargedProtos", + UnpackProtoParticle, + f"{stream}/pRec/ProtoP/Charged", + AddInfo=[ + ChargedProtoParticleAddRichInfo( + InputRichPIDLocation=richPIDs.OutputName), + ChargedProtoParticleAddMuonInfo( + InputMuonPIDLocation=muonPIDs.OutputName), + ChargedProtoParticleAddCombineDLLs() + ]) + + particles = FunctionalParticleMaker( + InputProtoParticles=charged_protos, + ParticleID="pion", + TrackSelector=get_long_track_selector(), + ProtoParticleFilter=standard_protoparticle_filter()).Particles + return particles -- GitLab