ATLAS Offline Software
Loading...
Searching...
No Matches
ObjectKinematicSelectorAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
8#include "Math/Vector4D.h"
9#include "TVector2.h"
10
11#include <algorithm>
12#include <cmath>
13
14using ROOT::Math::PtEtaPhiEVector;
15
16namespace CP {
17
18 ObjectKinematicSelectorAlg::ObjectKinematicSelectorAlg(const std::string &name, ISvcLocator *pSvcLocator)
19 : EL::AnaAlgorithm(name, pSvcLocator)
20 {}
21
26
29
30 // sanity checks on the configuration (the Python config guarantees these,
31 // but we fail early and clearly if the algorithm is driven directly)
32 std::size_t nParticleOperands = 0;
33 bool usesMET = false;
34 for (const std::string &kind : m_operandKinds) {
35 if (kind == "PARTICLE") ++nParticleOperands;
36 else if (kind == "MET") usesMET = true;
37 else {
38 ANA_MSG_ERROR("EXPR: unknown operand kind '" << kind << "'");
39 return StatusCode::FAILURE;
40 }
41 }
42 if (nParticleOperands != m_particlesHandles.size() ||
43 nParticleOperands != m_selectionKeys.size() ||
44 nParticleOperands != m_indices.size()) {
45 ANA_MSG_ERROR("EXPR: inconsistent operand configuration (particle handles/selections/indices mismatch)");
46 return StatusCode::FAILURE;
47 }
48 if (usesMET && !m_metHandle) {
49 ANA_MSG_ERROR("EXPR: a MET operand was requested but no MET container was configured");
50 return StatusCode::FAILURE;
51 }
52
53 // build one selection handle per particle operand, tied to its container
54 m_selections.clear();
55 m_selections.reserve(m_particlesHandles.size());
56 for (std::size_t i = 0; i < m_particlesHandles.size(); ++i) {
57 m_selections.emplace_back(m_selectionKeys[i], this);
59 }
60
61 ANA_CHECK(m_systematicsList.initialize());
62
64
65 return StatusCode::SUCCESS;
66 }
67
68 StatusCode ObjectKinematicSelectorAlg::execute(const EventContext& ctx) {
69
70 // a minimal kinematic record per operand; eta/e are unused for MET
71 struct Kin { double pt{0.}, eta{0.}, phi{0.}, e{0.}; bool isMET{false}; };
72
73 const std::string &var = m_variable.value();
74
75 for (const auto &sys : m_systematicsList.systematicsVector()) {
76 // retrieve the EventInfo
77 const xAOD::EventInfo *evtInfo = nullptr;
78 ANA_CHECK(m_eventInfoHandle.retrieve(evtInfo, sys, ctx));
79
80 // default-decorate EventInfo
81 m_decoration.setBool(*evtInfo, 0, sys);
82
83 // check the preselection
84 if (m_preselection && !m_preselection.getBool(*evtInfo, sys))
85 continue;
86
87 // build the per-operand kinematics, in expression order
88 std::vector<Kin> ops;
89 ops.reserve(m_operandKinds.size());
90 std::size_t pIdx = 0; // running index over the particle handle array
91
92 for (const std::string &kind : m_operandKinds) {
93 Kin k;
94 if (kind == "MET") {
95 const xAOD::MissingETContainer *met = nullptr;
96 ANA_CHECK(m_metHandle.retrieve(met, sys, ctx));
97 const xAOD::MissingET *term = (*met)[m_metTerm.value()];
98 if (term == nullptr) {
99 ANA_MSG_ERROR("EXPR: the MET term '" << m_metTerm.value() << "' does not exist! Aborting.");
100 return StatusCode::FAILURE;
101 }
102 k.pt = term->met();
103 k.phi = term->phi();
104 k.isMET = true;
105 ops.push_back(k);
106 continue;
107 }
108
109 // PARTICLE: collect objects passing the selection, pT-order, pick index
110 const xAOD::IParticleContainer *cont = nullptr;
111 ANA_CHECK(m_particlesHandles.at(pIdx).retrieve(cont, sys, ctx));
112
113 std::vector<const xAOD::IParticle*> passing;
114 passing.reserve(cont->size());
115 for (const xAOD::IParticle *p : *cont) {
116 if (!m_selections.at(pIdx) || m_selections.at(pIdx).getBool(*p, sys))
117 passing.push_back(p);
118 }
119 std::sort(passing.begin(), passing.end(),
120 [](const xAOD::IParticle *a, const xAOD::IParticle *b) {
121 return a->pt() > b->pt();
122 });
123
124 const int requested = m_indices[pIdx];
125 if (requested < 0 || static_cast<std::size_t>(requested) >= passing.size()) {
126 ANA_MSG_ERROR("EXPR: object index " << requested << " requested but only "
127 << passing.size() << " object(s) pass the selection; this event "
128 "selection cannot run. Add the appropriate multiplicity requirement "
129 "upstream (e.g. JET_N >= ...).");
130 return StatusCode::FAILURE;
131 }
132
133 const xAOD::IParticle *obj = passing[requested];
134 k.pt = obj->pt();
135 k.eta = obj->eta();
136 k.phi = obj->phi();
137 k.e = obj->e();
138 ops.push_back(k);
139 ++pIdx;
140 }
141
142 // compute the requested variable
143 double value = 0.;
144 if (var == "dR") {
145 const double deta = ops[0].eta - ops[1].eta;
146 const double dphi = TVector2::Phi_mpi_pi(ops[0].phi - ops[1].phi);
147 value = std::sqrt(deta * deta + dphi * dphi);
148 } else if (var == "dEta") {
149 value = std::abs(ops[0].eta - ops[1].eta);
150 } else if (var == "dPhi") {
151 value = std::abs(TVector2::Phi_mpi_pi(ops[0].phi - ops[1].phi));
152 } else if (var == "eta") {
153 value = ops[0].eta;
154 } else if (var == "phi") {
155 value = ops[0].phi;
156 } else if (var == "m" || var == "e" || var == "pt") {
157 if (ops.size() == 1 && ops[0].isMET) {
158 // only pt(met) reaches here (guaranteed by the config-time validation)
159 value = ops[0].pt;
160 } else {
161 PtEtaPhiEVector sum;
162 for (const Kin &k : ops)
163 sum += PtEtaPhiEVector(k.pt, k.eta, k.phi, k.e);
164 if (var == "m") value = sum.M();
165 else if (var == "e") value = sum.E();
166 else value = sum.Pt();
167 }
168 } else {
169 ANA_MSG_ERROR("EXPR: unsupported variable '" << var << "'");
170 return StatusCode::FAILURE;
171 }
172
173 // calculate decision
174 bool decision = SignEnum::checkValue(m_refValue.value(), m_signEnum, static_cast<float>(value));
175 m_decoration.setBool(*evtInfo, decision, sys);
176 }
177 return StatusCode::SUCCESS;
178 }
179
180} // namespace CP
Scalar eta() const
pseudorapidity method
#define ANA_MSG_ERROR(xmsg)
Macro printing error messages.
#define ANA_CHECK(EXP)
check whether the given expression was successful
static Double_t a
CP::SysWriteSelectionHandle m_decoration
the output selection decoration
SignEnum::ComparisonOperator m_signEnum
the operator version of the comparison (>, <, etc)
Gaudi::Property< std::string > m_variable
the kinematic variable to compute (dR, dPhi, dEta, m, pt, e, eta, phi)
Gaudi::Property< std::vector< int > > m_indices
per particle-operand pT-ordered index (parallel to the particle handles)
Gaudi::Property< std::string > m_sign
the comparison sign (GT, LT, etc)
virtual StatusCode initialize() override
std::vector< CP::SysReadSelectionHandle > m_selections
the per particle-operand selection handles, built from m_selectionKeys
CP::SysReadSelectionHandle m_preselection
the preselection
CP::SysReadHandle< xAOD::MissingETContainer > m_metHandle
the MET container (used iff any operand is MET)
ObjectKinematicSelectorAlg(const std::string &name, ISvcLocator *pSvcLocator)
Gaudi::Property< std::string > m_metTerm
the MET term to use for a MET operand
Gaudi::Property< float > m_refValue
the reference value against which to compare (in MeV / unitless)
CP::SysReadHandle< xAOD::EventInfo > m_eventInfoHandle
the event info handle
Gaudi::Property< std::vector< std::string > > m_selectionKeys
the per particle-operand selection keys (parallel to the particle handles)
CP::SysHandleArray< CP::SysReadHandle< xAOD::IParticleContainer > > m_particlesHandles
the particle-operand input containers (one per PARTICLE operand, in order)
CP::SysListHandle m_systematicsList
the systematics list
Gaudi::Property< std::vector< std::string > > m_operandKinds
per-operand kind, in expression order: "PARTICLE" or "MET"
size_type size() const noexcept
Returns the number of elements in the collection.
AnaAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
constructor with parameters
virtual::StatusCode execute()
execute this algorithm
Class providing the definition of the 4-vector interface.
float met() const
Returns .
float phi() const
Returns .
Select isolated Photons, Electrons and Muons.
This module defines the arguments passed from the BATCH driver to the BATCH worker.
bool checkValue(T reference, ComparisonOperator sign, T test)
the comparison test given the specified sign and two test values
Definition SignEnums.h:37
static const std::map< std::string, ComparisonOperator > stringToOperator
the map between user inputs and comparison operators
Definition SignEnums.h:27
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
setRcore setEtHad setFside pt
EventInfo_v1 EventInfo
Definition of the latest event info version.
MissingET_v1 MissingET
Version control by type defintion.
DataVector< IParticle > IParticleContainer
Simple convenience declaration of IParticleContainer.