ATLAS Offline Software
Loading...
Searching...
No Matches
EFexEMClusterTool.cxx
Go to the documentation of this file.
1// Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
2
9
10#include "EFexEMClusterTool.h"
12
13
14LVL1::EFexEMClusterTool::EFexEMClusterTool(const std::string& type, const std::string& name, const IInterface* parent)
15 : AthAlgTool(type, name, parent)
16{
17 declareProperty("CleanCellContainer", m_useProvenance=true);
18 declareProperty("QualBitMask", m_qualBitMask=0x40);
19
20 // baseline selection properties
21 declareProperty("ClusterEnergyThreshold", m_clustET_thresh = 28., "Cluster energy threshold for baseline selection");
22 declareProperty("EnergyThresholdToApplyIsolation", m_clustET_NoIso_thresh = 60., "Cluster energy above which no isolation cut is applied for baseline selection");
23 declareProperty("REtaThreshold", m_REta_thresh = 0.12, "Reta cut for baseline selection");
24 declareProperty("RHadThreshold", m_RHad_thresh = 0.16, "Rhad cut for baseline selection");
25 declareProperty("L1WidthThreshold", m_L1Width_thresh = 0.02, "L1Width cut for baseline selection");
26 declareProperty("EtaThresholdToApplyL1Width", m_eta_dropL1Width = 2.3, "Eta outside of which no L1Width cut is applied for baseline selection");
27
28 // loose selection properties
29 declareProperty("UseTileCells", m_use_tileCells = false);
30 declareProperty("NominalDigitizationValue", m_nominalDigitization = 25.);
31 declareProperty("NominalNoiseThreshold", m_nominalNoise_thresh = 100.);
32 declareProperty("TileNoiseThreshold", m_tileNoise_tresh = 100.);
33 declareProperty("EtaWidthTDRCluster", m_etaWidth_TDRCluster = 3);
34 declareProperty("PhiWidthTDRCluster", m_phiWidth_TDRCluster = 2);
35 declareProperty("EtaWidthWStotIsolation", m_etaWidth_wstotIsolation = 5);
36 declareProperty("PhiWidthWStotIsolation", m_phiWidth_wstotIsolation = 3);
37 declareProperty("EtaEMWidthRHadIsolation", m_etaEMWidth_RHadIsolation = 3); // 1 for a 1-eta-tower had cluster, 5 for 2-tower, 9 for 3-tower
38 declareProperty("PhiEMWidthRHadIsolation", m_phiEMWidth_RHadIsolation = 3);
39 declareProperty("EtaWidthREtaIsolationDenominator", m_etaWidth_REtaIsolation_den = 7);
40 declareProperty("PhiWidthREtaIsolationDenominator", m_phiWidth_REtaIsolation_den = 3);
41 declareProperty("EtaWidthREtaIsolationNumerator", m_etaWidth_REtaIsolation_num = 3);
42 declareProperty("PhiWidthREtaIsolationNumerator", m_phiWidth_REtaIsolation_num = 2);
43 declareProperty("ClusterEnergyThresholdLooseEFEX", m_clustET_looseAlg_thresh = 10.);
44 declareProperty("EtaHadWidthRHadIsolation", m_etaHadWidth_RHadIsolation = 9); // 1 for a 1-eta-tower had cluster, 5 for 2-tower, 9 for 3-tower
45 declareProperty("PhiHadWidthRHadIsolation", m_phiHadWidth_RHadIsolation = 3);
46}
47
48std::vector<LVL1::EFexEMClusterTool::AlgResult>
50 const CaloConstCellContainer* scells, const xAOD::TriggerTowerContainer* TTs,
51 const CaloCell_SuperCell_ID* idHelper, const TileID* tileIDHelper,
52 const CaloConstCellContainer* tileCellCon) const
53{
54 std::vector<AlgResult> baselineClusters;
55 for (auto & cluster : looseAlg(scells, TTs, idHelper, tileIDHelper, tileCellCon) ) {
56
57 // cluster E_T
58 cluster.passClusterEnergy = cluster.clusterET >= m_clustET_thresh; // if ET cut passes
59
60 // R_eta
61 cluster.passREta = cluster.rEta <= m_REta_thresh || // if reta cut passes
62 cluster.clusterET > m_clustET_NoIso_thresh; // or ET above threshold where any isolation is applied
63
64 // R_had
65 cluster.passRHad = cluster.rHad <= m_RHad_thresh || // if rhad cut passes
66 cluster.clusterET > m_clustET_NoIso_thresh; // or ET above threshold where any isolation is applied
67
68 // Wstot
69 cluster.passWstot = cluster.l1Width < m_L1Width_thresh || // if cut passes
70 std::abs(cluster.eta) > m_eta_dropL1Width || // or eta outside range where cut is applied
71 cluster.clusterET > m_clustET_NoIso_thresh; // or ET above threshold where any isolation is applied
72
73 bool passBaseLineSelection = cluster.passClusterEnergy &&
74 cluster.passRHad &&
75 cluster.passREta &&
76 cluster.passWstot;
77
78 if (applyBaselineCuts and not passBaseLineSelection ) {
79 continue;
80 }
81
82 baselineClusters.push_back(cluster);
83 }
84 return baselineClusters;
85}
86
87std::vector<LVL1::EFexEMClusterTool::AlgResult>
89 const CaloCell_SuperCell_ID* idHelper, const TileID* tileIDHelper,
90 const CaloConstCellContainer* tileCellCon ) const
91{
92 std::vector<AlgResult> result;
93 // Loops through and find L2 SCs that are local maxes and adds to list of local maxes if cluster ET is at least 10GeV
94 std::vector<const CaloCell*> potentialCentres;
95 for (auto ithCell : *SCs) {
96 if ( !( std::abs(CaloCellET(ithCell, m_nominalDigitization, m_nominalNoise_thresh)) > 0) ) {
97 continue;
98 }
99 Identifier ithID = ithCell->ID();
100 if (idHelper->sampling(ithID) != 2) {
101 continue;
102 }
103
104 if (idHelper->sub_calo(ithID) != 0) {
105 continue;
106 }
107
108 bool inEfexCoverage = false;
109 if ( std::abs(idHelper->pos_neg(ithID)) < 3) {
110 inEfexCoverage = true;
111 }
112
113 if (!inEfexCoverage) {
114 continue;
115 }
116
117 if (localMax(SCs, ithCell, idHelper, m_nominalDigitization, m_nominalNoise_thresh)) {
118 potentialCentres.push_back(ithCell);
119 }
120 }
121
122 // Looops through the local maxes and skips the less energetic ones that belong to the same TT
123 for (auto ithCell : potentialCentres){
124 bool useSC = true;
125 for (auto jthCell : potentialCentres){
126 if (jthCell == ithCell) continue;
127 if (!SameTT(ithCell, jthCell, idHelper)) continue;
130 if (ithEt > jthEt) continue;
131 if (ithEt == jthEt && ithCell->eta() > jthCell->eta()) continue;
132 useSC = false;
133 }
136 if (clustET < m_clustET_looseAlg_thresh) useSC = false;
137
138 if (useSC) {
139 float HadET = -999;
140 float ithRHad = -1;
141 float ithEta = ithCell->eta();
142 float ithPhi = ithCell->phi();
145 if (!m_use_tileCells) {
147 } else {
148 ithRHad = RHadTile(ithCell, m_etaEMWidth_RHadIsolation, m_phiEMWidth_RHadIsolation, SCs, idHelper, m_nominalDigitization, m_nominalNoise_thresh, tileIDHelper, tileCellCon, m_tileNoise_tresh, HadET);
149 }
150
151 float ithL1Width = L1Width( ithCell, m_etaWidth_wstotIsolation, m_phiWidth_wstotIsolation, SCs,
153 float L2ClusterET33 = L2clusET( ithCell, 3, 3, SCs, idHelper, m_nominalDigitization, m_nominalNoise_thresh)/1e3;
154 float L2ClusterET37 = L2clusET( ithCell, 7, 3, SCs, idHelper, m_nominalDigitization, m_nominalNoise_thresh)/1e3;
155
156 float ithREtaL12{-1};
157 if (m_use_REtaL12) {
161 }
162 result.push_back(AlgResult{ithEta, ithPhi, clustET, ithREta, ithRHad, ithL1Width, HadET, L2ClusterET33, L2ClusterET37, ithREtaL12});
163 }
164 }
165 return result;
166}
167
171
172float
173LVL1::EFexEMClusterTool::CaloCellET(const CaloCell* const &inputCell, float digitScale, float digitThreshold) const
174{
175 if (inputCell==nullptr) return 0.;
176 // Check that timing is correct
177 if ( m_useProvenance ) {
178 bool correctProv = (inputCell->provenance() & m_qualBitMask);
179 if (!correctProv) return 0.;
180 }
181 // Calculates the ET (before digitization)
182 float inputCell_energy = inputCell->energy();
183 float inputCell_eta = inputCell->eta();
184 float inputCell_ET = inputCell_energy / cosh(inputCell_eta);
185 // Check to see if negative ET values are allowed
186 bool allowNegs = false;
187 if (digitScale < 0.){
188 digitScale = std::abs(digitScale);
189 allowNegs = true;
190 }
191 if (inputCell_ET==0) return 0.;
192 else if (digitScale==0) return inputCell_ET;
193 if (allowNegs || inputCell_ET>0.){
194 // Split up ET into magnitude & whether it's positive or negative
195 float posOrNeg = inputCell_ET / std::abs(inputCell_ET);
196 inputCell_ET = std::abs(inputCell_ET);
197 // If no digitisation, return ET following noise cut
198 if (digitScale == 0){
199 if (inputCell_ET>digitThreshold) return inputCell_ET*posOrNeg;
200 else return 0.;
201 }
202 // Apply digitization & then noise cut
203 else {
204 float divET = inputCell_ET / digitScale;
205 int roundET = divET;
206 float result = digitScale * roundET;
207 if (digitThreshold == 0) return result*posOrNeg;
208 else if (result >= digitThreshold) return result*posOrNeg;
209 else return 0;
210 }
211 }
212 else return 0.;
213}
214
215bool
216LVL1::EFexEMClusterTool::SameTT(const CaloCell* inputCell1, const CaloCell* inputCell2, const CaloCell_SuperCell_ID* &idHelper) const
217{
218 const Identifier ID1 = inputCell1->ID();
219 int phi1 = idHelper->phi(ID1);
220 const Identifier ID2 = inputCell2->ID();
221 int phi2 = idHelper->phi(ID2);
222 if (phi1 != phi2) {
223 return false;
224 }
225 int pn1 = idHelper->pos_neg(ID1);
226 int pn2 = idHelper->pos_neg(ID2);
227 if (pn1 != pn2) {
228 return false;
229 }
230 // Is barrel
231 if (abs(pn1)==1) {
232 int reg1 = idHelper->region(ID1);
233 int reg2 = idHelper->region(ID2);
234 if (reg1 != reg2) {
235 return false;
236 }
237 int etaDiv1 = idHelper->eta(ID1)/4;
238 int etaDiv2 = idHelper->eta(ID2)/4;
239 if (etaDiv1 == etaDiv2) {
240 return true;
241 }
242 else {
243 return false;
244 }
245 }
246 // OW
247 else if (abs(pn1)==2){
248 int reg1 = idHelper->region(ID1);
249 int reg2 = idHelper->region(ID2);
250 int eta1 = idHelper->eta(ID1);
251 int eta2 = idHelper->eta(ID2);
252 if ((reg1 == 0 && reg2 == 1 && eta2 < 3 ) || (reg2 == 0 && reg1 == 1 && eta1 < 3 )) return true;
253 else {
254 if (reg1 != reg2) return false;
255 int etaDiv1 = (idHelper->eta(ID1) - 3)/4;
256 int etaDiv2 = (idHelper->eta(ID2) - 3)/4;
257 if (etaDiv1 == etaDiv2) return true;
258 else return false;
259 }
260 }
261 else return false;
262}
263
264bool
266 const CaloCell_SuperCell_ID* &idHelper, float digitScale, float digitThreshold) const
267{
268 return localMax(inputContainer, inputCell, 0, idHelper, digitScale, digitThreshold);
269}
270
271bool
272LVL1::EFexEMClusterTool::localMax(const CaloConstCellContainer* &inputContainer, const CaloCell* inputCell, int numOthers,
273 const CaloCell_SuperCell_ID* &idHelper, float digitScale, float digitThreshold) const
274{
275 if (inputCell == nullptr) return false;
276 // Get ID info
277 const Identifier inputID = inputCell->ID();
278 const int sub_calo = idHelper->sub_calo(inputID);
279 const int pos_neg = idHelper->pos_neg(inputID);
280 if (!(sub_calo == 0 || sub_calo == 1) || !(abs(pos_neg) < 4)){
281 ATH_MSG_DEBUG ( "Issue with local max logic");
282 return false;
283 }
284 double seedCandidateEnergy = CaloCellET(inputCell, digitScale, digitThreshold);
285 int nCellsMoreEnergetic = 0;
286 const CaloCell* leftCell = NextEtaCell(inputCell, true, inputContainer, idHelper);
287 if (leftCell != nullptr){
288 double leftEnergy = CaloCellET(leftCell, digitScale, 0.);
289 if (leftEnergy>seedCandidateEnergy) nCellsMoreEnergetic++;
290 }
291 const CaloCell* rightCell = NextEtaCell(inputCell, false, inputContainer, idHelper);
292 if (rightCell != nullptr){
293 double rightEnergy = CaloCellET(rightCell, digitScale, 0.);
294 if (rightEnergy>=seedCandidateEnergy) nCellsMoreEnergetic++;
295 }
296 const CaloCell* upCell = NextPhiCell(inputCell, true, inputContainer, idHelper);
297 if (upCell != nullptr){
298 double upEnergy = CaloCellET(upCell, digitScale, 0.);
299 if (upEnergy>=seedCandidateEnergy) nCellsMoreEnergetic++;
300 }
301 const CaloCell* downCell = NextPhiCell(inputCell, false, inputContainer, idHelper);
302 if (downCell != nullptr){
303 double downEnergy = CaloCellET(downCell, digitScale, 0.);
304 if (downEnergy>seedCandidateEnergy) nCellsMoreEnergetic++;
305 }
306 if (upCell != nullptr){
307 const CaloCell* upRightCell = NextEtaCell(upCell, false, inputContainer, idHelper);
308 if (upRightCell != nullptr){
309 double upRightEnergy = CaloCellET(upRightCell, digitScale, 0.);
310 if (upRightEnergy>=seedCandidateEnergy) nCellsMoreEnergetic++;
311 }
312 const CaloCell* upLeftCell = NextEtaCell(upCell, true, inputContainer, idHelper);
313 if (upLeftCell != nullptr){
314 double upLeftEnergy = CaloCellET(upLeftCell, digitScale, 0.);
315 if (upLeftEnergy>=seedCandidateEnergy) nCellsMoreEnergetic++;
316 }
317 }
318 if (downCell != nullptr){
319 const CaloCell* downRightCell = NextEtaCell(downCell, false, inputContainer, idHelper);
320 if (downRightCell != nullptr){
321 double downRightEnergy = CaloCellET(downRightCell, digitScale, 0.);
322 if (downRightEnergy>seedCandidateEnergy) nCellsMoreEnergetic++;
323 }
324 const CaloCell* downLeftCell = NextEtaCell(downCell, true, inputContainer, idHelper);
325 if (downLeftCell != nullptr){
326 double downLeftEnergy = CaloCellET(downLeftCell, digitScale, 0.);
327 if (downLeftEnergy>seedCandidateEnergy) nCellsMoreEnergetic++;
328 }
329 }
330 // If candidate is more energetic than all of neighbours, it is a local max
331 if (nCellsMoreEnergetic <= numOthers) return true;
332 else return false;
333}
334
335void
336LVL1::EFexEMClusterTool::addOnce(const CaloCell* inputCell, std::vector<const CaloCell*> &outputVector) const
337{
338 if (inputCell==nullptr) return;
339 bool alreadyThere = false;
340 for (auto oCell : outputVector){
341 if (oCell==nullptr) ATH_MSG_WARNING ( "nullptr cell in vector");
342 else if (inputCell->ID() == oCell->ID()) alreadyThere=true;
343 }
344 if (!alreadyThere) outputVector.push_back(inputCell);
345}
346
347double
348LVL1::EFexEMClusterTool::EMClusET(const CaloCell* centreCell, int etaWidth, int phiWidth, const CaloConstCellContainer* scells,
349 const CaloCell_SuperCell_ID* idHelper, float digitScale, float digitThresh) const
350{
351 // Sums the ET of the vector
352 std::vector<const CaloCell*> fullClus = TDR_Clus(centreCell, etaWidth, phiWidth, scells, idHelper, digitScale,digitThresh);
353 double EMcomp = sumVectorET(fullClus, digitScale, digitThresh);
354 bool EMcheck = checkDig(EMcomp, digitScale, digitThresh);
355 if (!EMcheck) ATH_MSG_WARNING ( "EMcomp not digitised " << EMcomp << " " << digitScale << " " << digitThresh);
356 double total = EMcomp;
357 return total;
358}
359
360double
361LVL1::EFexEMClusterTool::REta(const CaloCell* centreCell, int etaWidth1, int phiWidth1, int etaWidth2, int phiWidth2,
362 const CaloConstCellContainer* scells, const CaloCell_SuperCell_ID* idHelper, float digitScale, float digitThresh) const
363{
364 // Check windows sizes are right way round
365 if (etaWidth1 > etaWidth2) ATH_MSG_WARNING ( "REta: eta1 = " << etaWidth1 << ", eta2 = " << etaWidth2);
366 if (phiWidth1 > phiWidth2) ATH_MSG_WARNING ( "Rphi: phi1 = " << phiWidth1 << ", phi2 = " << phiWidth2);
367 // Finds ET of windows
368 double inner_ET = L2clusET(centreCell, etaWidth1, phiWidth1, scells, idHelper, digitScale, digitThresh);
369 double outer_ET = L2clusET(centreCell, etaWidth2, phiWidth2, scells, idHelper, digitScale, digitThresh);
370 // Find normal value of REta & changes it to my version
371 double normal_REta;
372 if (inner_ET != 0. && outer_ET==0.) normal_REta = 0.;
373 else if (inner_ET==0.) normal_REta = 0.;
374 else normal_REta = inner_ET / outer_ET;
375 if (normal_REta < 0) normal_REta = 0.;
376 double my_REta = 1-normal_REta;
377 return my_REta;
378}
379
380double
381LVL1::EFexEMClusterTool::RHad(const CaloCell* centreCell, int etaWidth, int phiWidth, const CaloConstCellContainer* scells,
382 const xAOD::TriggerTowerContainer* &TTContainer, const CaloCell_SuperCell_ID* idHelper, float digitScale, float digitThresh, float &HadET) const
383{
384 std::vector<const CaloCell*> fullClus = TDR_Clus(centreCell, etaWidth, phiWidth, scells, idHelper, digitScale, digitThresh);
385 double EMcomp = sumVectorET(fullClus, digitScale, digitThresh);
386 double HCALcomp = HadronicET(L2cluster(centreCell, m_etaHadWidth_RHadIsolation, m_phiHadWidth_RHadIsolation, scells, idHelper, digitScale, digitThresh), scells, TTContainer, idHelper, digitScale, digitThresh);
387 HadET = HCALcomp/1e3;
388 double result = HCALcomp/(EMcomp+HCALcomp);
389 if (result < 0. || result > 1.){
390 ATH_MSG_WARNING ( "RHAD -> " << etaWidth << " * " << phiWidth);
391 ATH_MSG_WARNING ( "fullClus count = " << fullClus.size() << ", EMcomp = " << EMcomp << ", HCALcomp = " << HCALcomp);
392 }
393 return result;
394}
395
396void
397LVL1::EFexEMClusterTool::checkTileCell(const TileCell* &inputCell, std::vector<const TileCell*> &tileCellVector, bool &isAlreadyThere) const
398{
399 for (auto ithCell : tileCellVector){
400 if (ithCell->ID() == inputCell->ID()) isAlreadyThere = true;
401 }
402 if (!isAlreadyThere) tileCellVector.push_back(inputCell);
403}
404
405double
406LVL1::EFexEMClusterTool::tileCellEnergyCalib(float eIn, float etaIn, float tileNoiseThresh) const
407{
408 if (eIn <= 0) return 0.;
409 float eOut = eIn/cosh(etaIn);
410 if (tileNoiseThresh == 0.) return eOut;
411 else {
412 if (eOut > tileNoiseThresh) return eOut;
413 else return 0.;
414 }
415}
416
417int
419{
420 float pos_neg = inEta/std::abs(inEta);
421 // Right PMT : inPos = 0, Left PMT : inPos = 1, Both PMTs : inPos = 2
422 int inPos = -1;
423 // True if even, false if odd
424 bool isEven = false;
425 if (((int)(std::abs(inEta)*10)) % 2 == 0) isEven = true;
426 if (pos_neg > 0){
427 // A side of TileCal
428 if (inEta < 0.1) inPos = 0;
429 else if (inEta > 0.8 && inEta < 0.9) inPos = 2;
430 else {
431 if (isEven) inPos = 0;
432 else inPos = 1;
433 }
434 }
435 else {
436 // C side of TileCal
437 if (inEta > -0.1) inPos = 1;
438 else if (inEta > -0.9 && inEta < -0.8) inPos = 2;
439 else {
440 if (isEven) inPos = 1;
441 else inPos = 0;
442 }
443 }
444 return inPos;
445}
446
447double
448LVL1::EFexEMClusterTool::L1Width(const CaloCell* centreCell, int etaWidth, int phiWidth, const CaloConstCellContainer* scells,
449 const CaloCell_SuperCell_ID* idHelper, float digitScale, float digitThresh) const
450{
451 // Finds a L2 cluster and the corresponding L1 cells
452 std::vector<const CaloCell*> L2cells = L2cluster(centreCell, etaWidth, phiWidth, scells, idHelper,digitScale, digitThresh);
457
458 float oldPhi = centreCell->phi();
459 int counter = 0;
460 std::vector<int> offsets;
461 std::vector<const CaloCell*> frontLayerCells;
462 for (auto ithL2Cell : L2cells){
463 // How many cells added already?
464 unsigned int oldsize = frontLayerCells.size();
465 // Add cells matching this L2 cell
466 fromLayer2toLayer1(scells, ithL2Cell, frontLayerCells, idHelper);
467 // HoW many were added?
468 unsigned int additions = frontLayerCells.size() - oldsize;
469 // Reset counter if phi has changed significantly
470 float dPhi = std::abs(ithL2Cell->phi() - oldPhi);
471 if (dPhi > M_PI) dPhi = 2*M_PI - dPhi;
472 if (dPhi > 0.09) {
473 counter = 0;
474 oldPhi = ithL2Cell->phi();
475 }
476 // Try storing signed offsets
477 int sign = (ithL2Cell->eta()-centreCell->eta() > 0 ? 1 : -1);
478 // Store current eta offset value for all added cells
479 for (unsigned int adds = 0; adds < additions; ++adds) offsets.push_back(sign*((counter+1)/2));
480 counter++;
481 }
482
483 // Finds the 'width' for the cluster, based on eta offsets found above
484 float sumET = 0, sumET_Eta2=0;
485 unsigned int cellCount = 0;
486 //for (auto ithCell : frontLayerCells){
487 for (std::vector<const CaloCell*>::iterator ithCell = frontLayerCells.begin(); ithCell != frontLayerCells.end(); ++ithCell){
488
489 // Find offset. As a precaution ignore cells where this can't be found, but warn user
490 int offset = (cellCount < offsets.size() ? offsets[cellCount] : -999);
491 if (offset < -2 || offset > 2) {
492 ATH_MSG_WARNING("Offset out of range, cell skipped");
493 offset = 0; // This will result in a weight of zero for the cell
494 }
495
496 // Is this one of the cells between 1.8-2.0 that will be divided?
497 Identifier cellID = (*ithCell)->ID();
498 int pos_neg = idHelper->pos_neg(cellID);
499 int region = idHelper->region(cellID);
500 int eta_index = idHelper->eta(cellID);
501 bool halfCell = false;
502 if (abs(pos_neg) == 2 && region == 3 && (eta_index == 1 || eta_index == 4 || eta_index == 7 || eta_index == 10)) halfCell = true;
503
504 // Total and weighted ET sums (integer weights to match firmware)
505 float ithET = CaloCellET((*ithCell), digitScale, digitThresh);
506 sumET += ithET;
507
508 // 4 cells will be shared with neighbours. Jiggery-pokery required here:
509 if (halfCell) {
510 sumET_Eta2 += 0.5*ithET*pow(offset,2);
511 // Now what should be the offset for the other half?
512 // Is this one shared with the previous cell?
513 // If so, which cell is shares with depends on which side of that cell it is
514 if ((int)cellCount-1 >= 0 && offsets[cellCount-1] == offset) {
515 auto ithPrev = std::prev(ithCell,1);
516 int sign = ((*ithCell)->eta() > (*ithPrev)->eta() ? 1 : -1);
517 int nextOffset = offset+sign;
518 if (abs(nextOffset) <= 2) sumET_Eta2 += 0.5*ithET*pow(nextOffset,2);
519 }
520 }
521 // Alternatively may be shared with next cell
522 else if (cellCount+1 < offsets.size() && offsets[cellCount+1] == offset) {
523 auto ithNext = std::next(ithCell,1);
524 int sign = ((*ithCell)->eta() > (*ithNext)->eta() ? 1 : -1);
525 int nextOffset = offset+sign;
526 if (abs(nextOffset) <= 2) sumET_Eta2 += 0.5*ithET*pow(nextOffset,2);
527 }
528 // For everything else just add cell with weight to the second sum
529 else {
530 sumET_Eta2 += ithET*pow(offset,2);
531 }
532 cellCount++;
533 }
534
537 float result = 4.;
538 if (sumET > 0.) result = sumET_Eta2/sumET;
539 return result;
540}
541
542double
543LVL1::EFexEMClusterTool::L2clusET(const CaloCell* centreCell, int etaWidth, int phiWidth, const CaloConstCellContainer* scells,
544 const CaloCell_SuperCell_ID* idHelper, float digitScale, float digitThresh) const
545{
546 return sumVectorET(L2cluster(centreCell, etaWidth, phiWidth, scells, idHelper, digitScale, digitThresh), digitScale, digitThresh);
547}
548
549double
550LVL1::EFexEMClusterTool::RHadTile(const CaloCell* centreCell, int etaWidth, int phiWidth, const CaloConstCellContainer* scells,
551 const CaloCell_SuperCell_ID* idHelper, float digitScale, float digitThresh, const TileID* tileIDHelper,
552 const CaloConstCellContainer* tileCellCon, float tileNoiseThresh, float &HadronicET) const
553{
554 std::vector<float> outVec;
555 double HadET = 0.;
556 std::vector<const CaloCell*> L2Cells = L2cluster(centreCell, etaWidth, phiWidth, scells, idHelper, digitScale, digitThresh);
557 std::vector<const CaloCell*> fullClus = TDR_Clus(centreCell, m_etaHadWidth_RHadIsolation, m_phiHadWidth_RHadIsolation, scells, idHelper, digitScale, digitThresh);
558 // Last Tile cell boundary: eta = 1.6
559 // Last outer wheel SC seed that still falls into Tile boundary: eta = 1.5625
560 if (std::abs(centreCell->eta()) < 1.57){
561 const int barrel_ec = idHelper->pos_neg(centreCell->ID());
562 bool isOW = false;
563 if (std::abs(barrel_ec) == 2) isOW = true;
564 std::vector<double> energyPerLayer = EnergyPerTileLayer(L2Cells, tileCellCon, tileIDHelper, isOW, tileNoiseThresh);
565 if (energyPerLayer.size() > 0){
566 for (auto ithLayerEnergy : energyPerLayer){
567 HadET += ithLayerEnergy;
568 }
569 }
570 }
571 else {
572 std::vector<const CaloCell*> HCAL_LAr_vector;
573 for (auto ithCell : L2Cells){
574 if (std::abs(ithCell->eta()) > 2.5) continue;
575 const CaloCell* tempLArHad = matchingHCAL_LAr(ithCell, scells, idHelper);
576 if (tempLArHad != nullptr) HCAL_LAr_vector.push_back(tempLArHad);
577 }
578 for (auto ithSC : HCAL_LAr_vector){
579 HadET += CaloCellET(ithSC, digitScale, digitThresh);
580 }
581 }
582 HadronicET = HadET/1e3;
583 double EMcomp = sumVectorET(fullClus, digitScale, digitThresh);
584 double result = HadET/(EMcomp+HadET);
585 if (result < 0. || result > 1.){
586 ATH_MSG_WARNING ( "RHADTILE -> " << etaWidth << " * " << phiWidth);
587 ATH_MSG_WARNING ( "fullClus count = " << fullClus.size() << ", EMcomp = " << EMcomp << ", HCALcomp = " << HadET);
588 return 1.;
589 }
590 return result;
591}
592
593double
594LVL1::EFexEMClusterTool::REtaL12(const CaloCell* centreCell, int etaWidth1, int phiWidth1, int etaWidth2, int phiWidth2,
595 const CaloConstCellContainer* scells, const CaloCell_SuperCell_ID* idHelper,
596 float digitScale, float digitThresh) const
597{
598 // Check windows sizes are right way round
599 if (etaWidth1 > etaWidth2) ATH_MSG_WARNING ( "REta: eta1 = " << etaWidth1 << ", eta2 = " << etaWidth2);
600 if (phiWidth1 > phiWidth2) ATH_MSG_WARNING ( "Rphi: phi1 = " << phiWidth1 << ", phi2 = " << phiWidth2);
601 // Finds ET of windows
602 double inner_ET = L2clusET(centreCell, etaWidth1, phiWidth1, scells, idHelper, digitScale, digitThresh);
603 double outer_ET = L2clusET(centreCell, etaWidth2, phiWidth2, scells, idHelper, digitScale, digitThresh);
604 // Find corresponding L1 cells, calculate the L1 ET and add them to L2 ET
605 std::vector<const CaloCell*> L2cells_inner = L2cluster(centreCell, etaWidth1, phiWidth1, scells, idHelper,digitScale, digitThresh);
606 std::vector<const CaloCell*> L1cells_inner;
607 for (auto ithL2Cell : L2cells_inner){
608 fromLayer2toLayer1(scells, ithL2Cell, L1cells_inner, idHelper);
609 }
610 inner_ET += sumVectorET(L1cells_inner, digitScale, digitThresh);
611 std::vector<const CaloCell*> L2cells_outer = L2cluster(centreCell, etaWidth2, phiWidth2, scells, idHelper,digitScale, digitThresh);
612 std::vector<const CaloCell*> L1cells_outer;
613 for (auto ithL2Cell : L2cells_outer){
614 fromLayer2toLayer1(scells, ithL2Cell, L1cells_outer, idHelper);
615 }
616 outer_ET += sumVectorET(L1cells_outer, digitScale, digitThresh);
617 // Find normal value of REta & changes it to my version
618 double normal_REta;
619 if (inner_ET != 0. && outer_ET==0.) normal_REta = 0.;
620 else if (inner_ET==0.) normal_REta = 0.;
621 else normal_REta = inner_ET / outer_ET;
622 if (normal_REta < 0) normal_REta = 0.;
623 double my_REta = 1-normal_REta;
624 return my_REta;
625}
626
627void
629 std::vector<const CaloCell*> &outputVector, const CaloCell_SuperCell_ID* &idHelper) const
630{
631 if (inputCell==nullptr) return;
632 // Gets ID info
633 Identifier inputID = inputCell->ID();
634 int sampling = idHelper->sampling(inputID);
635 const int sub_calo = idHelper->sub_calo(inputID);
636 int pos_neg = idHelper->pos_neg(inputID);
637 int region = idHelper->region(inputID);
638 int eta_index = idHelper->eta(inputID);
639 const int phi_index = idHelper->phi(inputID);
640 int tracker = 0;
641 if (sampling != 2) return;
642 // Default values are same as input
643 int outputRegion = region;
644 int outputEta = eta_index;
645 bool oneCell = false; // True if layer 2 SC only matches to a single layer 1 SC
646 // Barrel reg 0 (which is a simple one)
647 if ((abs(pos_neg) == 1)&&(region == 0)){
648 oneCell = true;
649 }
650 // Barrel reg 1: 3 layer 1 SCs for 1 layer 2 SC
651 // But we should map one of these onto the barrel SC, the other 2 onto EC SCs
652 else if ((abs(pos_neg) == 1)&&(region == 1)){
653 tracker = 2;
654 outputRegion = 1;
655 outputEta = 0;
656 oneCell = true;
657 /* This code produces a one-to-many matching, which is not how things work
658 for (unsigned int i = 0; i < 3; i++){
659 Identifier resultID = idHelper->CaloCell_SuperCell_ID::cell_id(sub_calo, pos_neg, 1, region, i, phi_index);
660 const CaloCell* resultCell = returnCellFromCont(resultID, inputContainer, idHelper);
661 addOnce(resultCell,outputVector);
662 }
663 */
664 }
667 else if (abs(pos_neg)==2 && region == 0) {
668 tracker = -1;
669 }
672 else if (abs(pos_neg)==2&&((region==1 && eta_index < 2))){
673 tracker = 3;
674 outputRegion = 1;
675 outputEta = eta_index + 1;
676 pos_neg /= abs(pos_neg);
677 oneCell = true;
678 }
680 else if (abs(pos_neg)==2&&((region==1 && eta_index == 2))){
681 tracker = 4;
682 outputRegion = 0;
683 outputEta = 0;
684 oneCell = true;
685 }
687 else if (abs(pos_neg)==2&&region==1 && eta_index <= 14){
688 // OW region 1 (on doc): 1:1 match
689 tracker = 5;
690 outputRegion = 2;
691 outputEta = eta_index - 3;
692 oneCell = true;
693 }
695 else if (abs(pos_neg) == 2 && region == 1 && eta_index <= 22){
696 // In this region there are 6 L1 supercells for every 4 L2 ones
697 // The code below groups them 2:1:1:2 2:1:1:2, which is an old proposal
698 // This is not what is actually done, but the structure of this code
699 // makes it impossible to do this correctly.
700 outputRegion = 3;
701 // Middle 2 layer cells match central 2 layer 1 cells
702 if (eta_index%4 == 0 || eta_index%4 ==1){
703 tracker = 6;
704 oneCell = true;
705 if (eta_index < 20) outputEta = eta_index -14;
706 else outputEta = eta_index - 12;
707 }
708 // Edges have a 2:1 ratio. 2 L1s for each L2
709 else {
710 tracker = 7;
711 int offset = 0;
712 if (eta_index == 15) offset = 15;
713 else if (eta_index == 18) offset = 14;
714 else if (eta_index == 19) offset = 13;
715 else if (eta_index == 22) offset = 12;
716 else {
717 ATH_MSG_DEBUG ( "ISSUE with: " << __LINE__);
718 }
719 for (unsigned int i = 0; i < 2; i++){
720 outputEta = i+eta_index - offset;
721 Identifier resultID = idHelper->CaloCell_SuperCell_ID::cell_id(sub_calo, pos_neg, 1, outputRegion, outputEta, phi_index);
722 const CaloCell* resultCell = returnCellFromCont(resultID, inputContainer, idHelper);
723 addOnce(resultCell,outputVector);
724 }
725 }
726 }
728 else if (abs(pos_neg)==2 && region == 1 && eta_index <= 38){
729 // OW Reg 3 (on doc): 1:1 match
730 tracker = 8;
731 oneCell = true;
732 outputRegion = 4;
733 outputEta = eta_index - 23;
734 }
736 else if (abs(pos_neg)==2 && region == 1 && eta_index == 40){
737 // OW Reg 4 (on doc): 1 L1 for all 4 L2s
738 // But this must be mapped onto a specific cell: second one seems best
739 // Note: to try alternative mapping of this cell (to Layer 0) should return without adding cell here
740 tracker = 9;
741 oneCell = true;
742 outputEta = 0;
743 outputRegion = 5;
744 }
745
746 if (oneCell){
747 Identifier resultID = idHelper->CaloCell_SuperCell_ID::cell_id(sub_calo, pos_neg, 1, outputRegion, outputEta, phi_index);
748 const CaloCell* resultCell = returnCellFromCont(resultID, inputContainer, idHelper);
749 addOnce(resultCell,outputVector);
750 }
751 ATH_MSG_DEBUG("L2->L1: sampling = " << sampling << ", region = " << region << ", eta = " << pos_neg*eta_index<< " tracker = " << tracker);
752}
753
754const CaloCell*
755LVL1::EFexEMClusterTool::fromLayer2toLayer3(const CaloConstCellContainer* &inputContainer, const CaloCell* inputCell, const CaloCell_SuperCell_ID* &idHelper) const
756{
757 // Gets ID info
758 int tracker = 0;
759 if ( inputCell == nullptr ) return nullptr;
760 const CaloCell* resultCell = nullptr;
761 Identifier inputID = inputCell->ID();
762 int sampling = idHelper->sampling(inputID);
763 const int sub_calo = idHelper->sub_calo(inputID);
764 const int pos_neg = idHelper->pos_neg(inputID);
765 int region = idHelper->region(inputID);
766 int eta_index = idHelper->eta(inputID);
767 const int phi_index = idHelper->phi(inputID);
768 if (sampling != 2) return nullptr;
769 else if (abs(pos_neg)==1 && ((region==0 && eta_index>53)||region==1)) return nullptr;
770 else if ((abs(pos_neg)==2) && (region == 0 || (region == 1 && eta_index < 3))) return nullptr;
771 else if (abs(pos_neg)==3) return nullptr;
772 // Default values are same as input
773 int outputRegion = region;
774 int outputEta = eta_index;
775 // Is barrel Reg 0
776 if (abs(pos_neg)==1 && region ==0){
777 int outputEta = eta_index/4;
778 Identifier resultID = idHelper->CaloCell_SuperCell_ID::cell_id(sub_calo, pos_neg, 3, outputRegion, outputEta, phi_index);
779 resultCell = returnCellFromCont(resultID, inputContainer, idHelper);
780 tracker = 1;
781 }
783 else if (abs(pos_neg)==1 && region ==1) {
784 int output_pos_neg = pos_neg*2;
785 outputRegion = 0;
786 int outputEta = 0;
787 Identifier resultID = idHelper->CaloCell_SuperCell_ID::cell_id(sub_calo, output_pos_neg, 2, outputRegion, outputEta, phi_index);
788 resultCell = returnCellFromCont(resultID, inputContainer, idHelper);
789 tracker = 2;
790 }
792 else if (abs(pos_neg)==2 && region ==1){
793 outputEta = (eta_index - 3)/4;
794 outputRegion = 0;
795 Identifier resultID = idHelper->CaloCell_SuperCell_ID::cell_id(sub_calo, pos_neg, 3, outputRegion, outputEta, phi_index);
796 resultCell = returnCellFromCont(resultID, inputContainer, idHelper);
797 tracker = 3;
798 }
799 ATH_MSG_DEBUG("L2->L3: sampling = " << sampling << ", region = " << region << ", eta = " << pos_neg*eta_index<< " tracker = " << tracker);
800 return resultCell;
801}
802
803const CaloCell*
804LVL1::EFexEMClusterTool::fromLayer2toPS(const CaloConstCellContainer* & inputContainer, const CaloCell* inputCell, const CaloCell_SuperCell_ID* &idHelper) const
805{
806 // Gets ID info
807 if (inputCell==nullptr) return nullptr;
808 const CaloCell* resultCell = nullptr;
809 Identifier inputID = inputCell->ID();
810 int sampling = idHelper->sampling(inputID);
811 const int sub_calo = idHelper->sub_calo(inputID);
812 const int pos_neg = idHelper->pos_neg(inputID);
813 int region = idHelper->region(inputID);
814 int eta_index = idHelper->eta(inputID);
815 const int phi_index = idHelper->phi(inputID);
816 if (sampling != 2) return nullptr;
817 if (abs(pos_neg)==2 && (eta_index<3 || eta_index>14)) return nullptr;
818 if (abs(pos_neg)==3) return nullptr;
819 // Default values are same as input
820 int outputRegion = region;
821 int outputEta = eta_index;
822 // Is barrel Reg 0
823 if (abs(pos_neg)==1 && region ==0){
824 int outputEta = eta_index/4;
825 Identifier resultID = idHelper->CaloCell_SuperCell_ID::cell_id(sub_calo, pos_neg, 0, outputRegion, outputEta, phi_index);
826 resultCell = returnCellFromCont(resultID, inputContainer, idHelper);
827 }
828 else if (abs(pos_neg)==1 && region ==1){
829 Identifier resultID = idHelper->CaloCell_SuperCell_ID::cell_id(sub_calo, pos_neg, 0, 0, 14, phi_index);
830 resultCell = returnCellFromCont(resultID, inputContainer, idHelper);
831 }
832 else if (abs(pos_neg)==2 && region ==1){
833 outputEta = (eta_index - 3)/4;
834 outputRegion = 0;
835 Identifier resultID = idHelper->CaloCell_SuperCell_ID::cell_id(sub_calo, pos_neg, 0, outputRegion, outputEta, phi_index);
836 resultCell = returnCellFromCont(resultID, inputContainer, idHelper);
837 }
838 return resultCell;
839}
840
841std::vector<const CaloCell*>
842LVL1::EFexEMClusterTool::L2cluster( const CaloCell* centreCell, int etaWidth, int phiWidth, const CaloConstCellContainer* scells,
843 const CaloCell_SuperCell_ID* idHelper, float digitScale, float digitThresh ) const
844{
845 // Forms the central band of cells, spread in phi
846 std::vector<const CaloCell*> centCells;
847 centCells.push_back(centreCell);
848 const CaloCell* upPhiCell = NextPhiCell(centreCell,true,scells,idHelper);
849 const CaloCell* downPhiCell = NextPhiCell(centreCell,false,scells,idHelper);
850 const CaloCell* energeticPhiCell;
851 // Finds the most energetic phi neighbour, defaulting to the 'down' side if they are equal
852 if ( CaloCellET(upPhiCell, digitScale, digitThresh) > CaloCellET(downPhiCell, digitScale, digitThresh)) energeticPhiCell = upPhiCell;
853 else energeticPhiCell = downPhiCell;
854 if (phiWidth == 2) addOnce(energeticPhiCell, centCells); //centCells.push_back(energeticPhiCell);
855 else if (phiWidth == 3){
856 addOnce(upPhiCell, centCells); //centCells.push_back(upPhiCell);
857 addOnce(downPhiCell, centCells); //centCells.push_back(downPhiCell);
858 }
859 else if (phiWidth > 3) {
860 ATH_MSG_DEBUG ( "phiWidth not 2 or 3!!!");
861 }
862 // Forms the main cluster. Starts with each SC in the central band and spreads outward in eta
863 std::vector<const CaloCell*> clusCells;
864 int halfEtaWidth = (etaWidth-1)/2;
865 int backToEta = (2*halfEtaWidth)+1;
866 if (backToEta != etaWidth) {
867 ATH_MSG_DEBUG ( "Eta width doesn't match! " << backToEta << " -> " << halfEtaWidth << " -> " << etaWidth << " " << __LINE__);
868 }
869 for (auto ithCentCell : centCells){
870 addOnce(ithCentCell, clusCells); //clusCells.push_back(ithCentCell);
871 if (etaWidth > 1){
872 const CaloCell* tempRightCell = NextEtaCell(ithCentCell,true,scells,idHelper);
873 const CaloCell* tempLeftCell = NextEtaCell(ithCentCell,false,scells,idHelper);
874 addOnce(tempRightCell, clusCells); //clusCells.push_back(tempRightCell);
875 addOnce(tempLeftCell, clusCells); //clusCells.push_back(tempLeftCell);
876 for (int i = 1; i < halfEtaWidth; i++){
877 tempRightCell = NextEtaCell(tempRightCell,true,scells,idHelper);
878 tempLeftCell = NextEtaCell(tempLeftCell,false,scells,idHelper);
879 addOnce(tempRightCell, clusCells); //clusCells.push_back(tempRightCell);
880 addOnce(tempLeftCell, clusCells); //clusCells.push_back(tempLeftCell);
881 }
882 }
883 }
884 return clusCells;
885}
886
887std::vector<double>
888LVL1::EFexEMClusterTool::EnergyPerTileLayer( const std::vector<const CaloCell*> & inputSCVector, const CaloConstCellContainer* CellCon,
889 const TileID* tileIDHelper, bool isOW, float tileNoiseThresh) const
890{
891 std::vector<double> layerEnergy;
892 if (CellCon==nullptr) return layerEnergy;
893 if (CellCon->size()==0) return layerEnergy;
894 if (inputSCVector.size()==0) return layerEnergy;
895 double ELayer0 = 0, ELayer1 = 0, ELayer2 = 0;
896 std::vector<const TileCell*> tileCellVector;
897 for (auto ithSC : inputSCVector){
898 float ithSCEta = ithSC->eta();
899 float ithSCPhi = ithSC->phi();
900 int matchingCells = 0;
903 for ( ; fCell != lCell; ++fCell){
904 const TileCell* tileCell = static_cast<const TileCell*>(*fCell);
905 if (!tileCell){
906 ATH_MSG_WARNING ( "Failed to cast from CaloCell to TileCell");
907 return layerEnergy;
908 }
909 int layer = tileIDHelper->sample(tileCell->ID());
910 float ithdR = dR(tileCell->eta(), tileCell->phi(), ithSCEta, ithSCPhi);
911 if (layer < 2){
912 float matchingDistance = 0.;
913 if (isOW && (std::abs(ithSCEta) > 1.38 && std::abs(ithSCEta) < 1.42)) matchingDistance = 0.065;
914 else matchingDistance = 0.05;
915 if (ithdR <= matchingDistance){
916 bool isAlreadyThere = false;
917 checkTileCell(tileCell, tileCellVector, isAlreadyThere);
918 if (isAlreadyThere) continue;
919 matchingCells++;
920 if (layer == 0) ELayer0 += tileCellEnergyCalib(tileCell->e(), tileCell->eta(), tileNoiseThresh);
921 if (layer == 1) ELayer1 += tileCellEnergyCalib(tileCell->e(), tileCell->eta(), tileNoiseThresh);
922 }
923 }
924 else if (layer == 2){
925 float matchingDistance = 0.;
926 if (std::abs(ithSCEta) > 0.7 && std::abs(ithSCEta) < 0.8) matchingDistance = 0.05;
927 else if (std::abs(ithSCEta) > 0.9 && std::abs(ithSCEta) < 1.0) matchingDistance = 0.05;
928 else matchingDistance = 0.09;
929 if (ithdR < matchingDistance){
930 bool isAlreadyThere = false;
931 checkTileCell(tileCell, tileCellVector, isAlreadyThere);
932 if (isAlreadyThere) continue;
933 matchingCells++;
934 int tempPos = detRelPos(ithSCEta);
935 // Unknown : tempPos = -1, Right PMT : tempPos = 0, Left PMT : tempPos = 1, Both PMTs : tempPos = 2
936 if (tempPos < 0){
937 ATH_MSG_WARNING ( "Unknown behaviour matching Tile cells to the SC");
938 layerEnergy.clear();
939 return layerEnergy;
940 }
941 else if (tempPos == 0) ELayer2 += tileCellEnergyCalib(tileCell->ene2(), tileCell->eta(), tileNoiseThresh);
942 else if (tempPos == 1) ELayer2 += tileCellEnergyCalib(tileCell->ene1(), tileCell->eta(), tileNoiseThresh);
943 else ELayer2 += tileCellEnergyCalib(tileCell->e(), tileCell->eta(), tileNoiseThresh);
944 }
945 }
946 }
947 if ((matchingCells > 3 && !isOW) || (matchingCells > 3 && isOW && std::abs(ithSCEta) > 1.42) || (matchingCells > 4 && isOW && std::abs(ithSCEta) < 1.42)){
948 ATH_MSG_WARNING ( matchingCells << " matching Tile cells:");
949 ATH_MSG_WARNING ( "Input SC: (eta,phi) = (" << ithSCEta << "," << ithSCPhi << ")");
950 for (auto cell : tileCellVector){
951 ATH_MSG_WARNING ( "Tile cell: (eta,phi) = (" << cell->eta() << "," << cell->phi() << ")" << " dR = " << dR(cell->eta(), cell->phi(), ithSCEta, ithSCPhi) << " layer = " << tileIDHelper->sample(cell->ID()));
952 }
953 layerEnergy.clear();
954 return layerEnergy;
955 }
956 }
957 layerEnergy = {ELayer0, ELayer1, ELayer2};
958 return layerEnergy;
959}
960
961double
963{
964 if (inputTower == nullptr){
965 ATH_MSG_WARNING ( "Tower is nullptr in phi transformation!");
966 return 0.;
967 }
968 else {
969 double phi = inputTower->phi();
970 if (phi > M_PI) phi = phi - 2*M_PI;
971 return phi;
972 }
973}
974
975double
976LVL1::EFexEMClusterTool::dR(double eta1, double phi1, double eta2, double phi2) const
977{
978 double etaDif = eta1 - eta2;
979 double phiDif = std::abs(phi1 - phi2);
980 if (phiDif > M_PI) phiDif = phiDif - (2*M_PI);
981 double result = std::sqrt(pow(etaDif,2)+pow(phiDif,2));
982 return result;
983}
984
987{
988 std::vector<const xAOD::TriggerTower*> matchingTTs;
989 if (TTContainer==nullptr) return nullptr;
990 if (TTContainer->size()==0) return nullptr;
991 if (inputCell==nullptr) return nullptr;
992 for (auto ithTT : *TTContainer){
993 if (ithTT->sampling()==1){
994 float ithTT_eta = ithTT->eta();
995 float ithTT_phi = TT_phi(ithTT);
996 float ithdR = dR(ithTT_eta, ithTT_phi, inputCell->eta(), inputCell->phi());
997 if (ithdR < 0.05) matchingTTs.push_back(ithTT);
998 }
999 }
1000 if (matchingTTs.size()==1) return matchingTTs[0];
1001 else if (matchingTTs.size()!=0){
1002 ATH_MSG_WARNING ( "More than one matching HCAL TT!!! (Returned Null)");
1003 }
1004 return nullptr;
1005}
1006
1007const CaloCell*
1008LVL1::EFexEMClusterTool::matchingHCAL_LAr(const CaloCell* &inputCell, const CaloConstCellContainer* &SCContainer, const CaloCell_SuperCell_ID* &idHelper) const
1009{
1010 std::vector<const CaloCell*> matchingCells;
1011 if (inputCell==nullptr) return nullptr;
1012 for (auto ithSC : *SCContainer){
1013 Identifier ithID = ithSC->ID();
1014 int ithSub_calo = idHelper->sub_calo(ithID);
1015 if (ithSub_calo == 1){
1016 double ithdR = dR(inputCell->eta(), inputCell->phi(), ithSC->eta(), ithSC->phi());
1017 if (ithdR < 0.05) matchingCells.push_back(ithSC);
1018 }
1019 }
1020
1021 if (matchingCells.size()==1)
1022 return matchingCells[0];
1023
1024
1025 if (matchingCells.size()==0){
1026
1027 ATH_MSG_WARNING ( "No match betweem LAr ECAL SC and LAr HCAL SC!!! Input coords: " << inputCell->eta() << ", " << inputCell->phi());
1028
1029 } else if (matchingCells.size()!=0) {
1030
1031 ATH_MSG_WARNING ( "More than one matching LAr HCAL SC!!! (Returned Null)");
1032 ATH_MSG_WARNING ( "Input cell coords: " << inputCell->eta() << " x " << inputCell->phi());
1033 for (auto ithMatch : matchingCells){
1034 ATH_MSG_WARNING ( " " << ithMatch->eta() << " x " << ithMatch->phi() << ", dR = "
1035 << dR(inputCell->eta(), inputCell->phi(), ithMatch->eta(), ithMatch->phi()));
1036 }
1037 }
1038 return nullptr;
1039}
1040
1041double
1043{
1044 if (inputTower == nullptr){
1045 ATH_MSG_WARNING ( "Tower is nullptr!");
1046 return 0.;
1047 }
1048 else if (inputTower->cpET() < 0.) {
1049 return 0;
1050 } else {
1051 return 500*inputTower->cpET();
1052 }
1053}
1054
1055std::vector<const CaloCell*>
1056LVL1::EFexEMClusterTool::TDR_Clus( const CaloCell* centreCell, int etaWidth, int phiWidth, const CaloConstCellContainer* scells,
1057 const CaloCell_SuperCell_ID* idHelper, float digitScale, float digitThresh ) const
1058{
1059 // Find the L2 cells
1060 std::vector<const CaloCell*> L2cells = L2cluster(centreCell, etaWidth, phiWidth, scells, idHelper, digitScale, digitThresh);
1061 // Forms a vector of the centre L2 cells (to be used to find L0/3 SCs)
1062 std::vector<const CaloCell*> centCells;
1063 centCells.push_back(centreCell);
1064 const CaloCell* upPhiCell = NextPhiCell(centreCell,true,scells,idHelper);
1065 const CaloCell* downPhiCell = NextPhiCell(centreCell,false,scells,idHelper);
1066 const CaloCell* energeticPhiCell;
1067 // If the phi width is 2, the most energetic neighbour is chosen (defaulting to the 'down' side)
1068 // If the phi width is 3, both neighbours are added
1069 if (phiWidth > 1){
1070 if (CaloCellET(upPhiCell, digitScale, digitThresh) > CaloCellET(downPhiCell, digitScale, digitThresh)) energeticPhiCell = upPhiCell;
1071 else energeticPhiCell = downPhiCell;
1072 if (phiWidth == 2) addOnce(energeticPhiCell, centCells); //centCells.push_back(energeticPhiCell);
1073 else if (phiWidth == 3){
1074 addOnce(upPhiCell, centCells); //centCells.push_back(upPhiCell);
1075 addOnce(downPhiCell, centCells); //centCells.push_back(downPhiCell);
1076 }
1077 else if (phiWidth > 3) ATH_MSG_WARNING ( "phiWidth not 2 or 3!!!. Value = " << phiWidth);
1078 }
1079 // The actual cluster is initialised
1080 std::vector<const CaloCell*> fullClus;
1081 // The L1&2 SCs are added that match the full width
1082 for (auto ithL2Cell : L2cells){
1083 fullClus.push_back(ithL2Cell);
1084 fromLayer2toLayer1(scells, ithL2Cell, fullClus, idHelper);
1085 }
1086 // The L0&3 SCs are added that match the central L2 cells
1087 for (auto ithL2CentCell : centCells){
1088 addOnce( fromLayer2toPS( scells, ithL2CentCell, idHelper),fullClus);
1089 addOnce( fromLayer2toLayer3( scells, ithL2CentCell, idHelper),fullClus);
1090 }
1091 return fullClus;
1092}
1093
1094double
1095LVL1::EFexEMClusterTool::sumVectorET(const std::vector<const CaloCell*> &inputVector, float digitScale, float digitThreshold) const
1096{
1097 double TotalET=0.0;
1098 for (auto ithCell : inputVector){
1099 if (ithCell!=nullptr) TotalET += CaloCellET(ithCell, digitScale, digitThreshold);
1100 }
1101 return TotalET;
1102}
1103
1104bool
1105LVL1::EFexEMClusterTool::checkDig(float EM_ET, float digitScale, float digitThresh) const
1106{
1107 if (EM_ET == 0 || digitScale == 0) return true;
1108 else {
1109 int div = EM_ET / digitScale;
1110 if (div * digitScale == EM_ET) return true;
1111 else {
1112 ATH_MSG_WARNING ( "ET = " << EM_ET << ", digitThresh = " << digitThresh << " digitScale = " << digitScale << " div = " << div << " " << " -> div * digitScale");
1113 return false;
1114 }
1115 }
1116}
1117
1118double
1119LVL1::EFexEMClusterTool::HadronicET( const std::vector<const CaloCell*> & inputVector, const CaloConstCellContainer* scells,
1120 const xAOD::TriggerTowerContainer* &TTContainer, const CaloCell_SuperCell_ID* idHelper,
1121 float digitScale, float digitThresh) const
1122{
1123 // Finds the HCAL SCs & TTs matching the input cluster
1124 std::vector<const CaloCell*> HCAL_LAr_vector;
1125 std::vector<const xAOD::TriggerTower*> HCAL_TT_vector;
1126 for (auto ithCell : inputVector){
1127 if (std::abs(ithCell->eta())<1.5){
1128 const xAOD::TriggerTower* tempTT = matchingHCAL_TT(ithCell, TTContainer);
1129 if (tempTT != nullptr) HCAL_TT_vector.push_back(tempTT);
1130 }
1131 else if (std::abs(ithCell->eta())<2.5){
1132 const CaloCell* tempLArHad = matchingHCAL_LAr(ithCell, scells, idHelper);
1133 if (tempLArHad != nullptr) HCAL_LAr_vector.push_back(tempLArHad);
1134 }
1135 }
1136 // Sums the ET in the HCAL
1137 double HadET = 0.;
1138 for (auto ithTT : HCAL_TT_vector) {HadET += TT_ET(ithTT);}
1139 for (auto ithSC : HCAL_LAr_vector) {HadET += CaloCellET(ithSC, digitScale, digitThresh);}
1140 return HadET;
1141}
1142
1143
1147const CaloCell*
1149{
1150 const CaloCell* isCell = cellContainer->findCell(idHelper->CaloCell_SuperCell_ID::calo_cell_hash(inputID));
1151 if (isCell) return isCell;
1152 else return nullptr;
1153}
1154
1155const CaloCell*
1156LVL1::EFexEMClusterTool::NextEtaCell( const CaloCell* inputCell, bool upwards, const CaloConstCellContainer* &cellContainer,
1157 const CaloCell_SuperCell_ID* &idHelper) const
1158{
1159 if (inputCell==nullptr) return nullptr;
1160 Identifier ithID = inputCell->ID();
1161 int ithSub_calo = idHelper->sub_calo(ithID);
1162 int ithPos_neg = idHelper->pos_neg(ithID);
1163 const CaloCell* tempCell = nullptr;
1164 // Only works for LArEM
1165 if (ithSub_calo==0){
1166 // Barrel regions
1167 if (abs(ithPos_neg)==1) tempCell = NextEtaCell_Barrel(inputCell, upwards, cellContainer, idHelper);
1168 // EC OW
1169 else if (abs(ithPos_neg)==2) tempCell = NextEtaCell_OW(inputCell, upwards, cellContainer, idHelper);
1170 // EC IW
1171 else if (abs(ithPos_neg)==3) tempCell = NextEtaCell_IW(inputCell, upwards, cellContainer, idHelper);
1172 // Not barrel or end cap
1173 else {
1174 ATH_MSG_WARNING ( "Layer 2 cell not passed to specific method at" << inputCell->eta() << " , " << inputCell->phi());
1175 return nullptr;
1176 }
1177 return tempCell;
1178 }
1179 // Is FCAL
1180 else {
1181 ATH_MSG_WARNING ( "Next eta cell called for non-EM SC!");
1182 return nullptr;
1183 }
1184}
1185
1186const CaloCell*
1187LVL1::EFexEMClusterTool::NextEtaCell_Barrel(const CaloCell* inputCell, bool upwards, const CaloConstCellContainer* &cellContainer,
1188 const CaloCell_SuperCell_ID* &idHelper) const
1189{
1190 const Identifier ithID = inputCell->ID();
1191 const int ithEta_index = idHelper->eta(ithID);
1192 const int ithPhi_index = idHelper->phi(ithID);
1193 const int ithSampling = idHelper->sampling(ithID);
1194 const int ithSub_calo = idHelper->sub_calo(ithID);
1195 const int ithPos_neg = idHelper->pos_neg(ithID);
1196 const int ithRegion = idHelper->region(ithID);
1197
1198 // Extreme indices of each region
1199 int maxEta_index = 0;
1200 int minEta_index = 0;
1201 if (ithRegion==0){
1202 if (ithSampling == 0) maxEta_index = 14;
1203 else if (ithSampling == 1 || ithSampling == 2) maxEta_index = 55;
1204 else if (ithSampling == 3) maxEta_index = 13;
1205 else ATH_MSG_DEBUG ( "ISSUE: " << __LINE__);
1206 }
1207 else if (ithRegion==1){
1208 if (ithSampling == 1) maxEta_index =2;
1209 else if (ithSampling == 2) maxEta_index=0;
1210 else ATH_MSG_DEBUG ( "ISSUE: " << __LINE__);
1211 }
1212 else ATH_MSG_DEBUG ( "ISSUE: " << __LINE__);
1213 // Declare next values, default initialisation is the same as cell
1214 int nextEta_index = ithEta_index;
1215 // Phi shouldn't change!
1216 // One special case where sampling does change, otherwise stays same
1217 int nextSampling = ithSampling;
1218 int nextSub_calo = ithSub_calo;
1219 int nextPos_neg = ithPos_neg;
1220 int nextRegion = ithRegion;
1221
1222 // Calculate the increment for eta: it depends on whether we are moving 'up' & which side we are on
1223 int incrementEta;
1224 if (upwards) incrementEta = ithPos_neg;
1225 else incrementEta = -1*ithPos_neg;
1226
1227 int tracker = 0;
1228
1229 // If first cell in region & moving more inwards
1230 if (ithEta_index==minEta_index && incrementEta==-1){
1231 if (ithRegion == 0){
1232 nextEta_index = 0;
1233 nextPos_neg = ithPos_neg * -1;
1234 tracker = 1;
1235 }
1236 else if (ithRegion == 1){
1237 nextEta_index = 55;
1238 nextRegion = 0;
1239 tracker = 2;
1240 }
1241 else ATH_MSG_DEBUG ( "ISSUE: " << __LINE__);
1242 }
1243
1244 // If last cell in region & moving outwards
1245 else if ((ithEta_index == maxEta_index) && (incrementEta == 1)) {
1246 // Reg 0, Layers 1 & 2 go to barrel region 1
1247 if ((ithRegion == 0)&&(ithSampling == 1 || ithSampling == 2)){
1248 nextRegion = 1;
1249 nextEta_index = 0;
1250 tracker = 3;
1251 }
1252 // Reg 0, Layer 0 goes to OW region 0
1253 else if ((ithRegion == 0)&&(ithSampling == 0)){
1254 nextEta_index = 0;
1255 nextRegion = 0;
1256 nextPos_neg = 2*ithPos_neg;
1257 tracker = 4;
1258 }
1259 // Reg 0, Layer 3 goes to OW Layer 2 region 0 (change by ATW)
1260 else if ((ithRegion == 0)&&(ithSampling == 3)){
1261 nextSampling = 2;
1262 nextEta_index = 0;
1263 nextRegion = 0;
1264 nextPos_neg = 2*ithPos_neg;
1265 tracker = 5;
1266 }
1267 // Reg 1, Layer 1 go to OW region 0 (change by ATW)
1268 else if ((ithRegion == 1)&&(ithSampling == 1)){
1269 nextEta_index=0;
1270 nextRegion = 0;
1271 nextPos_neg = 2 * ithPos_neg;
1272 tracker = 6;
1273 }
1274 // Reg 1, Layer 2 goes to OW region 1
1275 else if ((ithRegion == 1)&&(ithSampling == 2)){
1276 nextEta_index=0;
1277 nextRegion = 1;
1278 nextPos_neg = 2 * ithPos_neg;
1279 tracker = 7;
1280 }
1281 else ATH_MSG_DEBUG ( "ISSUE: " << __LINE__);
1282 }
1283 // Otherwise 'simply' next cell along
1284 else {
1285 nextEta_index = ithEta_index + incrementEta;
1286 tracker = 8;
1287 }
1288 //ATH_MSG_DEBUG ( "B Tracker = " << tracker);
1289 // Form identifier, find cell & return it
1290 // sub_calo, left_pos_neg, 2, region, eta_index, down_phi_index
1291 Identifier nextCellID = idHelper->CaloCell_SuperCell_ID::cell_id(nextSub_calo, nextPos_neg, nextSampling, nextRegion, nextEta_index, ithPhi_index);
1292 const CaloCell* nextCell = returnCellFromCont(nextCellID, cellContainer, idHelper);
1293 if (nextCell == nullptr) {
1294 ATH_MSG_DEBUG ( "ISSUE: " << __LINE__);
1295 ATH_MSG_DEBUG ( "Barrel Tracker = " << tracker);
1296 ATH_MSG_DEBUG ( "from nextCellID: "<<idHelper->sub_calo(nextCellID)<<", "<<idHelper->pos_neg(nextCellID)<<", "<<idHelper->sampling(nextCellID)<<", "<<idHelper->region(nextCellID)<<", "<<idHelper->eta(nextCellID)<<", "<<idHelper->phi(nextCellID)<<", "<<idHelper->calo_cell_hash(nextCellID)<<", "<<nextCellID);
1297 }
1298 else {
1299 Identifier newID = nextCell->ID();
1300 int IDsample = idHelper->sampling(nextCell->ID());
1302 if (IDsample!=ithSampling){
1303 ATH_MSG_DEBUG ( "Layer has changed " << " tracker = " << tracker);
1304 ATH_MSG_DEBUG ( "from nextCellID: "<<idHelper->sub_calo(nextCellID)<<", "<<idHelper->pos_neg(nextCellID)<<", "<<idHelper->sampling(nextCellID)<<", "<<idHelper->region(nextCellID)<<", "<<idHelper->eta(nextCellID)<<", "<<idHelper->phi(nextCellID)<<", "<<idHelper->calo_cell_hash(nextCellID)<<", "<<nextCellID);
1305 ATH_MSG_DEBUG ( "from ID from new cell: "<<idHelper->sub_calo(newID)<<", "<<idHelper->pos_neg(newID)<<", "<<idHelper->sampling(newID)<<", "<<idHelper->region(newID)<<", "<<idHelper->eta(newID)<<", "<<idHelper->phi(newID)<<", "<<idHelper->calo_cell_hash(newID)<<", "<<newID);
1306 ATH_MSG_DEBUG ( "comp indices: "<< (nextCellID == newID));
1307 }
1308 }
1309 if (nextCell && (nextCell->ID() != nextCellID)) ATH_MSG_DEBUG ( __LINE__ << " does not match");
1310 return nextCell;
1311}
1312
1313const CaloCell*
1314LVL1::EFexEMClusterTool::NextEtaCell_OW( const CaloCell*inputCell, bool upwards, const CaloConstCellContainer* &cellContainer,
1315 const CaloCell_SuperCell_ID* &idHelper) const
1316{
1317 Identifier ithID = inputCell->ID();
1318 int ithEta_index = idHelper->eta(ithID);
1319 const int ithPhi_index = idHelper->phi(ithID);
1320 const int ithSampling = idHelper->sampling(ithID);
1321 int ithSub_calo = idHelper->sub_calo(ithID);
1322 int ithPos_neg = idHelper->pos_neg(ithID);
1323 int ithRegion = idHelper->region(ithID);
1324 // Declare next values, default initialisation is the same as cell
1325 int nextEta_index = ithEta_index;
1326 int nextPhi_index = ithPhi_index;
1327 // Sampling may change in a couple of special cases (transition tower)
1328 int nextSampling = ithSampling;
1329 int nextSub_calo = ithSub_calo;
1330 int nextPos_neg = ithPos_neg;
1331 int nextRegion = ithRegion;
1332 // Maximum indices for barrel region 0:
1333 int maxEta_index = 0;
1334 int minEta_index = 0;
1335 // Set max / min values based on ithRegion
1336 if (ithSampling==0) maxEta_index = 2;
1337 else if (ithSampling==2 && ithRegion==0) maxEta_index = 0;
1338 else if (ithSampling==2 && ithRegion==1) maxEta_index = 42;
1339 else if (ithSampling==3) maxEta_index=9;
1340 else if (ithSampling==1) {
1341 switch(ithRegion){
1342 case 0:
1343 maxEta_index=0;
1344 break;
1345 case 1:
1346 ATH_MSG_DEBUG ( "ISSUE " << __LINE__);
1347 break;
1348 case 2:
1349 maxEta_index=11;
1350 break;
1351 case 3:
1352 maxEta_index=11;// Should this be 11? - it was 7
1353 break;
1354 case 4:
1355 maxEta_index=15;
1356 break;
1357 case 5:
1358 maxEta_index=0;
1359 break;
1360 default:
1361 ATH_MSG_WARNING ( "OW region is not covered: " << ithRegion);
1362 }
1363 }
1364 else ATH_MSG_DEBUG ( "ISSUE: " << __LINE__ );
1365
1366 // Calculate the increment for eta: it depends on whether we are moving 'up' & which side we are on
1367 int incrementEta;
1368 int ithSide = ithPos_neg / abs(ithPos_neg);
1369 if (upwards) incrementEta = ithSide;
1370 else incrementEta = ithSide * -1;
1371 int tracker = 0;
1372 // Lower end of OW, going inwards
1373 if (ithEta_index==minEta_index && ithRegion==0 && incrementEta==-1){
1374 nextPos_neg = ithSide;
1375 if (ithSampling==0){
1376 nextRegion = 0;
1377 nextEta_index = 14;
1378 tracker = 1;
1379 }
1380 else if (ithSampling==1){
1381 nextRegion = 1;
1382 nextEta_index = 2;
1383 tracker = 2;
1384 }
1386 else if (ithSampling==2){
1387 nextRegion = 0;
1388 nextSampling = 2;
1389 nextEta_index = 13;
1390 tracker = 3;
1391 }
1393 else if (ithSampling==3){
1394 nextRegion = 0;
1395 nextSampling = 2;
1396 nextEta_index = 0;
1397 nextPos_neg = ithPos_neg;
1398 tracker = 4;
1399 }
1400 }
1401 // Higher end of OW, going outwards
1402 else if (ithEta_index==maxEta_index && incrementEta==1){
1403 // Layers 0 & 3 aren't in IW
1404 if (ithSampling==0 || ithSampling==3) return nullptr;
1405 else if (ithSampling==2 && ithRegion==0){
1406 nextRegion = 1;
1407 nextEta_index = 0;
1408 tracker = 5;
1409 }
1410 else if ((ithSampling==2 && ithRegion==1)||(ithSampling==1 && ithRegion==5)){
1411 // Reaches IW
1412 nextEta_index=0;
1413 nextRegion=0;
1414 nextPhi_index=ithPhi_index/2;
1415 nextPos_neg=3*ithSide;
1416 tracker=6;
1417 }
1418 else if (ithSampling==1 && ithRegion==0){
1419 // Unsure what to do??
1420 nextRegion = 2;
1421 nextEta_index = 0;
1422 tracker = 7;
1423 }
1424 else if (ithSampling==1){
1425 nextRegion=ithRegion + 1;
1426 nextEta_index=0;
1427 tracker = 8;
1428 }
1429 }
1430 // Lower end of region in OW, going inwards
1431 else if (ithEta_index==minEta_index && incrementEta==-1){
1432 // Shouldn't apply to layers 0 & 3
1433 // Only case for layer 2 should be in region 1
1434 // But this one is special because we want to step into barrel (ATW)
1435 if (ithSampling==2){
1436 nextRegion = 1;
1437 nextEta_index = 0;
1438 nextPos_neg = ithPos_neg;
1439 tracker = 9;
1440 }
1441 else if (ithSampling==1){
1442 if (ithRegion==0){ // haven't we covered this? (ATW)
1443 nextPos_neg = ithSide;
1444 nextRegion = 1;
1445 nextEta_index = 2;
1446 tracker = 10;
1447 }
1448 else {
1449 tracker = 11;
1450 // Layer one has muliple regions
1451 nextRegion = ithRegion-1;
1452 if (nextRegion==0) {
1453 nextEta_index=0;
1454 ATH_MSG_DEBUG ( "ISSUE: "<< __LINE__);
1455 }
1456 else if (nextRegion==1) {
1457 nextRegion = 0;
1458 nextEta_index= 0;
1459 }
1460 else if (nextRegion==2) nextEta_index=11;
1461 else if (nextRegion==3) nextEta_index=7;
1462 else if (nextRegion==4) nextEta_index=15;
1463 }
1464 }
1465 }
1466 // Middle of region in middle of endcap
1467 else {
1468 nextEta_index = ithEta_index+incrementEta;
1469 tracker = 12;
1470 }
1471 Identifier nextCellID = idHelper->CaloCell_SuperCell_ID::cell_id(nextSub_calo, nextPos_neg, nextSampling, nextRegion, nextEta_index, nextPhi_index);
1472 const CaloCell* nextCell = returnCellFromCont(nextCellID, cellContainer, idHelper);
1473 if (nextCell == nullptr) {
1474 ATH_MSG_DEBUG ( "ISSUE: "<<__LINE__);
1475 ATH_MSG_DEBUG ( "OW Tracker = "<<tracker);
1476 ATH_MSG_DEBUG ( "from nextCellID: "<<idHelper->sub_calo(nextCellID)<<", "<<idHelper->pos_neg(nextCellID)<<", "<<idHelper->sampling(nextCellID)<<", "<<idHelper->region(nextCellID)<<", "<<idHelper->eta(nextCellID)<<", "<<idHelper->phi(nextCellID)<<", "<<idHelper->calo_cell_hash(nextCellID)<<", "<<nextCellID);
1477 ATH_MSG_DEBUG ( "Increment eta = "<<incrementEta<<", max_eta = "<<maxEta_index<<", min_eta = "<<minEta_index);
1478 }
1479 else {
1480 Identifier newID = nextCell->ID();
1481 int IDsample = idHelper->sampling(nextCell->ID());
1482 if (IDsample!=ithSampling){
1483 ATH_MSG_DEBUG ( "Layer has changed "<<" tracker = "<<tracker);
1484 ATH_MSG_DEBUG ( "from nextCellID: "<<idHelper->sub_calo(nextCellID)<<", "<<idHelper->pos_neg(nextCellID)<<", "<<idHelper->sampling(nextCellID)<<", "<<idHelper->region(nextCellID)<<", "<<idHelper->eta(nextCellID)<<", "<<idHelper->phi(nextCellID)<<", "<<idHelper->calo_cell_hash(nextCellID)<<", "<<nextCellID);
1485 ATH_MSG_DEBUG ( "from ID from new cell: "<<idHelper->sub_calo(newID)<<", "<<idHelper->pos_neg(newID)<<", "<<idHelper->sampling(newID)<<", "<<idHelper->region(newID)<<", "<<idHelper->eta(newID)<<", "<<idHelper->phi(newID)<<", "<<idHelper->calo_cell_hash(newID)<<", "<<newID);
1486 ATH_MSG_DEBUG ( "comp indices: "<<(nextCellID == newID));
1487 }
1488 }
1489 if (nextCell && (nextCell->ID() != nextCellID)) ATH_MSG_DEBUG ( __LINE__<< " does not match");
1490 return nextCell;
1491}
1492
1493const CaloCell*
1494LVL1::EFexEMClusterTool::NextEtaCell_IW( const CaloCell* inputCell, bool upwards, const CaloConstCellContainer* &cellContainer,
1495 const CaloCell_SuperCell_ID* &idHelper) const
1496{
1497 const Identifier ithID = inputCell->ID();
1498 const int ithEta_index = idHelper->eta(ithID);
1499 const int ithPhi_index = idHelper->phi(ithID);
1500 const int ithSampling = idHelper->sampling(ithID);
1501 const int ithSub_calo = idHelper->sub_calo(ithID);
1502 const int ithPos_neg = idHelper->pos_neg(ithID);
1503 const int ithRegion = idHelper->region(ithID);
1504 //int tracker =0;
1505 // Declare next values, default initialisation is the same as cell
1506 int nextEta_index = ithEta_index;
1507 int nextPhi_index = ithPhi_index;
1508 // Sampling shouldn't change!
1509 int nextSub_calo = ithSub_calo;
1510 int nextPos_neg = ithPos_neg;
1511 int nextRegion = ithRegion;
1512
1513 // Maximum indices for barrel region 0:
1514 int maxEta_index = 0;
1515 int minEta_index = 0;
1516
1517 if (ithRegion==0){
1518 maxEta_index=2;
1519 minEta_index=0;
1520 }
1521 else if (ithRegion!=1) ATH_MSG_DEBUG ( "ISSUE: " <<__LINE__);
1522
1523 // Calculate the increment for eta: it depends on whether we are moving 'up' & which side we are on
1524 int incrementEta;
1525 int ithSide = ithPos_neg / abs(ithPos_neg);
1526 if (upwards) incrementEta = ithSide;
1527 else incrementEta = ithSide * -1;
1528 // Lower end of region IW, going inwards
1529 if (ithEta_index==minEta_index&& incrementEta==-1){
1530 // Goes to OW
1531 if (ithRegion == 0){
1532 nextPos_neg = 2*ithSide;
1533 nextPhi_index=2*ithPhi_index;
1534 if (ithSampling==1){
1535 // tracker=1;
1536 nextRegion=5;
1537 nextEta_index=0;
1538 }
1539 else if (ithSampling==2){
1540 // tracker=2;
1541 nextRegion=1;
1542 nextEta_index=42;
1543 }
1544 else ATH_MSG_DEBUG ( "ISSUE: " <<__LINE__);
1545 }
1546 // Goes to IW region 0
1547 else if (ithRegion == 1){
1548 // tracker=3;
1549 nextRegion=0;
1550 nextEta_index=2;
1551 }
1552 }
1553 // Upper end of region in IW
1554 else if (ithEta_index==maxEta_index && incrementEta==1){
1555 // Goes to region 1
1556 if (ithRegion==0){
1557 // tracker=4;
1558 nextRegion=1;
1559 nextEta_index=0;
1560 }
1561 // Reaches FCAL
1562 else if (ithRegion==1) return nullptr;
1563 }
1564 // Increment eta like normal
1565 else {
1566 // tracker=5;
1567 nextEta_index=ithEta_index+incrementEta;
1568 }
1569 Identifier nextCellID = idHelper->CaloCell_SuperCell_ID::cell_id(nextSub_calo, nextPos_neg, ithSampling, nextRegion, nextEta_index, nextPhi_index);
1570 const CaloCell* nextCell = returnCellFromCont(nextCellID, cellContainer, idHelper);
1571 if (nextCell && (nextCell->ID() != nextCellID)) ATH_MSG_DEBUG ( __LINE__<<" does not match");
1572 return nextCell;
1573}
1574
1575int
1576LVL1::EFexEMClusterTool::restrictPhiIndex(int input_index, bool is64) const
1577{
1578 if (is64&&input_index<0) return input_index+64;
1579 else if (is64&&input_index>63) return input_index-64;
1580 else if (!(is64)&&input_index<0) return input_index+32;
1581 else if (!(is64)&&input_index>31) return input_index-32;
1582 else return input_index;
1583}
1584
1585const CaloCell*
1586LVL1::EFexEMClusterTool::NextPhiCell( const CaloCell * inputCell, bool upwards, const CaloConstCellContainer* &cellContainer,
1587 const CaloCell_SuperCell_ID* &idHelper) const
1588{
1589 if (inputCell==nullptr)
1590 return nullptr;
1591
1592 const Identifier ithID = inputCell->ID();
1593 const int ithEta_index = idHelper->eta(ithID);
1594 const int ithPhi_index = idHelper->phi(ithID);
1595 const int ithSampling = idHelper->sampling(ithID);
1596 const int ithSub_calo = idHelper->sub_calo(ithID);
1597 const int ithPos_neg = idHelper->pos_neg(ithID);
1598 const int ithRegion = idHelper->region(ithID);
1599
1600 bool is64;
1601 if (abs(ithPos_neg)==3) is64 = false;
1602 else is64 = true;
1603
1604 int incrementPhi;
1605 if (upwards==true) incrementPhi=1;
1606 else incrementPhi=-1;
1607
1608 const int nextPhi_index = restrictPhiIndex(ithPhi_index+incrementPhi, is64);
1609 Identifier nextCellID = idHelper->CaloCell_SuperCell_ID::cell_id(ithSub_calo, ithPos_neg, ithSampling, ithRegion, ithEta_index, nextPhi_index);
1610 const CaloCell* nextCell = returnCellFromCont(nextCellID, cellContainer, idHelper);
1611 if (nextCell && (nextCell->ID() != nextCellID)) ATH_MSG_DEBUG ( __LINE__ << " does not match");
1612 if (nextCell == nullptr) ATH_MSG_DEBUG ( "Next phi cell is nullptr at " << __LINE__);
1613 return nextCell;
1614}
#define M_PI
Scalar phi() const
phi method
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
int sign(int a)
constexpr int pow(int base, int exp) noexcept
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)
int phi(const Identifier id) const
LAr field values (NOT_VALID == invalid request)
int sampling(const Identifier id) const
LAr field values (NOT_VALID == invalid request)
int sub_calo(const Identifier id) const
returns an int taken from SUBCALO enum and describing the subCalo to which the Id belongs.
int region(const Identifier id) const
LAr field values (NOT_VALID == invalid request)
int pos_neg(const Identifier id) const
LAr field values (NOT_VALID == invalid request)
int eta(const Identifier id) const
LAr field values (NOT_VALID == invalid request)
IdentifierHash calo_cell_hash(const Identifier cellId) const
create hash id from 'global' cell id
Helper class for offline supercell identifiers.
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
virtual double e() const override final
get energy (data member) (synonym to method energy()
Definition CaloCell.h:333
virtual double phi() const override final
get phi (through CaloDetDescrElement)
Definition CaloCell.h:375
double energy() const
get energy (data member)
Definition CaloCell.h:327
uint16_t provenance() const
get provenance (data member)
Definition CaloCell.h:354
virtual double eta() const override final
get eta (through CaloDetDescrElement)
Definition CaloCell.h:382
Identifier ID() const
get ID (from cached data member) non-virtual and inline for fast access
Definition CaloCell.h:295
CaloCellContainer that can accept const cell pointers.
::CaloCellContainer::const_iterator beginConstCalo(CaloCell_ID::SUBCALO caloNum) const
get const begin iterator on cell of just one calo
const CaloCell * findCell(IdentifierHash theHash) const
fast find method given identifier hash.
::CaloCellContainer::const_iterator endConstCalo(CaloCell_ID::SUBCALO caloNum) const
get const begin iterator on cell of just one calo
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
size_type size() const noexcept
Returns the number of elements in the collection.
void checkTileCell(const TileCell *&inputCell, std::vector< const TileCell * > &tileCellVector, bool &isAlreadyThere) const
determine if Tile cell has already been taken into account
double RHadTile(const CaloCell *centreCell, int etaWidth, int phiWidth, const CaloConstCellContainer *scells, const CaloCell_SuperCell_ID *idHelper, float digitScale, float digitThresh, const TileID *m_tileIDHelper, const CaloConstCellContainer *tileCellCon, float tileNoiseThresh, float &HadronicET) const
calculate the hadronic isolation for a seed cell using TileCal cells
int m_etaWidth_TDRCluster
eta width of the TDR cluster formation given in number of SCs (including the central cell),...
int detRelPos(const float inEta) const
determine the PMT position of the Tile cell to be matched
float m_clustET_looseAlg_thresh
threshold for minimum cluster energy for the loose eFEX algorithm
float m_nominalNoise_thresh
noise threshold
float m_eta_dropL1Width
max eta for applying cut on L1Width (baseline selection)
int m_etaWidth_REtaIsolation_den
eta width for REta isolation given in number of SCs (denominator of fraction)
double HadronicET(const std::vector< const CaloCell * > &inputVector, const CaloConstCellContainer *scells, const xAOD::TriggerTowerContainer *&TTContainer, const CaloCell_SuperCell_ID *idHelper, float digitScale, float digitThresh) const
calculate the energy in the HCAL (LAr + Tile) for SC/TT that match the EM cluster cells of L2
const CaloCell * NextEtaCell_IW(const CaloCell *inputCell, bool upwards, const CaloConstCellContainer *&cellContainer, const CaloCell_SuperCell_ID *&idHelper) const
returns the SC left/right to the input cell for the IW
void fromLayer2toLayer1(const CaloConstCellContainer *&inputContainer, const CaloCell *inputCell, std::vector< const CaloCell * > &outputVector, const CaloCell_SuperCell_ID *&idHelper) const
match SCs from the cluster in L2 to L1
const CaloCell * NextEtaCell_OW(const CaloCell *inputCell, bool upwards, const CaloConstCellContainer *&cellContainer, const CaloCell_SuperCell_ID *&idHelper) const
returns the SC left/right to the input cell for the OW
double TT_ET(const xAOD::TriggerTower *&inputTower) const
calculate the energy of an input TT
double L1Width(const CaloCell *centreCell, int etaWidth, int phiWidth, const CaloConstCellContainer *scells, const CaloCell_SuperCell_ID *idHelper, float digitScale, float digitThresh) const
calculate the lateral isolation aorund the central cell
double sumVectorET(const std::vector< const CaloCell * > &inputVector, float digitScale=0., float digitThreshold=0.) const
calculate cluster energy from all SCs in PS, L1, L2, L3
std::vector< const CaloCell * > TDR_Clus(const CaloCell *centreCell, int etaWidth, int phiWidth, const CaloConstCellContainer *scells, const CaloCell_SuperCell_ID *idHelper, float digitScale, float digitThresh) const
form the cluster around the central SC
float m_clustET_thresh
threshold for minimum cluster energy (baseline selection)
int m_etaHadWidth_RHadIsolation
hadronic eta width for RHad isolation given in number of SCs
int m_etaEMWidth_RHadIsolation
EM eta width for RHad isolation given in number of SCs.
double tileCellEnergyCalib(float eIn, float etaIn, float tileNoiseThresh) const
determine transverse energy and apply noise threshold to Tile cells
int m_phiWidth_wstotIsolation
phi width for wstot isolation given in number of SCs
const CaloCell * fromLayer2toPS(const CaloConstCellContainer *&inputContainer, const CaloCell *inputCell, const CaloCell_SuperCell_ID *&idHelper) const
match SCs from the cluster in L2 to one cell of PS
EFexEMClusterTool(const std::string &type, const std::string &name, const IInterface *parent)
Name : EFexEMClusterTool.cxx PACKAGE : Trigger/TrigT1/TrigT1CaloFexPerf AUTHOR : Denis Oliveira Damaz...
int m_phiEMWidth_RHadIsolation
EM phi width for RHad isolation given in number of SCs.
std::vector< AlgResult > clusterAlg(bool applyBaselineCuts, const CaloConstCellContainer *scells, const xAOD::TriggerTowerContainer *TTs, const CaloCell_SuperCell_ID *idHelper, const TileID *m_tileIDHelper, const CaloConstCellContainer *tileCellCon) const
find cluster and associated variables using a user defined selection
const CaloCell * NextEtaCell_Barrel(const CaloCell *inputCell, bool upwards, const CaloConstCellContainer *&cellContainer, const CaloCell_SuperCell_ID *&idHelper) const
returns the SC left/right to the input cell for the barrel
bool checkDig(float EM_ET, float digitScale, float digitThresh) const
check if conversion from ET to energy after digitization was performed successfully
double EMClusET(const CaloCell *centreCell, int etaWidth, int phiWidth, const CaloConstCellContainer *scells, const CaloCell_SuperCell_ID *idHelper, float digitScale, float digitThresh) const
calculate cluster energy
std::vector< double > EnergyPerTileLayer(const std::vector< const CaloCell * > &inputSCVector, const CaloConstCellContainer *CellCon, const TileID *tileIDHelper, bool isOW, float tileNoiseThresh) const
match all Tile cells to a given L2Cluster and determine the summed energy per Tile layer
double RHad(const CaloCell *centreCell, int etaWidth, int phiWidth, const CaloConstCellContainer *scells, const xAOD::TriggerTowerContainer *&TTContainer, const CaloCell_SuperCell_ID *idHelper, float digitScale, float digitThresh, float &HadronicET) const
calculate the hadronic isolation of the central cell
int m_qualBitMask
Configurable quality bitmask.
const CaloCell * matchingHCAL_LAr(const CaloCell *&inputCell, const CaloConstCellContainer *&SCContainer, const CaloCell_SuperCell_ID *&idHelper) const
Match each SC from L2 to one corresponding HCAL SC.
float m_tileNoise_tresh
TileCal cell noise threshold.
int m_phiHadWidth_RHadIsolation
hadronic phi width for RHad isolation given in number of SCs
float m_REta_thresh
threshold for isolation REta (baseline selection)
int m_phiWidth_REtaIsolation_num
phi width for REta isolation given in number of SCs (numerator of fraction)
float m_L1Width_thresh
threshold for isolation L1Width (wstot) (baseline selection)
bool localMax(const CaloConstCellContainer *&inputContainer, const CaloCell *inputCell, const CaloCell_SuperCell_ID *&idHelper, float digitScale, float digitThreshold) const
helper function calling localMax()
int restrictPhiIndex(int input_index, bool is64) const
manager function for the phi index
const CaloCell * NextEtaCell(const CaloCell *inputCell, bool upwards, const CaloConstCellContainer *&cellContainer, const CaloCell_SuperCell_ID *&idHelper) const
helper function calling NextEtaCell_Barrel(), NextEtaCell_OW(), NextEtaCell_IW() according to positio...
double dR(double eta1, double phi1, double eta2, double phi2) const
calculate deltaR between two points in eta/phi space
float m_nominalDigitization
value of nominal digitisation
double REtaL12(const CaloCell *centreCell, int etaWidth1, int phiWidth1, int etaWidth2, int phiWidth2, const CaloConstCellContainer *scells, const CaloCell_SuperCell_ID *idHelper, float digitScale, float digitThresh) const
calculate the energy isolation of the central cell along eta using Layer 1 and Layer 2
const xAOD::TriggerTower * matchingHCAL_TT(const CaloCell *&inputCell, const xAOD::TriggerTowerContainer *&TTContainer) const
Match each SC from L2 to one corresponding TT.
float m_RHad_thresh
threshold for isolation RHad (baseline selection)
int m_etaWidth_REtaIsolation_num
eta width for REta isolation given in number of SCs (numerator of fraction)
bool SameTT(const CaloCell *inputCell1, const CaloCell *inputCell2, const CaloCell_SuperCell_ID *&idHelper) const
check if both input cells belong to the same TT
const CaloCell * fromLayer2toLayer3(const CaloConstCellContainer *&inputContainer, const CaloCell *inputCell, const CaloCell_SuperCell_ID *&idHelper) const
match SCs from the cluster in L2 to one cell of L3
float CaloCellET(const CaloCell *const &inputCell, float digitScale, float digitThreshold) const
private algorithms
double REta(const CaloCell *centreCell, int etaWidth1, int phiWidth1, int etaWidth2, int phiWidth2, const CaloConstCellContainer *scells, const CaloCell_SuperCell_ID *idHelper, float digitScale, float digitThresh) const
calculate the energy isolation of the central cell along eta
const CaloCell * returnCellFromCont(Identifier inputID, const CaloConstCellContainer *&cellContainer, const CaloCell_SuperCell_ID *&idHelper) const
helper functions to find neighbouring cells
std::vector< const CaloCell * > L2cluster(const CaloCell *centreCell, int etaWidth, int phiWidth, const CaloConstCellContainer *scells, const CaloCell_SuperCell_ID *idHelper, float digitScale, float digitThresh) const
form the cluster from cells of the second layer L2
bool m_use_tileCells
boolean for using Tile cells instead of Tile TT
int m_etaWidth_wstotIsolation
eta width for wstot isolation given in number of SCs
bool m_use_REtaL12
boolean for caluclating REta using Layer 1 in addition to Layer 2
float m_clustET_NoIso_thresh
threshold for applying cluster isolation cuts (baseline selection)
int m_phiWidth_TDRCluster
phi width of the TDR cluster formation given in number of SCs (including the central cell),...
const CaloCell * NextPhiCell(const CaloCell *inputCell, bool upwards, const CaloConstCellContainer *&cellContainer, const CaloCell_SuperCell_ID *&idHelper) const
returns the SC above/below the input cell
int m_phiWidth_REtaIsolation_den
phi width for REta isolation given in number of SCs (denominator of fraction)
void addOnce(const CaloCell *inputCell, std::vector< const CaloCell * > &outputVector) const
adds SC to vector if the SC is not part of this vector yet
double TT_phi(const xAOD::TriggerTower *&inputTower) const
convert the TT phi to match the definition of SC phi
double L2clusET(const CaloCell *centreCell, int etaWidth, int phiWidth, const CaloConstCellContainer *scells, const CaloCell_SuperCell_ID *idHelper, float digitScale, float digitThresh) const
calculate cluster energy of cells in L2 around the central cell in a given eta/phi width
std::vector< AlgResult > looseAlg(const CaloConstCellContainer *SCs, const xAOD::TriggerTowerContainer *TTs, const CaloCell_SuperCell_ID *idHelper, const TileID *m_tileIDHelper, const CaloConstCellContainer *tileCellCon) const
algorithm fors cluster building
float ene1(void) const
get energy of first PMT
Definition TileCell.h:187
float ene2(void) const
get energy of second PMT
Definition TileCell.h:189
Helper class for TileCal offline identifiers.
Definition TileID.h:67
int sample(const Identifier &id) const
uint8_t cpET() const
get cpET from peak of lut_cp
virtual double phi() const final
The azimuthal angle ( ) of the particle.
TriggerTowerContainer_v2 TriggerTowerContainer
Define the latest version of the TriggerTower container.
TriggerTower_v2 TriggerTower
Define the latest version of the TriggerTower class.