ATLAS Offline Software
CaloCellNeighborsAverageCorr.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2019 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 
19 #include "CaloIdentifier/TileID.h"
21 #include "Identifier/Identifier.h"
23 #include <map> //useful in testMode
24 
25 // ======================================================
26 // Constructor
27 
29  const std::string& type,
30  const std::string& name,
31  const IInterface* parent)
32  :base_class(type, name, parent),
33  m_calo_id(nullptr),
34  m_tile_id(nullptr)
35 {
36  declareProperty("testMode",m_testMode=false,"test mode");
37  declareProperty("skipDeadFeb", m_skipDeadFeb=true, "Skip dead LAr Febs (default = true)");
38  declareProperty("skipDeadLAr", m_skipDeadLAr=false, "Skip all dead LAr cells (default = false)");
39  declareProperty("skipDeadDrawer", m_skipDeadDrawer=false, "Skip dead Tile drawers (default = false)");
40  declareProperty("skipDeadTile", m_skipDeadTile=true, "Skip all dead Tile cells (default = true)");
41 }
42 
43 //========================================================
44 // Initialize
45 
47 {
48  ATH_MSG_INFO ( " in CaloCellNeighborsAverageCorr::initialize() " );
49 
50  if (m_testMode)
51  ATH_MSG_DEBUG ( " Running in Test Mode. " );
52 
53  // don't need to check status of the drawer if all dead cells are ignored
55  ATH_MSG_WARNING ( "Please, don't set skipDeadDrawer and skipDeadTile to True at the same time" );
56  ATH_MSG_WARNING ( "Setting skipDeadDrawer=False" );
57  m_skipDeadDrawer=false;
58  }
59 
60  ATH_MSG_INFO ( "Skip Dead Feb = " << ((m_skipDeadFeb)?"true":"false") );
61  ATH_MSG_INFO ( "Skip Dead LAr = " << ((m_skipDeadLAr)?"true":"false") );
62  ATH_MSG_INFO ( "Skip Dead Drawer = " << ((m_skipDeadDrawer)?"true":"false") );
63  ATH_MSG_INFO ( "Skip Dead Tile = " << ((m_skipDeadTile)?"true":"false") );
64 
65 
66  ATH_CHECK( detStore()->retrieve (m_calo_id, "CaloCell_ID") );
68 
69  ATH_MSG_INFO ( "CaloCellNeighborsAverageCorr initialize() end" );
70 
71  return StatusCode::SUCCESS;
72 }
73 
74 // ============================================================================
75 
78  const EventContext& /*ctx*/) const
79 {
80  ATH_MSG_VERBOSE ( " in process " );
81 
82  std::vector<IdentifierHash> theNeighbors;
83  theNeighbors.reserve(22);
84 
85  std::map<const CaloCell*,float> cannedUncorrectedEnergies;
86  if (m_testMode) { //fill in the map of uncorrected energies, to preserve it for later use.
87  CaloCellContainer::const_iterator itrCell_test=theCont->begin();
88  for (; itrCell_test!=theCont->end();++itrCell_test){
89  const CaloCell* pointerToCell=*itrCell_test; //yes, this is an iterator that when dereferenced returns a pointer, not a CaloCell directly.
90  cannedUncorrectedEnergies[pointerToCell] = pointerToCell->energy();
91  //std::cout << "GEORGIOS DEBUGGING For CaloCell* = " << pointerToCell << " we have energy = " << cannedUncorrectedEnergies[pointerToCell] << std::endl;
92  }
93  }
94 
95  int nGoodCellsPerDrawer[4][64];
96 
97  if (m_skipDeadDrawer) {
98  memset(nGoodCellsPerDrawer,0,sizeof(nGoodCellsPerDrawer));
99 
100  size_t cellItr = theCont->indexFirstCellCalo(CaloCell_ID::TILE);
101  size_t lastCell = theCont->indexLastCellCalo(CaloCell_ID::TILE);
102 
103  for (; cellItr <= lastCell; ++cellItr) {
104  const CaloCell* CCell = (*theCont)[cellItr];
105  if (CCell && ! CCell->badcell() ) {
106  Identifier id = CCell->ID();
107  int part = std::min(m_tile_id->section(id),2)+m_tile_id->side(id);
108  int module = m_tile_id->module(id);
109  ++nGoodCellsPerDrawer[part][module];
110  }
111  }
112  if (msgLvl(MSG::VERBOSE)) {
113  // 1-1 2-1 1+1 2+1
114  const char * name[4] = {"LBC","EBC","LBA","EBA"};
115  for (int part=0; part<4; ++part) {
116  for (int module=0; module<64; ++module) {
117  //log << MSG::VERBOSE << name[part] << module+1 << " nCells "
118  // << nGoodCellsPerDrawer[part][module]
119  // << ( ( nGoodCellsPerDrawer[part][module] < 2 ) ? " bad drawer" : "")
120  // << endmsg;
121  if ( nGoodCellsPerDrawer[part][module] < 2 ) {
122  ATH_MSG_VERBOSE ( "Bad drawer " << name[part] << module+1 );
123  }
124  }
125  }
126  }
127  }
128 
129  CaloCellContainer::iterator itrCell=theCont->begin();
130  for (; itrCell!=theCont->end();++itrCell){
131  CaloCell * aCell=*itrCell;
132 
133  if (aCell->badcell() || m_testMode) {
134 
135  const CaloDetDescrElement* caloDDE = aCell->caloDDE();
136  if (!caloDDE) continue;
137  int theCellSubCalo = caloDDE->getSubCalo();
138 
139  bool isTile = (theCellSubCalo == CaloCell_ID::TILE);
140 
141  if (isTile) {
142 
143  if (m_skipDeadTile) {
144  ATH_MSG_VERBOSE ( " skipping Tile hash " << m_calo_id->calo_cell_hash(aCell->ID()) );
145  continue;
146  } else if (m_skipDeadDrawer) {
147 
148  Identifier id = aCell->ID();
149  int part = std::min(m_tile_id->section(id),2)+m_tile_id->side(id);
150  int module = m_tile_id->module(id);
151  if ( nGoodCellsPerDrawer[part][module] < 2 ) {
152  ATH_MSG_VERBOSE ( " skipping Tile drawer hash " << m_calo_id->calo_cell_hash(aCell->ID()) );
153  continue;
154  }
155  }
156 
157  } else {
158 
159  if (m_skipDeadLAr) {
160  ATH_MSG_VERBOSE ( " skipping LAr hash " << m_calo_id->calo_cell_hash(aCell->ID()) );
161  continue;
162  } else if (m_skipDeadFeb && ((aCell->provenance() & 0x0200) == 0x0200) ) {
163  ATH_MSG_VERBOSE ( " skipping LAr Feb hash " << m_calo_id->calo_cell_hash(aCell->ID()) );
164  continue;
165  }
166  }
167 
168  //inspired from http://alxr.usatlas.bnl.gov/lxr-stb3/source/atlas/Calorimeter/CaloRec/src/CaloTopoClusterMaker.cxx#585
169  //We need a IdentifierHash to pass as input to the get_neighbors().
170  // IdentifierHash theCellHashID = theCell->getID(); //this doesn't work (any more?)
171  Identifier theCellID = aCell->ID();
172  const float oldE=aCell->energy();
173  IdentifierHash theCellHashID = m_calo_id->calo_cell_hash(theCellID);
174 
175  //Find now the neighbors around theCell, and store them in theNeighbors vector.
176  m_calo_id->get_neighbours(theCellHashID,LArNeighbours::all2D,theNeighbors);
177 
178  //std::cout << "Found " << theNeighbors.size() << " neighbors." << std::endl;
179 
180  //first let's find the volume of theCell we are correcting.
181  float volumeOfTheCell=0;
182  if (caloDDE) volumeOfTheCell = caloDDE->volume();
183  // std::cout << " volumeOfTheCell " << volumeOfTheCell << std::endl;
184  if (volumeOfTheCell==0) continue;
185  //int theCellSampling = caloDDE->getSampling();
186  // if (theCellSubCalo == CaloCell_ID::TILE) {
187  // 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;
188  // }
189 
190 
191  const Identifier theCellRegion=m_calo_id->region_id(theCellID);
192  //loop through neighbors, and calculate average energy density of guys who have a legitimate volume (namely >0).
193  //float totalEnergyDensity=0;
194  //float legitimateNeighbors=0;
195 
196  float goodNeighborEnergyDensitySum=0;
197  unsigned goodNeighbors=0;
198 
199  float betterNeighborEnergyDensitySum=0;
200  unsigned betterNeighbors=0;
201 
202  ATH_MSG_VERBOSE("Cell " << theCellID.get_identifier32().get_compact() << " has " << theNeighbors.size() << " neighbors");
203  for (unsigned int iN=0;iN<theNeighbors.size();iN++) {
204  const CaloCell* thisNeighbor = theCont->findCell(theNeighbors[iN]);
205  //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.
206  if (!thisNeighbor) continue;
207  const CaloDetDescrElement* thisNeighborDDE = (thisNeighbor)->caloDDE();
208  float thisEnergy = thisNeighbor->energy();
209  if (m_testMode) {
210  thisEnergy = cannedUncorrectedEnergies[thisNeighbor];
211  // std::cout << "GEORGIOS DEBUGGING Retrieving cannedUncorrectedEnergies[" << thisNeighbor << "] = " << cannedUncorrectedEnergies[thisNeighbor] << std::endl;
212  }
213  if (thisNeighbor->badcell()) {
214  ATH_MSG_VERBOSE("Ignoring neighbor " << thisNeighbor->ID().get_identifier32().get_compact() << " because of it's bad cell status");
215  continue;
216  }
217  //int thisNeighborSubCalo = thisNeighborDDE->getSubCalo();
218  //int thisNeighborSampling = thisNeighborDDE->getSampling();
219  //if (thisNeighborSubCalo != theCellSubCalo) continue;
220  //if (thisNeighborSampling != theCellSampling) continue; //if the quality of the cell is very different, it's a wrong idea that dE/dV would be similar.
221 
222 
223  float thisVolume = thisNeighborDDE->volume();
224  if (thisVolume <= 0) continue;
225 
226  //A good neightbor if we arrive at this point
227  goodNeighbors++;
228  float thisEnergyDensity= thisEnergy / thisVolume;
229  goodNeighborEnergyDensitySum += thisEnergyDensity;
230 
231 
232  const Identifier thisNeighborRegion=m_calo_id->region_id(thisNeighbor->ID());
233  //Better neighbors are in the same region
234  if (thisNeighborRegion==theCellRegion) {
235  ATH_MSG_VERBOSE("Neighbor is in different region " << thisNeighborRegion.get_identifier32().get_compact() << "/" << theCellRegion.get_identifier32().get_compact());
236  betterNeighbors++;
237  betterNeighborEnergyDensitySum+=thisEnergyDensity;
238  }
239 
240  // if (theCellSubCalo == CaloCell_ID::TILE && theCellSampling == CaloCell_ID::TileBar0)
241  // std::cout << "Neighbor " << iN << " : " << thisNeighborSubCalo << " , " << thisNeighborSampling << " : " << thisNeighbor->eta() << " , " << thisNeighbor->phi() << " E=" << thisNeighbor->energy() << " V=" << thisVolume*1e-6 << " D=" << thisEnergyDensity*1e6 << std::endl;
242 
243  } //end loop over neighbors
244 
245 
246  unsigned nNeighbors=0;
247  float neighborEnergyDensitySum=0;
248 
249  if (betterNeighbors>=2) {//Have at least 2 good neighbors in the same region
250  nNeighbors=betterNeighbors;
251  neighborEnergyDensitySum=betterNeighborEnergyDensitySum;
252  }
253  else {//No good neighbors in the same region
254  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");
255  nNeighbors=goodNeighbors;
256  neighborEnergyDensitySum=goodNeighborEnergyDensitySum;
257  }
258 
259  if(nNeighbors <= 0) {
260  ATH_MSG_DEBUG("Did not get any suitable neighbor for cell " << theCellID.get_identifier32().get_compact() << ". Not corrected.");
261  continue;
262  }
263 
264  const float averageEnergyDensity = neighborEnergyDensitySum/nNeighbors;
265 
266  //now use the average energy density to make a prediction for the energy of theCell
267  const float predictedEnergy = averageEnergyDensity * volumeOfTheCell;
268  aCell->setEnergy(predictedEnergy);
269  ATH_MSG_VERBOSE ( " correcting " << ((isTile)?"Tile":"LAr") << " id " << theCellID.get_identifier32().get_compact() << " Eold="
270  <<oldE << "Enew=" << predictedEnergy << ", used " << nNeighbors << " neighbors" );
271  } // end of if(badcell)
272  } // end loop over cells
273  return StatusCode::SUCCESS;
274 }
275 
276 //memo:
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
CaloCellContainer::indexLastCellCalo
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...
Definition: CaloCellContainer.cxx:141
DataModel_detail::const_iterator
Const iterator class for DataVector/DataList.
Definition: DVLIterator.h:82
CaloCell_Base_ID::calo_cell_hash
IdentifierHash calo_cell_hash(const Identifier cellId) const
create hash id from 'global' cell id
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
CaloDetDescrElement
This class groups all DetDescr information related to a CaloCell. Provides a generic interface for al...
Definition: Calorimeter/CaloDetDescr/CaloDetDescr/CaloDetDescrElement.h:66
CaloCell_Base_ID::region_id
Identifier region_id(const int subCalo, const int barec_or_posneg, const int sampling_or_fcalmodule, const int region_or_dummy) const
Make a region ID from constituting fields and subCalo index; for (Mini)FCAL and Tiles,...
Tile_Base_ID::side
int side(const Identifier &id) const
Definition: Tile_Base_ID.cxx:153
CaloCellNeighborsAverageCorr::m_skipDeadDrawer
bool m_skipDeadDrawer
Definition: CaloCellNeighborsAverageCorr.h:47
Identifier::get_identifier32
Identifier32 get_identifier32() const
Get the 32-bit version Identifier, will be invalid if >32 bits needed.
CaloCell.h
CaloCellNeighborsAverageCorr::m_testMode
bool m_testMode
Definition: CaloCellNeighborsAverageCorr.h:44
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
CaloCell::provenance
uint16_t provenance() const
get provenance (data member)
Definition: CaloCell.h:338
CaloCell::setEnergy
virtual void setEnergy(float energy)
set energy
Definition: CaloCell.cxx:136
Identifier32::get_compact
value_type get_compact() const
Get the compact id.
Definition: Identifier32.h:44
TileID.h
CaloCell_ID.h
CaloCell::energy
double energy() const
get energy (data member)
Definition: CaloCell.h:311
CaloCellNeighborsAverageCorr.h
CaloDetDescrElement::getSubCalo
CaloCell_ID::SUBCALO getSubCalo() const
cell subcalo
Definition: Calorimeter/CaloDetDescr/CaloDetDescr/CaloDetDescrElement.h:433
CaloCellNeighborsAverageCorr::CaloCellNeighborsAverageCorr
CaloCellNeighborsAverageCorr(const std::string &type, const std::string &name, const IInterface *parent)
Definition: CaloCellNeighborsAverageCorr.cxx:28
python.PyAthena.module
module
Definition: PyAthena.py:131
CaloCellContainer::indexFirstCellCalo
int indexFirstCellCalo(const CaloCell_ID::SUBCALO caloNum) const
index of first cell of given calorimeter (-1 if none).
Definition: CaloCellContainer.cxx:137
Tile_Base_ID::module
int module(const Identifier &id) const
Definition: Tile_Base_ID.cxx:159
DataModel_detail::iterator
(Non-const) Iterator class for DataVector/DataList.
Definition: DVLIterator.h:184
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
CaloCell::caloDDE
const CaloDetDescrElement * caloDDE() const
get pointer to CaloDetDescrElement (data member)
Definition: CaloCell.h:305
test_pyathena.parent
parent
Definition: test_pyathena.py:15
CaloCell::badcell
virtual bool badcell() const
check is cell is dead
Definition: CaloCell.cxx:210
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
CaloCell_Base_ID::TILE
@ TILE
Definition: CaloCell_Base_ID.h:46
CaloCellNeighborsAverageCorr::initialize
virtual StatusCode initialize() override
initialize method
Definition: CaloCellNeighborsAverageCorr.cxx:46
CaloCellNeighborsAverageCorr::m_skipDeadFeb
bool m_skipDeadFeb
Definition: CaloCellNeighborsAverageCorr.h:45
CaloCellContainer::findCell
const CaloCell * findCell(const IdentifierHash theHash) const
fast find method given identifier hash.
Definition: CaloCellContainer.cxx:345
python.PyKernel.detStore
detStore
Definition: PyKernel.py:41
CaloDetDescrElement::volume
float volume() const
cell volume
Definition: Calorimeter/CaloDetDescr/CaloDetDescr/CaloDetDescrElement.h:381
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
IdentifierHash.h
CaloCell_Base_ID::get_neighbours
int get_neighbours(const IdentifierHash caloHash, const LArNeighbours::neighbourOption &option, std::vector< IdentifierHash > &neighbourList) const
access to hashes for neighbours return == 0 for neighbours found
Definition: CaloCell_Base_ID.cxx:190
CaloCell::ID
Identifier ID() const
get ID (from cached data member) non-virtual and inline for fast access
Definition: CaloCell.h:279
CaloCellContainer.h
CaloCellContainer
Container class for CaloCell.
Definition: CaloCellContainer.h:55
CaloCellNeighborsAverageCorr::m_skipDeadLAr
bool m_skipDeadLAr
Definition: CaloCellNeighborsAverageCorr.h:46
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
CaloCell
Data object for each calorimeter readout cell.
Definition: CaloCell.h:57
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
CaloCellNeighborsAverageCorr::process
virtual StatusCode process(CaloCellContainer *theCellContainer, const EventContext &ctx) const override
process calo cell collection to apply corrections
Definition: CaloCellNeighborsAverageCorr.cxx:77
CaloIdManager.h
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
Tile_Base_ID::section
int section(const Identifier &id) const
Definition: Tile_Base_ID.cxx:147
IdentifierHash
This is a "hash" representation of an Identifier. This encodes a 32 bit index which can be used to lo...
Definition: IdentifierHash.h:25
CaloCellNeighborsAverageCorr::m_calo_id
const CaloCell_ID * m_calo_id
Definition: CaloCellNeighborsAverageCorr.h:42
CaloCellNeighborsAverageCorr::m_skipDeadTile
bool m_skipDeadTile
Definition: CaloCellNeighborsAverageCorr.h:48
CaloCell_ID::tile_idHelper
const TileID * tile_idHelper() const
access to Tile idHelper
Definition: CaloCell_ID.h:81
LArNeighbours::all2D
@ all2D
Definition: LArNeighbours.h:18
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
CaloCellNeighborsAverageCorr::m_tile_id
const TileID * m_tile_id
Definition: CaloCellNeighborsAverageCorr.h:43
Identifier
Definition: IdentifierFieldParser.cxx:14