ATLAS Offline Software
Loading...
Searching...
No Matches
CaloClusterMomentsMaker_DigiHSTruth.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5//-----------------------------------------------------------------------
6// File and Version Information:
7//
8// Description: see CaloClusterMomentsMaker_DigiHSTruth.h
9//
10// Environment:
11// Software developed for the ATLAS Detector at CERN LHC
12//
13// Author List:
14// Sven Menke
15// Peter Loch
16//
17//-----------------------------------------------------------------------
18
20#include "CaloEvent/CaloCell.h"
21#include "CaloEvent/CaloCluster.h"
26
29
30#include "CLHEP/Units/SystemOfUnits.h"
31#include "CxxUtils/prefetch.h"
33#include <Eigen/Dense>
34#include <cmath>
35#include <cstdint>
36#include <limits>
37
38#include <map>
39#include <tuple>
40#include <cstdio>
41#include <cmath>
42
43using CLHEP::deg;
44using CLHEP::cm;
46
47// Known moments
48namespace {
49 // name -> enum translator
50 const std::map<std::string,xAOD::CaloCluster::MomentType, std::less<>> momentNameToEnumMap = {
51 { "AVG_LAR_Q_DigiHSTruth", AVG_LAR_Q_DigiHSTruth },
52 { "AVG_TILE_Q_DigiHSTruth", AVG_TILE_Q_DigiHSTruth },
53 { "BADLARQ_FRAC_DigiHSTruth", BADLARQ_FRAC_DigiHSTruth },
54 { "BAD_CELLS_CORR_E_DigiHSTruth", BAD_CELLS_CORR_E_DigiHSTruth },
55 { "CELL_SIGNIFICANCE_DigiHSTruth", CELL_SIGNIFICANCE_DigiHSTruth },
56 { "CELL_SIG_SAMPLING_DigiHSTruth", CELL_SIG_SAMPLING_DigiHSTruth },
57 { "CENTER_LAMBDA_DigiHSTruth", CENTER_LAMBDA_DigiHSTruth },
58 { "CENTER_MAG_DigiHSTruth", CENTER_MAG_DigiHSTruth },
59 { "CENTER_X_DigiHSTruth", CENTER_X_DigiHSTruth },
60 { "CENTER_Y_DigiHSTruth", CENTER_Y_DigiHSTruth },
61 { "CENTER_Z_DigiHSTruth", CENTER_Z_DigiHSTruth },
62 { "DELTA_ALPHA_DigiHSTruth", DELTA_ALPHA_DigiHSTruth },
63 { "DELTA_PHI_DigiHSTruth", DELTA_PHI_DigiHSTruth },
64 { "DELTA_THETA_DigiHSTruth", DELTA_THETA_DigiHSTruth },
65 { "ENG_BAD_CELLS_DigiHSTruth", ENG_BAD_CELLS_DigiHSTruth },
66 { "ENG_BAD_HV_CELLS_DigiHSTruth", ENG_BAD_HV_CELLS_DigiHSTruth },
67 { "ENG_FRAC_CORE_DigiHSTruth", ENG_FRAC_CORE_DigiHSTruth },
68 { "ENG_FRAC_EM_DigiHSTruth", ENG_FRAC_EM_DigiHSTruth },
69 { "ENG_FRAC_MAX_DigiHSTruth", ENG_FRAC_MAX_DigiHSTruth },
70 { "ENG_POS_DigiHSTruth", ENG_POS_DigiHSTruth },
71 { "FIRST_ENG_DENS_DigiHSTruth", FIRST_ENG_DENS_DigiHSTruth },
72 { "FIRST_ETA_DigiHSTruth", FIRST_ETA_DigiHSTruth },
73 { "FIRST_PHI_DigiHSTruth", FIRST_PHI_DigiHSTruth },
74 { "ISOLATION_DigiHSTruth", ISOLATION_DigiHSTruth },
75 { "LATERAL_DigiHSTruth", LATERAL_DigiHSTruth },
76 { "LONGITUDINAL_DigiHSTruth", LONGITUDINAL_DigiHSTruth },
77 { "MASS_DigiHSTruth", MASS_DigiHSTruth },
78 { "N_BAD_CELLS_DigiHSTruth", N_BAD_CELLS_DigiHSTruth },
79 { "N_BAD_HV_CELLS_DigiHSTruth", N_BAD_HV_CELLS_DigiHSTruth },
80 { "N_BAD_CELLS_CORR_DigiHSTruth", N_BAD_CELLS_CORR_DigiHSTruth },
81 { "PTD_DigiHSTruth", PTD_DigiHSTruth },
82 { "SECOND_ENG_DENS_DigiHSTruth", SECOND_ENG_DENS_DigiHSTruth },
83 { "SECOND_LAMBDA_DigiHSTruth", SECOND_LAMBDA_DigiHSTruth },
84 { "SECOND_R_DigiHSTruth", SECOND_R_DigiHSTruth },
85 { "SECOND_TIME_DigiHSTruth", SECOND_TIME_DigiHSTruth },
86 { "SIGNIFICANCE_DigiHSTruth", SIGNIFICANCE_DigiHSTruth },
87 { "ENERGY_DigiHSTruth", ENERGY_DigiHSTruth },
88 { "ETA_DigiHSTruth", ETA_DigiHSTruth },
89 { "PHI_DigiHSTruth", PHI_DigiHSTruth }
90
91 };
92 // enum -> name translator
93 const std::map<xAOD::CaloCluster::MomentType,std::string> momentEnumToNameMap = {
94 { AVG_LAR_Q_DigiHSTruth, "AVG_LAR_Q_DigiHSTruth" },
95 { AVG_TILE_Q_DigiHSTruth, "AVG_TILE_Q_DigiHSTruth" },
96 { BADLARQ_FRAC_DigiHSTruth, "BADLARQ_FRAC_DigiHSTruth" },
97 { BAD_CELLS_CORR_E_DigiHSTruth, "BAD_CELLS_CORR_E_DigiHSTruth" },
98 { CELL_SIGNIFICANCE_DigiHSTruth, "CELL_SIGNIFICANCE_DigiHSTruth"},
99 { CELL_SIG_SAMPLING_DigiHSTruth, "CELL_SIG_SAMPLING_DigiHSTruth"},
100 { CENTER_LAMBDA_DigiHSTruth, "CENTER_LAMBDA_DigiHSTruth" },
101 { CENTER_MAG_DigiHSTruth, "CENTER_MAG_DigiHSTruth" },
102 { CENTER_X_DigiHSTruth, "CENTER_X_DigiHSTruth" },
103 { CENTER_Y_DigiHSTruth, "CENTER_Y_DigiHSTruth" },
104 { CENTER_Z_DigiHSTruth, "CENTER_Z_DigiHSTruth" },
105 { DELTA_ALPHA_DigiHSTruth, "DELTA_ALPHA_DigiHSTruth" },
106 { DELTA_PHI_DigiHSTruth, "DELTA_PHI_DigiHSTruth" },
107 { DELTA_THETA_DigiHSTruth, "DELTA_THETA_DigiHSTruth" },
108 { ENG_BAD_CELLS_DigiHSTruth, "ENG_BAD_CELLS_DigiHSTruth" },
109 { ENG_BAD_HV_CELLS_DigiHSTruth, "ENG_BAD_HV_CELLS_DigiHSTruth" },
110 { ENG_FRAC_CORE_DigiHSTruth, "ENG_FRAC_CORE_DigiHSTruth" },
111 { ENG_FRAC_EM_DigiHSTruth, "ENG_FRAC_EM_DigiHSTruth" },
112 { ENG_FRAC_MAX_DigiHSTruth, "ENG_FRAC_MAX_DigiHSTruth" },
113 { ENG_POS_DigiHSTruth, "ENG_POS_DigiHSTruth" },
114 { FIRST_ENG_DENS_DigiHSTruth, "FIRST_ENG_DENS_DigiHSTruth" },
115 { FIRST_ETA_DigiHSTruth, "FIRST_ETA_DigiHSTruth" },
116 { FIRST_PHI_DigiHSTruth, "FIRST_PHI_DigiHSTruth" },
117 { ISOLATION_DigiHSTruth, "ISOLATION_DigiHSTruth" },
118 { LATERAL_DigiHSTruth, "LATERAL_DigiHSTruth" },
119 { LONGITUDINAL_DigiHSTruth, "LONGITUDINAL_DigiHSTruth" },
120 { MASS_DigiHSTruth, "MASS_DigiHSTruth" },
121 { N_BAD_CELLS_DigiHSTruth, "N_BAD_CELLS_DigiHSTruth" },
122 { N_BAD_HV_CELLS_DigiHSTruth, "N_BAD_HV_CELLS_DigiHSTruth" },
123 { N_BAD_CELLS_CORR_DigiHSTruth, "N_BAD_CELLS_CORR_DigiHSTruth" },
124 { PTD_DigiHSTruth, "PTD_DigiHSTruth" },
125 { SECOND_ENG_DENS_DigiHSTruth, "SECOND_ENG_DENS_DigiHSTruth" },
126 { SECOND_LAMBDA_DigiHSTruth, "SECOND_LAMBDA_DigiHSTruth" },
127 { SECOND_R_DigiHSTruth, "SECOND_R_DigiHSTruth" },
128 { SECOND_TIME_DigiHSTruth, "SECOND_TIME_DigiHSTruth" },
129 { SIGNIFICANCE_DigiHSTruth, "SIGNIFICANCE_DigiHSTruth" },
130 { ENERGY_DigiHSTruth, "ENERGY_DigiHSTruth" },
131 { ETA_DigiHSTruth, "ETA_DigiHSTruth" },
132 { PHI_DigiHSTruth, "PHI_DigiHSTruth" }
133
134 };
135}
136
137//###############################################################################
138
140 const std::string& name,
141 const IInterface* parent)
142 : AthAlgTool(type, name, parent),
143 m_calo_id(nullptr),
145 m_minRLateral(4*cm),
147 m_minBadLArQuality(4000),
151 m_twoGaussianNoise(false),
152 m_caloDepthTool("CaloDepthTool",this),
153 m_larHVFraction("LArHVFraction",this),
154 m_absOpt(false)
155{
156 declareInterface<CaloClusterCollectionProcessor> (this);
157 // Name(s) of Moments to calculate
158 declareProperty("MomentsNames",m_momentsNames);
159
160 // Maximum allowed angle between shower axis and the vector pointing
161 // to the shower center from the IP in degrees. This property is needed
162 // to protect against cases where all significant cells are in one sampling
163 // and the shower axis can thus not be defined.
164 declareProperty("MaxAxisAngle",m_maxAxisAngle);
165 declareProperty("MinRLateral",m_minRLateral);
166 declareProperty("MinLLongitudinal",m_minLLongitudinal);
167 declareProperty("MinBadLArQuality",m_minBadLArQuality);
168 // Use 2-gaussian noise for Tile
169 declareProperty("TwoGaussianNoise",m_twoGaussianNoise);
170 declareProperty("LArHVFraction",m_larHVFraction,"Tool Handle for LArHVFraction");
171 // Not used anymore (with xAOD), but required when configured from COOL.
172 declareProperty("AODMomentsNames",m_momentsNamesAOD);
173 // Use weighting of neg. clusters option?
174 declareProperty("WeightingOfNegClusters", m_absOpt);
175 // Set eta boundary for transition from outer to inner wheel in EME2
176 declareProperty("EMECAbsEtaWheelTransition",m_etaInnerWheel);
177}
178
179//###############################################################################
180
182{
183 xAOD::CaloCluster dummyCluster;
184
185 // loop list of requested moments
186 std::string::size_type nstr(0); int nmom(0);
187 for (const auto& mom : m_momentsNames) {
188 ATH_MSG_DEBUG("Moment " << mom << " requested");
189 // check if moment is known (enumerator available)
190 auto fmap(momentNameToEnumMap.find(mom));
191 if (fmap != momentNameToEnumMap.end()) {
192 // valid moment found
193 nstr = std::max(nstr, mom.length());
194 ++nmom;
195 if (fmap->second == SECOND_TIME_DigiHSTruth) {
196 // special flag for second moment of cell times - this moment is not
197 // calculated in this tool! Do not add to internal (!) valid moments
198 // list. Its value is available from xAOD::CaloCluster::secondTime()!
199 m_secondTime = true;
200
201 // Make sure the variable used for the moment is declared
202 // to the auxiliary variable registry. Otherwise, if we don't
203 // set the moment for the first event (perhaps because there
204 // are no clusters), then we can get warnings from AuxSelection.
205 (void)dummyCluster.getMomentValue (fmap->second);
206 } else if (fmap->second == EM_PROBABILITY_DigiHSTruth) {
208 << " not calculated in this tool - misconfiguration?");
209 } else {
210 // Make sure the variable used for the moment is declared
211 // to the auxiliary variable registry.
212 (void)dummyCluster.getMomentValue (fmap->second);
213
214 // all other valid moments
215 m_validMoments.push_back(fmap->second);
216 // flag some special requests
217 switch (fmap->second) {
218 case SIGNIFICANCE_DigiHSTruth:
219 case CELL_SIGNIFICANCE_DigiHSTruth:
221 break;
222 case ISOLATION_DigiHSTruth:
224 break;
225 case ENG_BAD_HV_CELLS_DigiHSTruth:
227 break;
228 default:
229 break;
230 } // set special processing flags
231 } // moment calculated with this tool
232 } else {
233 ATH_MSG_ERROR("Moment name " << mom << " not known; known moments are:");
234 char buffer[128];
235 std::string::size_type lstr(nstr);
236 // determine field size
237 for (const auto& fmom : momentNameToEnumMap) {
238 lstr = std::max(lstr, fmom.first.length());
239 }
240 // print available moments
241 for (const auto& fmom : momentNameToEnumMap) {
242 sprintf(buffer, "moment name: %-*.*s - enumerator: %i", (int)lstr,
243 (int)lstr, fmom.first.c_str(), (int)fmom.second);
244 ATH_MSG_ERROR(buffer);
245 }
246 auto fmom(momentNameToEnumMap.find("SECOND_TIME_DigiHSTruth"));
247 if (fmom != momentNameToEnumMap.end()){
248 sprintf(buffer, "moment name: %-*.*s - enumerator: %i", (int)nstr,
249 (int)nstr, fmom->first.c_str(), (int)fmom->second);
250 ATH_MSG_ERROR(buffer);
251 }
252 fmom = momentNameToEnumMap.find("NCELL_SAMPLING_DigiHSTruth");
253 if (fmom != momentNameToEnumMap.end()){
254 sprintf(buffer, "moment name: %-*.*s - enumerator: %i", (int)nstr,
255 (int)nstr, fmom->first.c_str(), (int)fmom->second);
256 ATH_MSG_ERROR(buffer);
257 }
258 return StatusCode::FAILURE;
259 } // found unknown moment name
260 } // loop configured moment names
261
262 // sort and remove duplicates
264 m_validMoments.erase(
266 m_validMoments.end());
267
268 // print configured moments
269 ATH_MSG_INFO("Construct and save " << nmom << " cluster moments: ");
270 char buffer[128];
271 for (auto menum : m_validMoments) {
272 sprintf(buffer, "moment name: %-*.*s - enumerator: %i", (int)nstr,
273 (int)nstr, momentEnumToNameMap.at(menum).c_str(), (int)menum);
274 ATH_MSG_INFO(buffer);
275 }
276 if (m_secondTime) {
277 auto fmom(momentNameToEnumMap.find("SECOND_TIME_DigiHSTruth"));
278 if (fmom != momentNameToEnumMap.end()){
279 sprintf(buffer, "moment name: %-*.*s - enumerator: %i (save only)",
280 (int)nstr, (int)nstr, fmom->first.c_str(), (int)fmom->second);
281 ATH_MSG_INFO(buffer);
282 }
283 }
284
285 // retrieve CaloCell ID server
286 CHECK(detStore()->retrieve(m_calo_id,"CaloCell_ID"));
287
288 // retrieve the calo depth tool
289 CHECK(m_caloDepthTool.retrieve());
290 ATH_CHECK(m_caloMgrKey.initialize());
291
292 // retrieve specific servers and tools for selected processes
294 if (m_calculateLArHVFraction) { ATH_CHECK(m_larHVFraction.retrieve()); } else { m_larHVFraction.disable(); }
295
296 ATH_CHECK(m_signalCellKey.initialize());
297
298 return StatusCode::SUCCESS;
299}
300
302{
303 return StatusCode::SUCCESS;
304}
305
306//#############################################################################
307
309
310
311struct cellinfo {
312 double x{};
313 double y{};
314 double z{};
315 double energy{};
316 double eta{};
317 double phi{};
318 double r{};
319 double lambda{};
320 double volume{};
322 unsigned int identifier{};
323};
324
325} // namespace CaloClusterMomentsMaker_DigiHSTruth_detail
326
327StatusCode
329 xAOD::CaloClusterContainer *theClusColl)
330 const
331{
332 ATH_MSG_DEBUG("Executing " << name());
333
335
336 // Maps cell IdentifierHash to cluster index in cluster collection.
337 // Only used when cluster isolation moment is calculated.
338 using clusterIdx_t = std::uint16_t;
339 typedef std::pair<clusterIdx_t, clusterIdx_t> clusterPair_t;
340 std::vector<clusterPair_t> clusterIdx;
341 const clusterIdx_t noCluster = std::numeric_limits<clusterIdx_t>::max();
342
343 const CaloNoise* noise=nullptr;
346 noise=*noiseHdl;
347 }
348
350 const CaloDetDescrManager* caloDDMgr = *caloMgrHandle;
351 // Counters for number of empty and non-empty neighbor cells per sampling
352 // layer Only used when cluster isolation moment is calculated.
353 int nbEmpty[CaloCell_ID::Unknown];
354 int nbNonEmpty[CaloCell_ID::Unknown];
355
356 // prepare stuff from entire collection in case isolation moment
357 // should be calculated
358
359 if ( m_calculateIsolation ) {
360
361 if (theClusColl->size() >= noCluster) {
362 msg(MSG::ERROR) << "Too many clusters" << endmsg;
363 return StatusCode::FAILURE;
364 }
365
366 // initialize with "empty" values
367 clusterIdx.resize(m_calo_id->calo_cell_hash_max(),
368 clusterPair_t(noCluster, noCluster));
369
370 int iClus = 0;
371 for (xAOD::CaloCluster* theCluster : *theClusColl) {
372 // loop over all cell members and fill cell vector for used cells
373 xAOD::CaloCluster::cell_iterator cellIter = theCluster->cell_begin();
374 xAOD::CaloCluster::cell_iterator cellIterEnd = theCluster->cell_end();
375 for(; cellIter != cellIterEnd; cellIter++ ){
376 CxxUtils::prefetchNext(cellIter, cellIterEnd);
377 const CaloCell* pCell = *cellIter;
378 const CaloDetDescrElement * caloDDE = pCell->caloDDE();
379
380 // Specific DigiHSTruth part
381 IdentifierHash hashid=caloDDE->calo_hash() ;
382 if(! hashid.is_valid() ) continue;
383 if(hashid >= (signalCells)->size()) continue;
384
385 pCell = (*signalCells).findCell(hashid);
386 if(!pCell) continue;
387 // End specific DigiHSTruth part
388
389 Identifier myId = pCell->ID();
390 IdentifierHash myHashId = m_calo_id->calo_cell_hash(myId);
391 if ( clusterIdx[(unsigned int)myHashId].first != noCluster) {
392 // check weight and assign to current cluster if weight is > 0.5
393 double weight = cellIter.weight();
394 if ( weight > 0.5 )
395 clusterIdx[(unsigned int)myHashId].first = iClus;
396 }
397 else {
398 clusterIdx[(unsigned int)myHashId].first = iClus;
399 }
400 }
401 ++iClus;
402 }
403 }
404
405 // Move allocation of temporary arrays outside the cluster loop.
406 // That way, we don't need to delete and reallocate them
407 // each time through the loop.
408
409 std::vector<CaloClusterMomentsMaker_DigiHSTruth_detail::cellinfo> cellinfo;
410 std::vector<double> maxSampE (CaloCell_ID::Unknown);
411 std::vector<double> myMoments(m_validMoments.size(),0);
412 std::vector<double> myNorms(m_validMoments.size(),0);
413 std::vector<std::tuple<int,int> > nCellsSamp; nCellsSamp.reserve(CaloCell_ID::Unknown);
414 std::vector<IdentifierHash> theNeighbors;
415 // loop over individual clusters
416 xAOD::CaloClusterContainer::iterator clusIter = theClusColl->begin();
417 xAOD::CaloClusterContainer::iterator clusIterEnd = theClusColl->end();
418 int iClus = 0;
419 for( ;clusIter!=clusIterEnd;++clusIter,++iClus) {
420 xAOD::CaloCluster * theCluster = *clusIter;
421
422 double w(0),xc(0),yc(0),zc(0),mx(0),my(0),mz(0),mass(0);
423 double eBad(0),ebad_dac(0),ePos(0),eBadLArQ(0),sumSig2(0),maxAbsSig(0);
424 double eLAr2(0),eLAr2Q(0);
425 double eTile2(0),eTile2Q(0);
426 double eBadLArHV(0);
427 int nbad(0),nbad_dac(0),nBadLArHV(0);
428 unsigned int i,nSigSampl(0);
429 unsigned int theNumOfCells = theCluster->size();
430
431 double theClusterEnergy = 0;
432 double theClusterAbsEnergy = 0;
433 double theClusterEta = 0;
434 double theClusterPhi = 0;
435 double theNewSecondTime = 0;
436 double timeNorm = 0;
437
438 // these two are needed for the LATERAL moment
439 int iCellMax(-1);
440 int iCellScndMax(-1);
441
442 cellinfo.clear();
443 if (cellinfo.capacity() == 0)
444 cellinfo.reserve (theNumOfCells*2);
445
446 double phi0 = theCluster->phi();
447
448 for(i=0;i<(unsigned int)CaloCell_ID::Unknown;i++)
449 maxSampE[i] = 0;
450
451 if ( !m_momentsNames.empty() ) {
452 std::fill (myMoments.begin(), myMoments.end(), 0);
453 std::fill (myNorms.begin(), myNorms.end(), 0);
454 if ( m_calculateIsolation ) {
455 std::fill_n(nbNonEmpty, CaloCell_ID::Unknown, 0);
456 std::fill_n(nbEmpty, CaloCell_ID::Unknown, 0);
457 }
458
459 // loop over all cell members and calculate the center of mass
460 xAOD::CaloCluster::cell_iterator cellIter = theCluster->cell_begin();
461 xAOD::CaloCluster::cell_iterator cellIterEnd = theCluster->cell_end();
462 for(; cellIter != cellIterEnd; cellIter++ ){
463 CaloPrefetch::nextDDE(cellIter, cellIterEnd);
464
465 const CaloCell* pCell = (*cellIter);
466 const CaloDetDescrElement* caloDDE = pCell->caloDDE();
467
468 // specific DigiHSTruth part
469 IdentifierHash hashid=caloDDE->calo_hash() ;
470 if(! hashid.is_valid() ) continue;
471 if(hashid >= (signalCells)->size()) continue;
472 pCell = (*signalCells).findCell(hashid);
473 // end specific DigiHSTruth part
474
475 Identifier myId = pCell->ID();
476 const CaloDetDescrElement* myCDDE = pCell->caloDDE();
477 if (!myCDDE){
478 ATH_MSG_ERROR("Pointer myCDDE is null.");
479 return StatusCode::FAILURE;
480 }
481 double ene = pCell->e();
482 if(m_absOpt) ene = std::abs(ene);
483 double weight = cellIter.weight();
484
485 double cellPhi = myCDDE->phi();
486 double thePhi = proxim (cellPhi, phi0);
487
488 theClusterEnergy += weight * ene;
489 theClusterAbsEnergy += weight*std::abs(ene);
490 theClusterEta += weight*std::abs(ene)*pCell->eta();
491 theClusterPhi += weight*std::abs(ene)* thePhi;
492
493 if ( pCell->badcell() ) {
494 eBad += ene*weight;
495 nbad++;
496 if(ene!=0){
497 ebad_dac+=ene*weight;
498 nbad_dac++;
499 }
500 }
501 else {
502 if ( !(myCDDE->is_tile())
503 && ((pCell->provenance() & 0x2000) == 0x2000)
504 && !((pCell->provenance() & 0x0800) == 0x0800)) {
505 if ( pCell->quality() > m_minBadLArQuality ) {
506 eBadLArQ += ene*weight;
507 }
508 eLAr2 += ene*weight*ene*weight;
509 eLAr2Q += ene*weight*ene*weight*pCell->quality();
510 }
511 if ( myCDDE->is_tile() ) {
512 uint16_t tq = pCell->quality();
513 uint8_t tq1 = (0xFF00&tq)>>8; // quality in channel 1
514 uint8_t tq2 = (0xFF&tq); // quality in channel 2
515 // reject cells with either 0xFF00 or 0xFF
516 if ( ((tq1&0xFF) != 0xFF) && ((tq2&0xFF) != 0xFF) ) {
517 eTile2 += ene*weight*ene*weight;
518 // take the worse of both qualities (one might be 0 in
519 // 1-channel cases)
520 eTile2Q += ene*weight*ene*weight*(tq1>tq2?tq1:tq2);
521 }
522 }
523 }
524 if ( ene > 0 ) {
525 ePos += ene*weight;
526 }
527
529 // Avoid a spurious FPE from clang.
531
532 const float sigma = m_twoGaussianNoise ?\
533 noise->getEffectiveSigma(pCell->ID(),pCell->gain(),pCell->energy()) : \
534 noise->getNoise(pCell->ID(),pCell->gain());
535
536 sumSig2 += sigma*sigma;
537 // use geometry weighted energy of cell for leading cell significance
538 double Sig = (sigma>0?ene*weight/sigma:0);
539 if (m_useGPUCriteria) {
540 unsigned int thisSampl = myCDDE->getSampling();
541 if ( ( std::abs(Sig) > std::abs(maxAbsSig) ) ||
542 ( std::abs(Sig) == std::abs(maxAbsSig) && thisSampl > nSigSampl ) ||
543 ( std::abs(Sig) == std::abs(maxAbsSig) && thisSampl == nSigSampl && Sig > maxAbsSig ) ) {
544 maxAbsSig = Sig;
545 nSigSampl = thisSampl;
546 }
547
548 }
549 else {
550 if ( std::abs(Sig) > std::abs(maxAbsSig) ) {
551 maxAbsSig = Sig;
552 nSigSampl = myCDDE->getSampling();
553 }
554 }
555 }
556 if ( m_calculateIsolation ) {
557 // get all 2D Neighbours if the cell is not inside another cluster with
558 // larger weight
559
560 IdentifierHash myHashId = m_calo_id->calo_cell_hash(myId);
561 if ( clusterIdx[myHashId].first == iClus ) {
562 theNeighbors.clear();
563 m_calo_id->get_neighbours(myHashId, LArNeighbours::all2D, theNeighbors);
564 for (const auto& nhash: theNeighbors) {
565 clusterPair_t& idx = clusterIdx[nhash];
566
567 // only need to look at each cell once per cluster
568 if ( idx.second == iClus ) continue;
569 idx.second = iClus;
570
571 if ( idx.first == noCluster ) {
572 ++ nbEmpty[m_calo_id->calo_sample(nhash)];
573 } else if ( idx.first != iClus ) {
574 ++ nbNonEmpty[m_calo_id->calo_sample(nhash)];
575 }
576
577 }
578 }
579 }
580 if(m_secondTime){
582 if (sam != CaloSampling::PreSamplerB &&
583 sam != CaloSampling::PreSamplerE){
584 unsigned int pmask = myCDDE->is_tile() ? 0x8080 : 0x2000;
585 // Is time defined?
586 if ( pCell->provenance() & pmask ) {
587 // keep the sign of weight for the time norm in case a cell is removed
588 double theTimeNorm = std::abs(weight) * weight * ene * ene;
589 theNewSecondTime += theTimeNorm * pCell->time() * pCell->time();
590 timeNorm += theTimeNorm;
591 }
592 }
593 }
594
595
596 if ( ene > 0. && weight > 0) {
597 // get all geometric information needed ...
599 .x = myCDDE->x(),
600 .y = myCDDE->y(),
601 .z = myCDDE->z(),
602 .energy = ene*weight,
603 .eta = myCDDE->eta(),
604 .phi = myCDDE->phi(),
605 .r = 0, // These two are filled in later.
606 .lambda = 0,
607 .volume = myCDDE->volume(),
608 .sample = myCDDE->getSampling(),
609 .identifier = cellIter.index()
610 //Using the index instead of the hash ID as disambiguation criterion
611 //is relevant for the GPU now that we no longer assume the two are the same,
612 //and this gives us better performance.
613 });
614
616
617 if ( ci.energy > maxSampE[(unsigned int)ci.sample] )
618 maxSampE[(unsigned int)ci.sample] = ci.energy;
619
620 if (m_useGPUCriteria) {
621 if (iCellMax < 0 ||
622 ci.energy > cellinfo[iCellMax].energy ||
623 (ci.energy == cellinfo[iCellMax].energy && ci.identifier > cellinfo[iCellMax].identifier) ) {
624 iCellScndMax = iCellMax;
625 iCellMax = cellinfo.size()-1;
626 }
627 else if (iCellScndMax < 0 ||
628 ci.energy > cellinfo[iCellScndMax].energy ||
629 (ci.energy == cellinfo[iCellScndMax].energy && ci.identifier > cellinfo[iCellScndMax].identifier) )
630 {
631 iCellScndMax = cellinfo.size()-1;
632 }
633 }
634 else {
635 if (iCellMax < 0 || ci.energy > cellinfo[iCellMax].energy ) {
636 iCellScndMax = iCellMax;
637 iCellMax = cellinfo.size()-1;
638 }
639 else if (iCellScndMax < 0 ||
640 ci.energy > cellinfo[iCellScndMax].energy )
641 {
642 iCellScndMax = cellinfo.size()-1;
643 }
644 }
645
646 xc += ci.energy*ci.x;
647 yc += ci.energy*ci.y;
648 zc += ci.energy*ci.z;
649
650 double dir = ci.x*ci.x+ci.y*ci.y+ci.z*ci.z;
651
652 if ( dir > 0) {
653 dir = sqrt(dir);
654 dir = 1./dir;
655 }
656 mx += ci.energy*ci.x*dir;
657 my += ci.energy*ci.y*dir;
658 mz += ci.energy*ci.z*dir;
659
660 w += ci.energy;
661 } // cell has E>0 and weight != 0
662 } //end of loop over all cells
664 const auto hvFrac=m_larHVFraction->getLArHVFrac(theCluster->getCellLinks(),ctx);
665 eBadLArHV= hvFrac.first;
666 nBadLArHV=hvFrac.second;
667 }
668
669 if ( w > 0 || (m_useGPUCriteria && w >= 0) ) {
670 mass = w*w - mx*mx - my*my - mz*mz;
671 if ( mass > 0) {
672 mass = sqrt(mass);
673 }
674 else {
675 // make mass negative if m^2 was negative
676 mass = -sqrt(-mass);
677 }
678
679 if (w == 0) {
680 w = 1.0;
681 }
682
683 xc/=w;
684 yc/=w;
685 zc/=w;
686 Amg::Vector3D showerCenter(xc,yc,zc);
687 w=0;
688
689
690 //log << MSG::WARNING << "Found bad cells " << xbad_dac << " " << ybad_dac << " " << zbad_dac << " " << ebad_dac << endmsg;
691 //log << MSG::WARNING << "Found Cluster " << xbad_dac << " " << ybad_dac << " " << zbad_dac << " " << endmsg;
692 // shower axis is just the vector pointing from the IP to the shower center
693 // in case there are less than 3 cells in the cluster
694
695 Amg::Vector3D showerAxis(xc,yc,zc);
696 Amg::setMag(showerAxis,1.0);
697
698 // otherwise the principal direction with the largest absolute
699 // eigenvalue will be used unless it's angle w.r.t. the vector pointing
700 // from the IP to the shower center is larger than allowed by the
701 // property m_maxAxisAngle
702
703 double angle(0),deltaPhi(0),deltaTheta(0);
704 if ( cellinfo.size() > 2 ) {
705 Eigen::Matrix3d C=Eigen::Matrix3d::Zero();
707 const double e2 = ci.energy * ci.energy;
708
709 C(0,0) += e2*(ci.x-xc)*(ci.x-xc);
710 C(1,0) += e2*(ci.x-xc)*(ci.y-yc);
711 C(2,0) += e2*(ci.x-xc)*(ci.z-zc);
712
713 C(1,1) += e2*(ci.y-yc)*(ci.y-yc);
714 C(2,1) += e2*(ci.y-yc)*(ci.z-zc);
715
716 C(2,2) += e2*(ci.z-zc)*(ci.z-zc);
717 w += e2;
718 }
719 C/=(w != 0 ? w : 1.0);
720
721 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigensolver(C);
722 if (eigensolver.info() != Eigen::Success) {
723 msg(MSG::WARNING) << "Failed to compute Eigenvalues -> Can't determine shower axis" << endmsg;
724 }
725 else {
726 // don't use the principal axes if at least one of the 3
727 // diagonal elements is 0
728
729 const Eigen::Vector3d& S=eigensolver.eigenvalues();
730 const Eigen::Matrix3d& U=eigensolver.eigenvectors();
731
732 const double epsilon = 1.E-6;
733
734 if ( std::abs(S[0]) >= epsilon && std::abs(S[1]) >= epsilon && std::abs(S[2]) >= epsilon ) {
735
736 Amg::Vector3D prAxis(showerAxis);
737 int iEigen = -1;
738
739 for (i=0;i<3;i++) {
740 Amg::Vector3D tmpAxis=U.col(i);
741
742 // calculate the angle
743 double tmpAngle=Amg::angle(tmpAxis,showerAxis);
744
745 if ( tmpAngle > 90*deg ) {
746 tmpAngle = 180*deg - tmpAngle;
747 tmpAxis = -tmpAxis;
748 }
749
750 if ( iEigen == -1 || tmpAngle < angle ) {
751 iEigen = i;
752 angle = tmpAngle;
753 prAxis = tmpAxis;
754 }
755 }//end for loop
756
757 // calculate theta and phi angle differences
758
759 deltaPhi = CaloPhiRange::diff(showerAxis.phi(),prAxis.phi());
760
761 deltaTheta = showerAxis.theta() - prAxis.theta();
762
763 // check the angle
764
765 if ( angle < m_maxAxisAngle ) {
766 showerAxis = prAxis;
767 }
768 else
769 ATH_MSG_DEBUG("principal Direction (" << prAxis[Amg::x] << ", "
770 << prAxis[Amg::y] << ", " << prAxis[Amg::z] << ") deviates more than "
771 << m_maxAxisAngle*(1./deg)
772 << " deg from IP-to-ClusterCenter-axis (" << showerAxis[Amg::x] << ", "
773 << showerAxis[Amg::y] << ", " << showerAxis[Amg::z] << ")");
774 }//end if std::abs(S)<epsilon
775 else {
776 ATH_MSG_DEBUG("Eigenvalues close to 0, do not use principal axis");
777 }
778 }//end got eigenvalues
779 } //end if cellinfo.size()>2
780
781 ATH_MSG_DEBUG("Shower Axis = (" << showerAxis[Amg::x] << ", "
782 << showerAxis[Amg::y] << ", " << showerAxis[Amg::z] << ")");
783
784
785 // calculate radial distance from and the longitudinal distance
786 // along the shower axis for each cell. The cluster center is
787 // at r=0 and lambda=0
788
789 for (auto& ci : cellinfo) {
790 const Amg::Vector3D currentCell(ci.x,ci.y,ci.z);
791 // calculate distance from shower axis r
792 ci.r = ((currentCell-showerCenter).cross(showerAxis)).mag();
793 // calculate distance from shower center along shower axis
794 ci.lambda = (currentCell-showerCenter).dot(showerAxis);
795 }
796
797 // loop over all positive energy cells and calculate all desired moments
798
799 // define common norm for all simple moments
800 double commonNorm = 0;
801 double phi0 = cellinfo.size() > 0 ? cellinfo[0].phi : 0;
802
803 for(unsigned i=0;i<cellinfo.size();i++) {
805 // loop over all valid moments
806 commonNorm += ci.energy;
807 for(size_t iMoment = 0, size = m_validMoments.size();
808 iMoment != size;
809 ++ iMoment)
810 {
811 // now calculate the actual moments
812 switch (m_validMoments[iMoment]) {
813 case FIRST_ETA_DigiHSTruth:
814 myMoments[iMoment] += ci.energy*ci.eta;
815 break;
816 case FIRST_PHI_DigiHSTruth:
817 // first cell decides the sign in order to avoid
818 // overlap problem at phi = -pi == +pi
819 // need to be normalized to the range [-pi,+pi] in the end
820 myMoments[iMoment] += ci.energy * proxim (ci.phi, phi0);
821 break;
822 case SECOND_R_DigiHSTruth:
823 myMoments[iMoment] += ci.energy*ci.r*ci.r;
824 break;
825 case SECOND_LAMBDA_DigiHSTruth:
826 myMoments[iMoment] += ci.energy*ci.lambda*ci.lambda;
827 break;
828 case LATERAL_DigiHSTruth:
829 if ( (int)i != iCellMax && (int)i != iCellScndMax ) {
830 myMoments[iMoment] += ci.energy*ci.r*ci.r;
831 myNorms[iMoment] += ci.energy*ci.r*ci.r;
832 }
833 else {
834 double rm = ci.r;
835 if ( rm < m_minRLateral )
836 rm = m_minRLateral;
837 myNorms[iMoment] += rm*rm*ci.energy;
838 }
839 break;
840 case LONGITUDINAL_DigiHSTruth:
841 if ( (int)i != iCellMax && (int)i != iCellScndMax ) {
842 myMoments[iMoment] += ci.energy*ci.lambda*ci.lambda;
843 myNorms[iMoment] += ci.energy*ci.lambda*ci.lambda;
844 }
845 else {
846 double lm = ci.lambda;
847 if ( lm < m_minLLongitudinal )
849 myNorms[iMoment] += lm*lm*ci.energy;
850 }
851 break;
852 case FIRST_ENG_DENS_DigiHSTruth:
853 if ( ci.volume > 0 ) {
854 myMoments[iMoment] += ci.energy*ci.energy/ci.volume;
855 myNorms[iMoment] += ci.energy;
856 }
857 break;
858 case SECOND_ENG_DENS_DigiHSTruth:
859 if ( ci.volume > 0 ) {
860 myMoments[iMoment] += ci.energy*std::pow(ci.energy/ci.volume,2);
861 myNorms[iMoment] += ci.energy;
862 }
863 break;
864 case ENG_FRAC_EM_DigiHSTruth:
865 if ( ci.sample == CaloCell_ID::EMB1
866 || ci.sample == CaloCell_ID::EMB2
867 || ci.sample == CaloCell_ID::EMB3
868 || ci.sample == CaloCell_ID::EME1
869 || ci.sample == CaloCell_ID::EME2
870 || ci.sample == CaloCell_ID::EME3
871 || ci.sample == CaloCell_ID::FCAL0 )
872 myMoments[iMoment] += ci.energy;
873 break;
874 case ENG_FRAC_MAX_DigiHSTruth:
875 if ( (int)i == iCellMax )
876 myMoments[iMoment] = ci.energy;
877 break;
878 case PTD_DigiHSTruth:
879 // do not convert to pT since clusters are small and
880 // there is virtually no difference and cosh just costs
881 // time ...
882 myMoments[iMoment] += ci.energy*ci.energy;
883 myNorms[iMoment] += ci.energy;
884 break;
885 default:
886 // nothing to be done for other moments
887 break;
888 }
889 }
890 } //end of loop over cell
891
892 // assign moments which don't need the loop over the cells
893 for (size_t iMoment = 0, size = m_validMoments.size();
894 iMoment != size;
895 ++ iMoment)
896 {
897 // now calculate the actual moments
898 switch (m_validMoments[iMoment]) {
899 case FIRST_ETA_DigiHSTruth:
900 case FIRST_PHI_DigiHSTruth:
901 case SECOND_R_DigiHSTruth:
902 case SECOND_LAMBDA_DigiHSTruth:
903 case ENG_FRAC_EM_DigiHSTruth:
904 case ENG_FRAC_MAX_DigiHSTruth:
905 myNorms[iMoment] = commonNorm;
906 break;
907 case DELTA_PHI_DigiHSTruth:
908 myMoments[iMoment] = deltaPhi;
909 break;
910 case DELTA_THETA_DigiHSTruth:
911 myMoments[iMoment] = deltaTheta;
912 break;
913 case DELTA_ALPHA_DigiHSTruth:
914 myMoments[iMoment] = angle;
915 break;
916 case CENTER_X_DigiHSTruth:
917 myMoments[iMoment] = showerCenter.x();
918 break;
919 case CENTER_Y_DigiHSTruth:
920 myMoments[iMoment] = showerCenter.y();
921 break;
922 case CENTER_Z_DigiHSTruth:
923 myMoments[iMoment] = showerCenter.z();
924 break;
925 case CENTER_MAG_DigiHSTruth:
926 myMoments[iMoment] = showerCenter.mag();
927 break;
928 case CENTER_LAMBDA_DigiHSTruth:
929 // calculate the longitudinal distance along the shower axis
930 // of the shower center from the calorimeter start
931
932 // first need calo boundary at given eta phi try LAREM barrel
933 // first, then LAREM endcap OW, then LAREM endcap IW, then
934 // FCal
935 {
936 double r_calo(0),z_calo(0),lambda_c(0);
937 r_calo = m_caloDepthTool->get_entrance_radius(CaloCell_ID::EMB1,
938 showerCenter.eta(),
939 showerCenter.phi(),
940 caloDDMgr);
941 if ( r_calo == 0 ) {
942 z_calo = m_caloDepthTool->get_entrance_z(CaloCell_ID::EME1,
943 showerCenter.eta(),
944 showerCenter.phi(),
945 caloDDMgr);
946 if ( z_calo == 0 )
947 z_calo = m_caloDepthTool->get_entrance_z(CaloCell_ID::EME2,
948 showerCenter.eta(),
949 showerCenter.phi(),
950 caloDDMgr);
951 if ( z_calo == 0 )
952 z_calo = m_caloDepthTool->get_entrance_z(CaloCell_ID::FCAL0,
953 showerCenter.eta(),
954 showerCenter.phi(),
955 caloDDMgr);
956 if ( z_calo == 0 ) // for H6 TB without EMEC outer wheel
957 z_calo = m_caloDepthTool->get_entrance_z(CaloCell_ID::HEC0,
958 showerCenter.eta(),
959 showerCenter.phi(),
960 caloDDMgr);
961 if ( z_calo != 0 && showerAxis.z() != 0 ) {
962 lambda_c = std::abs((z_calo-showerCenter.z())/showerAxis.z());
963 }
964 }
965 else {
966 double r_s2 = showerAxis.x()*showerAxis.x()
967 +showerAxis.y()*showerAxis.y();
968 double r_cs = showerAxis.x()*showerCenter.x()
969 +showerAxis.y()*showerCenter.y();
970 double r_cr = showerCenter.x()*showerCenter.x()
971 +showerCenter.y()*showerCenter.y()-r_calo*r_calo;
972 if ( r_s2 > 0 ) {
973 double det = r_cs*r_cs/(r_s2*r_s2) - r_cr/r_s2;
974 if ( det > 0 ) {
975 det = sqrt(det);
976 double l1(-r_cs/r_s2);
977 double l2(l1);
978 l1 += det;
979 l2 -= det;
980 if ( std::abs(l1) < std::abs(l2) )
981 lambda_c = std::abs(l1);
982 else
983 lambda_c = std::abs(l2);
984 }
985 }
986 }
987 myMoments[iMoment] = lambda_c;
988 }
989 break;
990 case ENG_FRAC_CORE_DigiHSTruth:
991 for(i=0;i<(int)CaloCell_ID::Unknown;i++)
992 myMoments[iMoment] += maxSampE[i];
993 myNorms[iMoment] = commonNorm;
994 break;
995 case ISOLATION_DigiHSTruth:
996 {
997 // loop over empty and filled perimeter cells and
998 // get a weighted ratio by means of energy fraction per layer
999 for(unsigned int i=0; i != CaloSampling::Unknown; ++ i) {
1001 if (theCluster->hasSampling(s)) {
1002 const double eSample = theCluster->eSample(s);
1003 if (eSample > 0) {
1004 int nAll = nbEmpty[i]+nbNonEmpty[i];
1005 if (nAll > 0) {
1006 myMoments[iMoment] += (eSample*nbEmpty[i])/nAll;
1007 myNorms[iMoment] += eSample;
1008 }
1009 }//end of eSample>0
1010 }//end has sampling
1011 }//end loop over samplings
1012 }
1013 break;
1014 case ENG_BAD_CELLS_DigiHSTruth:
1015 myMoments[iMoment] = eBad;
1016 break;
1017 case N_BAD_CELLS_DigiHSTruth:
1018 myMoments[iMoment] = nbad;
1019 break;
1020 case N_BAD_CELLS_CORR_DigiHSTruth:
1021 myMoments[iMoment] = nbad_dac;
1022 break;
1023 case BAD_CELLS_CORR_E_DigiHSTruth:
1024 myMoments[iMoment] = ebad_dac;
1025 break;
1026 case BADLARQ_FRAC_DigiHSTruth:
1027 myMoments[iMoment] = eBadLArQ/(theCluster->e()!=0.?theCluster->e():1.);
1028 break;
1029 case ENG_POS_DigiHSTruth:
1030 myMoments[iMoment] = ePos;
1031 break;
1032 case SIGNIFICANCE_DigiHSTruth:
1033 myMoments[iMoment] = (sumSig2>0?theCluster->e()/sqrt(sumSig2):0.);
1034 break;
1035 case CELL_SIGNIFICANCE_DigiHSTruth:
1036 myMoments[iMoment] = maxAbsSig;
1037 break;
1038 case CELL_SIG_SAMPLING_DigiHSTruth:
1039 myMoments[iMoment] = nSigSampl;
1040 break;
1041 case AVG_LAR_Q_DigiHSTruth:
1042 myMoments[iMoment] = eLAr2Q/(eLAr2>0?eLAr2:1);
1043 break;
1044 case AVG_TILE_Q_DigiHSTruth:
1045 myMoments[iMoment] = eTile2Q/(eTile2>0?eTile2:1);
1046 break;
1047 case ENG_BAD_HV_CELLS_DigiHSTruth:
1048 myMoments[iMoment] = eBadLArHV;
1049 break;
1050 case N_BAD_HV_CELLS_DigiHSTruth:
1051 myMoments[iMoment] = nBadLArHV;
1052 break;
1053 case PTD_DigiHSTruth:
1054 myMoments[iMoment] = sqrt(myMoments[iMoment]);
1055 break;
1056 case MASS_DigiHSTruth:
1057 myMoments[iMoment] = mass;
1058 break;
1059 case ENERGY_DigiHSTruth:
1060 myMoments[iMoment] = theClusterEnergy;
1061 break;
1062 case ETA_DigiHSTruth:
1063 if(theClusterAbsEnergy > 0)
1064 myMoments[iMoment] = theClusterEta / theClusterAbsEnergy;
1065 else{
1066 myMoments[iMoment] = 0;
1067 }
1068 break;
1069 case PHI_DigiHSTruth:
1070 if(theClusterAbsEnergy > 0)
1071 myMoments[iMoment] = CaloPhiRange::fix(theClusterPhi / theClusterAbsEnergy);
1072 else{
1073 myMoments[iMoment] = 0;
1074 }
1075 break;
1076 default:
1077 // nothing to be done for other moments
1078 break;
1079 }
1080 }
1081 }
1082
1083 // normalize moments and copy to Cluster Moment Store
1084 size_t size= m_validMoments.size();
1085 for (size_t iMoment = 0; iMoment != size; ++iMoment) {
1087 if ( myNorms[iMoment] != 0 )
1088 myMoments[iMoment] /= myNorms[iMoment];
1089 if ( moment == FIRST_PHI_DigiHSTruth )
1090 myMoments[iMoment] = CaloPhiRange::fix(myMoments[iMoment]);
1091 theCluster->insertMoment(moment,myMoments[iMoment]);
1092 } // loop on moments for cluster
1093 } // check on requested moments
1094 // check on second moment of time if requested
1095 if ( m_secondTime ) {
1096 double secondTime(0.0);
1097 if (timeNorm > 0){
1098 secondTime = theNewSecondTime/timeNorm-theCluster->time()*theCluster->time();
1099 }
1101 }
1102
1103 } // loop on clusters
1104
1105 return StatusCode::SUCCESS;
1106}
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_INFO(x,...)
CaloPhiRange class declaration.
#define CHECK(...)
Evaluate an expression and check for errors.
#define deg
size_t size() const
Number of registered mappings.
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
const ServiceHandle< StoreGateSvc > & detStore() const
MsgStream & msg() const
CaloSampling::CaloSample CaloSample
Definition CaloCell_ID.h:53
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
float time() const
get time (data member)
Definition CaloCell.h:368
virtual double e() const override final
get energy (data member) (synonym to method energy()
Definition CaloCell.h:333
double energy() const
get energy (data member)
Definition CaloCell.h:327
const CaloDetDescrElement * caloDDE() const
get pointer to CaloDetDescrElement (data member)
Definition CaloCell.h:321
uint16_t provenance() const
get provenance (data member)
Definition CaloCell.h:354
virtual double eta() const override final
get eta (through CaloDetDescrElement)
Definition CaloCell.h:382
uint16_t quality() const
get quality (data member)
Definition CaloCell.h:348
virtual bool badcell() const
check is cell is dead
Definition CaloCell.cxx:144
CaloGain::CaloGain gain() const
get gain (data member )
Definition CaloCell.h:361
Identifier ID() const
get ID (from cached data member) non-virtual and inline for fast access
Definition CaloCell.h:295
double m_minRLateral
the minimal in the definition of the Lateral moment
SG::ReadCondHandleKey< CaloNoise > m_noiseCDOKey
Key of the CaloNoise Conditions data object.
std::vector< std::string > m_momentsNames
vector holding the input list of names of moments to calculate.
double m_etaInnerWheel
Transition from outer to inner wheel in EME2.
bool m_secondTime
Retrieve second moment of cell times and store as moment.
double m_minBadLArQuality
the minimal cell quality in the LAr for declaring a cell bad
SG::ReadHandleKey< CaloCellContainer > m_signalCellKey
bool m_calculateLArHVFraction
Set to true to calculate E and N of cells affected by LAr HV corrections.
bool m_absOpt
if set to true use abs E value of cells to calculate
virtual StatusCode execute(const EventContext &ctx, xAOD::CaloClusterContainer *theClusColl) const override final
Execute on an entire collection of clusters.
bool m_calculateIsolation
Set to true if cluster isolation is to be calculated.
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
bool m_twoGaussianNoise
if set to true use 2-gaussian noise description for TileCal
double m_maxAxisAngle
the maximal allowed deviation from the IP-to-ClusterCenter-axis.
double m_minLLongitudinal
the minimal in the definition of the Longitudinal moment
bool m_calculateSignificance
Set to true if significance moments are need.
CaloClusterMomentsMaker_DigiHSTruth(const std::string &type, const std::string &name, const IInterface *parent)
std::vector< xAOD::CaloCluster::MomentType > m_validMoments
set of moments which will be calculated.
std::string m_momentsNamesAOD
Not used anymore (with xAOD), but required when configured from COOL.
This class groups all DetDescr information related to a CaloCell.
CaloCell_ID::CaloSample getSampling() const
cell sampling
This class provides the client interface for accessing the detector description information common to...
static double fix(double phi)
static double diff(double phi1, double phi2)
simple phi1 - phi2 calculation, but result is fixed to respect range.
DataModel_detail::iterator< DataVector > iterator
Definition DataVector.h:865
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
This is a "hash" representation of an Identifier.
constexpr bool is_valid() const
double getMomentValue(MomentType type) const
Retrieve individual moment - no check for existance! Returns -999 on error.
const CaloClusterCellLink * getCellLinks() const
Get a pointer to the CaloClusterCellLink object (const version).
flt_t time() const
Access cluster time.
size_t size() const
size method (forwarded from CaloClusterCellLink obj)
CaloClusterCellLink::iterator cell_iterator
Iterator of the underlying CaloClusterCellLink (non-const version).
virtual double e() const
The total energy of the particle.
void insertMoment(MomentType type, double value)
const_cell_iterator cell_end() const
float eSample(const CaloSample sampling) const
virtual double phi() const
The azimuthal angle ( ) of the particle.
MomentType
Enums to identify different moments.
const_cell_iterator cell_begin() const
Iterator of the underlying CaloClusterCellLink (const version).
CaloSampling::CaloSample CaloSample
bool hasSampling(const CaloSample s) const
Checks if certain smapling contributes to cluster.
struct color C
void setMag(Amg::Vector3D &v, double mag)
scales the vector length without changing the angles
double angle(const Amg::Vector3D &v1, const Amg::Vector3D &v2)
calculates the opening angle between two vectors
Eigen::Matrix< double, 3, 1 > Vector3D
void nextDDE(Iter iter, Iter endIter)
Prefetch next CaloDDE.
void prefetchNext(Iter iter, Iter endIter)
Prefetch next object in sequence.
Definition prefetch.h:130
Definition dot.py:1
DataModel_detail::iterator< DVL > unique(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of unique for DataVector/List.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
CaloClusterContainer_v1 CaloClusterContainer
Define the latest version of the calorimeter cluster container.
Functions to prefetch blocks of memory.
double proxim(double b, double a)
Definition proxim.h:16
Tell the compiler to optimize assuming that FP may trap.
#define CXXUTILS_TRAPPING_FP
Definition trapping_fp.h:24