ATLAS Offline Software
Loading...
Searching...
No Matches
CaloCellNeighborsAverageCorr.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// ****************************************************************************************
6//
7// Assign as energy the average energy of the surrounding cells (i.e. the neibhgors).
8//
9// Georgios Choudalakis & Guillaume Unal, January 2009.
10//
11// ****************************************************************************************
12
14
15#include "CaloEvent/CaloCell.h"
17
21#include "Identifier/Identifier.h"
24#include <map> //useful in testMode
25
26//========================================================
27// Initialize
28
30{
31 ATH_MSG_INFO ( " in CaloCellNeighborsAverageCorr::initialize() " );
32
33 if (m_testMode)
34 ATH_MSG_DEBUG ( " Running in Test Mode. " );
35
36 // don't need to check status of the drawer if all dead cells are ignored
38 ATH_MSG_WARNING ( "Please, don't set skipDeadDrawer and skipDeadTile to True at the same time" );
39 ATH_MSG_WARNING ( "Setting skipDeadDrawer=False" );
40 m_skipDeadDrawer=false;
41 }
42
43 ATH_MSG_INFO ( "Skip already pached = " << ((m_skipDeadFeb)?"true":"false") );
44 ATH_MSG_INFO ( "Skip Dead LAr = " << ((m_skipDeadLAr)?"true":"false") );
45 ATH_MSG_INFO ( "Skip Dead Drawer = " << ((m_skipDeadDrawer)?"true":"false") );
46 ATH_MSG_INFO ( "Skip Dead Tile = " << ((m_skipDeadTile)?"true":"false") );
47
48
49 ATH_CHECK( detStore()->retrieve (m_calo_id, "CaloCell_ID") );
50 m_tile_id = m_calo_id->tile_idHelper();
51
52 ATH_MSG_INFO ( "CaloCellNeighborsAverageCorr initialize() end" );
53
54 return StatusCode::SUCCESS;
55}
56
57// ============================================================================
58
59StatusCode
61 const EventContext& /*ctx*/) const
62{
63 ATH_MSG_VERBOSE ( " in process " );
64
65 std::vector<IdentifierHash> theNeighbors;
66 theNeighbors.reserve(22);
67
68 std::map<const CaloCell*,float> cannedUncorrectedEnergies;
69 if (m_testMode) { //fill in the map of uncorrected energies, to preserve it for later use.
70 CaloCellContainer::const_iterator itrCell_test=theCont->begin();
71 for (; itrCell_test!=theCont->end();++itrCell_test){
72 const CaloCell* pointerToCell=*itrCell_test; //yes, this is an iterator that when dereferenced returns a pointer, not a CaloCell directly.
73 cannedUncorrectedEnergies[pointerToCell] = pointerToCell->energy();
74 }
75 }
76
77 int nGoodCellsPerDrawer[4][64];
78
79 if (m_skipDeadDrawer) {
80 memset(nGoodCellsPerDrawer,0,sizeof(nGoodCellsPerDrawer));
81
82 size_t cellItr = theCont->indexFirstCellCalo(CaloCell_ID::TILE);
83 size_t lastCell = theCont->indexLastCellCalo(CaloCell_ID::TILE);
84
85 for (; cellItr <= lastCell; ++cellItr) {
86 const CaloCell* CCell = (*theCont)[cellItr];
87 if (CCell && ! CCell->badcell() ) {
88 Identifier id = CCell->ID();
89 int part = std::min(m_tile_id->section(id),2)+m_tile_id->side(id);
90 int module = m_tile_id->module(id);
91 ++nGoodCellsPerDrawer[part][module];
92 }
93 }
94 if (msgLvl(MSG::VERBOSE)) {
95 // 1-1 2-1 1+1 2+1
96 const char * name[4] = {"LBC","EBC","LBA","EBA"};
97 for (int part=0; part<4; ++part) {
98 for (int module=0; module<64; ++module) {
99 //log << MSG::VERBOSE << name[part] << module+1 << " nCells "
100 // << nGoodCellsPerDrawer[part][module]
101 // << ( ( nGoodCellsPerDrawer[part][module] < 2 ) ? " bad drawer" : "")
102 // << endmsg;
103 if ( nGoodCellsPerDrawer[part][module] < 2 ) {
104 ATH_MSG_VERBOSE ( "Bad drawer " << name[part] << module+1 );
105 }
106 }
107 }
108 }
109 }
110
111 CaloCellContainer::iterator itrCell=theCont->begin();
112 for (; itrCell!=theCont->end();++itrCell){
113 CaloCell * aCell=*itrCell;
114
115 if (aCell->badcell() || m_testMode) {
116
117 const CaloDetDescrElement* caloDDE = aCell->caloDDE();
118 if (!caloDDE) continue;
119 int theCellSubCalo = caloDDE->getSubCalo();
120
121 bool isTile = (theCellSubCalo == CaloCell_ID::TILE);
122
123 if (isTile) {
124
125 if (m_skipDeadTile) {
126 ATH_MSG_VERBOSE ( " skipping Tile hash " << m_calo_id->calo_cell_hash(aCell->ID()) );
127 continue;
128 } else if (m_skipDeadDrawer) {
129
130 Identifier id = aCell->ID();
131 int part = std::min(m_tile_id->section(id),2)+m_tile_id->side(id);
132 int module = m_tile_id->module(id);
133 if ( nGoodCellsPerDrawer[part][module] < 2 ) {
134 ATH_MSG_VERBOSE ( " skipping Tile drawer hash " << m_calo_id->calo_cell_hash(aCell->ID()) );
135 continue;
136 }
137 }
138
139 } else {
140
141 if (m_skipDeadLAr) {
142 ATH_MSG_VERBOSE ( " skipping LAr hash " << m_calo_id->calo_cell_hash(aCell->ID()) );
143 continue;
145 ATH_MSG_VERBOSE ( " skipping already patched hash " << m_calo_id->calo_cell_hash(aCell->ID()) );
146 continue;
147 }
148 }
149
150 //We need a IdentifierHash to pass as input to the get_neighbors().
151 const Identifier theCellID = aCell->ID();
152 const float oldE=aCell->energy();
153 const IdentifierHash theCellHashID = m_calo_id->calo_cell_hash(theCellID);
154
155 //Find now the neighbors around theCell, and store them in theNeighbors vector.
156 m_calo_id->get_neighbours(theCellHashID,LArNeighbours::all2D,theNeighbors);
157
158 //std::cout << "Found " << theNeighbors.size() << " neighbors." << std::endl;
159
160 //first let's find the volume of theCell we are correcting.
161 float volumeOfTheCell=0;
162 if (caloDDE) volumeOfTheCell = caloDDE->volume();
163
164 if (volumeOfTheCell==0) continue;
165 //int theCellSampling = caloDDE->getSampling();
166 // if (theCellSubCalo == CaloCell_ID::TILE) {
167 // std::cout << "theCell = " << theCellSubCalo << " " << theCellSampling << " is at eta=" << aCell->eta() << " phi=" << aCell->phi() << " E=" << aCell->energy() << " V=" << volumeOfTheCell*1e-6 << "D=" << aCell->energy() / volumeOfTheCell * 1e6 << std::endl;
168 // }
169
170
171 const Identifier theCellRegion=m_calo_id->region_id(theCellID);
172 //loop through neighbors, and calculate average energy density of guys who have a legitimate volume (namely >0).
173
174 float goodNeighborEnergyDensitySum=0;
175 unsigned goodNeighbors=0;
176
177 float betterNeighborEnergyDensitySum=0;
178 unsigned betterNeighbors=0;
179
180 ATH_MSG_VERBOSE("Cell " << theCellID.get_identifier32().get_compact() << " has " << theNeighbors.size() << " neighbors");
181 for (unsigned int iN=0;iN<theNeighbors.size();iN++) {
182 const CaloCell* thisNeighbor = theCont->findCell(theNeighbors[iN]);
183 //if there is a hardware problem in real data, then the above pointer may be NULL. In that case the geometric neighbor is absent from the container, so we should move on to the next geometric neighbor.
184 if (!thisNeighbor) continue;
185 const CaloDetDescrElement* thisNeighborDDE = (thisNeighbor)->caloDDE();
186 float thisEnergy = thisNeighbor->energy();
187 if (m_testMode) {
188 thisEnergy = cannedUncorrectedEnergies[thisNeighbor];
189 }
190 if (thisNeighbor->badcell() || (!thisNeighbor->caloDDE()->is_tile() && LArProv::test(thisNeighbor->provenance(),LArProv::PATCHED))) {
191 ATH_MSG_VERBOSE("Ignoring neighbor " << thisNeighbor->ID().get_identifier32().get_compact() << " because of it's bad cell status");
192 continue;
193 }
194 //int thisNeighborSubCalo = thisNeighborDDE->getSubCalo();
195 //int thisNeighborSampling = thisNeighborDDE->getSampling();
196 //if (thisNeighborSubCalo != theCellSubCalo) continue;
197 //if (thisNeighborSampling != theCellSampling) continue; //if the quality of the cell is very different, it's a wrong idea that dE/dV would be similar.
198
199
200 float thisVolume = thisNeighborDDE->volume();
201 if (thisVolume <= 0) continue;
202
203 //A good neightbor if we arrive at this point
204 goodNeighbors++;
205 float thisEnergyDensity= thisEnergy / thisVolume;
206 goodNeighborEnergyDensitySum += thisEnergyDensity;
207
208
209 const Identifier thisNeighborRegion=m_calo_id->region_id(thisNeighbor->ID());
210 //Better neighbors are in the same region
211 if (thisNeighborRegion==theCellRegion) {
212 ATH_MSG_VERBOSE("Neighbor is in different region " << thisNeighborRegion.get_identifier32().get_compact() << "/" << theCellRegion.get_identifier32().get_compact());
213 betterNeighbors++;
214 betterNeighborEnergyDensitySum+=thisEnergyDensity;
215 }
216 } //end loop over neighbors
217
218
219 unsigned nNeighbors=0;
220 float neighborEnergyDensitySum=0;
221
222 if (betterNeighbors>=2) {//Have at least 2 good neighbors in the same region
223 nNeighbors=betterNeighbors;
224 neighborEnergyDensitySum=betterNeighborEnergyDensitySum;
225 }
226 else {//No good neighbors in the same region
227 ATH_MSG_DEBUG("Cell " << theCellID.get_identifier32().get_compact() << ": Did not find enough good neighbors in the same region. Will use neighbors from different regions");
228 nNeighbors=goodNeighbors;
229 neighborEnergyDensitySum=goodNeighborEnergyDensitySum;
230 }
231
232 if(nNeighbors <= 0) {
233 ATH_MSG_DEBUG("Did not get any suitable neighbor for cell " << theCellID.get_identifier32().get_compact() << ". Not corrected.");
234 continue;
235 }
236
237 const float averageEnergyDensity = neighborEnergyDensitySum/nNeighbors;
238
239 //now use the average energy density to make a prediction for the energy of theCell
240 const float predictedEnergy = averageEnergyDensity * volumeOfTheCell;
241 aCell->setEnergy(predictedEnergy);
242 //aCell->setProvenance(aCell->provenance()| LArProv::PATCHED); W.L. I think it would be better to label patched cells as 'patched' but this breaks FT0.
243 ATH_MSG_VERBOSE ( " correcting " << ((isTile)?"Tile":"LAr") << " id " << theCellID.get_identifier32().get_compact() << " Eold="
244 <<oldE << "Enew=" << predictedEnergy << ", used " << nNeighbors << " neighbors" );
245 } // end of if(badcell)
246 } // end loop over cells
247 return StatusCode::SUCCESS;
248}
249
250//memo:
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Container class for CaloCell.
int indexFirstCellCalo(const CaloCell_ID::SUBCALO caloNum) const
index of first cell of given calorimeter (-1 if none).
const CaloCell * findCell(const IdentifierHash theHash) const
fast find method given identifier hash.
int indexLastCellCalo(const CaloCell_ID::SUBCALO caloNum) const
index of last cell of given calorimeter (-2 if none) Note that it is normally more efficient to use i...
virtual StatusCode process(CaloCellContainer *theCellContainer, const EventContext &ctx) const override
process calo cell collection to apply corrections
virtual StatusCode initialize() override
initialize method
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
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 void setEnergy(float energy)
set energy
Definition CaloCell.h:472
virtual bool badcell() const
check is cell is dead
Definition CaloCell.cxx:144
Identifier ID() const
get ID (from cached data member) non-virtual and inline for fast access
Definition CaloCell.h:295
This class groups all DetDescr information related to a CaloCell.
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
DataModel_detail::iterator< DataVector > iterator
Definition DataVector.h:842
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.
value_type get_compact() const
Get the compact id.
This is a "hash" representation of an Identifier.
Identifier32 get_identifier32() const
Get the 32-bit version Identifier, will be invalid if >32 bits needed.
bool test(const uint16_t prov, const LArProvenance check)