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{
144 declareInterface<CaloClusterCollectionProcessor> (this);
145}
146
147//###############################################################################
148
150{
151 xAOD::CaloCluster dummyCluster;
152
153 // loop list of requested moments
154 std::string::size_type nstr(0); int nmom(0);
155 for (const auto& mom : m_momentsNames) {
156 ATH_MSG_DEBUG("Moment " << mom << " requested");
157 // check if moment is known (enumerator available)
158 auto fmap(momentNameToEnumMap.find(mom));
159 if (fmap != momentNameToEnumMap.end()) {
160 // valid moment found
161 nstr = std::max(nstr, mom.length());
162 ++nmom;
163 if (fmap->second == SECOND_TIME_DigiHSTruth) {
164 // special flag for second moment of cell times - this moment is not
165 // calculated in this tool! Do not add to internal (!) valid moments
166 // list. Its value is available from xAOD::CaloCluster::secondTime()!
167 m_secondTime = true;
168
169 // Make sure the variable used for the moment is declared
170 // to the auxiliary variable registry. Otherwise, if we don't
171 // set the moment for the first event (perhaps because there
172 // are no clusters), then we can get warnings from AuxSelection.
173 (void)dummyCluster.getMomentValue (fmap->second);
174 } else if (fmap->second == EM_PROBABILITY_DigiHSTruth) {
176 << " not calculated in this tool - misconfiguration?");
177 } else {
178 // Make sure the variable used for the moment is declared
179 // to the auxiliary variable registry.
180 (void)dummyCluster.getMomentValue (fmap->second);
181
182 // all other valid moments
183 m_validMoments.push_back(fmap->second);
184 // flag some special requests
185 switch (fmap->second) {
186 case SIGNIFICANCE_DigiHSTruth:
187 case CELL_SIGNIFICANCE_DigiHSTruth:
189 break;
190 case ISOLATION_DigiHSTruth:
192 break;
193 case ENG_BAD_HV_CELLS_DigiHSTruth:
195 break;
196 default:
197 break;
198 } // set special processing flags
199 } // moment calculated with this tool
200 } else {
201 ATH_MSG_ERROR("Moment name " << mom << " not known; known moments are:");
202 char buffer[128];
203 std::string::size_type lstr(nstr);
204 // determine field size
205 for (const auto& fmom : momentNameToEnumMap) {
206 lstr = std::max(lstr, fmom.first.length());
207 }
208 // print available moments
209 for (const auto& fmom : momentNameToEnumMap) {
210 sprintf(buffer, "moment name: %-*.*s - enumerator: %i", (int)lstr,
211 (int)lstr, fmom.first.c_str(), (int)fmom.second);
212 ATH_MSG_ERROR(buffer);
213 }
214 auto fmom(momentNameToEnumMap.find("SECOND_TIME_DigiHSTruth"));
215 if (fmom != momentNameToEnumMap.end()){
216 sprintf(buffer, "moment name: %-*.*s - enumerator: %i", (int)nstr,
217 (int)nstr, fmom->first.c_str(), (int)fmom->second);
218 ATH_MSG_ERROR(buffer);
219 }
220 fmom = momentNameToEnumMap.find("NCELL_SAMPLING_DigiHSTruth");
221 if (fmom != momentNameToEnumMap.end()){
222 sprintf(buffer, "moment name: %-*.*s - enumerator: %i", (int)nstr,
223 (int)nstr, fmom->first.c_str(), (int)fmom->second);
224 ATH_MSG_ERROR(buffer);
225 }
226 return StatusCode::FAILURE;
227 } // found unknown moment name
228 } // loop configured moment names
229
230 // sort and remove duplicates
232 m_validMoments.erase(
234 m_validMoments.end());
235
236 // print configured moments
237 ATH_MSG_INFO("Construct and save " << nmom << " cluster moments: ");
238 char buffer[128];
239 for (auto menum : m_validMoments) {
240 sprintf(buffer, "moment name: %-*.*s - enumerator: %i", (int)nstr,
241 (int)nstr, momentEnumToNameMap.at(menum).c_str(), (int)menum);
242 ATH_MSG_INFO(buffer);
243 }
244 if (m_secondTime) {
245 auto fmom(momentNameToEnumMap.find("SECOND_TIME_DigiHSTruth"));
246 if (fmom != momentNameToEnumMap.end()){
247 sprintf(buffer, "moment name: %-*.*s - enumerator: %i (save only)",
248 (int)nstr, (int)nstr, fmom->first.c_str(), (int)fmom->second);
249 ATH_MSG_INFO(buffer);
250 }
251 }
252
253 // retrieve CaloCell ID server
254 CHECK(detStore()->retrieve(m_calo_id,"CaloCell_ID"));
255
256 // retrieve the calo depth tool
257 CHECK(m_caloDepthTool.retrieve());
258 ATH_CHECK(m_caloMgrKey.initialize());
259
260 // retrieve specific servers and tools for selected processes
262 if (m_calculateLArHVFraction) { ATH_CHECK(m_larHVFraction.retrieve()); } else { m_larHVFraction.disable(); }
263
264 ATH_CHECK(m_signalCellKey.initialize());
265
266 return StatusCode::SUCCESS;
267}
268
270{
271 return StatusCode::SUCCESS;
272}
273
274//#############################################################################
275
277
278
279struct cellinfo {
280 double x{};
281 double y{};
282 double z{};
283 double energy{};
284 double eta{};
285 double phi{};
286 double r{};
287 double lambda{};
288 double volume{};
290 unsigned int identifier{};
291};
292
293} // namespace CaloClusterMomentsMaker_DigiHSTruth_detail
294
295StatusCode
297 xAOD::CaloClusterContainer *theClusColl)
298 const
299{
300 ATH_MSG_DEBUG("Executing " << name());
301
303
304 // Maps cell IdentifierHash to cluster index in cluster collection.
305 // Only used when cluster isolation moment is calculated.
306 using clusterIdx_t = std::uint16_t;
307 typedef std::pair<clusterIdx_t, clusterIdx_t> clusterPair_t;
308 std::vector<clusterPair_t> clusterIdx;
309 const clusterIdx_t noCluster = std::numeric_limits<clusterIdx_t>::max();
310
311 const CaloNoise* noise=nullptr;
314 noise=*noiseHdl;
315 }
316
318 const CaloDetDescrManager* caloDDMgr = *caloMgrHandle;
319 // Counters for number of empty and non-empty neighbor cells per sampling
320 // layer Only used when cluster isolation moment is calculated.
321 int nbEmpty[CaloCell_ID::Unknown];
322 int nbNonEmpty[CaloCell_ID::Unknown];
323
324 // prepare stuff from entire collection in case isolation moment
325 // should be calculated
326
327 if ( m_calculateIsolation ) {
328
329 if (theClusColl->size() >= noCluster) {
330 msg(MSG::ERROR) << "Too many clusters" << endmsg;
331 return StatusCode::FAILURE;
332 }
333
334 // initialize with "empty" values
335 clusterIdx.resize(m_calo_id->calo_cell_hash_max(),
336 clusterPair_t(noCluster, noCluster));
337
338 int iClus = 0;
339 for (xAOD::CaloCluster* theCluster : *theClusColl) {
340 // loop over all cell members and fill cell vector for used cells
341 xAOD::CaloCluster::cell_iterator cellIter = theCluster->cell_begin();
342 xAOD::CaloCluster::cell_iterator cellIterEnd = theCluster->cell_end();
343 for(; cellIter != cellIterEnd; cellIter++ ){
344 CxxUtils::prefetchNext(cellIter, cellIterEnd);
345 const CaloCell* pCell = *cellIter;
346 const CaloDetDescrElement * caloDDE = pCell->caloDDE();
347
348 // Specific DigiHSTruth part
349 IdentifierHash hashid=caloDDE->calo_hash() ;
350 if(! hashid.is_valid() ) continue;
351 if(hashid >= (signalCells)->size()) continue;
352
353 pCell = (*signalCells).findCell(hashid);
354 if(!pCell) continue;
355 // End specific DigiHSTruth part
356
357 Identifier myId = pCell->ID();
358 IdentifierHash myHashId = m_calo_id->calo_cell_hash(myId);
359 if ( clusterIdx[(unsigned int)myHashId].first != noCluster) {
360 // check weight and assign to current cluster if weight is > 0.5
361 double weight = cellIter.weight();
362 if ( weight > 0.5 )
363 clusterIdx[(unsigned int)myHashId].first = iClus;
364 }
365 else {
366 clusterIdx[(unsigned int)myHashId].first = iClus;
367 }
368 }
369 ++iClus;
370 }
371 }
372
373 // Move allocation of temporary arrays outside the cluster loop.
374 // That way, we don't need to delete and reallocate them
375 // each time through the loop.
376
377 std::vector<CaloClusterMomentsMaker_DigiHSTruth_detail::cellinfo> cellinfo;
378 std::vector<double> maxSampE (CaloCell_ID::Unknown);
379 std::vector<double> myMoments(m_validMoments.size(),0);
380 std::vector<double> myNorms(m_validMoments.size(),0);
381 std::vector<std::tuple<int,int> > nCellsSamp; nCellsSamp.reserve(CaloCell_ID::Unknown);
382 std::vector<IdentifierHash> theNeighbors;
383 // loop over individual clusters
384 xAOD::CaloClusterContainer::iterator clusIter = theClusColl->begin();
385 xAOD::CaloClusterContainer::iterator clusIterEnd = theClusColl->end();
386 int iClus = 0;
387 for( ;clusIter!=clusIterEnd;++clusIter,++iClus) {
388 xAOD::CaloCluster * theCluster = *clusIter;
389
390 double w(0),xc(0),yc(0),zc(0),mx(0),my(0),mz(0),mass(0);
391 double eBad(0),ebad_dac(0),ePos(0),eBadLArQ(0),sumSig2(0),maxAbsSig(0);
392 double eLAr2(0),eLAr2Q(0);
393 double eTile2(0),eTile2Q(0);
394 double eBadLArHV(0);
395 int nbad(0),nbad_dac(0),nBadLArHV(0);
396 unsigned int i,nSigSampl(0);
397 unsigned int theNumOfCells = theCluster->size();
398
399 double theClusterEnergy = 0;
400 double theClusterAbsEnergy = 0;
401 double theClusterEta = 0;
402 double theClusterPhi = 0;
403 double theNewSecondTime = 0;
404 double timeNorm = 0;
405
406 // these two are needed for the LATERAL moment
407 int iCellMax(-1);
408 int iCellScndMax(-1);
409
410 cellinfo.clear();
411 if (cellinfo.capacity() == 0)
412 cellinfo.reserve (theNumOfCells*2);
413
414 double phi0 = theCluster->phi();
415
416 for(i=0;i<(unsigned int)CaloCell_ID::Unknown;i++)
417 maxSampE[i] = 0;
418
419 if ( !m_momentsNames.empty() ) {
420 std::fill (myMoments.begin(), myMoments.end(), 0);
421 std::fill (myNorms.begin(), myNorms.end(), 0);
422 if ( m_calculateIsolation ) {
423 std::fill_n(nbNonEmpty, CaloCell_ID::Unknown, 0);
424 std::fill_n(nbEmpty, CaloCell_ID::Unknown, 0);
425 }
426
427 // loop over all cell members and calculate the center of mass
428 xAOD::CaloCluster::cell_iterator cellIter = theCluster->cell_begin();
429 xAOD::CaloCluster::cell_iterator cellIterEnd = theCluster->cell_end();
430 for(; cellIter != cellIterEnd; cellIter++ ){
431 CaloPrefetch::nextDDE(cellIter, cellIterEnd);
432
433 const CaloCell* pCell = (*cellIter);
434 const CaloDetDescrElement* caloDDE = pCell->caloDDE();
435
436 // specific DigiHSTruth part
437 IdentifierHash hashid=caloDDE->calo_hash() ;
438 if(! hashid.is_valid() ) continue;
439 if(hashid >= (signalCells)->size()) continue;
440 pCell = (*signalCells).findCell(hashid);
441 // end specific DigiHSTruth part
442
443 Identifier myId = pCell->ID();
444 const CaloDetDescrElement* myCDDE = pCell->caloDDE();
445 if (!myCDDE){
446 ATH_MSG_ERROR("Pointer myCDDE is null.");
447 return StatusCode::FAILURE;
448 }
449 double ene = pCell->e();
450 if(m_absOpt) ene = std::abs(ene);
451 double weight = cellIter.weight();
452
453 double cellPhi = myCDDE->phi();
454 double thePhi = proxim (cellPhi, phi0);
455
456 theClusterEnergy += weight * ene;
457 theClusterAbsEnergy += weight*std::abs(ene);
458 theClusterEta += weight*std::abs(ene)*pCell->eta();
459 theClusterPhi += weight*std::abs(ene)* thePhi;
460
461 if ( pCell->badcell() ) {
462 eBad += ene*weight;
463 nbad++;
464 if(ene!=0){
465 ebad_dac+=ene*weight;
466 nbad_dac++;
467 }
468 }
469 else {
470 if ( !(myCDDE->is_tile())
471 && ((pCell->provenance() & 0x2000) == 0x2000)
472 && !((pCell->provenance() & 0x0800) == 0x0800)) {
473 if ( pCell->quality() > m_minBadLArQuality ) {
474 eBadLArQ += ene*weight;
475 }
476 eLAr2 += ene*weight*ene*weight;
477 eLAr2Q += ene*weight*ene*weight*pCell->quality();
478 }
479 if ( myCDDE->is_tile() ) {
480 uint16_t tq = pCell->quality();
481 uint8_t tq1 = (0xFF00&tq)>>8; // quality in channel 1
482 uint8_t tq2 = (0xFF&tq); // quality in channel 2
483 // reject cells with either 0xFF00 or 0xFF
484 if ( ((tq1&0xFF) != 0xFF) && ((tq2&0xFF) != 0xFF) ) {
485 eTile2 += ene*weight*ene*weight;
486 // take the worse of both qualities (one might be 0 in
487 // 1-channel cases)
488 eTile2Q += ene*weight*ene*weight*(tq1>tq2?tq1:tq2);
489 }
490 }
491 }
492 if ( ene > 0 ) {
493 ePos += ene*weight;
494 }
495
497 // Avoid a spurious FPE from clang.
499
500 const float sigma = m_twoGaussianNoise ?\
501 noise->getEffectiveSigma(pCell->ID(),pCell->gain(),pCell->energy()) : \
502 noise->getNoise(pCell->ID(),pCell->gain());
503
504 sumSig2 += sigma*sigma;
505 // use geometry weighted energy of cell for leading cell significance
506 double Sig = (sigma>0?ene*weight/sigma:0);
507 if (m_useGPUCriteria) {
508 unsigned int thisSampl = myCDDE->getSampling();
509 if ( ( std::abs(Sig) > std::abs(maxAbsSig) ) ||
510 ( std::abs(Sig) == std::abs(maxAbsSig) && thisSampl > nSigSampl ) ||
511 ( std::abs(Sig) == std::abs(maxAbsSig) && thisSampl == nSigSampl && Sig > maxAbsSig ) ) {
512 maxAbsSig = Sig;
513 nSigSampl = thisSampl;
514 }
515
516 }
517 else {
518 if ( std::abs(Sig) > std::abs(maxAbsSig) ) {
519 maxAbsSig = Sig;
520 nSigSampl = myCDDE->getSampling();
521 }
522 }
523 }
524 if ( m_calculateIsolation ) {
525 // get all 2D Neighbours if the cell is not inside another cluster with
526 // larger weight
527
528 IdentifierHash myHashId = m_calo_id->calo_cell_hash(myId);
529 if ( clusterIdx[myHashId].first == iClus ) {
530 theNeighbors.clear();
531 m_calo_id->get_neighbours(myHashId, LArNeighbours::all2D, theNeighbors);
532 for (const auto& nhash: theNeighbors) {
533 clusterPair_t& idx = clusterIdx[nhash];
534
535 // only need to look at each cell once per cluster
536 if ( idx.second == iClus ) continue;
537 idx.second = iClus;
538
539 if ( idx.first == noCluster ) {
540 ++ nbEmpty[m_calo_id->calo_sample(nhash)];
541 } else if ( idx.first != iClus ) {
542 ++ nbNonEmpty[m_calo_id->calo_sample(nhash)];
543 }
544
545 }
546 }
547 }
548 if(m_secondTime){
550 if (sam != CaloSampling::PreSamplerB &&
551 sam != CaloSampling::PreSamplerE){
552 unsigned int pmask = myCDDE->is_tile() ? 0x8080 : 0x2000;
553 // Is time defined?
554 if ( pCell->provenance() & pmask ) {
555 // keep the sign of weight for the time norm in case a cell is removed
556 double theTimeNorm = std::abs(weight) * weight * ene * ene;
557 theNewSecondTime += theTimeNorm * pCell->time() * pCell->time();
558 timeNorm += theTimeNorm;
559 }
560 }
561 }
562
563
564 if ( ene > 0. && weight > 0) {
565 // get all geometric information needed ...
567 .x = myCDDE->x(),
568 .y = myCDDE->y(),
569 .z = myCDDE->z(),
570 .energy = ene*weight,
571 .eta = myCDDE->eta(),
572 .phi = myCDDE->phi(),
573 .r = 0, // These two are filled in later.
574 .lambda = 0,
575 .volume = myCDDE->volume(),
576 .sample = myCDDE->getSampling(),
577 .identifier = cellIter.index()
578 //Using the index instead of the hash ID as disambiguation criterion
579 //is relevant for the GPU now that we no longer assume the two are the same,
580 //and this gives us better performance.
581 });
582
584
585 if ( ci.energy > maxSampE[(unsigned int)ci.sample] )
586 maxSampE[(unsigned int)ci.sample] = ci.energy;
587
588 if (m_useGPUCriteria) {
589 if (iCellMax < 0 ||
590 ci.energy > cellinfo[iCellMax].energy ||
591 (ci.energy == cellinfo[iCellMax].energy && ci.identifier > cellinfo[iCellMax].identifier) ) {
592 iCellScndMax = iCellMax;
593 iCellMax = cellinfo.size()-1;
594 }
595 else if (iCellScndMax < 0 ||
596 ci.energy > cellinfo[iCellScndMax].energy ||
597 (ci.energy == cellinfo[iCellScndMax].energy && ci.identifier > cellinfo[iCellScndMax].identifier) )
598 {
599 iCellScndMax = cellinfo.size()-1;
600 }
601 }
602 else {
603 if (iCellMax < 0 || ci.energy > cellinfo[iCellMax].energy ) {
604 iCellScndMax = iCellMax;
605 iCellMax = cellinfo.size()-1;
606 }
607 else if (iCellScndMax < 0 ||
608 ci.energy > cellinfo[iCellScndMax].energy )
609 {
610 iCellScndMax = cellinfo.size()-1;
611 }
612 }
613
614 xc += ci.energy*ci.x;
615 yc += ci.energy*ci.y;
616 zc += ci.energy*ci.z;
617
618 double dir = ci.x*ci.x+ci.y*ci.y+ci.z*ci.z;
619
620 if ( dir > 0) {
621 dir = sqrt(dir);
622 dir = 1./dir;
623 }
624 mx += ci.energy*ci.x*dir;
625 my += ci.energy*ci.y*dir;
626 mz += ci.energy*ci.z*dir;
627
628 w += ci.energy;
629 } // cell has E>0 and weight != 0
630 } //end of loop over all cells
632 const auto hvFrac=m_larHVFraction->getLArHVFrac(theCluster->getCellLinks(),ctx);
633 eBadLArHV= hvFrac.first;
634 nBadLArHV=hvFrac.second;
635 }
636
637 if ( w > 0 || (m_useGPUCriteria && w >= 0) ) {
638 mass = w*w - mx*mx - my*my - mz*mz;
639 if ( mass > 0) {
640 mass = sqrt(mass);
641 }
642 else {
643 // make mass negative if m^2 was negative
644 mass = -sqrt(-mass);
645 }
646
647 if (w == 0) {
648 w = 1.0;
649 }
650
651 xc/=w;
652 yc/=w;
653 zc/=w;
654 Amg::Vector3D showerCenter(xc,yc,zc);
655 w=0;
656
657
658 //log << MSG::WARNING << "Found bad cells " << xbad_dac << " " << ybad_dac << " " << zbad_dac << " " << ebad_dac << endmsg;
659 //log << MSG::WARNING << "Found Cluster " << xbad_dac << " " << ybad_dac << " " << zbad_dac << " " << endmsg;
660 // shower axis is just the vector pointing from the IP to the shower center
661 // in case there are less than 3 cells in the cluster
662
663 Amg::Vector3D showerAxis(xc,yc,zc);
664 showerAxis = showerAxis.normalized();
665
666 // otherwise the principal direction with the largest absolute
667 // eigenvalue will be used unless it's angle w.r.t. the vector pointing
668 // from the IP to the shower center is larger than allowed by the
669 // property m_maxAxisAngle
670
671 double angle(0),deltaPhi(0),deltaTheta(0);
672 if ( cellinfo.size() > 2 ) {
673 Eigen::Matrix3d C=Eigen::Matrix3d::Zero();
675 const double e2 = ci.energy * ci.energy;
676
677 C(0,0) += e2*(ci.x-xc)*(ci.x-xc);
678 C(1,0) += e2*(ci.x-xc)*(ci.y-yc);
679 C(2,0) += e2*(ci.x-xc)*(ci.z-zc);
680
681 C(1,1) += e2*(ci.y-yc)*(ci.y-yc);
682 C(2,1) += e2*(ci.y-yc)*(ci.z-zc);
683
684 C(2,2) += e2*(ci.z-zc)*(ci.z-zc);
685 w += e2;
686 }
687 C/=(w != 0 ? w : 1.0);
688
689 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigensolver(C);
690 if (eigensolver.info() != Eigen::Success) {
691 msg(MSG::WARNING) << "Failed to compute Eigenvalues -> Can't determine shower axis" << endmsg;
692 }
693 else {
694 // don't use the principal axes if at least one of the 3
695 // diagonal elements is 0
696
697 const Eigen::Vector3d& S=eigensolver.eigenvalues();
698 const Eigen::Matrix3d& U=eigensolver.eigenvectors();
699
700 const double epsilon = 1.E-6;
701
702 if ( std::abs(S[0]) >= epsilon && std::abs(S[1]) >= epsilon && std::abs(S[2]) >= epsilon ) {
703
704 Amg::Vector3D prAxis(showerAxis);
705 int iEigen = -1;
706
707 for (i=0;i<3;i++) {
708 Amg::Vector3D tmpAxis=U.col(i);
709
710 // calculate the angle
711 double tmpAngle=Amg::angle(tmpAxis,showerAxis);
712
713 if ( tmpAngle > 90*deg ) {
714 tmpAngle = 180*deg - tmpAngle;
715 tmpAxis = -tmpAxis;
716 }
717
718 if ( iEigen == -1 || tmpAngle < angle ) {
719 iEigen = i;
720 angle = tmpAngle;
721 prAxis = tmpAxis;
722 }
723 }//end for loop
724
725 // calculate theta and phi angle differences
726
727 deltaPhi = CaloPhiRange::diff(showerAxis.phi(),prAxis.phi());
728
729 deltaTheta = showerAxis.theta() - prAxis.theta();
730
731 // check the angle
732
733 if ( angle < m_maxAxisAngle ) {
734 showerAxis = prAxis;
735 }
736 else
737 ATH_MSG_DEBUG("principal Direction (" << prAxis[Amg::x] << ", "
738 << prAxis[Amg::y] << ", " << prAxis[Amg::z] << ") deviates more than "
739 << m_maxAxisAngle*(1./deg)
740 << " deg from IP-to-ClusterCenter-axis (" << showerAxis[Amg::x] << ", "
741 << showerAxis[Amg::y] << ", " << showerAxis[Amg::z] << ")");
742 }//end if std::abs(S)<epsilon
743 else {
744 ATH_MSG_DEBUG("Eigenvalues close to 0, do not use principal axis");
745 }
746 }//end got eigenvalues
747 } //end if cellinfo.size()>2
748
749 ATH_MSG_DEBUG("Shower Axis = (" << showerAxis[Amg::x] << ", "
750 << showerAxis[Amg::y] << ", " << showerAxis[Amg::z] << ")");
751
752
753 // calculate radial distance from and the longitudinal distance
754 // along the shower axis for each cell. The cluster center is
755 // at r=0 and lambda=0
756
757 for (auto& ci : cellinfo) {
758 const Amg::Vector3D currentCell(ci.x,ci.y,ci.z);
759 // calculate distance from shower axis r
760 ci.r = ((currentCell-showerCenter).cross(showerAxis)).mag();
761 // calculate distance from shower center along shower axis
762 ci.lambda = (currentCell-showerCenter).dot(showerAxis);
763 }
764
765 // loop over all positive energy cells and calculate all desired moments
766
767 // define common norm for all simple moments
768 double commonNorm = 0;
769 double phi0 = cellinfo.size() > 0 ? cellinfo[0].phi : 0;
770
771 for(unsigned i=0;i<cellinfo.size();i++) {
773 // loop over all valid moments
774 commonNorm += ci.energy;
775 for(size_t iMoment = 0, size = m_validMoments.size();
776 iMoment != size;
777 ++ iMoment)
778 {
779 // now calculate the actual moments
780 switch (m_validMoments[iMoment]) {
781 case FIRST_ETA_DigiHSTruth:
782 myMoments[iMoment] += ci.energy*ci.eta;
783 break;
784 case FIRST_PHI_DigiHSTruth:
785 // first cell decides the sign in order to avoid
786 // overlap problem at phi = -pi == +pi
787 // need to be normalized to the range [-pi,+pi] in the end
788 myMoments[iMoment] += ci.energy * proxim (ci.phi, phi0);
789 break;
790 case SECOND_R_DigiHSTruth:
791 myMoments[iMoment] += ci.energy*ci.r*ci.r;
792 break;
793 case SECOND_LAMBDA_DigiHSTruth:
794 myMoments[iMoment] += ci.energy*ci.lambda*ci.lambda;
795 break;
796 case LATERAL_DigiHSTruth:
797 if ( (int)i != iCellMax && (int)i != iCellScndMax ) {
798 myMoments[iMoment] += ci.energy*ci.r*ci.r;
799 myNorms[iMoment] += ci.energy*ci.r*ci.r;
800 }
801 else {
802 double rm = ci.r;
803 if ( rm < m_minRLateral )
804 rm = m_minRLateral;
805 myNorms[iMoment] += rm*rm*ci.energy;
806 }
807 break;
808 case LONGITUDINAL_DigiHSTruth:
809 if ( (int)i != iCellMax && (int)i != iCellScndMax ) {
810 myMoments[iMoment] += ci.energy*ci.lambda*ci.lambda;
811 myNorms[iMoment] += ci.energy*ci.lambda*ci.lambda;
812 }
813 else {
814 double lm = ci.lambda;
815 if ( lm < m_minLLongitudinal )
817 myNorms[iMoment] += lm*lm*ci.energy;
818 }
819 break;
820 case FIRST_ENG_DENS_DigiHSTruth:
821 if ( ci.volume > 0 ) {
822 myMoments[iMoment] += ci.energy*ci.energy/ci.volume;
823 myNorms[iMoment] += ci.energy;
824 }
825 break;
826 case SECOND_ENG_DENS_DigiHSTruth:
827 if ( ci.volume > 0 ) {
828 myMoments[iMoment] += ci.energy*std::pow(ci.energy/ci.volume,2);
829 myNorms[iMoment] += ci.energy;
830 }
831 break;
832 case ENG_FRAC_EM_DigiHSTruth:
833 if ( ci.sample == CaloCell_ID::EMB1
834 || ci.sample == CaloCell_ID::EMB2
835 || ci.sample == CaloCell_ID::EMB3
836 || ci.sample == CaloCell_ID::EME1
837 || ci.sample == CaloCell_ID::EME2
838 || ci.sample == CaloCell_ID::EME3
839 || ci.sample == CaloCell_ID::FCAL0 )
840 myMoments[iMoment] += ci.energy;
841 break;
842 case ENG_FRAC_MAX_DigiHSTruth:
843 if ( (int)i == iCellMax )
844 myMoments[iMoment] = ci.energy;
845 break;
846 case PTD_DigiHSTruth:
847 // do not convert to pT since clusters are small and
848 // there is virtually no difference and cosh just costs
849 // time ...
850 myMoments[iMoment] += ci.energy*ci.energy;
851 myNorms[iMoment] += ci.energy;
852 break;
853 default:
854 // nothing to be done for other moments
855 break;
856 }
857 }
858 } //end of loop over cell
859
860 // assign moments which don't need the loop over the cells
861 for (size_t iMoment = 0, size = m_validMoments.size();
862 iMoment != size;
863 ++ iMoment)
864 {
865 // now calculate the actual moments
866 switch (m_validMoments[iMoment]) {
867 case FIRST_ETA_DigiHSTruth:
868 case FIRST_PHI_DigiHSTruth:
869 case SECOND_R_DigiHSTruth:
870 case SECOND_LAMBDA_DigiHSTruth:
871 case ENG_FRAC_EM_DigiHSTruth:
872 case ENG_FRAC_MAX_DigiHSTruth:
873 myNorms[iMoment] = commonNorm;
874 break;
875 case DELTA_PHI_DigiHSTruth:
876 myMoments[iMoment] = deltaPhi;
877 break;
878 case DELTA_THETA_DigiHSTruth:
879 myMoments[iMoment] = deltaTheta;
880 break;
881 case DELTA_ALPHA_DigiHSTruth:
882 myMoments[iMoment] = angle;
883 break;
884 case CENTER_X_DigiHSTruth:
885 myMoments[iMoment] = showerCenter.x();
886 break;
887 case CENTER_Y_DigiHSTruth:
888 myMoments[iMoment] = showerCenter.y();
889 break;
890 case CENTER_Z_DigiHSTruth:
891 myMoments[iMoment] = showerCenter.z();
892 break;
893 case CENTER_MAG_DigiHSTruth:
894 myMoments[iMoment] = showerCenter.mag();
895 break;
896 case CENTER_LAMBDA_DigiHSTruth:
897 // calculate the longitudinal distance along the shower axis
898 // of the shower center from the calorimeter start
899
900 // first need calo boundary at given eta phi try LAREM barrel
901 // first, then LAREM endcap OW, then LAREM endcap IW, then
902 // FCal
903 {
904 double r_calo(0),z_calo(0),lambda_c(0);
905 r_calo = m_caloDepthTool->get_entrance_radius(CaloCell_ID::EMB1,
906 showerCenter.eta(),
907 showerCenter.phi(),
908 caloDDMgr);
909 if ( r_calo == 0 ) {
910 z_calo = m_caloDepthTool->get_entrance_z(CaloCell_ID::EME1,
911 showerCenter.eta(),
912 showerCenter.phi(),
913 caloDDMgr);
914 if ( z_calo == 0 )
915 z_calo = m_caloDepthTool->get_entrance_z(CaloCell_ID::EME2,
916 showerCenter.eta(),
917 showerCenter.phi(),
918 caloDDMgr);
919 if ( z_calo == 0 )
920 z_calo = m_caloDepthTool->get_entrance_z(CaloCell_ID::FCAL0,
921 showerCenter.eta(),
922 showerCenter.phi(),
923 caloDDMgr);
924 if ( z_calo == 0 ) // for H6 TB without EMEC outer wheel
925 z_calo = m_caloDepthTool->get_entrance_z(CaloCell_ID::HEC0,
926 showerCenter.eta(),
927 showerCenter.phi(),
928 caloDDMgr);
929 if ( z_calo != 0 && showerAxis.z() != 0 ) {
930 lambda_c = std::abs((z_calo-showerCenter.z())/showerAxis.z());
931 }
932 }
933 else {
934 double r_s2 = showerAxis.x()*showerAxis.x()
935 +showerAxis.y()*showerAxis.y();
936 double r_cs = showerAxis.x()*showerCenter.x()
937 +showerAxis.y()*showerCenter.y();
938 double r_cr = showerCenter.x()*showerCenter.x()
939 +showerCenter.y()*showerCenter.y()-r_calo*r_calo;
940 if ( r_s2 > 0 ) {
941 double det = r_cs*r_cs/(r_s2*r_s2) - r_cr/r_s2;
942 if ( det > 0 ) {
943 det = sqrt(det);
944 double l1(-r_cs/r_s2);
945 double l2(l1);
946 l1 += det;
947 l2 -= det;
948 if ( std::abs(l1) < std::abs(l2) )
949 lambda_c = std::abs(l1);
950 else
951 lambda_c = std::abs(l2);
952 }
953 }
954 }
955 myMoments[iMoment] = lambda_c;
956 }
957 break;
958 case ENG_FRAC_CORE_DigiHSTruth:
959 for(i=0;i<(int)CaloCell_ID::Unknown;i++)
960 myMoments[iMoment] += maxSampE[i];
961 myNorms[iMoment] = commonNorm;
962 break;
963 case ISOLATION_DigiHSTruth:
964 {
965 // loop over empty and filled perimeter cells and
966 // get a weighted ratio by means of energy fraction per layer
967 for(unsigned int i=0; i != CaloSampling::Unknown; ++ i) {
969 if (theCluster->hasSampling(s)) {
970 const double eSample = theCluster->eSample(s);
971 if (eSample > 0) {
972 int nAll = nbEmpty[i]+nbNonEmpty[i];
973 if (nAll > 0) {
974 myMoments[iMoment] += (eSample*nbEmpty[i])/nAll;
975 myNorms[iMoment] += eSample;
976 }
977 }//end of eSample>0
978 }//end has sampling
979 }//end loop over samplings
980 }
981 break;
982 case ENG_BAD_CELLS_DigiHSTruth:
983 myMoments[iMoment] = eBad;
984 break;
985 case N_BAD_CELLS_DigiHSTruth:
986 myMoments[iMoment] = nbad;
987 break;
988 case N_BAD_CELLS_CORR_DigiHSTruth:
989 myMoments[iMoment] = nbad_dac;
990 break;
991 case BAD_CELLS_CORR_E_DigiHSTruth:
992 myMoments[iMoment] = ebad_dac;
993 break;
994 case BADLARQ_FRAC_DigiHSTruth:
995 myMoments[iMoment] = eBadLArQ/(theCluster->e()!=0.?theCluster->e():1.);
996 break;
997 case ENG_POS_DigiHSTruth:
998 myMoments[iMoment] = ePos;
999 break;
1000 case SIGNIFICANCE_DigiHSTruth:
1001 myMoments[iMoment] = (sumSig2>0?theCluster->e()/sqrt(sumSig2):0.);
1002 break;
1003 case CELL_SIGNIFICANCE_DigiHSTruth:
1004 myMoments[iMoment] = maxAbsSig;
1005 break;
1006 case CELL_SIG_SAMPLING_DigiHSTruth:
1007 myMoments[iMoment] = nSigSampl;
1008 break;
1009 case AVG_LAR_Q_DigiHSTruth:
1010 myMoments[iMoment] = eLAr2Q/(eLAr2>0?eLAr2:1);
1011 break;
1012 case AVG_TILE_Q_DigiHSTruth:
1013 myMoments[iMoment] = eTile2Q/(eTile2>0?eTile2:1);
1014 break;
1015 case ENG_BAD_HV_CELLS_DigiHSTruth:
1016 myMoments[iMoment] = eBadLArHV;
1017 break;
1018 case N_BAD_HV_CELLS_DigiHSTruth:
1019 myMoments[iMoment] = nBadLArHV;
1020 break;
1021 case PTD_DigiHSTruth:
1022 myMoments[iMoment] = sqrt(myMoments[iMoment]);
1023 break;
1024 case MASS_DigiHSTruth:
1025 myMoments[iMoment] = mass;
1026 break;
1027 case ENERGY_DigiHSTruth:
1028 myMoments[iMoment] = theClusterEnergy;
1029 break;
1030 case ETA_DigiHSTruth:
1031 if(theClusterAbsEnergy > 0)
1032 myMoments[iMoment] = theClusterEta / theClusterAbsEnergy;
1033 else{
1034 myMoments[iMoment] = 0;
1035 }
1036 break;
1037 case PHI_DigiHSTruth:
1038 if(theClusterAbsEnergy > 0)
1039 myMoments[iMoment] = CaloPhiRange::fix(theClusterPhi / theClusterAbsEnergy);
1040 else{
1041 myMoments[iMoment] = 0;
1042 }
1043 break;
1044 default:
1045 // nothing to be done for other moments
1046 break;
1047 }
1048 }
1049 }
1050
1051 // normalize moments and copy to Cluster Moment Store
1052 size_t size= m_validMoments.size();
1053 for (size_t iMoment = 0; iMoment != size; ++iMoment) {
1055 if ( myNorms[iMoment] != 0 )
1056 myMoments[iMoment] /= myNorms[iMoment];
1057 if ( moment == FIRST_PHI_DigiHSTruth )
1058 myMoments[iMoment] = CaloPhiRange::fix(myMoments[iMoment]);
1059 theCluster->insertMoment(moment,myMoments[iMoment]);
1060 } // loop on moments for cluster
1061 } // check on requested moments
1062 // check on second moment of time if requested
1063 if ( m_secondTime ) {
1064 double secondTime(0.0);
1065 if (timeNorm > 0){
1066 secondTime = theNewSecondTime/timeNorm-theCluster->time()*theCluster->time();
1067 }
1069 }
1070
1071 } // loop on clusters
1072
1073 return StatusCode::SUCCESS;
1074}
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:
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
SG::ReadCondHandleKey< CaloNoise > m_noiseCDOKey
Key of the CaloNoise Conditions data object.
Gaudi::Property< bool > m_absOpt
if set to true use abs E value of cells to calculate
bool m_secondTime
Retrieve second moment of cell times and store as moment.
SG::ReadHandleKey< CaloCellContainer > m_signalCellKey
bool m_calculateLArHVFraction
Set to true to calculate E and N of cells affected by LAr HV corrections.
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.
Gaudi::Property< double > m_minLLongitudinal
the minimal in the definition of the Longitudinal moment
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
Gaudi::Property< double > m_minRLateral
the minimal in the definition of the Lateral moment
Gaudi::Property< bool > m_twoGaussianNoise
if set to true use 2-gaussian noise description for TileCal
Gaudi::Property< std::vector< std::string > > m_momentsNames
vector holding the input list of names of moments to calculate.
Gaudi::Property< double > m_maxAxisAngle
the maximal allowed deviation from the IP-to-ClusterCenter-axis.
Gaudi::Property< double > m_minBadLArQuality
the minimal cell quality in the LAr for declaring a cell bad
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.
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
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