ATLAS Offline Software
Loading...
Searching...
No Matches
CaloTopoTowerFromClusterMaker.cxx
Go to the documentation of this file.
1/* Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration */
2#include "GaudiKernel/MsgStream.h"
3#include "GaudiKernel/SystemOfUnits.h"
4
6
9
11
14
15#include "CaloGeoHelpers/CaloSampling.h"
18
19#include "CaloProtoCluster.h"
20
21#include "CaloDetDescr/CaloDetDescrElement.h"
23
24#include <algorithm>
25
26#include <cstdio>
27#include <cstdarg>
28#include <string>
29#include <cmath>
30#include <memory>
31#include <vector>
32#include <atomic>
33#include <tuple>
34
35namespace {
36 MsgStream& operator<<(MsgStream& mstr,const SG::ReadHandleKey<CaloCellContainer>& ckey) { mstr << ckey.key(); return mstr; }
37 MsgStream& operator<<(MsgStream& mstr,const SG::ReadHandleKey<xAOD::CaloClusterContainer>& ckey) { mstr << ckey.key(); return mstr; }
38}
39
41
43// CaloTopoTowerFromClusterMaker //
45
46const double CaloTopoTowerFromClusterMaker::m_energyThresholdDef = -100000000.; // in MeV
49
51 const std::string& name,
52 const IInterface* pParent)
53 : AthAlgTool(type,name,pParent)
54 , m_clusterContainerKey("CaloTopoClusters")
55 , m_cellContainerKey("AllCalo")
58 // , m_numberOfCells(0)
59 // , m_maxCellHash(0)
61 // , m_numberOfTowers(0)
62{
63 declareInterface<CaloTowerCollectionProcessor>(this);
64 declareProperty("CaloCellContainerKey", m_cellContainerKey, "SG Key for CaloCellContainer (input)");
65 declareProperty("BuildTopoTowers", m_useCellsFromClusters, "Turn on/off topo-tower formation");
66 declareProperty("CaloTopoClusterContainerKey", m_clusterContainerKey, "SG Key for CaloClusterContainer (input)");
67 declareProperty("OrderClusterByPt", m_orderByPt, "Turn on/off pT-ordering of CaloClusterContainer (output)");
68 declareProperty("ApplyCellEnergyThreshold", m_applyCellEnergyThreshold, "Turn on/off cell energy thresholds");
69 declareProperty("CellEnergyThreshold", m_energyThreshold, "Energy threshold for cells filled in clusters");
70 declareProperty("PrepareLCW", m_prepareLCW, "Prepare data structure to apply LCW");
71 declareProperty("ExcludedSamplings", m_excludedSamplingsName, "Excluded samplings by name");
72 declareProperty("DoCellIndexCheck", m_doCellIndexCheck, "Check cell hash indices for consistency");
73 declareProperty("BuildCombinedTopoSignal", m_buildCombinedSignal, "Build topo-clusters and topo-towers");
74 declareProperty("TopoClusterRange", m_clusterRange, "Rapidity range for using topo-clusters in combined signal mode");
75 declareProperty("RemoveSamplingData", m_removeSamplingData, "Remove the associated sampling data");
76}
77
79{
80 //--------------------//
81 // Set up handle keys //
82 //--------------------//
83
84 ATH_CHECK(m_cellContainerKey.initialize());
85
86 //---------------------//
87 // Check configuration //
88 //---------------------//
89
90 ATH_CHECK(m_towerGeoKey.initialize());
91 ATH_CHECK(m_caloMgrKey.initialize());
92
93 // tower builder configurations
95 // topo-tower
96 ATH_MSG_INFO("Configure for building topo-towers (filtered mode):");
97 // energy threshold not (yet) implemented for topo-towers
99 ATH_MSG_WARNING("[ignore] cannot apply energy thresholds to topo-towers!");
101 }
102 ATH_CHECK(m_clusterContainerKey.initialize());
103 // // check on request for LCW
104 // if ( m_prepareLCW ) {
105 // ATH_CHECK(m_cellClusterWeightKey.initialize());
106 // ATH_MSG_INFO("[accept] prepare for LCW calibration - initialize CaloCellClusterWeights key object <" << m_cellClusterWeightKey << ">");
107 // } else {
108 // ATH_MSG_INFO("[accept] use EM scale");
109 // }
110 } else {
111 // inclusive/exclusive towers
112 ATH_MSG_INFO("Configure for building cell towers:");
114 ATH_MSG_INFO("[accept] configure exclusive towers: use cell energy threshold");
116 ATH_MSG_ERROR("######## [reject] invalid cell energy threshold " << m_energyThreshold/Athena::Units::GeV
117 << " GeV is smaller than default (no-op) " << m_energyThresholdDef/Athena::Units::GeV << " GeV - fatal");
118 return StatusCode::FAILURE;
119 }
120 ATH_MSG_INFO("######## [accept] energy threshold for cells to contribute to towers is " << m_energyThreshold/Athena::Units::GeV << " GeV");
121 } else {
122 ATH_MSG_INFO("[accept] configure inclusive towers");
123 } // end inclusive/exclusive tower configuration
124 } // end tower builder configuration
125
126 // local data (constant parameters)
127 //m_numberOfCells = m_towerGeometrySvc->totalNumberCells();
128 //m_maxCellHash = m_towerGeometrySvc->maxCellHash();
129 //m_numberOfTowers = m_towerGeometrySvc->towerBins();
130 // ATH_MSG_INFO("Additional tool parameters:");
131 // if ( m_numberOfCells > 0 ) {
132 // ATH_MSG_INFO("[accept] maximum cell hash index is " << m_maxCellHash);
133 // ATH_MSG_INFO("[accept] maximum number of cells is " << m_numberOfCells);
134 // } else {
135 // ATH_MSG_ERROR("[reject] invalid maximum cell hash index/total number of cells " << m_maxCellHash << "/" << m_numberOfCells << " - fatal");
136 // return StatusCode::FAILURE;
137 // }
138 // if ( m_numberOfTowers > 0 ) {
139 // ATH_MSG_INFO("[accept] maximum number of towers is " << m_numberOfTowers);
140 // } else {
141 // ATH_MSG_ERROR("[reject] invalid maximum number of towers " << m_numberOfTowers << " - fatal");
142 // return StatusCode::FAILURE;
143 // }
144
145 if ( m_excludedSamplingsName.empty() ) {
146 m_excludedSamplings.clear();
148 ATH_MSG_INFO("Cells from all samplings used for topo-cluster included");
149 } else {
150 size_t nex(std::min(m_excludedSamplingsName.size(), m_excludedSamplingsPattern.size()));
152 ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("Configuration problem: number of excluded sampling names %zu exceeds expected maximum %zu - ignore last %zu name(s)",
154 }
155 m_excludedSamplings.resize(nex);
157 for ( size_t i(0); i<nex; ++i ) {
160 ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("CaloSampling \042%10.10s\042 has id %2zu (name in lookup table \042%10.10s\042)",
162 }
163 }
164
165 ATH_MSG_INFO("Other properties:");
166 std::map<bool,std::string> blu { { true, "true" }, { false, "false" } };
167 ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("PrepareLCW ................. %s", blu[m_prepareLCW].c_str()) );
168 ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("BuildTopoTowers ............ %s", blu[m_useCellsFromClusters].c_str()) );
169 ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("ApplyCellEnergyThreshold ... %s", blu[m_applyCellEnergyThreshold].c_str()) );
170 ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("OrderClusterByPt ........... %s", blu[m_orderByPt].c_str()) );
171 ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("DoCellIndexCheck ........... %s", blu[m_doCellIndexCheck].c_str()) );
172 ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("BuildCombinedTopoSignal .... %s", blu[m_buildCombinedSignal].c_str()) );
173 ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("TopoClusterRange ........... %.2f", m_clusterRange) );
174 ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("ExcludedSamplings .......... %zu (number of)",m_excludedSamplingsName.size()) );
175 ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("RemoveSamplingData ......... %s", blu[m_removeSamplingData].c_str()) );
176
177 return StatusCode::SUCCESS;
178}
179
181{ return StatusCode::SUCCESS; }
182
183StatusCode CaloTopoTowerFromClusterMaker::execute(const EventContext& ctx,
185 CaloCellClusterWeights* cellWeights) const
186{
188 // Check input //
190
191 // CaloCellContainer is needed to construct CaloProtoCluster
193 if ( !pCellCont.isValid() ) {
194 ATH_MSG_ERROR("Cannot allocate CaloCellContainer with key <" << m_cellContainerKey << ">");
195 return StatusCode::FAILURE;
196 }
197
199 const CaloTowerGeometry* towerGeo=*towerGeoHandle;
200
202 const CaloDetDescrManager* caloDDMgr = *caloMgrHandle;
203
204
205 if ( msgLvl(MSG::DEBUG) && towerGeo->totalNumberCells() != pCellCont->size() ) {
206 ATH_MSG_DEBUG( CaloRec::Helpers::fmtMsg("[mismatch] number of cells in CaloCellContainer %6zu, total number of cell descriptors %6zu",
207 pCellCont->size(),towerGeo->totalNumberCells()) );
208 }
209
210 if ( m_doCellIndexCheck ) { this->checkCellIndices(towerGeo,caloDDMgr, pCellCont.cptr()); }
211
213 // Set up ProtoCluster //
215
216 // index of CaloProtoCluster in container relates to tower position! DO NOT sort, shuffle, or remove elements!
217 size_t numberOfTowers=towerGeo->towerBins();
218 protocont_t pProtoCont; pProtoCont.reserve(numberOfTowers);
219 for ( uint_t i(0); i<numberOfTowers; ++i ) { pProtoCont.push_back(CaloProtoCluster(pCellCont.cptr())); }
220
222 // Apply overall cell filter and fill protoclusters //
224
225 // The weights extracted for cells from clusters are LCW weights (typically). The total
226 // contribution of a LCW-weighted cell to towers is Ecell*Weight_LCW*Weight_tower.
227
228 // If EM clusters are used, the weights of a clustered cell are completely defined
229 // by the tower grid. As cells can shared between clusters, each cell can only be
230 // projected onto the towergrid once, with Ecell*Weight_tower
231
232 // The CaloCellClusterWeights object is used to store the combined LCW weight.
233 // for each clustered cell. In case of EM, the LCW weights are ignored and this
234 // object is not used - a simple vector<bool> tags cells already put into towers.
235
236 uint_t cCtr(0);
238 // retrieve topo-cluster container for topo-towers
240 if ( !pTopoClusCont.isValid() ) {
241 ATH_MSG_ERROR("Cannot allocate xAOD::CaloClusterContainer with key <" << m_clusterContainerKey << ">");
242 return StatusCode::FAILURE;
243 } // check on ReadHandle validity
244 cCtr = m_prepareLCW && cellWeights != nullptr ? this->buildLCWTopoTowers(towerGeo,*pTopoClusCont,pProtoCont,cellWeights) : this->buildEMTopoTowers(towerGeo,*pTopoClusCont,pProtoCont);
245 if ( !isValidIndex(cCtr) ) { ATH_MSG_WARNING("problems building EM or LCW topo-towers"); return StatusCode::SUCCESS; }
246 } else {
247 // fill inclusive/exclusive towers
248 cCtr = m_applyCellEnergyThreshold ? this->buildExclTowers(towerGeo,*pCellCont,pProtoCont) : this->buildInclTowers(towerGeo,*pCellCont,pProtoCont);
249 if ( !isValidIndex(cCtr) ) { ATH_MSG_WARNING("problems building EM inclusive or exclusive towers"); return StatusCode::SUCCESS; }
250 } // end topo-towers/inclusive-exclusive towers
251
252
253
254 // allocate sufficient space in vector
255 pClusCont->reserve(cCtr);
256 // pick up cluster size tag and set up counter
258 // loop proto-clusters
259 for ( uint_t ipc(0); ipc<pProtoCont.size(); ++ipc ) {
260 CaloProtoCluster& pProto = pProtoCont.at(ipc); // pick up proto-cluster
261 std::unique_ptr<CaloClusterCellLink> lptr(pProto.releaseCellLinks()); // take over CaloClusterCellLink object
262 this->cleanupCells(towerGeo,lptr.get(),ipc); // clean up cell links
263 if ( CaloTopoTowerFromClusterMaker::filterProtoCluster(*lptr.get()) ) { // ignore empty proto-clusters (no cells assigned)
264 xAOD::CaloCluster* clptr = pClusCont->push_back(new xAOD::CaloCluster()); // new empty cluster
265 clptr->addCellLink(std::move(lptr)); // transfer cell links to CaloCluster
266 clptr->setClusterSize(csize); // set the cluster size spec
267 CaloRec::Helpers::calculateKine(clptr,false); // calculate kinematics and other signals from cells
268 if ( m_removeSamplingData ) { // remove sampling data and invalidate tower center
269 clptr->clearSamplingData(); clptr->setEta0(0.); clptr->setPhi0(0.);
270 } else { // keep sampling data and valid tower center
271 clptr->setEta0(towerGeo->towerEta(ipc)); clptr->setPhi0(towerGeo->towerPhi(ipc));
272 }
273 }
274 } // proto-cluster loop
275
276 // clean up proto-cluster container
277 pProtoCont.clear();
278
280 // Sorting //
282
283 // All towers/clusters at this point are on EM scale. Sorting LCW towers by pT should be done in the
284 // CaloTopoClusterFromTowerCalibrator tool to assure desired ordering on the final scale.
285 // The link between tower location and index of tower representation (CaloCluster) in its
286 // container is definitively broken after sorting (was never ok in mixed cluster/tower mode).
287 if ( m_orderByPt ) {
288 std::sort(pClusCont->begin(),pClusCont->end(),[](xAOD::CaloCluster* pc1,xAOD::CaloCluster* pc2) {
289 volatile double pt1(pc1->pt()); // FIXME needed? (this was just copied)
290 volatile double pt2(pc2->pt()); // FIXME needed? (this was just copied)
291 return ( pt1 > pt2 );
292 }
293 );
294 } // end ordered by pT
295
296 return StatusCode::SUCCESS;
297} // end execute
298
300// Fill topo-towers //
302
303// EM
305{
306 // presets
307 uint_t cCtr(0);
308 std::vector<bool> cellTags(towerGeo->totalNumberCells(),false);
309
310 // -- EM scale clusters
311 if ( !m_buildCombinedSignal ) {
312 // topo-towers
313 for ( const auto *pClus : pClusCont ) {
314 for ( auto fCell(pClus->cell_begin()); fCell != pClus->cell_end(); ++fCell ) {
315 uint_t cidx(static_cast<uint_t>((*fCell)->caloDDE()->calo_hash()));
316 if ( cidx < cellTags.size() ) {
317 if ( !cellTags.at(cidx) ) { cellTags[cidx] = this->addCellToProtoCluster(towerGeo,*fCell,pProtoCont); }
318 } else {
319 ATH_MSG_ERROR( CaloRec::Helpers::fmtMsg("Invalid cell hash index %6zu >= maximum index %6zu for cell in %s at (eta,phi) = (%6.3f,%6.3f)",
320 cidx,cellTags.size(),CaloSampling::getSamplingName((*fCell)->caloDDE()->getSampling()).c_str(),(*fCell)->eta(),(*fCell)->phi()) );
321 return m_errorValueUINT;
322 }
323 } // end cells-in-cluster loop
324 } // end cluster loop
325 } else {
326 // selected topo-towers for combined signal
327 std::vector<std::tuple<const CaloCell*,double> > cellList(towerGeo->totalNumberCells(),std::tuple<const CaloCell*,double>(nullptr,0.));
328 for ( const auto *pClus : pClusCont ) {
329 if ( std::abs(pClus->eta()) > m_clusterRange ) {
330 for ( auto fCell(pClus->cell_begin()); fCell != pClus->cell_end(); ++fCell ) {
331 uint_t cidx(static_cast<uint_t>((*fCell)->caloDDE()->calo_hash()));
332 if ( cellTags.at(cidx) ) {
333 std::get<1>(cellList[cidx]) += fCell.weight();
334 } else {
335 cellList[cidx] = std::tuple<const CaloCell*,double>(*fCell,fCell.weight());
336 cellTags[cidx] = true;
337 }
338 } // cell in cluster loop
339 } else {
340 ++cCtr;
341 } // cluster range check
342 } // cluster loop
343 // fill proto-cluster
344 for ( auto tpl : cellList ) { this->addCellToProtoCluster(towerGeo,std::get<0>(tpl),pProtoCont,std::get<1>(tpl)); }
345 } // end of fill mode
346
347 //
348 return cCtr+pProtoCont.size();
349}
350
351// LCW
353{
354 // Need to keep track of LCW weights (up to two per cell) available from the topo-cluster(s) the cell is assigned to.
355 // Each cell in a topo-cluster is, at first occurance, added to the CaloProtoCluster(s) representing the tower(s) and its
356 // LCW calibration weight is stored in a lookup table indexed by the calorimeter hash id of the cell. The second
357 // time the same cell is found in another topo-cluster, only its LCW weight is added to the lookup table (stored in
358 // CaloCellClusterWeights for use in the downstream tower calibration tool) - the assignment to tower(s) has already
359 // happened.
360
361 uint_t cCtr(0);
362 // project cells on tower grid
363 if ( !m_buildCombinedSignal ) {
364 // loop original topo-cluster container
365 for ( const auto *pClus : pClusCont ) {
366 // loop over cells in the original topo-cluster
367 for ( auto fCell(pClus->cell_begin()); fCell != pClus->cell_end(); ++fCell ) {
368 // map to towers only once
369 if ( !cellWeights->check(*fCell) ) { this->addCellToProtoCluster(towerGeo,*fCell,pProtoCont); }
370 // store all associated LCW weights
371 cellWeights->set(*fCell,fCell.weight());
372 } // end cells-in-cluster loop
373 } // end cluster loop
374 } else {
375 // loop topo-cluster
376 for ( const auto *pClus : pClusCont ) {
377 // keep top-clusters in configured eta range
378 if ( std::abs(pClus->eta()) > m_clusterRange ) {
379 // loop over cells of topo-clusters for the forward towards
380 for ( auto fCell(pClus->cell_begin()); fCell != pClus->cell_end(); ++fCell ) {
381 // map to towers only once
382 if ( !cellWeights->check(*fCell) ) { this->addCellToProtoCluster(towerGeo,*fCell,pProtoCont); }
383 // store all associated LCW weights
384 cellWeights->set(*fCell,fCell.weight());
385 } // end cells-in-cluster loop
386 } else {
387 ++cCtr;
388 } // end range check
389 } // end cluster loop
390 } // end combined signal check
391
392 //
393 return cCtr+pProtoCont.size();
394}
395
397// Fill towers //
399
400// inclusive
402{
403 // loop cell container - counter icl replaces cell hash index for NULL pointers in cell container
404 uint_t icl(0);
405 for ( const auto *cptr : pCellCont ) {
406 if ( cptr == nullptr ) {
407 ATH_MSG_ERROR( CaloRec::Helpers::fmtMsg("CaloCellContainer[%6zu] contains invalid cell object pointer %p",icl,(void*)cptr) );
408 return m_errorValueUINT;
409 } else {
410 // existing cell with non-zero energy (negative or positive)
411 if ( std::fabs(cptr->e()) > 0. ) { this->addCellToProtoCluster(towerGeo,cptr,pProtoCont); }
412 } // end pointer check
413 ++icl;
414 } // end cell loop
415 return pProtoCont.size();
416}
417
418// exclusive
420{
421 // loop cell container
422 uint_t icl(0);
423 for ( const auto *cptr : pCellCont ) {
424 if ( cptr == nullptr ) {
425 ATH_MSG_ERROR( CaloRec::Helpers::fmtMsg("CaloCellContainer[%6zu] contains invalid cell object pointer %p",icl,(void*)cptr) );
426 return m_errorValueUINT;
427 } else {
428 // existing cell with energy above threshold
429 if ( cptr->e() > m_energyThreshold ) { this->addCellToProtoCluster(towerGeo,cptr,pProtoCont); }
430 } // end pointer check
431 ++icl;
432 } // end cell loop
433 //return StatusCode::SUCCESS;
434 return pProtoCont.size();
435}
436
438 protocont_t& pProtoCont,double weight) const
439
440{
441 // invalid input
442 if ( cptr == nullptr ) { return false; }
443
444 // get towers for cell from geometry service
445 uint_t nctr(0);
446 for ( auto elm : towerGeo->getTowers(cptr->caloDDE()->calo_hash()) ) {
447 auto towerIdx(towerGeo->towerIndex(elm));
448 if ( !towerGeo->isInvalidIndex(towerIdx) ) {
449 if ( !m_excludedSamplingsPattern[(size_t)cptr->caloDDE()->getSampling()] ) {
450 uint_t cellIdx(pProtoCont.at(towerIdx).getCellLinks()->getCellContainer()->findIndex(cptr->caloDDE()->calo_hash()));
451 pProtoCont[towerIdx].addCell(cellIdx,towerGeo->cellWeight(elm)*weight); ++nctr;
452 }
453 }
454 }
455 return nctr > 0;
456}
457
459// Helpers //
461
464
466{
467 // check for tower sizes
468 return nTowers == 6400 // known "standard" towers 0,1 x 0.1
470 : nTowers == 25600 // known "fine" towers 0.05 x 0.05
472 : xAOD::CaloCluster::Tower_fixed_area; // unspecified towers
473}
474
476{
477 // Any pathology here probably indicates a configuration problem with the conditions (geometry)
478 // database (wrong tag for data?)
479
480 // check on null pointers in cell links
481 int nrc(0); int hid(0);
482 auto fcell(clk->begin());
483 while ( fcell != clk->end() ) {
484 const CaloCell* pCell = *fcell;
485 auto nc(clk->getCellContainer()->size());
486 const CaloCell* aCell = fcell.index() < nc ? clk->getCellContainer()->at(fcell.index()) : (const CaloCell*)nullptr;
487 if ( pCell == nullptr ) {
488 ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("CaloCellContainer[%6u/%6zu] - tower %5zu at (%6.3f,%6.3f) - cell pointer invalid (%p/%p) [removed %3i of %3zu cells]",
489 fcell.index(),nc-1,nclus,towerGeo->towerEta(nclus),towerGeo->towerPhi(nclus),
490 (void*)pCell,(void*)aCell,++nrc,clk->size()) );
491 fcell = clk->removeCell(fcell);
492 } else {
493 uint_t chash(static_cast<uint_t>(pCell->caloDDE()->calo_hash()));
494 uint_t csamp(static_cast<uint_t>(pCell->caloDDE()->getSampling()));
495 if (chash > towerGeo->maxCellHash() ) {
496 // check cell hash
497 ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("Tower %5zu at (%6.3f,%6.3f) linked cell %3i - cell hash index (%6zu/%6zu) invalid",
498 nclus,towerGeo->towerEta(nclus),towerGeo->towerPhi(nclus),hid,chash,towerGeo->maxCellHash()) );
499 fcell = clk->removeCell(fcell); ++nrc;
500 } else if ( csamp >= m_numberOfSamplings ) {
501 // check sampling id
502 ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("Tower %5zu at (%6.3f,%6.3f) linked cell %3i -cell sampling id (%3zu/%3zu) invalid",
503 nclus,towerGeo->towerEta(nclus),towerGeo->towerPhi(nclus),hid,csamp,m_numberOfSamplings) );
504 fcell = clk->removeCell(fcell); ++nrc;
505 } else if ( fcell.weight() <= 0.0000001 ) {
506 // remove cells with 0 weight
507 fcell = clk->removeCell(fcell); ++nrc;
508 } else {
509 // next cell
510 ++fcell;
511 }
512 } // end remove cell due to pointer invalid
513 ++hid;
514 } // end loop on cells in cell link object
515 return nrc;
516}
517
520
522 const CaloCellContainer* pCellCont) const
523{
525 // input and setup checks //
527
528 // check argument
529 if ( pCellCont == nullptr ) {
530 ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("Invalid pointer to CaloCellContainer (%p)",(void*)pCellCont) ); return false;
531 } else if ( pCellCont->empty() ) {
532 ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("CaloCellContainer at %p is empty (size %zu)",(void*)pCellCont,pCellCont->size()) ); return false;
533 }
534 // check the atomic state
536 // set the atomic flag
537 ATH_MSG_INFO( "Cell hash index check requested" );
539 // assign output file
540 std::string algname(this->name());
541 if ( algname.find_last_of('.') != std::string::npos ) { algname = algname.substr(algname.find_last_of('.')+1); }
542 std::string logname(CaloRec::Helpers::fmtMsg("%s.cellhash_index_check.dat",this->name().c_str()));
543 std::ofstream logstream; logstream.open(logname);
544 if ( !logstream.is_open() ) {
545 ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("Cannot open log file \042%s\042 - no hash index checking",logname.c_str()) );
546 return false;
547 }
548 logstream << "##########################################################################" << std::endl;
549 logstream << "### This file contains a list of CaloCell indices in CaloCellContainer ###" << std::endl;
550 logstream << "### for which this index is not the same as the calorimeter cell hash ###" << std::endl;
551 logstream << "### identifier. An empty list indicates full consistency between this ###" << std::endl;
552 logstream << "### index and the hash identifier for all cells. ###" << std::endl;
553 logstream << "##########################################################################" << std::endl;
554 logstream << "<begin list>--------------------------------------------------------------" << std::endl;
555
557 // loop cell container //
559
560 // prepare tag store
561 size_t ifc(0);
562 auto chkflg = std::make_unique<std::bitset<200000> >();
563 chkflg->reset();
564 for ( size_t i(0); i<pCellCont->size(); ++i ) {
565 if ( pCellCont->at(i) != nullptr ) {
566 size_t chash((size_t)pCellCont->at(i)->caloDDE()->calo_hash());
567 if ( chash != i ) {
568 std::string cni("UKNOWN");
569 double etai(0.); double phii(0.);
570 const CaloDetDescrElement* iel = i < caloDDMgr->element_size() ? caloDDMgr->get_element(i) : nullptr;
571 if ( iel != nullptr ) {
573 etai = iel->eta_raw();
574 phii = iel->phi_raw();
575 }
576 std::string cnc("UNKNOWN");
577 double etac(0.); double phic(0.);
578 const CaloDetDescrElement* cel = chash < caloDDMgr->element_size() ? caloDDMgr->get_element(chash) : nullptr;
579 if ( cel != nullptr ) {
581 etac = cel->eta_raw();
582 phic = cel->phi_raw();
583 }
584 size_t cidx(pCellCont->findIndex(chash));
585 logstream << CaloRec::Helpers::fmtMsg("[%06zu] Cell %6zu [%12.12s %5.3f %5.3f] non-matching id %6zu [%12.12s %5.3f %5.3f] findCell() index %6zu",
586 ++ifc,i,cni.c_str(),etai,phii,chash,cnc.c_str(),etac,phic,cidx) << std::endl;
587 }
588 chkflg->set(chash);
589 }
590 }
591 logstream << "<end list>----------------------------------------------------------------" << std::endl;
592 logstream.close();
593
595 // check missed hashes //
597
598 // number of non-matched hashes
599 if ( ifc > 0 ) {
600 ATH_MSG_DEBUG( CaloRec::Helpers::fmtMsg("Found %zu non-matching cell hashes",ifc) );
601 }
602 // list of non-matched hashes
603 std::vector<size_t> chl; chl.reserve(towerGeo->totalNumberCells());
604 for ( size_t i(0); i<chl.size(); ++i ) { if ( !chkflg->test(i) ) { chl.push_back(i); } }
605 if ( !chl.empty() ) {
606 for ( auto h : chl ) { ATH_MSG_DEBUG( CaloRec::Helpers::fmtMsg("Cell hash %6zu not in CaloCellContainer",h) ); }
607 }
608
609 return true;
610}
611
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Definition of CaloDetDescrManager.
CaloPhiRange class declaration.
std::atomic< bool > CaloTopoTowerFromClusterMaker_checkCellIndices(false)
std::ostream & operator<<(std::ostream &lhs, const TestGaudiProperty &rhs)
@ Unknown
Definition TruthClasses.h:9
Wrapper to avoid constant divisions when using units.
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)
bool msgLvl(const MSG::Level lvl) const
Header file for AthHistogramAlgorithm.
Hash lookup of calibration weights for calorimeter cells.
bool check(size_t hash) const
Safe checking if cell is used by any cluster.
void set(size_t hash, double value)
Container class for CaloCell.
int findIndex(const IdentifierHash theHash) const
Return index of the cell with a given hash.
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
const CaloDetDescrElement * caloDDE() const
get pointer to CaloDetDescrElement (data member)
Definition CaloCell.h:321
This class groups all DetDescr information related to a CaloCell.
CaloCell_ID::CaloSample getSampling() const
cell sampling
const CaloDetDescrElement * get_element(const Identifier &cellId) const
get element by its identifier
calo_element_vec_size element_size() const
total number of elements
This class provides the client interface for accessing the detector description information common to...
CaloClusterCellLink * releaseCellLinks()
Hand over ownership of CaloClusterCellLink to client.
static std::string getSamplingName(CaloSample theSample)
Returns a string (name) for each CaloSampling.
static const double m_energyThresholdDef
Default energy threshold.
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
double m_clusterRange
Range where topo-clusters are used when m_buildCombinedSignal = true
static const double m_clusterRangeDef
Default cluster range.
virtual StatusCode execute(const EventContext &ctx, xAOD::CaloClusterContainer *pClusCont, CaloCellClusterWeights *cellWeights) const override
Execute the tool and fill the xAOD::CaloClusterContainer pointed to by pClusCont.
uint_t m_numberOfSamplings
Number of samplings.
SG::ReadHandleKey< CaloCellContainer > m_cellContainerKey
Calorimeter cell container.
bool checkCellIndices(const CaloTowerGeometry *towerGeo, const CaloDetDescrManager *caloDDM, const CaloCellContainer *pCellCont) const
Checks consistency between cell indices and hash identifiers.
bool m_buildCombinedSignal
Build topo-clusters within given range, else topo-towers.
static const uint_t m_errorValueUINT
Error value for uint_t type values.
double m_energyThreshold
Cell energy threshold, default is set in m_energyThresholdDef.
std::bitset< _CALOTOPOTOWERFROMCLUSTERMAKER_BITSET_SIZE > m_excludedSamplingsPattern
Bit pattern indicates if sampling is excluded.
std::vector< std::string > m_excludedSamplingsName
List of excluded samplings (human-readable names)
bool addCellToProtoCluster(const CaloTowerGeometry *towerGeo, const CaloCell *cptr, protocont_t &pProtoCont, double weight=1.) const
Adding cells to proto-clusters.
bool m_useCellsFromClusters
Use cells from topo-clusters if true, else use all cells, default is true.
std::vector< CaloProtoCluster > protocont_t
Container for CaloProtoCluster objects.
static xAOD::CaloCluster::ClusterSize getClusterSize(uint_t etaBins, uint_t phiBins)
Returns a cluster size tag from number of eta and phi bins in tower grid.
bool m_prepareLCW
Prepare LCW calibration, default is false.
bool m_doCellIndexCheck
Check cell hash index consistency if true (default false)
uint_t buildInclTowers(const CaloTowerGeometry *towerGeo, const CaloCellContainer &pCellCont, protocont_t &pProtoCont) const
Inclusive towers.
std::vector< CaloSampling::CaloSample > m_excludedSamplings
List of excluded samplings (CaloSampling::CaloSample enumerators)
bool isValidIndex(uint_t idx) const
Checks if argument is a valid index value.
bool m_removeSamplingData
Remove sampling data for towers.
CaloTopoTowerFromClusterMaker(const std::string &type, const std::string &name, const IInterface *pParent)
Tool constructor.
uint_t buildExclTowers(const CaloTowerGeometry *towerGeo, const CaloCellContainer &pCellCont, protocont_t &pProtoCont) const
Exclusive towers.
uint_t buildLCWTopoTowers(const CaloTowerGeometry *towerGeo, const xAOD::CaloClusterContainer &clusCont, protocont_t &protoCont, CaloCellClusterWeights *cellWeights) const
LCW topo-towers.
std::size_t uint_t
Unsigned integral type.
bool m_applyCellEnergyThreshold
Apply cell energy threshold, default is false.
SG::ReadCondHandleKey< CaloTowerGeometry > m_towerGeoKey
the name of the key of the CaloTowerGeometry object in the ConditonsStore
virtual StatusCode initialize() override
Setting up the operational mode and corresponding parameters.
virtual StatusCode finalize() override
Finalize the tool (no action)
static bool filterProtoCluster(const CaloClusterCellLink &clnk)
Checks for and removes invalid cell links.
uint_t buildEMTopoTowers(const CaloTowerGeometry *towerGeo, const xAOD::CaloClusterContainer &clusCont, protocont_t &protoCont) const
EM topo-towers.
bool m_orderByPt
Orders cluster container by , default true.
SG::ReadHandleKey< xAOD::CaloClusterContainer > m_clusterContainerKey
Topo-cluster container key.
int cleanupCells(const CaloTowerGeometry *towerGeo, CaloClusterCellLink *clk, uint_t nclus) const
Checks CaloClusterCellLink for consistency.
Retrieve the list of towers associated with a calorimeter cell referenced by its hash identifier.
index_t towerIndex(IdentifierHash cellHash) const
Get global tower index for a calorimeter cell referenced by its hash identifier.
uint_t totalNumberCells() const
Total number of cells.
double towerEta(index_t towerIndex) const
Return pseudorapidity from global tower index (bin center)
uint_t towerBins() const
Total number of towers.
double cellWeight(const element_t &elm) const
Retrieve cell signal weight from lookup table entry.
double towerPhi(index_t towerIndex) const
Return azimuth from global tower index (bin center)
bool isInvalidIndex(index_t idx) const
Returns true if argument is equal to the value provided by invalidIndex()
elementvector_t getTowers(IdentifierHash cellHash) const
Retrieve the list of towers associated with a calorimeter cell referenced its hash identifier.
uint_t maxCellHash() const
Maximum cell hash value.
void reserve(size_type n)
Attempt to preallocate enough memory for a specified number of elements.
const T * at(size_type n) const
Access an element, as an rvalue.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
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.
bool empty() const noexcept
Returns true if the collection is empty.
Property holding a SG store/key/clid from which a ReadHandle is made.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
void addCellLink(CaloClusterCellLink *CCCL)
void setClusterSize(const ClusterSize)
Get cluster size.
ClusterSize
Enumeration to identify different cluster sizes.
void setPhi0(flt_t)
Set raw of cluster seed.
void clearSamplingData()
Clear the sampling data.
bool calculateKine(xAOD::CaloCluster *pClus, bool onlyKine=false)
Kinematic updates.
std::string fmtMsg(const char *fmt,...)
static const std::string & getSamplingName(CaloSampling::CaloSample sid)
Lookup sampling name by identifier (function)
static CaloSampling::CaloSample getSamplingId(const std::string &sname)
Lookup sampling identifier by name (function)
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.