5 #if !defined(XAOD_ANALYSIS) && !defined(GENERATIONBASE) // Can only be used in Athena
29 if (pvtx ==
nullptr)
return nullptr;
39 return std::make_unique<Trk::CurvilinearParameters>(
pos,
mom,
charge);
48 const EventContext& ctx =
info ?
info->eventContext : Gaudi::Hive::currentContext();
52 if (!truthParticleContainerReadHandle.
isValid()) {
53 ATH_MSG_WARNING(
" Invalid ReadHandle for xAOD::TruthParticleContainer with key: " << truthParticleContainerReadHandle.
key());
58 if (!caloMgrHandle.isValid()) {
59 ATH_MSG_WARNING(
" Invalid ReadCondHandle for CaloDetDescrManager with key: " << m_caloMgrKey.key());
68 double LeadingPhtPT(0);
69 double LeadingPartPT(0);
70 double LeadingPhtdR(999.);
71 double LeadingPartdR(999.);
72 double BestPartdR(999.);
73 double etaClus = clus->
etaBE(2);
74 double phiClus = clus->
phiBE(2);
76 etaClus = clus->
eta();
79 phiClus = clus->
phi();
81 std::vector<const xAOD::TruthParticle*> tps;
82 if (!m_truthInConeTool->particlesInCone(ctx, etaClus, phiClus, 0.5, tps)) {
87 for (
const auto*
const thePart : tps) {
92 long iParticlePDG = thePart->
pdgId();
94 if (std::abs(iParticlePDG) == 12 || std::abs(iParticlePDG) == 14 || std::abs(iParticlePDG) == 16)
continue;
96 double q = thePart?thePart->charge():0.0;
98 if (
q != 0 &&
pt < m_pTChargePartCut)
continue;
99 if (
q == 0 &&
pt < m_pTNeutralPartCut)
continue;
102 if (!isFwrdEle && m_ROICone && std::hypot( detPhi(phiClus, thePart->phi())/m_partExtrConePhi, detEta(etaClus, thePart->eta())/m_partExtrConeEta) > 1.0) {
107 (((etaClus < 0) - (thePart->eta() < 0) != 0)
109 || (std::fabs(thePart->eta()) < m_FwdElectronTruthExtrEtaCut)
110 || (std::fabs(thePart->eta() - etaClus) > m_FwdElectronTruthExtrEtaWindowCut)
116 bool isNCone =
false;
117 bool isExt = genPartToCalo(ctx, clus, thePart, isFwrdEle, dR, isNCone, *caloDDMgr);
118 if (!isExt)
continue;
121 info->egPartPtr.push_back(thePart);
122 info->egPartdR.push_back(dR);
123 info->egPartClas.push_back(particleTruthClassifier(theMatchPart,
info));
129 if ((iParticlePDG == 22 || std::abs(iParticlePDG) == 11) && isNCone &&
pt > LeadingPhtPT) {
136 if ((iParticlePDG != 22 && std::abs(iParticlePDG) != 11) && isNCone &&
pt > LeadingPartPT) {
137 theLeadingPartInCone = thePart;
143 if (!isNCone && dR < BestPartdR) {
144 theBestPartOutCone = thePart;
148 if (dR < BestPartdR) {
149 theBestPartdR = thePart;
155 if (theEgamma !=
nullptr) {
157 if (
info)
info->deltaRMatch = LeadingPhtdR;
158 }
else if (theLeadingPartInCone !=
nullptr) {
159 theMatchPart =
MC::findMatching(truthParticleContainerReadHandle.
ptr(),theLeadingPartInCone);
160 if (
info)
info->deltaRMatch = LeadingPartdR;
161 }
else if (theBestPartOutCone !=
nullptr) {
162 theMatchPart =
MC::findMatching(truthParticleContainerReadHandle.
ptr(),theBestPartOutCone);
163 if (
info)
info->deltaRMatch = BestPartdR;
164 }
else if (isFwrdEle && theBestPartdR !=
nullptr) {
166 if (
info)
info->deltaRMatch = BestPartdR;
168 theMatchPart =
nullptr;
170 if (isFwrdEle || theMatchPart !=
nullptr || !m_inclG4part)
return theMatchPart;
173 for (
const auto*
const thePart : tps) {
176 long iParticlePDG = thePart->
pdgId();
178 if (std::abs(iParticlePDG) == 12 || std::abs(iParticlePDG) == 14 || std::abs(iParticlePDG) == 16)
continue;
179 if (thePart->decayVtx() !=
nullptr)
continue;
180 if (std::hypot( detPhi(phiClus, thePart->phi())/m_partExtrConePhi, detEta(etaClus, thePart->eta())/m_partExtrConeEta ) > 1.0)
continue;
183 double q = thePart->charge();
185 if (
q != 0 &&
pt < m_pTChargePartCut)
continue;
186 if (
q == 0 &&
pt < m_pTNeutralPartCut)
continue;
189 bool isNCone =
false;
190 bool isExt = genPartToCalo(ctx, clus, thePart, isFwrdEle, dR, isNCone, *caloDDMgr);
191 if (!isExt)
continue;
195 info->egPartPtr.push_back(thePart);
196 info->egPartdR.push_back(dR);
197 info->egPartClas.push_back(particleTruthClassifier(theMatchPart,
info));
201 if ((iParticlePDG == 22 || std::abs(iParticlePDG) == 11) && isNCone &&
pt > LeadingPhtPT) {
208 if ((iParticlePDG != 22 && std::abs(iParticlePDG) != 11) && isNCone &&
pt > LeadingPartPT) {
209 theLeadingPartInCone = thePart;
215 if (!isNCone && dR < BestPartdR) {
216 theBestPartOutCone = thePart;
221 if (theEgamma !=
nullptr) {
223 if (
info)
info->deltaRMatch = LeadingPhtdR;
224 }
else if (theLeadingPartInCone !=
nullptr) {
225 theMatchPart =
MC::findMatching(truthParticleContainerReadHandle.
ptr(),theLeadingPartInCone);
226 if (
info)
info->deltaRMatch = LeadingPartdR;
227 }
else if (theBestPartOutCone !=
nullptr) {
228 theMatchPart =
MC::findMatching(truthParticleContainerReadHandle.
ptr(),theBestPartOutCone);
229 if (
info)
info->deltaRMatch = BestPartdR;
231 theMatchPart =
nullptr;
246 isNarrowCone =
false;
247 if (thePart ==
nullptr)
return false;
248 double phiClus = clus->
phiBE(2);
249 double etaClus = clus->
etaBE(2);
250 if (etaClus < -900) {
251 etaClus = clus->
eta();
253 if (phiClus < -900) {
254 phiClus = clus->
phi();
257 if (isFwrdEle || (etaClus == 0. && phiClus == 0.)) {
258 phiClus = clus->
phi();
259 etaClus = clus->
eta();
271 }
else if (isFwrdEle && clus->
inEndcap()) {
277 std::unique_ptr<Trk::CurvilinearParameters>
params = extractParamFromTruth(*thePart);
278 if (!
params)
return false;
280 std::vector<CaloSampling::CaloSample> samples = {
sample };
281 auto extension = m_caloExtensionTool->layersCaloExtension(ctx, *
params, samples, etaClus, caloDDMgr);
282 bool extensionOK = (!extension.empty());
284 ATH_MSG_WARNING(
"extrapolation of Truth Particle with eta " << thePart->
eta() <<
" , charge " << thePart->
charge() <<
" , Pt " << thePart->
pt() <<
" to calo failed");
287 double etaCalo = extension[0].second->position().eta();
288 double phiCalo = extension[0].second->position().phi();
290 double dPhi = detPhi(phiCalo, phiClus);
291 double dEta = detEta(etaCalo, etaClus);
294 if ((!isFwrdEle && dRmatch > m_phtdRtoTrCut) || (isFwrdEle && dRmatch > m_fwrdEledRtoTrCut))
return false;
295 if (!isFwrdEle && std::hypot(
dPhi/m_phtClasConePhi,
dEta/m_phtClasConeEta ) <= 1.0) isNarrowCone =
true;