ATLAS Offline Software
Loading...
Searching...
No Matches
CaloTowerGeometry.cxx
Go to the documentation of this file.
1/* Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */
3
4namespace { constexpr auto pi = 3.14159265358979323846; }
5
7const double CaloTowerGeometry::m_invalidValue = -999.;
8
10 m_caloDDM(caloDDM)
11 , m_towerEtaWidth(0.)
12 , m_towerPhiWidth(0.)
13 , m_towerArea(0.)
14 , m_towerBins(0)
15 , m_maxCellHash(0) //----------------------------------------//
16 , m_towerEtaBins(100) // Default tower definition is "hadronic" //
17 , m_towerEtaMin(-5.0) // towers of size 0.1 x pi/32. //
18 , m_towerEtaMax(5.0) //----------------------------------------//
19 , m_adjustEta(true)
20 , m_towerPhiBins(64)
21 , m_towerPhiMin(-pi) //----------------------------------------//
22 , m_towerPhiMax(pi) // FCal vertical and horizontal cell //
23 , m_fcal1Xslice(8.) // slicing creates "mini-cells" which are //
24 , m_fcal1Yslice(8.) // then projected onto towers. The mini- //
25 , m_fcal2Xslice(8.) // cell signal is 1/(Nx x Ny) x Ecell, //
26 , m_fcal2Yslice(12.) // where Nx(y) are the number of x(y) //
27 , m_fcal3Xslice(12.) // slices. //
28 , m_fcal3Yslice(12.) //----------------------------------------//
29{}
30
31
32StatusCode CaloTowerGeometry::initialize(MsgStream& msg)
33{
34 // prepare FCal segmentation
37 for ( uint_t i(0); i<m_ndxFCal.size(); ++i ) { m_wgtFCal[i] = 1./(m_ndxFCal.at(i)*m_ndyFCal.at(i)); }
38
39 // other derived quantities
40 if ( m_towerEtaBins > 0 ) {
42 } else {
43 msg << MSG::ERROR << "Number of tower eta bins is invalid (" << m_towerEtaBins << " bins)" << endmsg;
44 return StatusCode::FAILURE;
45 }
46 if ( m_towerPhiBins > 0 ) {
48 } else {
49 msg << MSG::ERROR << "Number of tower phi bins is invalid (" << m_towerPhiBins << " bins)" << endmsg;
50 return StatusCode::FAILURE;
51 }
52
55 m_maxCellHash = m_caloDDM->element_size()-1;
56 m_numberOfCells = m_caloDDM->element_size();
57
58 return f_setupTowerGrid(msg);
59}
60
62{
63 // initialized
64 if ( m_maxCellHash == 0 ) {
65 msg << "Service not initialized? Maximum cell hash is " << m_maxCellHash << endmsg;
66 return StatusCode::FAILURE;
67 }
68
69 // payload template
71
72 // set up lookup table
73 msg << "Setting up cell-to-tower lookup for " << m_numberOfCells << " calorimeter cells" << endmsg;
75
76 // loop cells
77 for ( auto fcell(m_caloDDM->element_begin()); fcell != m_caloDDM->element_end(); ++fcell ) {
78 // reference cell descriptor
79 const CaloDetDescrElement* pCaloDDE = *fcell;
80 // check hash id validity
81 index_t cidx(pCaloDDE->calo_hash());
82 if ( cidx >= m_towerLookup.size() ) {
83 msg << MSG::WARNING << "Cell hash identifier out of range " << cidx << "/" << m_towerLookup.size() << ", ignore cell" << endmsg;
84 } else {
85 if ( pCaloDDE->is_lar_fcal() ) {
86 if ( this->f_setupTowerGridFCal(pCaloDDE,msg).isFailure() ) { return StatusCode::FAILURE; }
87 } else {
88 if ( this->f_setupTowerGridProj(pCaloDDE,msg).isFailure() ) { return StatusCode::FAILURE; }
89 }
90 } // cell hash in range?
91 } // loop cell descriptors
92
93 return StatusCode::SUCCESS;
94}
95
97{
98 //-----------------------------------------------------------------------------------------//
99 // FCal special - the rectangular (in linear space) calorimeter cells are sub-divided into //
100 // small cells and then shared across as many towers as the small cells cover. //
101 //-----------------------------------------------------------------------------------------//
102
103 // collect geometrical variables
104 int cLayer(pCaloDDE->getLayer()-1); // FCal layer number 1..3 -> array indices 0..2
105
106 double cXpos(pCaloDDE->x_raw()); // FCal cell x position (cell center)
107 double cYpos(pCaloDDE->y_raw()); // FCal cell y position (cell center)
108 double cZpos(pCaloDDE->z_raw()); // FCal cell z position (cell center)
109 double cZpos2(cZpos*cZpos);
110
111 double cXwid(pCaloDDE->dx()); // FCal cell x full width
112 double cYwid(pCaloDDE->dy()); // FCal cell y full width
113
114 // double xSlice(cXwid/m_ndxFCal[cLayer]); // FCal cell x slize width
115 // double ySlice(cYwid/m_ndyFCal[cLayer]); // FCal cell y slice width
116 double cWght(m_wgtFCal[cLayer]); // FCal cell geometrical (signal) weight
117
118 int nXslice((int)m_ndxFCal[cLayer]); // FCal number of x slices
119 int nYslice((int)m_ndyFCal[cLayer]); // FCal number of y slices
120 double cXstp(cXwid/((double)nXslice)); // FCal slice x width
121 double cYstp(cYwid/((double)nYslice)); // FCal slice y width
122
123 // fill cell fragments
124 // double xoff(cXpos-cXwid/2.+cXstp/2.); double yoff(cYpos-cYwid/2.+cYstp/2.);
125 double x(cXpos-(cXwid-cXstp)/2.);
126 double xlim(cXpos+cXwid/2.); double ylim(cYpos+cYwid/2.);
127 double etaOrig(0.);
128 // for ( int ix(0); ix < nXslice; ++ix ) {
129 // double x(xoff+ix*cXstp);
130 while ( x < xlim ) {
131 // for ( int iy(0); iy < nYslice; ++iy ) {
132 // double y(yoff+iy*cYstp);
133 double y(cYpos-(cYwid-cYstp)/2.);
134 while ( y < ylim ) {
135 double r(std::sqrt(x*x+y*y+cZpos2));
136 double eta(-0.5*std::log((r-cZpos)/(r+cZpos)));
137 bool etaAdjusted(false);
138 if ( m_adjustEta ) {
139 if ( eta < m_towerEtaMin ) {
140 etaAdjusted = true;
141 etaOrig = eta;
143 } else if ( eta > m_towerEtaMax ) {
144 etaAdjusted = true;
145 etaOrig = eta;
147 }
148 }
149 double phi(CaloPhiRange::fix(std::atan2(y,x)));
150 index_t towerIdx(this->towerIndex(eta,phi));
151 // tower index not valid
152 if ( isInvalidIndex(towerIdx) ) {
153 msg << MSG::WARNING << "Found invalid tower index for FCal cell (eta,phi) = (" << eta << "," << phi << ") at (x,y,z) = ("
154 << x << "," << y << "," << cZpos << ") [cell ignored]" << endmsg;
155 } else {
156 // add tower to lookup
157 if ( etaAdjusted ) {
158 msg << MSG::WARNING << "FCal cell direction (eta,phi) = (" << etaOrig << "," << phi << ") for cell at (x,y,z) = ("
159 << x << "," << y << "," << cZpos << ") adjusted to (eta,phi) = (" << eta << "," << phi << ") [cell adjusted]" << endmsg;
160 }
161 f_assign(pCaloDDE->calo_hash(),towerIdx,cWght);
162 } // tower index ok
163 y += cYstp;
164 } // loop on y fragments
165 x += cXstp;
166 } // loop on x fragments
167 return StatusCode::SUCCESS;
168}
169
171{
172 // projective readout calos - collect geometrical variables
173 double cEtaPos(pCaloDDE->eta_raw()); // projective cell center in pseudorapidity
174 double cEtaWid(pCaloDDE->deta()); // projective cell width in pseudorapidity
175 double cPhiPos(pCaloDDE->phi_raw()); // projective cell center in azimuth
176 double cPhiWid(pCaloDDE->dphi()); // projective cell width in azimuth
177
178 // check cell-tower overlap area fractions
179 uint_t kEta(static_cast<uint_t>(cEtaWid/m_towerEtaWidth+0.5)); kEta = kEta == 0 ? 1 : kEta; // fully contained cell may have 0 fragments (protection)
180 uint_t kPhi(static_cast<uint_t>(cPhiWid/m_towerPhiWidth+0.5)); kPhi = kPhi == 0 ? 1 : kPhi;
181
182 // print out
183 if ( kEta > 1 || kPhi > 1 ) {
184 msg << MSG::VERBOSE << "Found cell [" << pCaloDDE->calo_hash() << "/0x" << std::hex << pCaloDDE->identify().get_compact()
185 << std::dec << "] spawning several towers."
186 << " Neta = " << kEta << ", Nphi = " << kPhi << endmsg;
187 }
188
189 // share cells
190 double cWght(1./((double)kEta*kPhi)); // area weight
191 double sEta(cEtaWid/((double)kEta)); // step size (pseudorapidity)
192 double sPhi(cPhiWid/((double)kPhi)); // step size (azimuth)
193 double oEta(cEtaPos-sEta/2.); // offset (pseudorapidity)
194 double oPhi(cPhiPos-sPhi/2.); // offset (azimuth)
195
196 // loop over cell fragments
197 for ( uint_t ie(1); ie<=kEta; ++ie ) {
198 double ceta(oEta+((double)ie-0.5)*sEta); // eta of fragment
199 for ( uint_t ip(1); ip<=kPhi; ++ip ) {
200 double cphi(oPhi+((double)ip-0.5)*sPhi); // phi fragment
201 // tower index
202 index_t towerIdx(this->towerIndex(ceta,cphi));
203 if ( isInvalidIndex(towerIdx) ) {
204 msg << MSG::ERROR << "Found invalid tower index for non-FCal cell (id,eta,phi) = (" << pCaloDDE->calo_hash()
205 << "," << ceta << "," << cphi << ")" << endmsg;
206 return StatusCode::FAILURE;
207 } // invalid tower index
208 f_assign(pCaloDDE->calo_hash(),towerIdx,cWght);
209 } // phi fragment loop
210 } // eta fragment loop
211 return StatusCode::SUCCESS;
212}
213
214//------//
215// Fill //
216//------//
217
218double CaloTowerGeometry::f_assign(IdentifierHash cellHash,index_t towerIdx,double wght)
219{
220 // check if cell-tower already related
221 uint_t cidx(static_cast<uint_t>(cellHash));
222 for ( element_t& elm : m_towerLookup.at(cidx) ) {
223 if ( towerIndex(elm) == towerIdx ) { std::get<1>(elm) += wght; return cellWeight(elm); }
224 }
225 // not yet related
226 m_towerLookup[cidx].emplace_back(towerIdx,wght);
227 return cellWeight(m_towerLookup.at(cidx).back());
228}
229
230//--------//
231// Access //
232//--------//
233
234StatusCode CaloTowerGeometry::access(IdentifierHash cellHash,std::vector<index_t>& towerIdx,std::vector<double>& towerWghts) const
235{
236 towerIdx.clear();
237 towerWghts.clear();
238
239 uint_t cidx(static_cast<uint_t>(cellHash));
240
241 if ( cidx >= m_towerLookup.size() ) {
242 //ATH_MSG_WARNING("Invalid cell hash index " << cellHash << ", corresponding index " << cidx << " not found in tower lookup");
243 return StatusCode::SUCCESS;
244 }
245
246 if ( towerIdx.capacity() < m_towerLookup.at(cidx).size() ) { towerIdx.reserve(m_towerLookup.at(cidx).size()); }
247 if ( towerWghts.capacity() < m_towerLookup.at(cidx).size() ) { towerWghts.reserve(m_towerLookup.at(cidx).size()); }
248
249 for ( const auto& elm : m_towerLookup.at(cidx) ) { towerIdx.push_back(towerIndex(elm)); towerWghts.push_back(cellWeight(elm)); }
250
251 return StatusCode::SUCCESS;
252}
253
255{
256 // check input
257 uint_t cidx(static_cast<uint_t>(cellHash));
258 if ( cidx >= m_towerLookup.size() ) {
259 //ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("invalid cell hash %6zu beyond range (max hash is %6zu)",cidx,m_maxCellHash) );
260 return {};
261 } else {
262 return m_towerLookup.at(cidx);
263 }
264}
265
266//-----------------------//
267// Tower Geometry Helper //
268//-----------------------//
269
271{
272 index_t cidx(static_cast<uint_t>(cellHash));
273 double cwght(0.);
274
275 if ( cidx < m_towerLookup.size() ) {
276 for ( auto elm : m_towerLookup.at(cidx) ) {
277 if ( towerIndex(elm) == towerIdx ) { cwght = cellWeight(elm); break; }
278 }
279 }
280 return cwght;
281}
282
283//---------------//
284// Index Helpers //
285//---------------//
286
288{
289 const auto *const cdde = f_caloDDE(cellHash);
290 return cdde != nullptr ? etaIndex(cdde->eta()) : invalidIndex();
291}
292
299
301{
302 const auto *const cdde = f_caloDDE(cellHash);
303 return cdde != nullptr ? phiIndex(cdde->phi()) : invalidIndex();
304}
305
307{
309 return dphi >= m_towerPhiMin && dphi <= m_towerPhiMax
310 ? index_t(std::min(static_cast<uint_t>((phi-m_towerPhiMin)/m_towerPhiWidth),m_towerPhiBins-1))
311 : invalidIndex();
312}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define endmsg
#define pi
#define y
#define x
This class groups all DetDescr information related to a CaloCell.
virtual int getLayer() const
cell layer
Identifier identify() const override final
cell identifier
bool is_lar_fcal() const
cell belongs to FCAL
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.
index_t invalidIndex() const
Returns value of invalid index.
double m_fcal3Xslice
Number of x slices for cells in FCal3.
uint_t m_towerBins
Maximum number of towers.
index_t towerIndex(IdentifierHash cellHash) const
Get global tower index for a calorimeter cell referenced by its hash identifier.
double m_fcal2Yslice
Number of y slices for cells in FCal2.
double m_fcal2Xslice
Number of x slices for cells in FCal2.
IdentifierHash::value_type index_t
Type for scalar (pseudorapidity,azimuth) index (is an unsigned int type)
static const index_t m_invalidIndex
Invalid index indicator.
double m_fcal3Yslice
Number of y slices for cells in FCal3.
uint_t m_maxCellHash
Maximum cell hash value.
double m_towerPhiMin
Lower boundary .
uint_t m_towerPhiBins
Number of bins.
CaloTowerGeometry()=delete
StatusCode initialize(MsgStream &msg)
Initialize object.
index_t etaIndex(IdentifierHash cellHash) const
Get tower bin index for a calorimeter cell referenced by its hash identifier.
StatusCode f_setupTowerGridFCal(const CaloDetDescrElement *pCaloDDE, MsgStream &msg)
Internally used function mapping an FCal cell onto the tower grid.
double m_towerPhiMax
Upper boundary .
uint_t m_towerEtaBins
Internally stored tower grid descriptors.
index_t phiIndex(IdentifierHash cellHash) const
Get tower bin index for a calorimeter cell referenced by its hash identifier.
double m_fcal1Yslice
Number of y slices for cells in FCal1.
std::size_t uint_t
Type for unsigned integer.
double m_towerPhiWidth
Width of tower bin in azimuth.
uint_t m_numberOfCells
Total number of cells.
std::array< double, 3 > m_ndxFCal
Stores number of fragments along x for each FCal module.
const CaloDetDescrElement * f_caloDDE(IdentifierHash cellHash) const
Retrieve calorimeter detector description element for a given cell hash identifier.
double m_towerEtaMin
Lower boundary .
double f_assign(IdentifierHash cellHash, index_t towerIdx, double wgt)
Internally used function assigning tower to cell with update of weight if same tower is already assig...
elementmap_t m_towerLookup
Cell-to-tower mapping lookup store.
std::array< double, 3 > m_wgtFCal
Stores geometrical weights.
const CaloDetDescrManager * m_caloDDM
Pointer to calorimeter detector description.
std::array< double, 3 > m_ndyFCal
Stores number of fragments along y for each FCal module.
StatusCode access(IdentifierHash cellHash, std::vector< index_t > &towerIdx, std::vector< double > &towerWghts) const
double cellWeight(const element_t &elm) const
Retrieve cell signal weight from lookup table entry.
std::tuple< index_t, double > element_t
Type storing tower index and geometrical weight.
double m_towerEtaWidth
Width of tower bin in pseudorapidity.
double m_fcal1Xslice
Number of x slices for cells in FCal1.
double m_towerArea
Area of individual tower.
StatusCode f_setupTowerGrid(MsgStream &msg)
Internally used function setting up the lookup store.
bool m_adjustEta
Adjust FCal cells to eta boundary (default true )
StatusCode f_setupTowerGridProj(const CaloDetDescrElement *pCaloDDE, MsgStream &msg)
Internally used function mapping a projective cell onto the tower grid.
std::vector< element_t > elementvector_t
Type for list of elements holding tower index and list of weights.
bool isInvalidIndex(index_t idx) const
Returns true if argument is equal to the value provided by invalidIndex()
static const double m_invalidValue
Return value for out-of-range indices andother invalid conversions to a physical quantity.
elementvector_t getTowers(IdentifierHash cellHash) const
Retrieve the list of towers associated with a calorimeter cell referenced its hash identifier.
double m_towerEtaMax
Upper boundary .
This is a "hash" representation of an Identifier.
value_type get_compact() const
Get the compact id.
int r
Definition globals.cxx:22
int ev
Definition globals.cxx:25
int32_t index_t
The index type of the node in the vector.
MsgStream & msg
Definition testRead.cxx:32