19#include <unordered_set>
29 struct LeptonCounter {
41 std::vector<const xAOD::TruthParticle*>& out,
42 std::unordered_set<const xAOD::TruthParticle*>& visited) {
43 if (!
particle->hasDecayVtx())
return true;
44 if (!visited.insert(particle).second)
return false;
54 if (!getAllChildren(child, out, visited))
return false;
60 std::vector<int> getDRSortedIndices(
61 const std::vector<const xAOD::TruthParticle*>& hadrons,
63 std::vector<float> dRs;
65 for (
const auto*
h : hadrons) {
66 dRs.push_back(
jet.p4().DeltaR(
h->p4()));
68 std::vector<int>
idx(dRs.size());
69 std::iota(
idx.begin(),
idx.end(), 0);
71 [&](
int a,
int b) { return dRs[a] < dRs[b]; });
77 LeptonCounter countLeptons(
78 const std::vector<const xAOD::TruthParticle*>& hadrons,
82 std::vector<int>
indices = getDRSortedIndices(hadrons,
jet);
83 for (
unsigned iHad = 0; iHad <
hadrons.size(); ++iHad) {
85 std::vector<const xAOD::TruthParticle*>
children;
86 std::unordered_set<const xAOD::TruthParticle*> visited;
87 if (!getAllChildren(had, children, visited)) {
92 for (
unsigned i = 0;
i <
children.size(); ++
i) {
93 int absId = std::abs(children[i]->
pdgId());
94 if (absId == 11)
lc.el_fromHad += 1;
95 if (absId == 13)
lc.mu_fromHad += 1;
99 for (
unsigned j = 1;
j <= 3; ++
j) {
100 int tauChildId = std::abs(children[i + j]->
pdgId());
101 if (tauChildId == 11)
lc.el_fromTau += 1;
102 if (tauChildId == 13)
lc.mu_fromTau += 1;
113 int getDecayLabel(
const std::vector<int>& leps) {
117 if (leps.size()>9)
throw std::overflow_error(
"getDecayLabel: too many leptons");
120 for (
int pdg : leps) {
121 if (pdg == 15)
label += factor * 3;
122 if (pdg == 13)
label += factor * 2;
123 if (pdg == 11)
label += factor * 1;
131 int getTauLabel(
const std::vector<int>& tauLeps,
132 const std::vector<int>& leps) {
133 if (std::find(leps.begin(), leps.end(), 15) == leps.end()) {
136 int maxFactor = std::numeric_limits<int>::max() / 10;
139 for (
int pdg : tauLeps) {
142 if (factor>maxFactor)
throw std::overflow_error(
"getTauLabel:(pdg = 11) factor overflow");
147 if (factor>maxFactor)
throw std::overflow_error(
"getTauLabel:(pdg = 13) factor overflow");
160 const std::string& name, ISvcLocator* loc)
168 return StatusCode::SUCCESS;
173 if (!jets.isValid()) {
175 return StatusCode::FAILURE;
180 const std::string bHadronsStr{
"ConeExclBHadronsFinal"};
181 const std::string cHadronsStr{
"ConeExclCHadronsFinal"};
183 std::vector<const xAOD::TruthParticle*> bHadrons;
186 std::vector<const xAOD::TruthParticle*> cHadrons;
189 decDecay(*
jet) = -999;
192 if (bHadrons.empty() && cHadrons.empty())
continue;
194 LeptonCounter allLep = countLeptons(bHadrons, *
jet);
195 LeptonCounter cLep = countLeptons(cHadrons, *
jet);
197 int el_fromB = allLep.el_fromHad - cLep.el_fromHad;
198 int mu_fromB = allLep.mu_fromHad - cLep.mu_fromHad;
199 int tau_fromB = allLep.tau_fromHad - cLep.tau_fromHad;
200 int tauel_fromB = allLep.el_fromTau - cLep.el_fromTau;
201 int taumu_fromB = allLep.mu_fromTau - cLep.mu_fromTau;
203 int el_fromC = cLep.el_fromHad;
204 int mu_fromC = cLep.mu_fromHad;
205 int tau_fromC = cLep.tau_fromHad;
206 int tauel_fromC = cLep.el_fromTau;
207 int taumu_fromC = cLep.mu_fromTau;
209 std::vector<int> leps_in_decays;
210 if (tau_fromB > 0) leps_in_decays.push_back(15);
211 if (tau_fromC > 0) leps_in_decays.push_back(15);
212 if (mu_fromB > 0) leps_in_decays.push_back(13);
213 if (mu_fromC > 0) leps_in_decays.push_back(13);
214 if (el_fromB > 0) leps_in_decays.push_back(11);
215 if (el_fromC > 0) leps_in_decays.push_back(11);
217 std::vector<int> tauleps_in_decays;
218 tauleps_in_decays.push_back(tauel_fromB > 0 ? 11 : 0);
219 tauleps_in_decays.push_back(tauel_fromC > 0 ? 11 : 0);
220 tauleps_in_decays.push_back(taumu_fromB > 0 ? 13 : 0);
221 tauleps_in_decays.push_back(taumu_fromC > 0 ? 13 : 0);
223 decDecay(*
jet) = getDecayLabel(leps_in_decays);
224 decTau(*
jet) = getTauLabel(tauleps_in_decays, leps_in_decays);
227 return StatusCode::SUCCESS;
#define ATH_CHECK
Evaluate an expression and check for errors.
Handle class for adding a decoration to an object.
Header file for AthHistogramAlgorithm.
An algorithm that can be simultaneously executed in multiple threads.
JetLeptonDecayLabelAlg(const std::string &name, ISvcLocator *pSvcLocator)
virtual StatusCode initialize() override
virtual StatusCode execute(const EventContext &) const override
SG::ReadHandleKey< xAOD::JetContainer > m_jetContainerKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_dec_leptonDecayLabel
SG::WriteDecorHandleKey< xAOD::JetContainer > m_dec_tauDecayLabel
Handle class for adding a decoration to an object.
bool isSimulationParticle() const
Check if this particle was produced during the simulation.
int status() const
Status code.
bool isBottomHadron() const
Determine if the PID is that of a b-hadron.
bool isCharmHadron() const
Determine if the PID is that of a c-hadron.
const TruthParticle_v1 * outgoingParticle(size_t index) const
Get one of the outgoing particles.
size_t nOutgoingParticles() const
Get the number of outgoing particles.
std::string label(const std::string &format, int i)
float j(const xAOD::IParticle &, const xAOD::TrackMeasurementValidation &hit, const Eigen::Matrix3d &jab_inv)
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
std::pair< long int, long int > indices
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
Jet_v1 Jet
Definition of the current "jet version".
TruthVertex_v1 TruthVertex
Typedef to implementation.
TruthParticle_v1 TruthParticle
Typedef to implementation.