Commit d0c92274 authored by Alex Pearce's avatar Alex Pearce
Browse files

Add suite of tests for HLT2 analysis.

Checks that:

1. Moore can output a DST with Turbo candidates.
2. The DST can be read by an analysis application to produce an ntuple.
3. The ntuple contains sensible information.

Ideally these test would live in Moore, where the HLT2 logic lives, but
we require access to the Analysis project for DecayTreeTuple.

All in a new package: HltIntegrationTests.
parent 3598cab6
Pipeline #2385976 passed with stage
in 23 seconds
###############################################################################
# (c) Copyright 2021 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. #
###############################################################################
gaudi_add_test(QMTest QMTEST)
# HltIntegrationTests
The test suites in this package check data and logical consistency by running a
chain of applications and verifying the output.
They 'integrate over' the behaviour of multiple applications to ensure
consistency of configuration between them, e.g. that the input data expected by
an application is persisted during the run of an upstream application.
###############################################################################
# (c) Copyright 2021 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. #
###############################################################################
"""Dump the HltANNSvc configuration.
To be used as the last options file of a job, after `run_moore` has been called.
"""
import json
from Configurables import HltANNSvc
with open("hlt2_example.tck.json", "w") as outfile:
json.dump(HltANNSvc().PackedObjectLocations, outfile)
###############################################################################
# (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. #
###############################################################################
"""Configure HLT2 with a D0 -> K- K+ HLT2 line."""
from Moore import options, run_moore
from Moore.lines import Hlt2Line
from Hlt2Conf.lines.charm.d0_to_hh import (
make_charm_kaons,
make_charm_soft_pions,
make_dzeros,
make_pvs,
upfront_reconstruction,
)
from RecoConf.global_tools import stateProvider_with_simplified_geom
input_files = [
# D*-tagged D0 to KK, 27163002
# sim+std://MC/Upgrade/Beam7000GeV-Upgrade-MagDown-Nu7.6-25ns-Pythia8/Sim09c-Up02/Reco-Up01/27163002/LDST
'root://eoslhcb.cern.ch//eos/lhcb/grid/prod/lhcb/MC/Upgrade/LDST/00070317/0000/00070317_00000033_2.ldst'
]
options.input_files = input_files
options.input_type = 'ROOT'
options.input_raw_format = 4.3
options.evt_max = 1000
options.simulation = True
options.data_type = 'Upgrade'
options.dddb_tag = 'dddb-20171126'
options.conddb_tag = 'sim-20171127-vc-md100'
options.output_file = 'hlt2_example.dst'
options.output_type = 'ROOT'
def make_lines():
kaons = make_charm_kaons()
pvs = make_pvs()
dzeros = make_dzeros(particles=kaons, descriptors=['D0 -> K- K+'], pvs=pvs)
soft_pions = make_charm_soft_pions()
line = Hlt2Line(
name="Hlt2CharmD0ToKmKpLine",
algs=upfront_reconstruction() + [dzeros],
prescale=1.0,
extra_outputs=[
("SoftPions", soft_pions),
])
return [line]
public_tools = [stateProvider_with_simplified_geom()]
run_moore(options, make_lines, public_tools)
###############################################################################
# (c) Copyright 2021 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. #
###############################################################################
"""Read the output of an HLT2 job with DecayTreeTuple.
See the Moore HLT2 output analysis tutorial for more information:
https://lhcbdoc.web.cern.ch/lhcbdoc/moore/master/tutorials/hlt2_analysis.html
"""
from Configurables import (
ApplicationMgr,
DecayTreeTuple,
LHCbApp,
)
from Gaudi.Configuration import appendPostConfigAction
from GaudiConf import IOHelper
from DecayTreeTuple import Configuration # noqa: magic import to augment DecayTreeTuple
from DecayTreeTuple import DecayTreeTupleTruthUtils
from PhysSelPython.Selections import (
AutomaticData,
CombineSelection,
SelectionSequence,
)
# The output of the HLT2 line
kk_line = AutomaticData("/Event/HLT2/Hlt2CharmD0ToKmKpLine/Particles")
# Extra pions
soft_pions = AutomaticData(
"/Event/HLT2/Hlt2CharmD0ToKmKpLine/SoftPions/Particles")
dstars = CombineSelection(
"CombineD0pi",
inputs=[kk_line, soft_pions],
DecayDescriptors=[
"D*(2010)+ -> D0 pi+",
"D*(2010)- -> D0 pi+",
],
DaughtersCuts={
"pi+": "PT > 250 * MeV",
},
CombinationCut=("in_range(0, (AM - AM1 - AM2), 170) &"
"ADOCACHI2CUT(15, '')"),
MotherCut=("(VFASPF(VCHI2PDOF) < 10) &"
"in_range(0, (M - M1 - M2), 150)"))
selseq = SelectionSequence(dstars.name() + "Sequence", TopSelection=dstars)
relations = [
"Relations/ChargedPP2MCP",
"Relations/NeutralPP2MCP",
]
mc_tools = [
'MCTupleToolKinematic',
# ...plus any other MC tuple tools you'd like to use
]
dtt_kk = DecayTreeTuple(
"TupleD0ToKK",
Inputs=[kk_line.outputLocation()],
Decay="D0 -> ^K- ^K+",
)
dtt_kk.addBranches({
"D0": "D0 -> K- K+",
"D0_h1": "D0 -> ^K- K+",
"D0_h2": "D0 -> K- ^K+",
})
dtt_kk.ToolList += [
"TupleToolMCBackgroundInfo",
"TupleToolMCTruth",
]
DecayTreeTupleTruthUtils.makeTruth(
dtt_kk, relations, mc_tools, stream="/Event/HLT2")
dtt_kk_dst = DecayTreeTuple(
"TupleDstToD0pi_D0ToKK",
Inputs=[selseq.outputLocation()],
Decay="[D*(2010)+ -> ^([D0]cc -> ^K- ^K+) ^pi+]CC",
)
dtt_kk_dst.addBranches({
"Dst": "[D*(2010)+ -> ([D0]cc -> K- K+) pi+]CC",
"Dst_pi": "[D*(2010)+ -> ([D0]cc -> K- K+) ^pi+]CC",
"D0": "[D*(2010)+ -> ^([D0]cc -> K- K+) pi+]CC",
"D0_h1": "[D*(2010)+ -> ([D0]cc -> ^K- K+) pi+]CC",
"D0_h2": "[D*(2010)+ -> ([D0]cc -> K- ^K+) pi+]CC",
})
dtt_kk_dst.ToolList += [
"TupleToolMCBackgroundInfo",
"TupleToolMCTruth",
]
DecayTreeTupleTruthUtils.makeTruth(
dtt_kk_dst, relations, mc_tools, stream="/Event/HLT2")
LHCbApp().DataType = "Upgrade"
from Configurables import GaudiSequencer
ApplicationMgr().TopAlg = [
GaudiSequencer(
"Blah",
Members=[selseq.sequence(), dtt_kk, dtt_kk_dst],
IgnoreFilterPassed=True)
]
LHCbApp().TupleFile = "hlt2_example.root"
LHCbApp().Simulation = True
LHCbApp().CondDBtag = "sim-20171127-vc-md100"
LHCbApp().DDDBtag = "dddb-20171126"
IOHelper().inputFiles(["./hlt2_example.dst"])
@appendPostConfigAction
def read_hlt2():
"""Configures algorithms for reading HLT2 output.
This is a temporary measure until support for Run 3 HLT2 output is added to
an LHCb application.
"""
import json
from Configurables import HltANNSvc, createODIN
from GaudiConf import reading
# NOTE: You will need to set `raw_event_format` below to 0.3 if:
# - Your Moore output was MDF or;
# - Your Moore input was XDIGI.
reading_algs = ([reading.decoder(raw_event_format=4.3)] +
reading.unpackers() + [createODIN()])
if LHCbApp().Simulation:
reading_algs = reading.mc_unpackers() + reading_algs
ApplicationMgr().TopAlg = reading_algs + ApplicationMgr().TopAlg
# Load the 'TCK' dumped from the Moore job
with open("hlt2_example.tck.json") as f:
tck = json.load(f)
HltANNSvc(PackedObjectLocations={str(k): v for k, v in tck.items()})
###############################################################################
# (c) Copyright 2021 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 print_function
import sys
import ROOT
def error(msg):
print("ReadNtuple ERROR", msg)
f = ROOT.TFile("hlt2_example.root")
t = f.Get("TupleD0ToKK/DecayTree")
# The ntuple should exist and not be empty
# If these checks fail there's no point in continuing
if not t:
error("No ntuple in output file")
sys.exit(1)
if t.GetEntries() == 0:
error("Empty ntuple")
sys.exit(1)
# The truth matching should have been able to associate the reconstructed
# objects with MC objects
if t.GetEntries("D0_BKGCAT < 60") == 0:
error("Truth matching D0 failed")
if t.GetEntries("abs(D0_TRUEID) > 0") == 0:
error("Truth matching D0 failed")
if t.GetEntries("abs(D0_h1_TRUEID) > 0") == 0:
error("Truth matching D0_h1 failed")
if t.GetEntries("abs(D0_h2_TRUEID) > 0") == 0:
error("Truth matching D0_h2 failed")
# The P2PV tables from Moore should allow associated PV look-ups (-999 is the
# sentinal value for 'no associated PV')
if t.GetEntries("D0_OWNPV_X != -999") == 0:
error("PV association D0 failed")
if t.GetEntries("D0_h1_OWNPV_X != -999") == 0:
error("PV association D0_h1 failed")
if t.GetEntries("D0_h2_OWNPV_X != -999") == 0:
error("PV association D0_h2 failed")
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE extension PUBLIC '-//QM/2.3/Extension//EN' 'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/extension//en.dtd'>
<!--
(c) Copyright 2021 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.
-->
<!--
Read the output of running the HLT2 example from Moore.
-->
<extension class="GaudiTest.GaudiExeTest" kind="test">
<argument name="prerequisites"><set>
<tuple><text>hlt2_analysis.run_hlt2_example</text><enumeral>PASS</enumeral></tuple>
</set></argument>
<argument name="program"><text>gaudirun.py</text></argument>
<argument name="args"><set>
<text>$HLTINTEGRATIONTESTSROOT/tests/options/hlt2_analysis/read_hlt2.py</text>
</set></argument>
<argument name="use_temp_dir"><enumeral>true</enumeral></argument>
<argument name="validator"><text>
from GaudiConf.QMTest.LHCbTest import extract_counters
from Moore.qmtest.exclusions import remove_known_warnings
# Expect 1 warning:
# - RootHistSvc WARNING no ROOT output file name, Histograms cannot be persistified
countErrorLines({"FATAL": 0, "ERROR": 0, "WARNING": 1},
stdout=remove_known_warnings(stdout))
counters = extract_counters(stdout)
_, ncandidates, _, _, _, _ = map(float, counters['TupleD0ToKK']['# HLT2/Hlt2CharmD0ToKmKpLine'])
if ncandidates &lt; 1:
causes.append("no candidates in ntuple")
</text></argument>
</extension>
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE extension PUBLIC '-//QM/2.3/Extension//EN' 'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/extension//en.dtd'>
<!--
(c) Copyright 2021 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.
-->
<!--
Read the ntuple output of an analysis job.
-->
<extension class="GaudiTest.GaudiExeTest" kind="test">
<argument name="prerequisites"><set>
<tuple><text>hlt2_analysis.read_hlt2_example_output</text><enumeral>PASS</enumeral></tuple>
</set></argument>
<argument name="program"><text>python</text></argument>
<argument name="args"><set>
<text>$HLTINTEGRATIONTESTSROOT/tests/options/hlt2_analysis/read_ntuple.py</text>
</set></argument>
<argument name="use_temp_dir"><enumeral>true</enumeral></argument>
<argument name="validator"><text>
countErrorLines()
</text></argument>
</extension>
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE extension PUBLIC '-//QM/2.3/Extension//EN' 'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/extension//en.dtd'>
<!--
(c) Copyright 2021 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.
-->
<!--
Re-run the HLT2 example from Moore.
We run no validation here, assuming a test in Moore has already done so.
This test is the first of a series in this suite which validates that Moore
can produce an output DST from which one can run a separate application to
produce an ntuple.
-->
<extension class="GaudiTest.GaudiExeTest" kind="test">
<argument name="program"><text>gaudirun.py</text></argument>
<argument name="args"><set>
<text>$HLTINTEGRATIONTESTSROOT/tests/options/hlt2_analysis/hlt2_d0_to_kk.py</text>
<text>$HLTINTEGRATIONTESTSROOT/tests/options/hlt2_analysis/dump_tck.py</text>
</set></argument>
<argument name="use_temp_dir"><enumeral>true</enumeral></argument>
<argument name="timeout"><integer>2400</integer></argument>
</extension>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment