ATLAS Offline Software
Loading...
Searching...
No Matches
JetCaloEnergies.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
9
12
14#include "xAODPFlow/PFO.h"
16
17#include <memory>
18#include <vector>
19
20//**********************************************************************
21
22JetCaloEnergies::JetCaloEnergies(const std::string& name)
23: AsgTool(name) { }
24
25//**********************************************************************
26
27bool JetCaloEnergies::isInVector(const std::string& key, const std::vector<std::string>& calculations) {
28 // Split key to get back the actual handle key
29 std::vector<std::string> split;
30 std::string sub_string;
31 std::istringstream tokenStream(key);
32
33 while (std::getline(tokenStream, sub_string, '.'))
34 {
35 split.push_back(sub_string);
36 }
37
38 // Return true if handle key in list of calculations
39 return std::find(calculations.begin(), calculations.end(), split[1]) != calculations.end();
40}
41
43 ATH_MSG_INFO("Initializing JetCaloEnergies " << name());
44
45 if(m_jetContainerName.empty()){
46 ATH_MSG_ERROR("JetCaloEnergies needs to have its input jet container configured!");
47 return StatusCode::FAILURE;
48 }
49
59
73 }
74
75 // Init calo based variables if necessary
83
85
88
89 // Init standard variables if necessary
90 ATH_CHECK(m_ePerSamplingKey.initialize());
91 ATH_CHECK(m_emFracKey.initialize());
92 ATH_CHECK(m_hecFracKey.initialize());
93 ATH_CHECK(m_psFracKey.initialize());
102
103 return StatusCode::SUCCESS;
104}
105
106//**********************************************************************
107
108StatusCode JetCaloEnergies::decorate(const xAOD::JetContainer& jets) const {
109 ATH_MSG_VERBOSE("Begin decorating jets.");
110 for(const xAOD::Jet* jet : jets) {
112 size_t numConstit = jet->numConstituents();
113 ePerSamplingHandle(*jet) = std::vector<float>(CaloSampling::Unknown, 0.);
114 std::vector<float>& ePerSampling = ePerSamplingHandle(*jet);
115 for ( float& e : ePerSampling ) e = 0.0; // re-initialize
116
117 if ( numConstit == 0 ) {
118 ATH_MSG_VERBOSE("Jet has no constituents.");
119 continue;
120 }
121
122 // should find a more robust solution than using 1st constit type.
123 xAOD::Type::ObjectType ctype = jet->rawConstituent( 0 )->type();
124 if ( ctype == xAOD::Type::CaloCluster ) {
125 ATH_MSG_VERBOSE(" Constituents are calo clusters.");
126 fillEperSamplingCluster(*jet, ePerSampling);
127
128 } else if (ctype == xAOD::Type::ParticleFlow) {
129 ATH_MSG_VERBOSE(" Constituents are pflow objects.");
130 fillEperSamplingPFO(*jet, ePerSampling);
131
132 } else if (ctype == xAOD::Type::FlowElement) {
133 ATH_MSG_VERBOSE(" Constituents are FlowElements.");
134 fillEperSamplingFE(*jet, ePerSampling);
135
136 // In addition, calculate variables using the underlying cluster rather than
137 // the energy-subtracted FlowElements (improved implementation)
139 ATH_MSG_VERBOSE(" Constituents are FlowElements - Additional calculation");
140
142 ePerSamplingClusterHandle(*jet) = std::vector<float>(CaloSampling::Unknown, 0.);
143 std::vector<float>& ePerSamplingCluster = ePerSamplingClusterHandle(*jet);
144 for ( float& e : ePerSamplingCluster ) e = 0.0; // re-initialize
145
146 fillEperSamplingFEClusterBased(*jet, ePerSamplingCluster);
147 }
148
149 }else {
150 ATH_MSG_VERBOSE("Constituents are not CaloClusters, PFOs, or FlowElements.");
151 }
152
153 }
154 return StatusCode::SUCCESS;
155}
156
157void JetCaloEnergies::fillEperSamplingCluster(const xAOD::Jet& jet, std::vector<float> & ePerSampling ) const {
158 // loop over raw constituents
159 size_t numConstit = jet.numConstituents();
160 for ( size_t i=0; i<numConstit; i++ ) {
161 if(jet.rawConstituent(i)->type()!=xAOD::Type::CaloCluster) {
162 ATH_MSG_WARNING("Tried to call fillEperSamplingCluster with a jet constituent that is not a cluster!");
163 continue;
164 }
165 const xAOD::CaloCluster* constit = static_cast<const xAOD::CaloCluster*>(jet.rawConstituent(i));
166 for ( size_t s= CaloSampling::PreSamplerB; s< CaloSampling::Unknown; s++ ) {
167 ePerSampling[s] += constit->eSample( (xAOD::CaloCluster::CaloSample) s );
168 }
169 }
170
171 double fracSamplingMax = -999999999.;
172 int fracSamplingMaxIndex = -1;
173 double sumE_samplings = 0.0;
174
176 for(unsigned int i = 0; i < ePerSampling.size(); ++i){
177 double e = ePerSampling[i];
178 sumE_samplings += e;
179 if (e>fracSamplingMax){
180 fracSamplingMax=e;
181 fracSamplingMaxIndex = i;
182 }
183 }
184 }
185
189
190 emFracHandle(jet) = jet::JetCaloQualityUtils::emFraction( ePerSampling );
191 hecFracHandle(jet) = jet::JetCaloQualityUtils::hecF( &jet );
193
196 fracSamplingMaxHandle(jet) = sumE_samplings != 0. ? fracSamplingMax/sumE_samplings : 0.;
198 fracSamplingMaxIndexHandle(jet) = fracSamplingMaxIndex;
199 }
200}
201
202#define FillESamplingPFO( LAYERNAME ) \
203 float E_##LAYERNAME = 0.0; \
204 if (constit->attribute(xAOD::PFODetails::eflowRec_LAYERENERGY_##LAYERNAME, E_##LAYERNAME)) { \
205 ePerSampling[CaloSampling::LAYERNAME] += E_##LAYERNAME; \
206 }
207
208void JetCaloEnergies::fillEperSamplingPFO(const xAOD::Jet & jet, std::vector<float> & ePerSampling ) const {
209
210 float emTot=0;
211 float hecTot=0;
212 float eTot =0;
213 size_t numConstit = jet.numConstituents();
214
215 for ( size_t i=0; i<numConstit; i++ ) {
216 if (jet.rawConstituent(i)->type()==xAOD::Type::ParticleFlow){
217 const xAOD::PFO* constit = static_cast<const xAOD::PFO*>(jet.rawConstituent(i));
218 if ( fabs(constit->charge())>FLT_MIN ){
219 eTot += constit->track(0)->e();
220 } else {
221 eTot += constit->e();
222 FillESamplingPFO(PreSamplerB);
223 FillESamplingPFO(EMB1);
224 FillESamplingPFO(EMB2);
225 FillESamplingPFO(EMB3);
226
227 FillESamplingPFO(PreSamplerE);
228 FillESamplingPFO(EME1);
229 FillESamplingPFO(EME2);
230 FillESamplingPFO(EME3);
231
232 FillESamplingPFO(HEC0);
233 FillESamplingPFO(HEC1);
234 FillESamplingPFO(HEC2);
235 FillESamplingPFO(HEC3);
236
237 FillESamplingPFO(TileBar0);
238 FillESamplingPFO(TileBar1);
239 FillESamplingPFO(TileBar2);
240
241 FillESamplingPFO(TileGap1);
242 FillESamplingPFO(TileGap2);
243 FillESamplingPFO(TileGap3);
244
245 FillESamplingPFO(TileExt0);
246 FillESamplingPFO(TileExt1);
247 FillESamplingPFO(TileExt2);
248
249 FillESamplingPFO(FCAL0);
250 FillESamplingPFO(FCAL1);
251 FillESamplingPFO(FCAL2);
252
253 FillESamplingPFO(MINIFCAL0);
254 FillESamplingPFO(MINIFCAL1);
255 FillESamplingPFO(MINIFCAL2);
256 FillESamplingPFO(MINIFCAL3);
257
258 emTot += ( E_PreSamplerB+E_EMB1+E_EMB2+E_EMB3+
259 E_PreSamplerE+E_EME1+E_EME2+E_EME3+
260 E_FCAL0 );
261 hecTot += ( E_HEC0+E_HEC1+E_HEC2+E_HEC3 );
262
263 }//only consider neutral PFO
264 } else {
265 ATH_MSG_WARNING("Tried to call fillEperSamplingPFlow with a jet constituent that is not a PFO!");
266 }
267 }
268
270 if(eTot != 0.0){
271 emFracHandle(jet) = emTot/eTot;
272 /*
273 * Ratio of EM layer calorimeter energy of neutrals to sum of all constituents
274 * at EM scale (note charged PFO have an EM scale at track scale, and charged weights are ignored)
275 * */
276 }
277 else {
278 emFracHandle(jet) = 0.;
279 }
280
282 if (eTot != 0.0){
283 hecFracHandle(jet) = hecTot/eTot;
284 }
285 else{
286 hecFracHandle(jet) = 0.;
287 }
288
289}
290
291// R21 way of calculating energy-per-layer using directly the FE decorations
292// In R21, the link from PFOs to clusters was broken and thus energy after charged subtraction was used
293void JetCaloEnergies::fillEperSamplingFE(const xAOD::Jet& jet, std::vector<float> & ePerSampling ) const {
294 float emTot = 0.;
295 float em3Tot = 0.;
296 float hecTot = 0.;
297 float psTot = 0.;
298 float tile0Tot = 0.;
299 float eTot = 0.;
300 float e2Tot = 0.;
301 size_t numConstit = jet.numConstituents();
302
303 std::vector<int> indicesNeutralFE;
304 std::vector<int> indicesChargedFE;
305
306 for ( size_t i=0; i<numConstit; i++ ) {
307 if(jet.rawConstituent(i)->type()!=xAOD::Type::FlowElement) {
308 ATH_MSG_WARNING("Tried to call fillEperSamplingFE with a jet constituent that is not a FlowElement!");
309 continue;
310 }
311 const xAOD::FlowElement* constit = static_cast<const xAOD::FlowElement*>(jet.rawConstituent(i));
312
313 // Need to distinguish two cases:
314 // (1) Jet is a PFlow jet (constituents are charged or neutral FEs) or
315 // (2) Jet is a UFO jet (need to get the underlying charged and neutral FEs first)
316
317 //For PFlow jets, we can directly get the information from the constituent
318 if(constit->signalType() & xAOD::FlowElement::PFlow){
319
320 //Charged FlowElements:
321 if(constit->isCharged()){
322 eTot += constit->chargedObject(0)->e();
323 e2Tot += constit->chargedObject(0)->e()*constit->chargedObject(0)->e();
324 }
325 //Neutral FlowElements
326 else{
327 eTot += constit->e();
328 e2Tot += constit->e()*constit->e();
329 //Get the energy-per-layer information from the FE, not the underlying cluster (i.e. after subtraction)
330 std::vector<float> constitEPerSampling = FEHelpers::getEnergiesPerSampling(*constit);
331 for ( size_t s = CaloSampling::PreSamplerB; s < CaloSampling::Unknown; s++ ) {
332 ePerSampling[s] += constitEPerSampling[s];
333 }
334 emTot += (constitEPerSampling[CaloSampling::PreSamplerB] + constitEPerSampling[CaloSampling::EMB1]
335 + constitEPerSampling[CaloSampling::EMB2] + constitEPerSampling[CaloSampling::EMB3]
336 + constitEPerSampling[CaloSampling::PreSamplerE] + constitEPerSampling[CaloSampling::EME1]
337 + constitEPerSampling[CaloSampling::EME2] + constitEPerSampling[CaloSampling::EME3]
338 + constitEPerSampling[CaloSampling::FCAL0]);
339
340 hecTot += (constitEPerSampling[CaloSampling::HEC0] + constitEPerSampling[CaloSampling::HEC1]
341 + constitEPerSampling[CaloSampling::HEC2] + constitEPerSampling[CaloSampling::HEC3]);
342
343 psTot += (constitEPerSampling[CaloSampling::PreSamplerB] + constitEPerSampling[CaloSampling::PreSamplerE]);
344
345 em3Tot += (constitEPerSampling[CaloSampling::EMB3] + constitEPerSampling[CaloSampling::EME3]);
346
347 tile0Tot += (constitEPerSampling[CaloSampling::TileBar0] + constitEPerSampling[CaloSampling::TileExt0]);
348 }
349 }
350 else{
351 //For UFO jets, we first need to get the charged and neutral FE + corresponding energy from combined UFOs
352
353 // UFO is simply a charged FlowElement
354 if(constit->signalType() == xAOD::FlowElement::Charged){
355 eTot += constit->chargedObject(0)->e();
356 e2Tot += constit->chargedObject(0)->e()*constit->chargedObject(0)->e();
357 }
358 //UFO is simply a neutral Flowelement
359 else if(constit->signalType() == xAOD::FlowElement::Neutral){
360 // For neutral UFOs, there is only one "other object" stored which is the neutral FE
361 // Protection in case there is something wrong with this FE
362 if(constit->otherObjects().size() != 1 || !constit->otherObject(0)){
363 continue;
364 }
365
366 // Cast other object as FlowElement
367 const xAOD::FlowElement* nFE = static_cast<const xAOD::FlowElement*>(constit->otherObject(0));
368
369 eTot += nFE->e();
370 e2Tot += nFE->e()*nFE->e();
371
372 std::vector<float> neutralEPerSampling = FEHelpers::getEnergiesPerSampling(*nFE);
373 for ( size_t s = CaloSampling::PreSamplerB; s < CaloSampling::Unknown; s++ ) {
374 ePerSampling[s] += neutralEPerSampling[s];
375 }
376 emTot += (neutralEPerSampling[CaloSampling::PreSamplerB] + neutralEPerSampling[CaloSampling::EMB1]
377 + neutralEPerSampling[CaloSampling::EMB2] + neutralEPerSampling[CaloSampling::EMB3]
378 + neutralEPerSampling[CaloSampling::PreSamplerE] + neutralEPerSampling[CaloSampling::EME1]
379 + neutralEPerSampling[CaloSampling::EME2] + neutralEPerSampling[CaloSampling::EME3]
380 + neutralEPerSampling[CaloSampling::FCAL0]);
381
382 hecTot += (neutralEPerSampling[CaloSampling::HEC0] + neutralEPerSampling[CaloSampling::HEC1]
383 + neutralEPerSampling[CaloSampling::HEC2] + neutralEPerSampling[CaloSampling::HEC3]);
384
385 psTot += (neutralEPerSampling[CaloSampling::PreSamplerB] + neutralEPerSampling[CaloSampling::PreSamplerE]);
386
387 em3Tot += (neutralEPerSampling[CaloSampling::EMB3] + neutralEPerSampling[CaloSampling::EME3]);
388
389 tile0Tot += (neutralEPerSampling[CaloSampling::TileBar0] + neutralEPerSampling[CaloSampling::TileExt0]);
390 }
391 else if(constit->signalType() == xAOD::FlowElement::Combined){
392 // For the combined UFOs, otherObjects are neutral or charged FEs
393 // matched to this tracks (via track-to-cluster extrapolation)
394 for (size_t n = 0; n < constit->otherObjects().size(); ++n) {
395 if(! constit->otherObject(n)) continue;
396 const xAOD::FlowElement* FE_from_combined = static_cast<const xAOD::FlowElement*>(constit->otherObject(n));
397
398 //Charged FE (add energy to total energy only)
399 if(FE_from_combined->isCharged()){
400 if(std::find(indicesChargedFE.begin(), indicesChargedFE.end(), FE_from_combined->index()) == indicesChargedFE.end()){
401 eTot += FE_from_combined->e();
402 e2Tot += FE_from_combined->e()*FE_from_combined->e();
403 indicesChargedFE.push_back(FE_from_combined->index());
404 }
405 continue;
406 }
407 //Neutral FE:
408 //One neutral FE can be matched to various tracks and therefore be used for several UFOs
409 //We do not want to double count the energy and only add it once
410 if(std::find(indicesNeutralFE.begin(), indicesNeutralFE.end(), FE_from_combined->index()) == indicesNeutralFE.end()){
411 eTot += FE_from_combined->e();
412 e2Tot += FE_from_combined->e()*FE_from_combined->e();
413 std::vector<float> neutralFromCombEPerSampling = FEHelpers::getEnergiesPerSampling(*FE_from_combined);
414 for ( size_t s = CaloSampling::PreSamplerB; s < CaloSampling::Unknown; s++ ) {
415 ePerSampling[s] += neutralFromCombEPerSampling[s];
416 }
417 emTot += (neutralFromCombEPerSampling[CaloSampling::PreSamplerB] + neutralFromCombEPerSampling[CaloSampling::EMB1]
418 + neutralFromCombEPerSampling[CaloSampling::EMB2] + neutralFromCombEPerSampling[CaloSampling::EMB3]
419 + neutralFromCombEPerSampling[CaloSampling::PreSamplerE] + neutralFromCombEPerSampling[CaloSampling::EME1]
420 + neutralFromCombEPerSampling[CaloSampling::EME2] + neutralFromCombEPerSampling[CaloSampling::EME3]
421 + neutralFromCombEPerSampling[CaloSampling::FCAL0]);
422
423 hecTot += (neutralFromCombEPerSampling[CaloSampling::HEC0] + neutralFromCombEPerSampling[CaloSampling::HEC1]
424 + neutralFromCombEPerSampling[CaloSampling::HEC2] + neutralFromCombEPerSampling[CaloSampling::HEC3]);
425
426 psTot += (neutralFromCombEPerSampling[CaloSampling::PreSamplerB] + neutralFromCombEPerSampling[CaloSampling::PreSamplerE]);
427
428 em3Tot += (neutralFromCombEPerSampling[CaloSampling::EMB3] + neutralFromCombEPerSampling[CaloSampling::EME3]);
429
430 tile0Tot += (neutralFromCombEPerSampling[CaloSampling::TileBar0] + neutralFromCombEPerSampling[CaloSampling::TileExt0]);
431
432 indicesNeutralFE.push_back(FE_from_combined->index());
433 }
434 }
435 }
436 }
437 }
438
439 double fracSamplingMax = -999999999.;
440 int fracSamplingMaxIndex = -1;
441 double sumE_samplings = 0.0;
442
444 for(unsigned int i = 0; i < ePerSampling.size(); ++i){
445 double e = ePerSampling[i];
446 sumE_samplings += e;
447 if (e>fracSamplingMax){
448 fracSamplingMax=e;
449 fracSamplingMaxIndex = i;
450 }
451 }
452 }
453
454 for( const std::string & calcN : m_calculationNames){
455 if ( calcN == "EMFrac" ) {
457 emFracHandle(jet) = eTot != 0. ? emTot/eTot : 0.;
458 } else if ( calcN == "HECFrac" ) {
460 hecFracHandle(jet) = eTot != 0. ? hecTot/eTot : 0.;
461 } else if ( calcN == "PSFrac" ) {
463 psFracHandle(jet) = eTot != 0. ? psTot/eTot : 0.;
464 } else if ( calcN == "EM3Frac" ) {
466 em3FracHandle(jet) = eTot != 0. ? em3Tot/eTot : 0.;
467 } else if ( calcN == "Tile0Frac" ) {
469 tile0FracHandle(jet) = eTot != 0. ? tile0Tot/eTot : 0.;
470 } else if ( calcN == "EffNClusts" ) {
472 effNClustsFracHandle(jet) = eTot != 0. ? std::sqrt(eTot*eTot/e2Tot) : 0.;
473 } else if ( calcN == "FracSamplingMax" ){
475 fracSamplingMaxHandle(jet) = sumE_samplings != 0. ? fracSamplingMax/sumE_samplings : 0.;
477 fracSamplingMaxIndexHandle(jet) = fracSamplingMaxIndex;
478 }
479 }
480}
481
482
483// New way of calculating energy per layer for FE-based jets
484// The underlying cluster is used to calculate the variables rather than the energy-subtracted FE
485void JetCaloEnergies::fillEperSamplingFEClusterBased(const xAOD::Jet& jet, std::vector<float> & ePerSampling ) const {
486 float emTot = 0.;
487 float em3Tot = 0.;
488 float hecTot = 0.;
489 float psTot = 0.;
490 float tile0Tot = 0.;
491 float eTot = 0.;
492 float e2Tot = 0.;
493 float sumRadialDistanceSquared = 0;
494 float sumLongitudinalDistanceSquared = 0;
495 size_t numConstit = jet.numConstituents();
496 std::unique_ptr<std::vector<const xAOD::CaloCluster*> > constitV_tot = std::make_unique<std::vector<const xAOD::CaloCluster*>>();
497 const xAOD::CaloCluster* leadingCluster = nullptr;
498
499 for ( size_t i=0; i<numConstit; i++ ) {
500 if(jet.rawConstituent(i)->type()!=xAOD::Type::FlowElement) {
501 ATH_MSG_WARNING("Tried to call fillEperSamplingFE with a jet constituent that is not a FlowElement!");
502 continue;
503 }
504 const xAOD::FlowElement* constit = static_cast<const xAOD::FlowElement*>(jet.rawConstituent(i));
505
506 for (size_t n = 0; n < constit->otherObjects().size(); ++n) {
507 if(! constit->otherObject(n)) continue;
508 int index_pfo = constit->otherObject(n)->index();
509 if(index_pfo<0) continue;
510
511 const auto* fe = (constit->otherObject(n));
512 const xAOD::CaloCluster* cluster = nullptr;
513
514 //If we have a cluster, we can directly access the calorimeter information
515 if(fe->type() == xAOD::Type::CaloCluster){
516 cluster = dynamic_cast<const xAOD::CaloCluster*> (fe);
517 }
518 //If we have a PFO, we should still get the associated cluster first
519 else {
520 const xAOD::FlowElement* pfo = dynamic_cast<const xAOD::FlowElement*>(fe);
521 if(!pfo->otherObjects().empty() && pfo->otherObject(0) && pfo->otherObject(0)->type() == xAOD::Type::CaloCluster){
522 cluster = dynamic_cast<const xAOD::CaloCluster*> (pfo->otherObject(0));
523 }
524 }
525 if(!cluster) continue;
526
527 if (!leadingCluster || (cluster->rawE() > leadingCluster->rawE())){
528 leadingCluster = cluster;
529 }
530
531
532 if(std::find(constitV_tot->begin(), constitV_tot->end(), cluster) == constitV_tot->end()){
533 for ( size_t s= CaloSampling::PreSamplerB; s< CaloSampling::Unknown; s++ ) {
534 ePerSampling[s] += cluster->eSample( (xAOD::CaloCluster::CaloSample) s );
535 }
536 eTot += cluster->rawE();
537 e2Tot += cluster->rawE()*cluster->rawE();
538
539 emTot += (cluster->eSample( CaloSampling::PreSamplerB) + cluster->eSample( CaloSampling::EMB1)
540 + cluster->eSample( CaloSampling::EMB2) + cluster->eSample( CaloSampling::EMB3)
541 + cluster->eSample( CaloSampling::PreSamplerE) + cluster->eSample( CaloSampling::EME1)
542 + cluster->eSample( CaloSampling::EME2) + cluster->eSample( CaloSampling::EME3)
543 + cluster->eSample( CaloSampling::FCAL0));
544
545 hecTot += (cluster->eSample( CaloSampling::HEC0) + cluster->eSample( CaloSampling::HEC1)
546 + cluster->eSample( CaloSampling::HEC2) + cluster->eSample( CaloSampling::HEC3));
547
548 psTot += (cluster->eSample( CaloSampling::PreSamplerB) + cluster->eSample( CaloSampling::PreSamplerE));
549
550 em3Tot += (cluster->eSample( CaloSampling::EMB3) + cluster->eSample( CaloSampling::EME3));
551
552 tile0Tot += (cluster->eSample( CaloSampling::TileBar0) + cluster->eSample( CaloSampling::TileExt0));
553
554 sumRadialDistanceSquared += cluster->rawE() * getMoment(cluster, xAOD::CaloCluster::SECOND_R);
555 sumLongitudinalDistanceSquared += cluster->rawE() * getMoment(cluster, xAOD::CaloCluster::SECOND_LAMBDA);
556
557 constitV_tot->push_back(cluster);
558 }
559 }
560 }
561
562 float fracSamplingMax = -999999999.;
563 int fracSamplingMaxIndex = -1;
564 float sumE_samplings = 0.0;
565
567 for(unsigned int i = 0; i < ePerSampling.size(); ++i){
568 float e = ePerSampling[i];
569 sumE_samplings += e;
570 if (e>fracSamplingMax){
571 fracSamplingMax=e;
572 fracSamplingMaxIndex = i;
573 }
574 }
575 }
576
577 for( const std::string & calcN : m_calculationNames){
578 if ( calcN == "EMFrac" ) {
580 emFracClusterHandle(jet) = eTot != 0. ? emTot/eTot : 0.;
581 } else if ( calcN == "HECFrac" ) {
583 hecFracClusterHandle(jet) = eTot != 0. ? hecTot/eTot : 0.;
584 } else if ( calcN == "PSFrac" ) {
586 psFracClusterHandle(jet) = eTot != 0. ? psTot/eTot : 0.;
587 } else if ( calcN == "EM3Frac" ) {
589 em3FracClusterHandle(jet) = eTot != 0. ? em3Tot/eTot : 0.;
590 } else if ( calcN == "Tile0Frac" ) {
592 tile0FracClusterHandle(jet) = eTot != 0. ? tile0Tot/eTot : 0.;
593 } else if ( calcN == "EffNClusts" ) {
595 effNClustsFracClusterHandle(jet) = eTot != 0. ? std::sqrt(eTot*eTot/e2Tot) : 0.;
596 } else if ( calcN == "FracSamplingMax" ){
598 fracSamplingMaxClusterHandle(jet) = sumE_samplings != 0. ? fracSamplingMax/sumE_samplings : 0.;
600 fracSamplingMaxIndexClusterHandle(jet) = fracSamplingMaxIndex;
601 }
602 }
603
605 lambdaLeadingClusterHandle(jet) = getMoment(leadingCluster, xAOD::CaloCluster::CENTER_LAMBDA);
606
608 meanRadialDistanceSquaredHandle(jet) = eTot != 0. ? sumRadialDistanceSquared/eTot : 0.;
609
611 meanLongitudinalDistanceSquaredHandle(jet) = eTot != 0. ? sumLongitudinalDistanceSquared/eTot : 0.;
612}
613
614float JetCaloEnergies::getMoment(const xAOD::CaloCluster* cluster, const xAOD::CaloCluster::MomentType& momentType) const {
615 if (cluster){
616 double moment = 0.0;
617 bool isRetrieved = cluster->retrieveMoment(momentType, moment);
618 if (isRetrieved) return (float) moment;
619 }
620 ATH_MSG_DEBUG("Can not retrieve moment from cluster");
621 return 0.0;
622}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Handle class for adding a decoration to an object.
#define FillESamplingPFO(LAYERNAME)
SG::WriteDecorHandleKey< xAOD::JetContainer > m_effNClustsFracKey
Gaudi::Property< bool > m_calcClusterBasedVars
SG::WriteDecorHandleKey< xAOD::JetContainer > m_ePerSamplingKey
void fillEperSamplingCluster(const xAOD::Jet &jet, std::vector< float > &ePerSampling) const
SG::WriteDecorHandleKey< xAOD::JetContainer > m_meanRadialDistanceSquaredKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_hecFracKey
JetCaloEnergies(const std::string &t)
Gaudi::Property< std::string > m_jetContainerName
SG::WriteDecorHandleKey< xAOD::JetContainer > m_em3FracKey
Gaudi::Property< std::vector< std::string > > m_calculationNames
SG::WriteDecorHandleKey< xAOD::JetContainer > m_tile0FracKey
void fillEperSamplingPFO(const xAOD::Jet &jet, std::vector< float > &ePerSampling) const
SG::WriteDecorHandleKey< xAOD::JetContainer > m_psFracClusterKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_fracSamplingMaxKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_ePerSamplingClusterKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_fracSamplingMaxIndexKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_effNClustsFracClusterKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_meanLongitudinalDistanceSquaredKey
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
SG::WriteDecorHandleKey< xAOD::JetContainer > m_hecFracClusterKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_fracSamplingMaxClusterKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_tile0FracClusterKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_psFracKey
virtual StatusCode decorate(const xAOD::JetContainer &jets) const override
Decorate a jet collection without otherwise modifying it.
void fillEperSamplingFEClusterBased(const xAOD::Jet &jet, std::vector< float > &ePerSampling) const
float getMoment(const xAOD::CaloCluster *cluster, const xAOD::CaloCluster::MomentType &momentType) const
SG::WriteDecorHandleKey< xAOD::JetContainer > m_em3FracClusterKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_emFracClusterKey
bool isInVector(const std::string &key, const std::vector< std::string > &calculations)
SG::WriteDecorHandleKey< xAOD::JetContainer > m_emFracKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_fracSamplingMaxIndexClusterKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_lambdaLeadingClusterKey
void fillEperSamplingFE(const xAOD::Jet &jet, std::vector< float > &ePerSampling) const
size_t index() const
Return the index of this element within its container.
Handle class for adding a decoration to an object.
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
static double emFraction(const std::vector< float > &ePerSampling)
static double hecF(const Jet *jet)
static double presamplerFraction(const Jet *jet)
bool retrieveMoment(MomentType type, double &value) const
Retrieve individual moment.
flt_t rawE() const
float eSample(const CaloSample sampling) const
MomentType
Enums to identify different moments.
@ SECOND_LAMBDA
Second Moment in .
@ SECOND_R
Second Moment in .
@ CENTER_LAMBDA
Shower depth at Cluster Centroid.
CaloSampling::CaloSample CaloSample
std::vector< const xAOD::IParticle * > otherObjects() const
signal_t signalType() const
const xAOD::IParticle * chargedObject(std::size_t i) const
virtual double e() const override
The total energy of the particle.
const xAOD::IParticle * otherObject(std::size_t i) const
virtual Type::ObjectType type() const =0
The type of the object as a simple enumeration.
virtual double e() const =0
The total energy of the particle.
const TrackParticle * track(unsigned int index) const
Retrieve a const pointer to a Rec::TrackParticle.
Definition PFO_v1.cxx:691
virtual double e() const
The total energy of the particle.
Definition PFO_v1.cxx:81
float charge() const
get charge of PFO
virtual double e() const override final
The total energy of the particle.
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
std::vector< float > getEnergiesPerSampling(const xAOD::FlowElement &fe)
Definition FEHelpers.cxx:78
ObjectType
Type of objects that have a representation in the xAOD EDM.
Definition ObjectType.h:32
@ ParticleFlow
The object is a particle-flow object.
Definition ObjectType.h:41
@ FlowElement
The object is a track-calo-cluster.
Definition ObjectType.h:52
@ CaloCluster
The object is a calorimeter cluster.
Definition ObjectType.h:39
Jet_v1 Jet
Definition of the current "jet version".
PFO_v1 PFO
Definition of the current "pfo version".
Definition PFO.h:17
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
FlowElement_v1 FlowElement
Definition of the current "pfo version".
Definition FlowElement.h:16
JetContainer_v1 JetContainer
Definition of the current "jet container version".