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()) {
176 return StatusCode::FAILURE;
186 std::vector<const xAOD::TruthParticle*> bHadrons;
188 "ConeExclBHadronsFinal", bHadrons);
190 std::vector<const xAOD::TruthParticle*> cHadrons;
192 "ConeExclCHadronsFinal", cHadrons);
194 decDecay(*
jet) = -999;
197 if (bHadrons.empty() && cHadrons.empty())
continue;
199 LeptonCounter allLep = countLeptons(bHadrons, *
jet);
200 LeptonCounter cLep = countLeptons(cHadrons, *
jet);
202 int el_fromB = allLep.el_fromHad - cLep.el_fromHad;
203 int mu_fromB = allLep.mu_fromHad - cLep.mu_fromHad;
204 int tau_fromB = allLep.tau_fromHad - cLep.tau_fromHad;
205 int tauel_fromB = allLep.el_fromTau - cLep.el_fromTau;
206 int taumu_fromB = allLep.mu_fromTau - cLep.mu_fromTau;
208 int el_fromC = cLep.el_fromHad;
209 int mu_fromC = cLep.mu_fromHad;
210 int tau_fromC = cLep.tau_fromHad;
211 int tauel_fromC = cLep.el_fromTau;
212 int taumu_fromC = cLep.mu_fromTau;
214 std::vector<int> leps_in_decays;
215 if (tau_fromB > 0) leps_in_decays.push_back(15);
216 if (tau_fromC > 0) leps_in_decays.push_back(15);
217 if (mu_fromB > 0) leps_in_decays.push_back(13);
218 if (mu_fromC > 0) leps_in_decays.push_back(13);
219 if (el_fromB > 0) leps_in_decays.push_back(11);
220 if (el_fromC > 0) leps_in_decays.push_back(11);
222 std::vector<int> tauleps_in_decays;
223 tauleps_in_decays.push_back(tauel_fromB > 0 ? 11 : 0);
224 tauleps_in_decays.push_back(tauel_fromC > 0 ? 11 : 0);
225 tauleps_in_decays.push_back(taumu_fromB > 0 ? 13 : 0);
226 tauleps_in_decays.push_back(taumu_fromC > 0 ? 13 : 0);
228 decDecay(*
jet) = getDecayLabel(leps_in_decays);
229 decTau(*
jet) = getTauLabel(tauleps_in_decays, leps_in_decays);
232 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.