From ea051a21c9fc8a37e5305423c7c74cb7724dbf33 Mon Sep 17 00:00:00 2001 From: Jonathan Burr <jon.burr@cern.ch> Date: Tue, 19 Nov 2019 10:14:01 +0000 Subject: [PATCH] Revert "Merge branch 'revert-9c7cf5e1' into 'master'" This reverts merge request !28085 --- .../TrigEFMissingET/CMakeLists.txt | 55 ++++- .../TrigEFMissingET/METComponent.h | 78 +++++++ .../TrigEFMissingET/SignedKinematics.h | 127 ++++++++++++ .../TrigEFMissingET/StatusFlags.h | 47 +++++ .../TrigEFMissingET/src/FexBase.cxx | 167 +++++++++++++++ .../TrigEFMissingET/src/FexBase.h | 122 +++++++++++ .../TrigEFMissingET/src/METComponent.cxx | 121 +++++++++++ .../TrigEFMissingET/src/MonGroupBuilder.cxx | 33 +++ .../TrigEFMissingET/src/MonGroupBuilder.h | 90 ++++++++ .../TrigEFMissingET/src/SignedKinematics.cxx | 196 ++++++++++++++++++ .../TrigEFMissingET/src/StatusFlags.cxx | 66 ++++++ .../TrigEFMissingET/src/TrkMHTFex.cxx | 159 ++++++++++++++ .../TrigEFMissingET/src/TrkMHTFex.h | 108 ++++++++++ .../components/TrigEFMissingET_entries.cxx | 3 +- .../share/q221_RDOtoRDOTrig_mt1_build.ref | 2 + .../TrigUpgradeTest/share/full_menu_build.ref | 2 + .../TrigUpgradeTest/share/slice_met.ref | 22 +- .../TrigEDMConfig/python/TriggerEDMRun3.py | 3 + .../MET/METChainConfiguration.py | 12 +- .../HLTMenuConfig/MET/METMenuSequences.py | 16 ++ .../HLTMenuConfig/MET/METRecoSequences.py | 43 +++- .../python/HLTMenuConfig/Menu/LS2_v1.py | 1 + .../HLTMenuConfig/Menu/SignatureDicts.py | 2 +- 23 files changed, 1449 insertions(+), 26 deletions(-) create mode 100644 Trigger/TrigAlgorithms/TrigEFMissingET/TrigEFMissingET/METComponent.h create mode 100644 Trigger/TrigAlgorithms/TrigEFMissingET/TrigEFMissingET/SignedKinematics.h create mode 100644 Trigger/TrigAlgorithms/TrigEFMissingET/TrigEFMissingET/StatusFlags.h create mode 100644 Trigger/TrigAlgorithms/TrigEFMissingET/src/FexBase.cxx create mode 100644 Trigger/TrigAlgorithms/TrigEFMissingET/src/FexBase.h create mode 100644 Trigger/TrigAlgorithms/TrigEFMissingET/src/METComponent.cxx create mode 100644 Trigger/TrigAlgorithms/TrigEFMissingET/src/MonGroupBuilder.cxx create mode 100644 Trigger/TrigAlgorithms/TrigEFMissingET/src/MonGroupBuilder.h create mode 100644 Trigger/TrigAlgorithms/TrigEFMissingET/src/SignedKinematics.cxx create mode 100644 Trigger/TrigAlgorithms/TrigEFMissingET/src/StatusFlags.cxx create mode 100644 Trigger/TrigAlgorithms/TrigEFMissingET/src/TrkMHTFex.cxx create mode 100644 Trigger/TrigAlgorithms/TrigEFMissingET/src/TrkMHTFex.h diff --git a/Trigger/TrigAlgorithms/TrigEFMissingET/CMakeLists.txt b/Trigger/TrigAlgorithms/TrigEFMissingET/CMakeLists.txt index 6c24106d7ae..ca238691323 100644 --- a/Trigger/TrigAlgorithms/TrigEFMissingET/CMakeLists.txt +++ b/Trigger/TrigAlgorithms/TrigEFMissingET/CMakeLists.txt @@ -34,6 +34,7 @@ atlas_depends_on_subdirs( Event/EventKernel Event/xAOD/xAODEventInfo Reconstruction/Jet/JetEvent + Reconstruction/Jet/JetEDM Trigger/TrigEvent/TrigMuonEvent Trigger/TrigEvent/TrigSteeringEvent Trigger/TrigT1/TrigT1Interfaces ) @@ -44,18 +45,52 @@ find_package( FastJetContrib COMPONENTS SoftKiller ConstituentSubtractor ) find_package( ROOT COMPONENTS Core Hist Matrix ) find_package( tdaq-common COMPONENTS eformat ) +atlas_add_library( TrigEFMissingETLib + src/METComponent.cxx + src/StatusFlags.cxx + src/SignedKinematics.cxx + PUBLIC_HEADERS TrigEFMissingET + INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} + LINK_LIBRARIES xAODTrigMissingET xAODBase +) + # Component(s) in the package: atlas_add_component( TrigEFMissingET - src/*.cxx - src/components/*.cxx - INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${TDAQ-COMMON_INCLUDE_DIRS} ${FASTJETCONTRIB_INCLUDE_DIRS} ${FASTJET_INCLUDE_DIRS} - LINK_LIBRARIES ${ROOT_LIBRARIES} ${FASTJET_LIBRARIES} ${TDAQ-COMMON_LIBRARIES} ${FASTJETCONTRIB_LIBRARIES} - AthenaBaseComps CaloDetDescrLib CaloEvent CaloGeoHelpers - CaloIdentifier CxxUtils EventKernel GaudiKernel Identifier - JetEvent LArIdentifier PathResolver - TrigCaloEvent TrigInterfacesLib TrigMissingEtEvent TrigMuonEvent - TrigParticle TrigSteeringEvent TrigT1Interfaces TrigT2CaloCommonLib - TrigTimeAlgsLib xAODCaloEvent xAODEventInfo xAODJet xAODTrigMissingET ) + src/EFMissingET.cxx + src/EFMissingETHelper.cxx + src/EFMissingETBaseTool.cxx + src/EFMissingETComponentCopier.cxx + src/EFMissingETFromCells.cxx + src/EFMissingETFromClusters.cxx + src/EFMissingETFromClustersPS.cxx + src/EFMissingETFromClustersPUC.cxx + src/EFMissingETFromFEBHeader.cxx + src/EFMissingETFromJets.cxx + src/EFMissingETFromTrackAndJets.cxx + src/EFMissingETFromClustersTracksPUC.cxx + src/EFMissingETFromTrackAndClusters.cxx + src/EFMissingETFlags.cxx + src/EFMissingETFromHelper.cxx + src/EFMissingETAlgMT.cxx + src/EFMissingETFromCellsMT.cxx + src/EFMissingETFromClustersMT.cxx + src/EFMissingETFromClustersPufitMT.cxx + src/EFMissingETFromJetsMT.cxx + src/EFMissingETFlagsMT.cxx + src/FexBase.cxx + src/MonGroupBuilder.cxx + src/TrkMHTFex.cxx + src/components/TrigEFMissingET_entries.cxx + src/components/TrigEFMissingET_load.cxx + INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${TDAQ-COMMON_INCLUDE_DIRS} ${FASTJETCONTRIB_INCLUDE_DIRS} ${FASTJET_INCLUDE_DIRS} + LINK_LIBRARIES ${ROOT_LIBRARIES} ${FASTJET_LIBRARIES} ${TDAQ-COMMON_LIBRARIES} ${FASTJETCONTRIB_LIBRARIES} + TrigEFMissingETLib + AthenaBaseComps CaloDetDescrLib CaloEvent CaloGeoHelpers + CaloIdentifier CxxUtils EventKernel GaudiKernel Identifier + JetEvent LArIdentifier PathResolver JetEDM + TrigCaloEvent TrigInterfacesLib TrigMissingEtEvent TrigMuonEvent + TrigParticle TrigSteeringEvent TrigT1Interfaces TrigT2CaloCommonLib + TrigTimeAlgsLib xAODCaloEvent xAODEventInfo xAODJet xAODTrigMissingET ) # Install files from the package: atlas_install_python_modules( python/*.py ) diff --git a/Trigger/TrigAlgorithms/TrigEFMissingET/TrigEFMissingET/METComponent.h b/Trigger/TrigAlgorithms/TrigEFMissingET/TrigEFMissingET/METComponent.h new file mode 100644 index 00000000000..570a0f80c0b --- /dev/null +++ b/Trigger/TrigAlgorithms/TrigEFMissingET/TrigEFMissingET/METComponent.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + */ + +/****************************************************************************** + * @package Trigger/TrigAlgorithms/TrigEFMissingET + * @class METComponent + * + * @brief Helper class to build up MET values + * @author Jon Burr + *****************************************************************************/ + +#ifndef TRIGEFMISSINGET_METCOMPONENT_H +#define TRIGEFMISSINGET_METCOMPONENT_H + +#include "xAODTrigMissingET/TrigMissingET.h" +#include "TrigEFMissingET/SignedKinematics.h" +#include <TLorentzVector.h> +#include <ostream> + +namespace HLT { namespace MET { + /** + * @brief Helper struct to build up MET values before moving them into the EDM + * + * The reason for doing this is that the EDM doesn't allow += operators etc + * which makes interacting with it rather painful and (maybe?) slow. + */ + struct METComponent { + METComponent() {} + /// Initialize from an xAOD::TrigMissingET object + METComponent(const xAOD::TrigMissingET& met); + /// Initialize from a *component* of an xAOD::TrigMissingET object + METComponent(std::size_t idx, const xAOD::TrigMissingET& met); + /// Momentum components + /// x momentum + float mpx{0.}; + /// y momentum + float mpy{0.}; + /// z momentum + float mpz{0.}; + /// The actual met + float met() const; + /// The magnitude of the missing 3-vector + float magnitude() const; + /// The direction + float phi() const; + /// The (pseudo) eta + float eta() const; + + /// Also store the sumE + float sumE{0.}; + /// And the sumEt + float sumEt{0.}; + /// The status flag + int status{0}; + + /// Add two of these things together + friend METComponent operator+(const METComponent& lhs, const METComponent& rhs); + /// Add one to us + METComponent& operator+=(const METComponent& other); + /// Add a four momentum. Use the convention used in xAOD::MissingET + /// where adding particle *subtracts* its four momentum. So 'adding' a + /// particle to the MET works as you'd expect. + METComponent& operator+=(const TLorentzVector& otherP4); + /// Add a signed object. This uses the same convention as above (so a + /// negative energy object increases the object + METComponent& operator+=(const SignedKinematics& kin); + + /// Fill the main component of the MET with this + void fillMET(xAOD::TrigMissingET& met) const; + /// Fill a component of the MET with this + void fillMETComponent(std::size_t idx, xAOD::TrigMissingET& met) const; + }; //> end class METComponent + + std::ostream& operator<<(std::ostream& os, const METComponent& component); + +} } //> end namespace HLT::MET +#endif //> !TRIGEFMISSINGET_METCOMPONENT_H diff --git a/Trigger/TrigAlgorithms/TrigEFMissingET/TrigEFMissingET/SignedKinematics.h b/Trigger/TrigAlgorithms/TrigEFMissingET/TrigEFMissingET/SignedKinematics.h new file mode 100644 index 00000000000..5c764d0102c --- /dev/null +++ b/Trigger/TrigAlgorithms/TrigEFMissingET/TrigEFMissingET/SignedKinematics.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + */ + +/****************************************************************************** + * @package Trigger/TrigAlgorithms/TrigEFMissingET + * + * @brief Helper class to describe the kinematics of an object that can have + * negative energies. + * @author Jon Burr + *****************************************************************************/ + +#ifndef TRIGEFMISSINGET_SIGNEDKINEMATICS_H +#define TRIGEFMISSINGET_SIGNEDKINEMATICS_H + +#include "Math/Vector4D.h" + +// Forward declares +class TLorentzVector; + +namespace xAOD { + class IParticle; +} + +namespace HLT { namespace MET { + + /** + * @brief Class to describe the kinematics of an object that can have negative + * energies. + * + * This class is used instead of TLorentzVector anywhere that there could be a + * negative energy. This is to get complete control of the behaviour in that + * case as TLorentzVector behaves oddly. + * + * Algebraic operators are provided but it's worth noting that negative-energy + * objects behaviour a little oddly (they are not valid four-momenta after + * all). This should only really affect the mass. + * + * The sign of the vector is defined as sign(E) where E is the scalar sum of + * all constituents energies + */ + class SignedKinematics { + public: + SignedKinematics(); + /// Constructor from px, py, pz and E + SignedKinematics(double px, double py, double pz, double energy); + /// Construct from a TLorentzVector + SignedKinematics(const TLorentzVector& tlv); + /// Construct from an IParticle + SignedKinematics(const xAOD::IParticle& particle); + /// Factory function to construct from energy, eta, phi (massless) + static SignedKinematics fromEnergyEtaPhi( + double energy, double eta, double phi); + /// Factory function to construct from energy eta, phi and m + static SignedKinematics fromEnergyEtaPhiM( + double energy, double eta, double phi, double mass); + /// Factory function to construct from et, eta, phi (massless) + static SignedKinematics fromEtEtaPhi( + double et, double eta, double phi); + /// Factory function to construct from et eta, phi and m + static SignedKinematics fromEtEtaPhiM( + double et, double eta, double phi, double mass); + + /// The sign of the kinematics + int sign() const; + + /// Direction + double eta() const; + double phi() const; + /// Provide accessors for sin and cos phi + double sinPhi() const; + double cosPhi() const; + /// Provide accessors for sinh and cosh eta + double sinhEta() const; + double coshEta() const; + + /// Momentum values + /// (signed) momentum + double p() const; + /// unsigned momentum + double absP() const; + double p2() const; + /// (signed) pt + double pt() const; + /// unsigned pt + double absPt() const; + double pt2() const; + double px() const; + double py() const; + double pz() const; + + /// Energy values + /// (signed) energy + double energy() const; + /// unsigned energy + double absEnergy() const; + double energy2() const; + /// (signed) et + double et() const; + /// Unsigned et + double absEt() const; + double et2() const; + double ex() const; + double ey() const; + double ez() const; + + /// The squared mass. There is no guarantee that this will be > 0 + double m2() const; + + explicit operator ROOT::Math::PxPyPzEVector() const; + + /// Add another SignedKinematics to this + SignedKinematics& operator+=(const SignedKinematics& other); + /// Subtract a SignedKinematics from this (exact opposite of the above + /// function. + SignedKinematics& operator-=(const SignedKinematics& other); + private: + /// The actual kinematics + ROOT::Math::PxPyPzEVector m_p4; + }; //> end class SignedKinematics + /// 'free' sum operator + SignedKinematics operator+(const SignedKinematics& lhs, const SignedKinematics& rhs); + /// 'free' difference operator + SignedKinematics operator-(const SignedKinematics& lhs, const SignedKinematics& rhs); + +} } //> end namespace HLT::MET +#endif //> !TRIGEFMISSINGET_SIGNEDKINEMATICS_H diff --git a/Trigger/TrigAlgorithms/TrigEFMissingET/TrigEFMissingET/StatusFlags.h b/Trigger/TrigAlgorithms/TrigEFMissingET/TrigEFMissingET/StatusFlags.h new file mode 100644 index 00000000000..3fb5356accd --- /dev/null +++ b/Trigger/TrigAlgorithms/TrigEFMissingET/TrigEFMissingET/StatusFlags.h @@ -0,0 +1,47 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +/******************************************************************** + * @package Trigger/TrigAlgorithms/TrigEFMissingET + * + * @brief Enum for EDM status flags + * @author Jon Burr + ********************************************************************/ + +#include <string> + +namespace HLT { namespace MET { + namespace StatusFlag { + // Right now just taking these from the values in the old code for + // consistency + // + // Use bitshift notation as these represent different bits in the status + // word. 1 << x is equivalent to 2^x. + enum StatusFlag : int { + // 1 << 0 free + BSConvError = 1 << 1, + MuonError = 1 << 2, + FEBError = 1 << 3, + // 1 << 4 free + ComponentBigMEtSEtRatio = 1 << 5, + BadComponentEnergy = 1 << 6, + BadEnergyRatio = 1 << 7, + NoisyEnergyRatio = 1 << 8, + BadCellQuality = 1 << 9, + BadCellEnergy = 1 << 10, + BadCellTime = 1 << 11, + NoMuonTrack = 1 << 12, + // 1 << 13 free + // 1 << 14 free + ComponentErrors = 1 << 15, + // everything until 1 << 27 free + GlobalNoisyEnergyRatio = 1 << 27, + BadEMFraction = 1 << 28, + GlobalBigMEtSEtRatio = 1 << 29, + ObjectInCrack = 1 << 30, + GlobalErrors = 1 << 31 + }; //> end enum StatusFlag + std::string flagIndexToString(int idx); + } //> end namespace StatusFlag +} } //> end namespace HLT::MET diff --git a/Trigger/TrigAlgorithms/TrigEFMissingET/src/FexBase.cxx b/Trigger/TrigAlgorithms/TrigEFMissingET/src/FexBase.cxx new file mode 100644 index 00000000000..d3b361a9a89 --- /dev/null +++ b/Trigger/TrigAlgorithms/TrigEFMissingET/src/FexBase.cxx @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + */ + +/****************************************************************************** + * @package Trigger/TrigAlgorithms/TrigEFMissingET + * @file FexBase.cxx + * + * Implementation of base Fex class + * @author Jon Burr + *****************************************************************************/ + +#include "FexBase.h" +#include "xAODTrigMissingET/TrigMissingETAuxContainer.h" +#include "TrigEFMissingET/METComponent.h" +#include "TrigEFMissingET/StatusFlags.h" +#include "AthenaMonitoring/Monitored.h" +#include <memory> +#include <algorithm> +#include <iterator> + +namespace { + // Convert from MeV to GeV if above threshold, else fallback value + float toLinGeV(float x, float fallback=0, float epsilon=1e-6) + { + float xGeV = x / Gaudi::Units::GeV; + if (std::fabs(xGeV) < epsilon) + return fallback; + return xGeV; + } + // convert from MeV to GeV and then log10, preserving the sign and the minimum + // dictated by monitoring histograms + float toLog10GeV(float x, float fallback=0, float epsilon=1e-6) + { + float absXGeV = std::fabs(x / Gaudi::Units::GeV); + if (absXGeV < epsilon) + return fallback; + return std::copysign(std::log10(absXGeV), x); + } +} //> end anonymous namespace + +namespace HLT { namespace MET { + FexBase::FexBase(const std::string& name, ISvcLocator* pSvcLocator) : + AthReentrantAlgorithm(name, pSvcLocator) + { + } + + StatusCode FexBase::initializeBase( + const std::vector<std::string>& componentNames) + { + ATH_MSG_DEBUG("Initialising FexBase base class"); + m_baseInitialised = true; + m_componentNames = componentNames; + CHECK( m_metContainerKey.initialize() ); + CHECK( m_monTool.retrieve() ); + return StatusCode::SUCCESS; + } + + StatusCode FexBase::execute( const EventContext& context ) const + { + if (!m_baseInitialised) { + ATH_MSG_ERROR("Base class was not initialised! This means that the " + << "derived class was not correctly written!"); + return StatusCode::FAILURE; + } + ATH_MSG_DEBUG("Executing " << name() << "..."); + Monitored::Timer totalTimer("TIME_Total"); + // Create the output + auto metCont = std::make_unique<xAOD::TrigMissingETContainer>(); + auto metContAux = std::make_unique<xAOD::TrigMissingETAuxContainer>(); + metCont->setStore(metContAux.get() ); + + // Create the actual output object + metCont->push_back(std::make_unique<xAOD::TrigMissingET>()); + xAOD::TrigMissingET* met = metCont->back(); + + // Initialise the components + met->defineComponents(m_componentNames); + // We also need to initialise all of the values. This is not done by the EDM + // class so you can easily get missing aux element errors if you don't do + // this + met->setEx(0); + met->setEy(0); + met->setEz(0); + met->setSumEt(0); + met->setSumE(0); + met->setFlag(0); + met->setRoiWord(0); + + MonGroupBuilder monitors; + CHECK( fillMET(*met, context, monitors) ); + // Add flags + CHECK( flagMET(*met) ); + // Add extra monitors + CHECK( monitor(*met, monitors) ); + // Create the actual group and trigger the monitoring + monitors.build(m_monTool); + + // Output REGTEST information + if (msgLvl(MSG::DEBUG) ) { + ATH_MSG_DEBUG( "REGTEST " << METComponent(*met) ); + ATH_MSG_DEBUG( "REGTEST flag = " << met->flag() ); + ATH_MSG_DEBUG( "REGTEST Name, status, values: "); + for (std::size_t ii = 0; ii < met->getNumberOfComponents(); ++ii) + ATH_MSG_DEBUG( "REGTEST " + << met->nameOfComponent(ii) << ", " + << met->statusComponent(ii) << ", " + << METComponent(ii, *met) ); + } + + // Push this output to the store + auto handle = SG::makeHandle(m_metContainerKey, context); + CHECK( handle.record( std::move(metCont), std::move(metContAux) ) ); + return StatusCode::SUCCESS; + } + + StatusCode FexBase::flagMET(xAOD::TrigMissingET& met) const + { + // Start with the components + // Keep a flag to OR into the main value + int overall = 0; + for (std::size_t ii = 0; ii < met.getNumberOfComponents(); ++ii) { + METComponent component(ii, met); + if (component.sumEt > 0 && + component.met() / component.sumEt > m_maxComponentMetSumEtRatio) { + component.status |= StatusFlag::ComponentBigMEtSEtRatio; + overall |= StatusFlag::ComponentBigMEtSEtRatio; + } + met.setStatusComponent(ii, component.status); + } + METComponent total(met); + total.status |= overall; + if (total.sumEt > 0 && + total.met() / total.sumEt > m_maxGlobalMetSumEtRatio) + total.status |= StatusFlag::GlobalBigMEtSEtRatio; + met.setFlag(total.status); + return StatusCode::SUCCESS; + } + + StatusCode FexBase::monitor( + const xAOD::TrigMissingET& met, + MonGroupBuilder& monitors) const + { + METComponent metComponent(met); + // Increase the capacity of the vector + monitors.increaseCapacity(16, true); + // Add the standard variables + monitors.add(Monitored::Scalar("EF_MEx_log", toLog10GeV(metComponent.mpx) ) ); + monitors.add(Monitored::Scalar("EF_MEy_log", toLog10GeV(metComponent.mpy) ) ); + monitors.add(Monitored::Scalar("EF_MEz_log", toLog10GeV(metComponent.mpz) ) ); + monitors.add(Monitored::Scalar("EF_MET_log", toLog10GeV(metComponent.met() ) ) ); + monitors.add(Monitored::Scalar("EF_ME_log", toLog10GeV(metComponent.magnitude() ) ) ); + monitors.add(Monitored::Scalar("EF_SumEt_log", toLog10GeV(metComponent.sumEt) ) ); + monitors.add(Monitored::Scalar("EF_SumE_log", toLog10GeV(metComponent.sumE, -9e9) ) ); + monitors.add(Monitored::Scalar("EF_MEx_lin", toLinGeV(metComponent.mpx) ) ); + monitors.add(Monitored::Scalar("EF_MEy_lin", toLinGeV(metComponent.mpy) ) ); + monitors.add(Monitored::Scalar("EF_MEz_lin", toLinGeV(metComponent.mpz) ) ); + monitors.add(Monitored::Scalar("EF_MET_lin", toLinGeV(metComponent.met() ) ) ); + monitors.add(Monitored::Scalar("EF_ME_lin", toLinGeV(metComponent.magnitude() ) ) ); + monitors.add(Monitored::Scalar("EF_SumEt_lin", toLinGeV(metComponent.sumEt) ) ); + monitors.add(Monitored::Scalar("EF_SumE_lin", toLinGeV(metComponent.sumE) ) ); + monitors.add(Monitored::Scalar( + "EF_XS", toLinGeV(metComponent.met() ) / toLinGeV(metComponent.sumEt, 1) ) ); + monitors.add(Monitored::Scalar("EF_MET_phi", metComponent.phi() ) ); + return StatusCode::SUCCESS; + } +} } //> end namespace HLT::MET diff --git a/Trigger/TrigAlgorithms/TrigEFMissingET/src/FexBase.h b/Trigger/TrigAlgorithms/TrigEFMissingET/src/FexBase.h new file mode 100644 index 00000000000..07f9c8064c3 --- /dev/null +++ b/Trigger/TrigAlgorithms/TrigEFMissingET/src/FexBase.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + */ + +/****************************************************************************** + * @package Trigger/TrigAlgorithms/TrigEFMissingET + * @class FexBase + * + * @brief Base class for MET Trigger Fexs + * @author Jon Burr + *****************************************************************************/ + +#ifndef TRIGEFMISSINGET_FEXBASE_H +#define TRIGEFMISSINGET_FEXBASE_H 1 + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "AthenaMonitoring/GenericMonitoringTool.h" +#include "GaudiKernel/Property.h" +#include "xAODTrigMissingET/TrigMissingETContainer.h" +#include "GaudiKernel/SystemOfUnits.h" +#include "MonGroupBuilder.h" + +#include <string> +#include <vector> + +/****************************************************************************** + * @class FexBase + * + * Base class for HLT MET Fex algorithms. + * + * Responsible for creating the MET object + *****************************************************************************/ + +namespace HLT { namespace MET { + class FexBase : public ::AthReentrantAlgorithm { + public: + /// Constructor + FexBase(const std::string& name, ISvcLocator* pSvcLocator); + + /// Run the algorithm + virtual StatusCode execute(const EventContext& context) const override; + + protected: + /************************************************************************ + * Data members (accessible from derived classes) + ***********************************************************************/ + /// The names of the output MET components + std::vector<std::string> m_componentNames; + + /************************************************************************ + * Internal functions + ***********************************************************************/ + /** + * @brief Initialize the base class + * @param componentNames The names of any components in the output MET + * object. + * + * The xAOD::TrigMissingET writes out a main 'met' value but can also + * write out extra MET components - either for debugging, monitoring or + * further use offline. The object has to be initialized with this names, + * they cannot be extended after this, so this information must be + * available for the base class to use. + */ + StatusCode initializeBase( + const std::vector<std::string>& componentNames); + + /** + * @brief Calculate and fill the output MET value + * @param met The object to fill + * @param context The event context + * @param monitors Extra variables to be monitored + * + * The builder passed in to the monitors variable can be filled with any + * variables that the particular algorithm wishes to monitor. Extra + * variables that can be calculated directly from the xAOD::TrigMissingET + * object can also be added using the monitor function. + */ + virtual StatusCode fillMET( + xAOD::TrigMissingET& met, + const EventContext& context, + MonGroupBuilder& monitors) const = 0; + + /** + * @brief Add monitor variables from an xAOD::TrigMissingET object + * @param met The object to fill from + * @param monitors Extra variables to be monitored + */ + virtual StatusCode monitor( + const xAOD::TrigMissingET& met, + MonGroupBuilder& monitors) const; + + /** + * @brief Flag suspicious values in the output MET + * @param met The xAOD::TrigMissingET object to flag + */ + virtual StatusCode flagMET(xAOD::TrigMissingET& met) const; + + private: + /************************************************************************ + * Properties (Not accessible from derived classes) + ***********************************************************************/ + /// The output MET object + SG::WriteHandleKey<xAOD::TrigMissingETContainer> m_metContainerKey { + this, "METContainerKey", "HLT_MET", "Name of the output MET object"}; + /// The monitoring tool + ToolHandle<GenericMonitoringTool> m_monTool{ + this, "MonTool", "", "Monitoring tool"}; + Gaudi::Property<float> m_maxComponentMetSumEtRatio{ + "MaxComponentMetSumEtRatio", 1., + "The maximum MET/SumEt ratio per component"}; + Gaudi::Property<float> m_maxGlobalMetSumEtRatio{ + "MaxGlobalMetSumEtRatio", 1., + "The maximum MET/SumEt ratio for the total value"}; + + /************************************************************************ + * Data members (Not accessible from derived classes) + ***********************************************************************/ + /// Whether or not this class has been correctly initialised. + bool m_baseInitialised{false}; + }; //> end class FexBase +} } //> end namespace HTL::MET +#endif //> !TRIGEFMISSINGET_FEXBASE_H diff --git a/Trigger/TrigAlgorithms/TrigEFMissingET/src/METComponent.cxx b/Trigger/TrigAlgorithms/TrigEFMissingET/src/METComponent.cxx new file mode 100644 index 00000000000..f000813943f --- /dev/null +++ b/Trigger/TrigAlgorithms/TrigEFMissingET/src/METComponent.cxx @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + */ + +#include "TrigEFMissingET/METComponent.h" +#include <cmath> + +namespace HLT { namespace MET { + METComponent::METComponent(const xAOD::TrigMissingET& met) : + mpx(met.ex() ), + mpy(met.ey() ), + mpz(met.ez() ), + sumE(met.sumE() ), + sumEt(met.sumEt() ), + status(met.flag() ) + {} + + METComponent::METComponent( + std::size_t idx, const xAOD::TrigMissingET& met) : + mpx(met.exComponent(idx) ), + mpy(met.eyComponent(idx) ), + mpz(met.ezComponent(idx) ), + sumE(met.sumEComponent(idx) ), + sumEt(met.sumEtComponent(idx) ), + status(met.statusComponent(idx) ) + {} + + float METComponent::met() const { + return sqrt(mpx*mpx+mpy*mpy); + } + + float METComponent::magnitude() const { + return sqrt(mpx*mpx+mpy*mpy+mpz*mpz); + } + + float METComponent::phi() const { + return std::atan2(mpy, mpx); + } + + float METComponent::eta() const { + if (met() == 0) + return 0; + return std::asinh(mpz/met() ); + } + + METComponent operator+( + const METComponent& lhs, + const METComponent& rhs) + { + METComponent ret(lhs); + ret += rhs; + return ret; + } + + METComponent& METComponent::operator+=( + const METComponent& other) + { + mpx += other.mpx; + mpy += other.mpy; + mpz += other.mpz; + sumE += other.sumE; + sumEt += other.sumEt; + status |= other.status; + return *this; + } + + METComponent& METComponent::operator+=( + const TLorentzVector& otherP4) + { + mpx -= otherP4.Px(); + mpy -= otherP4.Py(); + mpz -= otherP4.Pz(); + sumE += otherP4.E(); + sumEt += otherP4.Pt(); + return *this; + } + + METComponent& METComponent::operator+=( + const SignedKinematics& kin) + { + mpx -= kin.px(); + mpy -= kin.py(); + mpz -= kin.pz(); + sumE += kin.energy(); + sumEt += kin.pt(); + return *this; + } + + void METComponent::fillMET(xAOD::TrigMissingET& met) const + { + met.setEx(mpx); + met.setEy(mpy); + met.setEz(mpz); + met.setSumE(sumE); + met.setSumEt(sumEt); + met.setFlag(status); + } + + void METComponent::fillMETComponent( + std::size_t ii, xAOD::TrigMissingET& met) const + { + met.setExComponent(ii, mpx); + met.setEyComponent(ii, mpy); + met.setEzComponent(ii, mpy); + met.setSumEComponent(ii, sumE); + met.setSumEtComponent(ii, sumEt); + met.setStatusComponent(ii, status); + } + + std::ostream& operator<<(std::ostream& os, const METComponent& component) + { + os << "(mpx, mpy, mpz, met, sumEt, sumE) = (" + << component.mpx << ", " + << component.mpy << ", " + << component.mpz << ", " + << component.met() << ", " + << component.sumEt << ", " + << component.sumE << ") [MeV]"; + return os; + } +} } //> end namespace HLT::MET diff --git a/Trigger/TrigAlgorithms/TrigEFMissingET/src/MonGroupBuilder.cxx b/Trigger/TrigAlgorithms/TrigEFMissingET/src/MonGroupBuilder.cxx new file mode 100644 index 00000000000..48dc0b7ff8e --- /dev/null +++ b/Trigger/TrigAlgorithms/TrigEFMissingET/src/MonGroupBuilder.cxx @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + */ + +/****************************************************************************** + * @package Trigger/TrigAlgorithms/TrigEFMissingET + * @file MonGroupBuilder.cxx + * + * Implementation of monitoring group builder + * @author Jon Burr + *****************************************************************************/ + +#include "MonGroupBuilder.h" + +namespace HLT { namespace MET { + void MonGroupBuilder::add(Monitored::IMonitoredVariable& variable) + { + m_references.push_back(variable); + } + + Monitored::Group MonGroupBuilder::build( + const ToolHandle<GenericMonitoringTool>& tool) const + { + return Monitored::Group(tool, m_references); + } + + void MonGroupBuilder::increaseCapacity(std::size_t value, bool owned) + { + m_references.reserve(value+m_references.capacity() ); + if (owned) + m_ptrs.reserve(value+m_ptrs.capacity() ); + } +} } //> end namespace HLT::MET diff --git a/Trigger/TrigAlgorithms/TrigEFMissingET/src/MonGroupBuilder.h b/Trigger/TrigAlgorithms/TrigEFMissingET/src/MonGroupBuilder.h new file mode 100644 index 00000000000..07436042a7d --- /dev/null +++ b/Trigger/TrigAlgorithms/TrigEFMissingET/src/MonGroupBuilder.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + */ + +/****************************************************************************** + * @package Trigger/TrigAlgorithms/TrigEFMissingET + * @class MonGroupBuilder + * + * @brief Class to help with building monitoring groups + * @author Jon Burr + *****************************************************************************/ + +#ifndef TRIGEFMISSINGET_MONGROUPBUILDER_H +#define TRIGEFMISSINGET_MONGROUPBUILDER_H 1 + +#include "AthenaMonitoringKernel/MonitoredGroup.h" +#include <type_traits> +#include <memory> + +/****************************************************************************** + * @class MonGroupBuilder + * + * Class allowing incremental building of Monitored::Groups. + * + * Currently, it's only possible to load all members of a single + * Monitored::Group simultaneously, i.e. it's not possible to build up the group + * a few members at a time. However in these algorithms I found times where I + * wanted to monitor several variables at the same time, but trigger these from + * different locations. + *****************************************************************************/ + +namespace HLT { namespace MET { + class MonGroupBuilder { + public: + /** + * @brief Add a new monitored variable + * @param variable The variable to monitor + * + * This overload will not take ownership of the variable + */ + void add(Monitored::IMonitoredVariable& variable); + + /** + * @brief Add a new monitored variable + * @tparam T The type of monitored variable + * @param variable The variable to monitor + * + * This overload will take ownership of the variable + */ + template <typename T, + typename = std::enable_if_t< + !std::is_lvalue_reference_v<T> && + std::is_base_of_v<Monitored::IMonitoredVariable, T>>> + void add(T&& variable) + { + m_ptrs.push_back(std::make_unique<T>(std::move(variable) ) ); + add(*m_ptrs.back() ); + } + + /** + * @brief Build the monitored group + * @param tool The monitoring tool to add the group to + * + * Builds the monitored group. Note that if this builder owns any + * variables then fill *must* be called on the group before this object + * goes out of scope (remembering that groups call fill on destruction if + * it hasn't been called before this). + */ + Monitored::Group build( + const ToolHandle<GenericMonitoringTool>& tool) const; + + /** + * @brief Increase the internal capacity + * @param value The amount to increase capacity by + * @param owned Whether to increase the 'owned' capacity by the same + * amount + * + * Increase the capacity of the internal vectors. This function is used + * for performance only. + */ + void increaseCapacity(std::size_t value, bool owned=false); + private: + /// References to monitored variables + std::vector<std::reference_wrapper<Monitored::IMonitoredVariable>> m_references; + /// Any monitored variables that we own directly + std::vector<std::unique_ptr<Monitored::IMonitoredVariable>> m_ptrs; + }; //> end class MonGroupBuilder +} } //> end namespace HLT::MET + +#endif //> !TRIGEFMISSINGET_MONGROUPBUILDER_H diff --git a/Trigger/TrigAlgorithms/TrigEFMissingET/src/SignedKinematics.cxx b/Trigger/TrigAlgorithms/TrigEFMissingET/src/SignedKinematics.cxx new file mode 100644 index 00000000000..a85a4a40a68 --- /dev/null +++ b/Trigger/TrigAlgorithms/TrigEFMissingET/src/SignedKinematics.cxx @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + */ + +#include "TrigEFMissingET/SignedKinematics.h" +#include <TLorentzVector.h> +#include "xAODBase/IParticle.h" +#include <TVector2.h> + +namespace HLT { namespace MET { + SignedKinematics::SignedKinematics() {} + SignedKinematics::SignedKinematics( + double px, double py, double pz, double energy) : + m_p4(px, py, pz, energy) + {} + + SignedKinematics::SignedKinematics(const TLorentzVector& tlv) : + m_p4(tlv.Px(), tlv.Py(), tlv.Pz(), tlv.E() ) + {} + + SignedKinematics::SignedKinematics(const xAOD::IParticle& particle) : + SignedKinematics(fromEnergyEtaPhiM( + particle.e(), particle.eta(), particle.phi(), particle.m() ) ) + {} + + SignedKinematics SignedKinematics::fromEnergyEtaPhi( + double energy, double eta, double phi) + { + return fromEnergyEtaPhiM(energy, eta, phi, 0.); + } + + SignedKinematics SignedKinematics::fromEnergyEtaPhiM( + double energy, double eta, double phi, double mass) + { + double p = energy; + if (mass != 0) { + int sgn = (p > 0) - (p < 0); + p = sgn * sqrt(p*p - mass*mass); + } + double pt = p/std::cosh(eta); + double pz = pt*std::sinh(eta); + return SignedKinematics( + pt*std::cos(phi), pt*std::sin(phi), pz, energy); + } + + SignedKinematics SignedKinematics::fromEtEtaPhi( + double et, double eta, double phi) + { + return fromEtEtaPhiM(et, eta, phi, 0.); + } + + SignedKinematics SignedKinematics::fromEtEtaPhiM( + double et, double eta, double phi, double mass) + { + return fromEnergyEtaPhiM(et*std::cosh(eta), eta, phi, mass); + } + + int SignedKinematics::sign() const { + return (energy() > 0) - (energy() < 0); + } + + double SignedKinematics::eta() const { + return sign() * m_p4.Eta(); + } + + double SignedKinematics::phi() const { + double val = m_p4.Phi(); + if (sign() < 0) + val += TMath::Pi(); + return TVector2::Phi_0_2pi(val); + } + + double SignedKinematics::sinPhi() const { + double thePt = pt(); + // if pt() is 0 then the value is not determined. + // For this phi = 0 + return (thePt == 0 ? 0 : py() / thePt ); + } + double SignedKinematics::cosPhi() const { + double thePt = pt(); + // if pt() is 0 then the value is not determined. + // Take phi = 0 + return (thePt == 0 ? 1 : px() / thePt ); + } + + double SignedKinematics::sinhEta() const { + double thePt = pt(); + // if pt is 0 then the value is not determined. + // Take eta = 0 + return (thePt == 0 ? 0 : pz() / thePt ); + } + double SignedKinematics::coshEta() const { + double thePt2 = pt2(); + // if pt is 0 then the value is not determined. + // Take eta = 0 + if (thePt2 == 0) + return 1; + // Otherwise, calculate sinh^2 eta, then use + // cosh eta = sqrt(1 + sinh^2 eta) + return sqrt(1 + pz()*pz() / thePt2); + } + + double SignedKinematics::p() const { + return sign() * absP(); + } + double SignedKinematics::absP() const { + return sqrt(p2() ); + } + double SignedKinematics::p2() const { + return pt2() + pz()*pz(); + } + double SignedKinematics::pt() const { + return sign() * absPt(); + } + double SignedKinematics::absPt() const { + return sqrt(pt2() ); + } + double SignedKinematics::pt2() const { + return px()*px() + py()*py(); + } + double SignedKinematics::px() const { + return m_p4.Px(); + } + double SignedKinematics::py() const { + return m_p4.Py(); + } + double SignedKinematics::pz() const { + return m_p4.Pz(); + } + + double SignedKinematics::energy() const { + return m_p4.E(); + } + double SignedKinematics::absEnergy() const { + return abs(energy() ); + } + double SignedKinematics::energy2() const { + return energy()*energy(); + } + double SignedKinematics::et() const { + return energy() / coshEta(); + } + double SignedKinematics::absEt() const { + return abs(et() ); + } + double SignedKinematics::et2() const { + return et()*et(); + } + double SignedKinematics::ex() const { + return et() * cosPhi(); + } + double SignedKinematics::ey() const { + return et() * sinPhi(); + } + double SignedKinematics::ez() const { + return et() * sinhEta(); + } + + double SignedKinematics::m2() const { + return energy2() - p2(); + } + + SignedKinematics::operator ROOT::Math::PxPyPzEVector() const { + return m_p4; + } + + SignedKinematics& SignedKinematics::operator+=(const SignedKinematics& other) + { + m_p4.SetPx(px()+other.px() ); + m_p4.SetPy(py()+other.py() ); + m_p4.SetPz(pz()+other.pz() ); + m_p4.SetE(energy()+other.energy() ); + return *this; + } + SignedKinematics& SignedKinematics::operator-=(const SignedKinematics& other) + { + m_p4.SetPx(px()-other.px() ); + m_p4.SetPy(py()-other.py() ); + m_p4.SetPz(pz()-other.pz() ); + m_p4.SetE(energy()-other.energy() ); + return *this; + } + + SignedKinematics operator+(const SignedKinematics& lhs, const SignedKinematics& rhs) + { + SignedKinematics val(lhs); + val += rhs; + return val; + } + SignedKinematics operator-(const SignedKinematics& lhs, const SignedKinematics& rhs) + { + SignedKinematics val(lhs); + val -= rhs; + return val; + } +} } //> end namespace HLT::MET diff --git a/Trigger/TrigAlgorithms/TrigEFMissingET/src/StatusFlags.cxx b/Trigger/TrigAlgorithms/TrigEFMissingET/src/StatusFlags.cxx new file mode 100644 index 00000000000..3252af0fc0c --- /dev/null +++ b/Trigger/TrigAlgorithms/TrigEFMissingET/src/StatusFlags.cxx @@ -0,0 +1,66 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ +#include "TrigEFMissingET/StatusFlags.h" +#include <stdexcept> + +namespace HLT { namespace MET { namespace StatusFlag { + std::string flagIndexToString(int idx) { + switch(idx) { + case 0: + case 4: + case 13: + case 14: + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + return "UNUSED"; + case 1: + return "BSConvError"; + case 2: + return "MuonError"; + case 3: + return "FEBError"; + case 5: + return "ComponentBigMEtSEtRatio"; + case 6: + return "BadComponentEnergy"; + case 7: + return "BadEnergyRatio"; + case 8: + return "NoisyEnergyRatio"; + case 9: + return "BadCellQuality"; + case 10: + return "BadCellEnergy"; + case 11: + return "BadCellTime"; + case 12: + return "NoMuonTrack"; + case 15: + return "ComponentErrors"; + case 27: + return "GlobalNoisyEnergyRatio"; + case 28: + return "BadEMFraction"; + case 29: + return "GlobalNoisyEnerygRatio"; + case 30: + return "ObjectInCrack"; + case 31: + return "GlobalErrors"; + default: + throw std::out_of_range("Invalid index provided " + std::to_string(idx) ); + // Make gcc happy + return ""; + } + } +} } } //> end namespace HLT::MET::StatusFlag diff --git a/Trigger/TrigAlgorithms/TrigEFMissingET/src/TrkMHTFex.cxx b/Trigger/TrigAlgorithms/TrigEFMissingET/src/TrkMHTFex.cxx new file mode 100644 index 00000000000..7fe6951b2b8 --- /dev/null +++ b/Trigger/TrigAlgorithms/TrigEFMissingET/src/TrkMHTFex.cxx @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + */ + +/****************************************************************************** + * @package Trigger/TrigAlgorithms/TrigEFMissingET + * @file TrkMHTFex.cxx + * + * Implementation of trkmht fex class + * @author Jon Burr + *****************************************************************************/ + +#include "TrkMHTFex.h" +#include "TrigEFMissingET/METComponent.h" +#include "StoreGate/DecorKeyHelpers.h" +#include "StoreGate/ReadDecorHandle.h" +#include "AthLinks/ElementLink.h" +#include "xAODBase/IParticleContainer.h" +#include <unordered_set> +#include <numeric> + +namespace { + bool isCentral(const xAOD::Jet* ijet) { + return fabs(ijet->eta() ) < 2.4; + } +} + +namespace HLT { namespace MET { + TrkMHTFex::TrkMHTFex(const std::string& name, ISvcLocator* pSvcLocator): + FexBase(name, pSvcLocator) + {} + + StatusCode TrkMHTFex::initialize() + { + CHECK( m_jetKey.initialize() ); + CHECK( m_trackKey.initialize() ); + CHECK( m_vertexKey.initialize() ); + CHECK( m_tvaKey.initialize() ); + CHECK( m_trackSelTool.retrieve() ); + + // Update the decor keys if necessary + if (m_jvtKey.key().find(".") == std::string::npos) { + m_jvtKey = m_jetKey.key() + "." + m_jvtKey.key(); + CHECK( m_jvtKey.initialize() ); + } + else if (SG::contKeyFromKey(m_jvtKey.key() ) != m_jetKey.key() ) { + ATH_MSG_ERROR("JVT container key does not match jet key!"); + return StatusCode::FAILURE; + } + if (m_trackGAKey.key().find(".") == std::string::npos) { + m_trackGAKey = m_jetKey.key() + "." + m_trackGAKey.key(); + CHECK( m_trackGAKey.initialize() ); + } + else if (SG::contKeyFromKey(m_trackGAKey.key() ) != m_jetKey.key() ) { + ATH_MSG_ERROR("track links container key does not match jet key!"); + return StatusCode::FAILURE; + } + + return initializeBase( + {"JETB1", "JETB2", "JETE1", "JETE2", "TrackSoftTerm"}); + } + + StatusCode TrkMHTFex::fillMET( + xAOD::TrigMissingET& met, + const EventContext& context, + MonGroupBuilder&) const + { + // Retrieve the inputs + auto jets = SG::makeHandle(m_jetKey, context); + auto tracks = SG::makeHandle(m_trackKey, context); + auto vertices = SG::makeHandle(m_vertexKey, context); + auto tva = SG::makeHandle(m_tvaKey, context); + auto jvtAcc = SG::makeHandle<float>(m_jvtKey, context); + auto trackLinksAcc = SG::makeHandle<std::vector<ElementLink<xAOD::IParticleContainer>>>(m_trackGAKey, context); + + // Work out which is the primary vertex + // I do not know if there is a way to see which vertex was counted as + // primary by the JVT calculation but I see no reason to suspect that it + // would be anything other than the one found by this method + const xAOD::Vertex* priVtx = nullptr; + for (const xAOD::Vertex* vtx : *vertices) + if (vtx->vertexType() == xAOD::VxType::PriVtx) { + priVtx = vtx; + break; + } + + // Prepare the output values + std::array<METComponent, 4> mhtSums; + METComponent tstSum; + + // If no primary vertex is identified, the algorithm will return 0 + if (priVtx) { + // Prepare a list of primary vertex tracks + std::vector<const xAOD::TrackParticle*> tstTracks; + tstTracks.reserve(tracks->size() ); + for (const xAOD::TrackParticle* itrk : *tracks) + if (tva->associatedVertex(itrk) == priVtx && + itrk->pt() < m_tstPtCeil && + m_trackSelTool->accept(*itrk, priVtx) ) + tstTracks.push_back(itrk); + // Keep indices of tracks associated to hard-scatter jets + std::unordered_set<std::size_t> jetTrackIndices; + // Iterate over the jets + for (const xAOD::Jet* ijet : *jets) { + if (isCentral(ijet) ) { + if (ijet->pt() < m_minJvtJetPt) + // Skip central jets below the JVT pT threshold + continue; + if (ijet->pt() < m_maxJvtJetPt && jvtAcc(*ijet) < m_jvtSelection) + // Skip central jets below the maximum JVT pT threshold and with JVT + // below threshold + continue; + } // end if isCentral(ijet) + else { + if (ijet->pt() < m_forwardJetPt) + // Skip forward jets below the forward jet pT threshold + continue; + } + // The index of the mht METComponent + std::size_t componentIdx = 0; + if (ijet->eta() < 0) + ++componentIdx; + if (isCentral(ijet) ) + componentIdx += 2; + // Add the jet into the correct component + mhtSums.at(componentIdx) += ijet->p4(); + // Iterate over the ghost-associated tracks + for (const auto& link : trackLinksAcc(*ijet) ) { + if (link.getDataPtr() != tracks.ptr() ) { + ATH_MSG_ERROR("Tracks linked with key '" << m_trackGAKey + << "' do not match tracks retrieved with '" + << m_trackKey << "'!"); + return StatusCode::FAILURE; + } + jetTrackIndices.insert(link.index() ); + } + } + // Build up the track soft term + for (const xAOD::TrackParticle* itrk : tstTracks) + if (jetTrackIndices.count(itrk->index() ) == 0) + // Only include tracks that weren't associated to a hard-scatter jet + tstSum += itrk->p4(); + } //> end if priVtx + // Save the sum over components + std::accumulate(mhtSums.begin(), mhtSums.end(), tstSum).fillMET(met); + // Save each component + for (std::size_t ii = 0; ii < 4; ++ii) + mhtSums.at(ii).fillMETComponent(ii, met); + // Save the tst + tstSum.fillMETComponent(4, met); + + // Debugging information + ATH_MSG_DEBUG("Jets: " + << std::accumulate(mhtSums.begin(), mhtSums.end(), METComponent{}) ); + + return StatusCode::SUCCESS; + } + +} } //> end namespace HLT::MET diff --git a/Trigger/TrigAlgorithms/TrigEFMissingET/src/TrkMHTFex.h b/Trigger/TrigAlgorithms/TrigEFMissingET/src/TrkMHTFex.h new file mode 100644 index 00000000000..d094100a374 --- /dev/null +++ b/Trigger/TrigAlgorithms/TrigEFMissingET/src/TrkMHTFex.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + */ + +/****************************************************************************** + * @package Trigger/TrigAlgorithms/TrigEFMissingET + * @class TrkMHTFex + * + * @brief Fex class for trkmht algorithm + * @author Jon Burr, Ren-Jie Wang + *****************************************************************************/ + +#ifndef TRIGEFMISSINGET_TRKMHTFEX_H +#define TRIGEFMISSINGET_TRKMHTFEX_H 1 + +#include "FexBase.h" +#include "xAODJet/JetContainer.h" +#include "xAODTracking/TrackParticleContainer.h" +#include "xAODTracking/VertexContainer.h" +#include "JetEDM/TrackVertexAssociation.h" +#include "StoreGate/ReadDecorHandleKey.h" +#include "InDetTrackSelectionTool/IInDetTrackSelectionTool.h" + +/****************************************************************************** + * @class TrkMHTFex + * + * Class to create output from the trkmht algorithm. + * + * trkmht calculates the MET using jets with JVT suppression applied. There is + * an additional track soft term which adds in any tracks associated to the hard + * scatter vertex which are not associated to jets passing the JVT selection. + *****************************************************************************/ + +namespace HLT { namespace MET { + class TrkMHTFex : public FexBase + { + public: + /// Constructor + TrkMHTFex(const std::string& name, ISvcLocator* pSvcLocator); + + /// Initialise the fex + virtual StatusCode initialize() override; + + private: + /************************************************************************ + * Properties + ***********************************************************************/ + /// Input jets and jvt + SG::ReadHandleKey<xAOD::JetContainer> m_jetKey{ + this, "JetName", "jets", "Input jet collection"}; + /// Input tracks + SG::ReadHandleKey<xAOD::TrackParticleContainer> m_trackKey{ + this, "TrackName", "tracks", + "Input track collection. Should be ghost-associated to the jets"}; + /// Input vertices + SG::ReadHandleKey<xAOD::VertexContainer> m_vertexKey{ + this, "VertexName", "vertices", "Input vertex collection"}; + /// The track-vertex assocation name + SG::ReadHandleKey<jet::TrackVertexAssociation> m_tvaKey{ + this, "TVAName", "trackVtxAssoc", + "The name of the track-vertex association"}; + /// The Jvt selection name + SG::ReadDecorHandleKey<xAOD::JetContainer> m_jvtKey{ + this, "JvtName", "Jvt", "The name of the JVT decorator"}; + /// The ghost-association aux element name + SG::ReadDecorHandleKey<xAOD::JetContainer> m_trackGAKey{ + this, "TrackLinkName", "tracks", "The name of the jet track links"}; + /// Pt selection on forward jets + Gaudi::Property<float> m_forwardJetPt{ + this, "ForwardJetPt", 0., "The pT cut applied to forward jets"}; + /// Minimum pt selection for JVT on central jets + Gaudi::Property<float> m_minJvtJetPt{ + this, "MinimumJvtJetPt", 20. * Gaudi::Units::GeV, + "The minimum pT for central jets for JVT selections to be used"}; + /// Maximum pt selection for JVT on central jets + Gaudi::Property<float> m_maxJvtJetPt{ + this, "MaximumJvtJetPt", 50. * Gaudi::Units::GeV, + "The maximum pT for central jets for JVT selections to be used"}; + /// The JVT selection + Gaudi::Property<float> m_jvtSelection{ + this, "JVTCut", 0.9, "The JVT selection"}; + /// The track selection tool + ToolHandle<InDet::IInDetTrackSelectionTool> m_trackSelTool{ + this, "TrackSelTool", "InDet::InDetTrackSelectionTool/TrackSelTool", + "The track selection tool to use for tracks entering the track soft " + "term."}; + /// The maximum pT for tracks in the soft term + Gaudi::Property<float> m_tstPtCeil{ + this, "TrackSoftTermPtCeiling", 20. * Gaudi::Units::GeV, + "The maximum pT for tracks entering the track soft term."}; + + /************************************************************************ + * Internal functions + ***********************************************************************/ + /** + * @brief Calculate and fill the output MET value + * @param met The object to fill + * @param context The event context + * @param monitors[out] Any extra monitors to fill + */ + virtual StatusCode fillMET( + xAOD::TrigMissingET& met, + const EventContext& context, + MonGroupBuilder& monitors) const override; + }; //> end class TrkMHTFex +} } //> end namespace HLT::MET + +#endif //> !TRIGEFMISSINGET_TRKMHTFEX_H diff --git a/Trigger/TrigAlgorithms/TrigEFMissingET/src/components/TrigEFMissingET_entries.cxx b/Trigger/TrigAlgorithms/TrigEFMissingET/src/components/TrigEFMissingET_entries.cxx index 7f26a6b52de..d0439c10f39 100644 --- a/Trigger/TrigAlgorithms/TrigEFMissingET/src/components/TrigEFMissingET_entries.cxx +++ b/Trigger/TrigAlgorithms/TrigEFMissingET/src/components/TrigEFMissingET_entries.cxx @@ -19,6 +19,7 @@ #include "../EFMissingETFromJetsMT.h" #include "../EFMissingETFlagsMT.h" #include "../EFMissingETComponentCopier.h" +#include "../TrkMHTFex.h" DECLARE_COMPONENT( EFMissingET ) DECLARE_COMPONENT( EFMissingETBaseTool ) @@ -40,4 +41,4 @@ DECLARE_COMPONENT( EFMissingETFromClustersMT ) DECLARE_COMPONENT( EFMissingETFromClustersPufitMT ) DECLARE_COMPONENT( EFMissingETFromJetsMT ) DECLARE_COMPONENT( EFMissingETFlagsMT ) - +DECLARE_COMPONENT( HLT::MET::TrkMHTFex ) diff --git a/Trigger/TrigValidation/TrigAnalysisTest/share/q221_RDOtoRDOTrig_mt1_build.ref b/Trigger/TrigValidation/TrigAnalysisTest/share/q221_RDOtoRDOTrig_mt1_build.ref index 51d3609672a..e96f0af15b1 100644 --- a/Trigger/TrigValidation/TrigAnalysisTest/share/q221_RDOtoRDOTrig_mt1_build.ref +++ b/Trigger/TrigValidation/TrigAnalysisTest/share/q221_RDOtoRDOTrig_mt1_build.ref @@ -162,5 +162,7 @@ TrigSignatureMoniMT INFO HLT_xe30_mht_L1XE10 TrigSignatureMoniMT INFO HLT_xe30_mht_L1XE10 decisions 0 0 0 0 0 0 TrigSignatureMoniMT INFO HLT_xe30_tcpufit_L1XE10 0 0 0 0 0 0 0 0 0 TrigSignatureMoniMT INFO HLT_xe30_tcpufit_L1XE10 decisions 0 0 0 0 0 0 +TrigSignatureMoniMT INFO HLT_xe30_trkmht_L1XE10 0 0 0 0 0 0 0 0 0 +TrigSignatureMoniMT INFO HLT_xe30_trkmht_L1XE10 decisions 0 0 0 0 0 0 TrigSignatureMoniMT INFO HLT_xe65_cell_L1XE50 0 0 0 0 0 0 0 0 0 TrigSignatureMoniMT INFO HLT_xe65_cell_L1XE50 decisions 0 0 0 0 0 0 diff --git a/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu_build.ref b/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu_build.ref index fc41dfb568e..4c39dfe4022 100644 --- a/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu_build.ref +++ b/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu_build.ref @@ -172,5 +172,7 @@ TrigSignatureMoniMT INFO HLT_xe30_mht_L1XE10 TrigSignatureMoniMT INFO HLT_xe30_mht_L1XE10 decisions 17 0 0 0 0 0 TrigSignatureMoniMT INFO HLT_xe30_tcpufit_L1XE10 20 20 3 0 0 0 0 0 3 TrigSignatureMoniMT INFO HLT_xe30_tcpufit_L1XE10 decisions 3 0 0 0 0 0 +TrigSignatureMoniMT INFO HLT_xe30_trkmht_L1XE10 20 20 9 0 0 0 0 0 9 +TrigSignatureMoniMT INFO HLT_xe30_trkmht_L1XE10 decisions 9 0 0 0 0 0 TrigSignatureMoniMT INFO HLT_xe65_cell_L1XE50 20 20 3 0 0 0 0 0 3 TrigSignatureMoniMT INFO HLT_xe65_cell_L1XE50 decisions 3 0 0 0 0 0 diff --git a/Trigger/TrigValidation/TrigUpgradeTest/share/slice_met.ref b/Trigger/TrigValidation/TrigUpgradeTest/share/slice_met.ref index 0e0a1342de7..04ce1025af2 100644 --- a/Trigger/TrigValidation/TrigUpgradeTest/share/slice_met.ref +++ b/Trigger/TrigValidation/TrigUpgradeTest/share/slice_met.ref @@ -1,10 +1,12 @@ -TrigSignatureMoniMT INFO HLT_xe30_cell_L1XE10 50 50 30 30 -TrigSignatureMoniMT INFO HLT_xe30_cell_L1XE10 decisions 30 -TrigSignatureMoniMT INFO HLT_xe30_cell_xe30_tcpufit_L1XE1050 50 31 4 -TrigSignatureMoniMT INFO HLT_xe30_cell_xe30_tcpufit_L1XE10 decisions 39 -TrigSignatureMoniMT INFO HLT_xe30_mht_L1XE10 50 50 39 39 -TrigSignatureMoniMT INFO HLT_xe30_mht_L1XE10 decisions 39 -TrigSignatureMoniMT INFO HLT_xe30_tcpufit_L1XE10 50 50 5 5 -TrigSignatureMoniMT INFO HLT_xe30_tcpufit_L1XE10 decisions 5 -TrigSignatureMoniMT INFO HLT_xe65_cell_L1XE50 50 50 7 7 -TrigSignatureMoniMT INFO HLT_xe65_cell_L1XE50 decisions 7 +TrigSignatureMoniMT INFO HLT_xe30_cell_L1XE10 50 50 30 30 +TrigSignatureMoniMT INFO HLT_xe30_cell_L1XE10 decisions 30 +TrigSignatureMoniMT INFO HLT_xe30_cell_xe30_tcpufit_L1XE1050 50 31 4 +TrigSignatureMoniMT INFO HLT_xe30_cell_xe30_tcpufit_L1XE10 decisions 39 +TrigSignatureMoniMT INFO HLT_xe30_mht_L1XE10 50 50 39 39 +TrigSignatureMoniMT INFO HLT_xe30_mht_L1XE10 decisions 39 +TrigSignatureMoniMT INFO HLT_xe30_tcpufit_L1XE10 50 50 5 5 +TrigSignatureMoniMT INFO HLT_xe30_tcpufit_L1XE10 decisions 5 +TrigSignatureMoniMT INFO HLT_xe30_trkmht_L1XE10 50 50 18 18 +TrigSignatureMoniMT INFO HLT_xe30_trkmht_L1XE10 decisions 18 +TrigSignatureMoniMT INFO HLT_xe65_cell_L1XE50 50 50 7 7 +TrigSignatureMoniMT INFO HLT_xe65_cell_L1XE50 decisions 7 diff --git a/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py b/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py index 092f9b29fea..95afbcfc28f 100644 --- a/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py +++ b/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py @@ -251,6 +251,9 @@ TriggerHLTListRun3 = [ ('xAOD::TrigMissingETContainer#HLT_MET_tc', 'BS ESD AODFULL AODSLIM AODVERYSLIM', 'MET'), ('xAOD::TrigMissingETAuxContainer#HLT_MET_tcAux.', 'BS ESD AODFULL AODSLIM AODVERYSLIM', 'MET'), + ('xAOD::TrigMissingETContainer#HLT_MET_trkmht', 'BS ESD AODFULL AODSLIM AODVERYSLIM', 'MET'), + ('xAOD::TrigMissingETAuxContainer#HLT_MET_trkmhtAux.', 'BS ESD AODFULL AODSLIM AODVERYSLIM', 'MET'), + ('xAOD::CaloClusterContainer#HLT_TopoCaloClustersFS', 'BS ESD AODFULL AODSLIM AODVERYSLIM', 'MET'), ('xAOD::CaloClusterTrigAuxContainer#HLT_TopoCaloClustersFSAux.nCells', 'BS ESD AODFULL AODSLIM AODVERYSLIM', 'MET'), diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/MET/METChainConfiguration.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/MET/METChainConfiguration.py index 9acbfa54f06..b0129c6d94c 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/MET/METChainConfiguration.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/MET/METChainConfiguration.py @@ -7,7 +7,9 @@ log = logging.getLogger("TriggerMenuMT.HLTMenuConfig.MET.METChainConfiguration") from TriggerMenuMT.HLTMenuConfig.Menu.ChainConfigurationBase import ChainConfigurationBase -from TriggerMenuMT.HLTMenuConfig.MET.METMenuSequences import metCellMenuSequence, metClusterPufitMenuSequence, metJetMenuSequence +from TriggerMenuMT.HLTMenuConfig.MET.METMenuSequences import ( + metCellMenuSequence, metClusterPufitMenuSequence, metJetMenuSequence, + metTrkMHTMenuSequence) #---------------------------------------------------------------- # fragments generating configuration will be functions in New JO, @@ -24,7 +26,8 @@ def MetClusterPufitSequenceCfg( flags ): def MetJetSequenceCfg( flags ): return metJetMenuSequence() - +def MetTrkMHTSequenceCfg( flags ): + return metTrkMHTMenuSequence() #---------------------------------------------------------------- # Class to configure chain @@ -47,6 +50,7 @@ class MetChainConfiguration(ChainConfigurationBase): "cell":[self.getMetCellStep()], "tcpufit":[self.getMetClusterPufitStep()], "mht":[self.getMetJetStep()], + "trkmht" : [self.getMetTrkMHTStep()], } @@ -79,7 +83,9 @@ class MetChainConfiguration(ChainConfigurationBase): def getMetClusterPufitStep(self): return self.getStep(1,"met_clusterpufit", [MetClusterPufitSequenceCfg] ) - + # Configuration of trkmht chain + def getMetTrkMHTStep(self): + return self.getStep(1, "met_trkmht", [MetTrkMHTSequenceCfg] ) diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/MET/METMenuSequences.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/MET/METMenuSequences.py index 5541242f676..34c5a5bdd8d 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/MET/METMenuSequences.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/MET/METMenuSequences.py @@ -72,3 +72,19 @@ def metJetMenuSequence(): Maker = InputMakerAlg, Hypo = metHypoAlg, HypoToolGen = TrigMETCellHypoToolFromDict ) + +def metTrkMHTMenuSequence(): + from TriggerMenuMT.HLTMenuConfig.MET.METRecoSequences import metTrkMHTAthSequence + reco_seq, input_alg, seq_out = RecoFragmentsPool.retrieve( + metTrkMHTAthSequence, ConfigFlags) + + # The hypo + hypo = TrigMissingETHypoAlgMT("METHypoAlg_trkmht") + hypo.METContainerKey = seq_out + + # NB - the function is called 'TrigMETCellHypoToolFromDict' but it isn't + # actually specific to cell at all... something to change in the future + return MenuSequence( Sequence = reco_seq, + Maker = input_alg, + Hypo = hypo, + HypoToolGen = TrigMETCellHypoToolFromDict ) diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/MET/METRecoSequences.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/MET/METRecoSequences.py index 8b0674859c6..a0859aa9763 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/MET/METRecoSequences.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/MET/METRecoSequences.py @@ -5,10 +5,14 @@ from AthenaCommon.CFElements import seqAND from TrigEDMConfig.TriggerEDMRun3 import recordable from TriggerMenuMT.HLTMenuConfig.Menu.MenuComponents import RecoFragmentsPool -from TrigEFMissingET.TrigEFMissingETConf import EFMissingETAlgMT, EFMissingETFlagsMT +from TrigEFMissingET.TrigEFMissingETConf import ( + EFMissingETAlgMT, EFMissingETFlagsMT, HLT__MET__TrkMHTFex) from TrigEFMissingET.TrigEFMissingETMTConfig import getMETMonTool from TrigT2CaloCommon.CaloDef import clusterFSInputMaker +import GaudiKernel.SystemOfUnits as Units +from AthenaCommon.Logging import logging +log = logging.getLogger(__name__) def metCellAthSequence(ConfigFlags): InputMakerAlg= clusterFSInputMaker() @@ -152,3 +156,40 @@ def metJetRecoSequence(RoIs = 'FSJETRoI'): seqOut = metAlg.METContainerKey return (metJetRecoSequence, seqOut) +def metTrkMHTAthSequence(ConfigFlags): + InputMakerAlg = clusterFSInputMaker() + reco_seq, seq_out = metTrkMHTRecoSequence() + ath_seq = seqAND("MetTrkMHTAthSequence", [InputMakerAlg, reco_seq]) + return ath_seq, InputMakerAlg, seq_out + +def metTrkMHTRecoSequence(): + + # Prepare the inputs from the jet slice + from TriggerMenuMT.HLTMenuConfig.Jet.JetRecoSequences import jetRecoSequence + jetRecoDict={"recoAlg":"a4", "dataType": "tc", "calib": "em", "jetCalib": "subjesIS", "trkopt": "ftf", "cleaning": "noCleaning"} + (jetSeq, jetOut) = RecoFragmentsPool.retrieve( jetRecoSequence, None, dataSource="data", **jetRecoDict ) + + # These are the names set by the downstream algorithms. Unfortunately these + # aren't passed to us - we just have to 'know' them + tracks = "HLT_xAODTracks_FS" + vertices = "HLT_EFHistoPrmVtx" + tva = "JetTrackVtxAssoc_{trkopt}".format(**jetRecoDict) + track_links = "GhostTrack_{trkopt}".format(**jetRecoDict) + + alg = HLT__MET__TrkMHTFex( + name="EFMET_trkmht", + METContainerKey = recordable("HLT_MET_trkmht"), + MonTool = getMETMonTool(), + JetName = jetOut, + TrackName = tracks, + VertexName = vertices, + TVAName = tva, + TrackLinkName = track_links) + alg.TrackSelTool.CutLevel = "Loose" + alg.TrackSelTool.maxZ0SinTheta = 1.5 + alg.TrackSelTool.maxD0overSigmaD0 = 3 + alg.TrackSelTool.minPt = 1 * Units.GeV + + reco_seq = seqAND("metTrkMHTRecoSequence", [jetSeq, alg]) + return (reco_seq, alg.METContainerKey) + diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py index bc5ecbceefe..7c133678a38 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py @@ -81,6 +81,7 @@ def setupMenu(): ChainProp(name='HLT_xe30_cell_L1XE10', groups=SingleMETGroup), ChainProp(name='HLT_xe30_mht_L1XE10', groups=SingleMETGroup), ChainProp(name='HLT_xe30_tcpufit_L1XE10', groups=SingleMETGroup), + ChainProp(name='HLT_xe30_trkmht_L1XE10', groups=SingleMETGroup), # MultiMET Chain ChainProp(name='HLT_xe30_cell_xe30_tcpufit_L1XE10',l1SeedThresholds=['XE10']*2, groups=MultiMETGroup), #must be FS seeded diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py index b3206be7944..727248e60e0 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py @@ -276,7 +276,7 @@ METChainParts = { 'extra' : ['noL1'], 'calib' : ['lcw',], 'L2recoAlg' : [], - 'EFrecoAlg' : ['cell', 'tcpufit', 'mht'], + 'EFrecoAlg' : ['cell', 'tcpufit', 'mht', 'trkmht'], 'L2muonCorr' : [], 'EFmuonCorr' : [], 'addInfo' : ['FStracks'], -- GitLab