ATLAS Offline Software
Loading...
Searching...
No Matches
eflowLayerIntegrator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
5/********************************************************************
6
7NAME: eflowLayerIntegrator.h
8PACKAGE: offline/Reconstruction/eflowRec
9
10AUTHORS: M.Hodgkinson, R Duxfield (based on R.Duxfields Root package)
11CREATED: 18th Aug, 2005
12
13********************************************************************/
14
15//Athena Headers
26
27#include "CaloDetDescr/CaloDetDescrElement.h"
28#include "CaloEvent/CaloCell.h"
29
31
32eflowLayerIntegrator::eflowLayerIntegrator(double stdDev, double error, double rMaxOverStdDev, bool isHLLHC) :
33 m_rMax(rMaxOverStdDev * stdDev),
34 m_isHLLHC(isHLLHC),
35 m_allClustersIntegral(eflowCalo::nRegions, 0.0),
37 m_integrator(std::make_unique<eflowCellIntegrator<0> >(stdDev, error)),
38 m_integratorLookup(std::make_unique<eflowCellIntegrator<1> >(stdDev, error)) {
39 eflowDatabase database;
40
41 /* Set up density conversion factors */
42 double emX0PerUnitLengthToTheMinus3 = pow(database.getEmX0PerUnitLength(), -3.0);
43 double hadX0PerUnitLengthToTheMinus3 = pow(database.getHadX0PerUnitLength(), -3.0);
44 for (int i = 0; i < eflowCalo::nRegions; i++) {
45 eflowCaloENUM layer = (eflowCaloENUM)(i);
46 m_densityConversion[i] = (layer >= eflowCalo::EMB1 && layer <= eflowCalo::EME3) ?
47 emX0PerUnitLengthToTheMinus3 :
48 hadX0PerUnitLengthToTheMinus3;
49 if(i==13) m_densityConversion[i] = pow(database.getFCalX0PerUnitLength(0), -3.0);
50 if(i==14) m_densityConversion[i] = pow(database.getFCalX0PerUnitLength(1), -3.0);
51 if(i==15) m_densityConversion[i] = pow(database.getFCalX0PerUnitLength(2), -3.0);
52 }
53
54 /* More setup */
55 double nUnitCellsPerWindow = M_PI * stdDev * stdDev / (database.getEtaUnit() * database.getPhiUnit());
56 std::vector<double> cellEtaWidth = database.getCellEtaWidth();
57 std::vector<double> cellPhiWidth = database.getCellPhiWidth();
58 for (int i = 0; i < eflowCalo::nRegions; i++){
60 nUnitCellsPerWindow / (cellEtaWidth[i] * cellPhiWidth[i]);
61 }
62}
63
65 : m_rMax (originalEflowLayerIntegrator.m_rMax),
66 m_isHLLHC (originalEflowLayerIntegrator.m_isHLLHC),
67 m_allClustersIntegral (originalEflowLayerIntegrator.m_allClustersIntegral),
69 m_integrator (std::make_unique<eflowCellIntegrator<0> >(*originalEflowLayerIntegrator.m_integrator)),
70 m_integratorLookup (std::make_unique<eflowCellIntegrator<1> >(*originalEflowLayerIntegrator.m_integratorLookup))
71{
72 for (int i = 0; i < eflowCalo::nRegions; i++){
73 m_densityConversion[i] = originalEflowLayerIntegrator.m_densityConversion[i];
75 }
76}
77
79 if (this == &originalEflowLayerIntegrator) return *this;
80 //if not assigning to self, then we copy the data to the new object
81 else {
82 m_rMax = originalEflowLayerIntegrator.m_rMax;
83 m_isHLLHC = originalEflowLayerIntegrator.m_isHLLHC;
84 m_allClustersIntegral = originalEflowLayerIntegrator.m_allClustersIntegral;
86 m_integrator = std::make_unique<eflowCellIntegrator<0> >(*originalEflowLayerIntegrator.m_integrator);
87 m_integratorLookup = std::make_unique<eflowCellIntegrator<1> >(*originalEflowLayerIntegrator.m_integratorLookup);
88
89 for (int i = 0; i < eflowCalo::nRegions; i++){
90 m_densityConversion[i] = originalEflowLayerIntegrator.m_densityConversion[i];
92 }
93 return *this;
94 }//if not assigning to self, then we have copied the data to the new object
95}
96
98
100 for (int iLayer = 0; iLayer < eflowCalo::nRegions; iLayer++) {
102 }
103 /* Calculate the caloDepthArray */
104 double em2Eta = trackCalo.getEM2eta();
105 if (!m_isHLLHC) {
106 if ( fabs(em2Eta) > 2.5 ) em2Eta = 2.49; //sometimes track extrapolator returns e.g. 2.51 for em2Eta, which causes depth array to be filled with zeroes.
107 }
108 else{
109 if(em2Eta<-998.) em2Eta = trackCalo.getFCAL0eta();
110 if ( fabs(em2Eta) > 4.0 ) { em2Eta = 3.99; } //sometimes track extrapolator returns e.g. 4.01 for em2Eta, which causes depth array to be filled with zeroes.
111 }
112
113 m_caloModel.calcDepthArray(em2Eta, 1.0e-4);
114}
115
116void eflowLayerIntegrator::addToAllClustersIntegral(const std::vector<double>& clusterIntegral) {
117 assert(clusterIntegral.size() == m_allClustersIntegral.size());
118
119 if (clusterIntegral.size() != m_allClustersIntegral.size()){
120 std::cerr << " eflowLayerIntegrator ERROR: cluster integral sizes do not match" << std::endl;
121 return;
122 }
123
124 for (int i = 0; i < eflowCalo::nRegions; i++) {
126 m_allClustersIntegral[i] += clusterIntegral[i];
127 }
128 }
129}
130
131void eflowLayerIntegrator::measureNewClus(const std::vector<xAOD::CaloCluster*>& clusVec, const eflowTrackCaloPoints& trackCalo) {
133
134 for (xAOD::CaloCluster* cluster : clusVec) {
135 measureCluster(cluster, trackCalo);
136 }
137}
138
139void eflowLayerIntegrator::measureNewClus(const std::vector<eflowRecCluster*>& efRecClusters, eflowRecTrack* track) {
140 resetAllClustersIntegralForNewTrack(track->getTrackCaloPoints());
141
142 const EventContext& ctx = Gaudi::Hive::currentContext();
143 for (eflowRecCluster* cluster : efRecClusters) {
145 }
146}
147
150
151 measureCluster(trackClusterLink);
152}
153
156
157 measureCluster(clus, trackCalo);
158}
159
161 if (trackClusterLink->getClusterIntegral().empty()){
162 /* The track-cluster pair hasn't been integrated yet. Integrate as usual and store the results */
163 measureCluster(trackClusterLink->getCluster()->getCluster(), trackClusterLink->getTrack()->getTrackCaloPoints());
165 if (trackClusterLink->getTrack()->getCaloDepthArray().empty()) {
166 trackClusterLink->getTrack()->setCaloDepthArray(m_caloModel.getDepthArray());
167 }
168 } else {
169 /* The track-cluster pair has already been integrated. Take integral from the TrackClusterLink and add to total integral */
170 addToAllClustersIntegral(trackClusterLink->getClusterIntegral());
171 }
172}
173
176
177 const CaloClusterCellLink* theCellLink = clus->getCellLinks();
178
179 if (theCellLink){
180
181 CaloClusterCellLink::const_iterator itCell = theCellLink->begin();
182 CaloClusterCellLink::const_iterator itCellEnd = theCellLink->end();
183
184 for (; itCell != itCellEnd; ++itCell) {
185 measureCell(*itCell, trackCalo);
186 }
187 }//if valid cell link
188
190
191}
192
194 const CaloDetDescrElement* caloDetDescrElement = cell->caloDDE();
195 if (!caloDetDescrElement) return;
196 //very rarely a calorimeter cell has zero volume - in such cases one cannot calculate an energy fensity.
197 //This is expected to happen for certain cells, for example presampler barrel or some tile gap cells.
198 //See https://its.cern.ch/jira/browse/ATR-20919 for discussion of this bug.
199 if ( caloDetDescrElement->volume() < 1e-6 ) return;
200
201 eflowCaloENUM layer = eflowCalo::translateSampl(caloDetDescrElement->getSampling());
202 if (eflowCalo::Unknown == layer) { return; }
203
204 const double extrapTrackEta = trackCalo.getEta(layer);
205 const double extrapTrackPhi = trackCalo.getPhi(layer);
206 if (extrapTrackEta == eflowTrackCaloPoints::defaultEta() ||
207 extrapTrackPhi == eflowTrackCaloPoints::defaultPhi()) {
208 return;
209 }
210
211 const double etaWidth = caloDetDescrElement->deta();
212 const double phiWidth = caloDetDescrElement->dphi();
213
214 const double dEta = cell->eta() - extrapTrackEta;
215 const double dPhi = xAOD::P4Helpers::deltaPhi(cell->phi(), extrapTrackPhi);
216 const double dr = sqrt(dEta * dEta + dPhi * dPhi);
217
218 if ( fabs(dr - std::max(etaWidth, phiWidth)) <= m_rMax || dr <= m_rMax ) {
219
220 eflowRange etaRange(dEta - etaWidth/2.0, dEta + etaWidth/2.0);
221 eflowRange phiRange(dPhi - phiWidth/2.0, dPhi+phiWidth/2.0);
222
223 const double weight = m_integratorLookup->integrate(etaRange, phiRange);
224
225 m_singleClusterIntegral[layer] += weight * cell->energy() / caloDetDescrElement->volume();
226 }
227
228}
229
231
232 const double* depthArray = m_caloModel.getDepthArray();
233
234 double xPrev = 0.0;
235 double yPrev = 0.0;
237 double maxGradient = -10.0;
238
239 for (int layer = 0; layer < eflowCalo::nRegions; ++layer){
240
241 if (m_allClustersIntegral[layer] == eflowTrackCaloPoints::defaultEta()) { continue; }
242
243 double convertedDensity = m_allClustersIntegral[layer] * m_densityConversion[layer];
245
246 const double dx = depthArray[depthLayer+1] - xPrev;
247 const double dy = convertedDensity - yPrev;
248 xPrev = depthArray[depthLayer+1];
249 yPrev = convertedDensity;
250 const double gradient = dy / dx;
251
252 if (gradient > maxGradient) {
253 maxGradient = gradient;
254 result = layer;
255 }
256 }
257
259}
#define M_PI
constexpr int pow(int base, int exp) noexcept
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
This class groups all DetDescr information related to a CaloCell.
CaloCell_ID::CaloSample getSampling() const
cell sampling
This defines the eflowCalo enum, which is used to label calorimeter layers in a simplified scheme whi...
static LAYER translateSampl(CaloCell_ID::CaloSample sampl)
static const int nRegions
Class that controls the 2D integration.
Stores calorimeter cell eta and phi widths, a X0 per unit length in the EM and HAD calorimeters.
static DEPTHLAYER depthIndex(eflowCaloENUM layer)
static J1STLAYER translateCalo(eflowCaloENUM layer)
std::vector< double > m_allClustersIntegral
void resetAllClustersIntegralForNewTrack(const eflowTrackCaloPoints &trackCalo)
std::unique_ptr< eflowCellIntegrator< 1 > > m_integratorLookup
void measureCluster(eflowTrackClusterLink *trackClusterLink)
eflowLayerIntegrator & operator=(const eflowLayerIntegrator &originalEflowLayerIntegrator)
eflowDepthCalculator m_caloModel
void addToAllClustersIntegral(const std::vector< double > &clusterIntegral)
void measureCell(const CaloCell *cell, const eflowTrackCaloPoints &trackCalo)
void measureNewClus(const xAOD::CaloCluster *clus, const eflowTrackCaloPoints &trackCalo)
eflowLayerIntegrator(double stdDev, double error, double rMaxOverStdDev, bool isHLLHC=false)
double m_densityConversion[eflowCalo::nRegions]
std::vector< double > m_singleClusterIntegral
std::vector< double > m_nUnitCellPerWindowOverCellEtaPhiArea
eflowFirstIntENUM getFirstIntLayer() const
std::unique_ptr< eflowCellIntegrator< 0 > > m_integrator
This class extends the information about a xAOD::CaloCluster.
xAOD::CaloCluster * getCluster()
This class extends the information about a xAOD::Track.
const std::vector< double > & getCaloDepthArray() const
const eflowTrackCaloPoints & getTrackCaloPoints() const
void setCaloDepthArray(const double *depthArray)
This class stores a map of calorimeter layers and track parameters (the result of the track extrapola...
double getPhi(eflowCalo::LAYER layer) const
double getEta(eflowCalo::LAYER layer) const
bool haveLayer(eflowCalo::LAYER layer) const
const CaloClusterCellLink * getCellLinks() const
Get a pointer to the CaloClusterCellLink object (const version)
eflowCalo::LAYER eflowCaloENUM
eflowFirstIntRegions::J1STLAYER eflowFirstIntENUM
eflowDepthCalculator::DEPTHLAYER eflowDepthLayerENUM
eflowRangeBase< double > eflowRange
Definition eflowUtil.h:139
STL namespace.
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.