ATLAS Offline Software
Loading...
Searching...
No Matches
TrackDepositInCaloTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7// --- Tracking ---
10
11// --- Calorimeter ---
13#include "CaloEvent/CaloCell.h"
30// --- ROOT ---
31#include <cmath>
32
33#include "TH1F.h"
34#include "TH2F.h"
35
36namespace {
38 constexpr float solenoidRadius = 1280.;
39} // namespace
41// Constructor
43TrackDepositInCaloTool::TrackDepositInCaloTool(const std::string& type, const std::string& name, const IInterface* pInterface) :
44 AthAlgTool(type, name, pInterface),
45 m_histSvc("THistSvc", name) {
46 declareInterface<ITrackDepositInCaloTool>(this);
47 declareProperty("doExtrapolation", m_doExtr = true);
48 declareProperty("doEDeposHist", m_doHist = false);
49}
50
52// Initialize
55 ATH_CHECK(detStore()->retrieve(m_tileDDM));
56 if (!m_tileDDM) { return StatusCode::FAILURE; }
57 if (m_doHist) { ATH_CHECK(bookHistos()); }
58
59 ATH_CHECK(m_extrapolator.retrieve());
62 ATH_CHECK(m_caloDetDescrMgrKey.initialize());
63 ATH_MSG_INFO("initialize() successful in " << name());
64 return StatusCode::SUCCESS;
65}
66
68// getDeposits
70std::vector<DepositInCalo> TrackDepositInCaloTool::getDeposits(const Trk::TrackParameters* par,
71 const CaloCellContainer* caloCellCont) const {
72 const EventContext& ctx = Gaudi::Hive::currentContext();
73 ATH_MSG_DEBUG("In TrackDepositInCaloTool::getDeposits()");
74 std::vector<DepositInCalo> result;
75
76 // --- from now on, par can be assumed to exist ---
77 if (!par) { return result; }
78
79 if (!caloCellCont) return result;
80
82 if (!caloDetDescrMgrHandle.isValid()) {
83 return result;
84 }
85
86 const CaloDetDescrManager* caloDDM = *caloDetDescrMgrHandle;
87
88 const Trk::ParticleHypothesis muonHypo = Trk::muon;
89
90 // --- Preselection of track's crossing with detector elements ---
91 std::vector<Amg::Vector3D> extrapolations;
92 std::map<double, const CaloDetDescriptor*> caloInfo;
93 std::unique_ptr<const Trk::TrackParameters> currentPar = extrapolateToSolenoid(ctx, par);
94 if (!currentPar) {
95 ATH_MSG_WARNING("Extrapolation to solenoid did not succeed!");
96 return result;
97 }
98 if (getTraversedLayers(caloDDM,currentPar.get(), caloInfo, extrapolations).isFailure()) {
99 ATH_MSG_WARNING("Failure in getTraversedLayers(). ");
100 return result;
101 }
102
103 // --- Iterate over all the detector regions ---
104 for (const std::pair<const double, const CaloDetDescriptor*>& detDescrIt : caloInfo) {
105 const CaloDetDescriptor* descr = detDescrIt.second;
106 // ---- extrapolate to entrance of layer ---
107 std::unique_ptr<const Trk::TrackParameters> parEntrance = extrapolateToEntranceOfLayer(ctx, currentPar.get(), descr);
108 if (!parEntrance) {
109 ATH_MSG_DEBUG("Could not extrapolate to entrance.");
110 continue;
111 }
112 // ---- extrapolate to exit of layer ---
113 std::unique_ptr<const Trk::TrackParameters> parExit = extrapolateToExitOfLayer(ctx, parEntrance.get(), descr);
114 if (!parExit) {
115 ATH_MSG_DEBUG("Could not extrapolate to exit.");
116 // delete parEntrance;
117 currentPar.swap(parEntrance);
118 continue;
119 }
120 // --- Calculate energy loss ---
121 double energyLoss = calcEnergy(parEntrance.get(), muonHypo) - calcEnergy(parExit.get(), muonHypo);
122 double distance = (parEntrance->position() - parExit->position()).mag();
123 // --- Retrieve crossed cells ---
124 std::vector<const CaloCell*> cells =
125 getCaloCellsForLayer(caloDDM, descr, parEntrance.get(), parExit.get(), caloCellCont);
126
127 // --- Add contributions ---
128 double sumEnergy = 0;
129 double sumEt = 0;
130 for (const CaloCell* cell : cells) {
131 if (cell) {
132 sumEnergy += cell->energy();
133 sumEt += cell->et();
134 } else {
135 ATH_MSG_VERBOSE("Cell NULL pointer found!");
136 }
137 }
138 // --- Write DepositInCalo ---
139 ATH_MSG_DEBUG("Energy = " << sumEnergy << " for sample " << descr->getSampling() << " in " << cells.size() << " cells.");
140 if (distance) { result.emplace_back(descr->getSampling(), sumEnergy, energyLoss, sumEt); }
141
142 // --- Free memory and prepare for next round ---
143 currentPar.swap(parEntrance);
144 }
145 return result;
146}
147
149// - New getDeposits
151std::vector<DepositInCalo> TrackDepositInCaloTool::getDeposits(const xAOD::TrackParticle* tp, const CaloCellContainer* caloCellCont,
152 const CaloExtensionCollection* extensionCache) const {
153 ATH_MSG_DEBUG("In TrackDepositsInCaloTool::getDeposits() - new");
154 std::vector<DepositInCalo> result;
155 const unsigned int nSamples = CaloSampling::getNumberOfSamplings();
156
157 // - associate calocells to trackparticle, cone size 0.2, use cache
158
159 std::unique_ptr<const Rec::ParticleCellAssociation> association =
160 m_caloCellAssociationTool->particleCellAssociation(*tp, 0.2, caloCellCont, extensionCache);
161
162 if (!association) return result;
163 ATH_MSG_VERBOSE(" particleCellAssociation done " << association.get());
164
165 // - pick up the cell intersections
166
167 std::vector<std::pair<const CaloCell*, Rec::ParticleCellIntersection*>> cellIntersections = association->cellIntersections();
168
169 const Trk::CaloExtension& caloExtension = association->caloExtension();
170
171 if (!caloExtension.caloEntryLayerIntersection()) {
172 ATH_MSG_WARNING(" No caloEntryLayerIntersection found ");
173 return result;
174 }
175
176 ATH_MSG_DEBUG(" nr of cell intersections " << cellIntersections.size());
177 if (cellIntersections.size() < 3) ATH_MSG_WARNING(" Strange nr of calorimeter cell intersections " << cellIntersections.size());
178
180 CaloExtensionHelpers::entryExitLayerMap(caloExtension, entryExitLayerMap);
181 ATH_MSG_VERBOSE("EntryExitLayerMap " << entryExitLayerMap.size());
182
184 CaloExtensionHelpers::eLossLayerMap(caloExtension, eLossLayerMap);
185 ATH_MSG_VERBOSE("eLossLayerMap " << eLossLayerMap.size());
186
187 std::vector<float> exp_E(nSamples, 0.0);
188 std::vector<float> meas_E(nSamples, 0.0);
189 std::vector<float> meas_Et(nSamples, 0.0);
190 std::vector<int> LayerHit(nSamples, 0);
192 Amg::Vector3D lEntry, lExit;
193
194 // loop over cellIntersections, there can be more than one cell hit in a layer
195
196 for (auto& it : cellIntersections) {
197 const CaloCell* curr_cell = it.first;
198 if (curr_cell->badcell()) continue;
199 int cellSampling = curr_cell->caloDDE()->getSampling();
200 CaloSampling::CaloSample sample = static_cast<CaloSampling::CaloSample>(cellSampling);
201 // bool badCell = curr_cell->badcell();
202 auto pos = entryExitLayerMap.find(sample);
203 if (pos == entryExitLayerMap.end()) continue;
204 lEntry = pos->second.first;
205 lExit = pos->second.second;
206 if (TrackDepositInCaloTool::inCell(curr_cell, lEntry) || TrackDepositInCaloTool::inCell(curr_cell, lExit)) {
207 meas_E[cellSampling] += Float_t(curr_cell->energy());
208 meas_Et[cellSampling] += Float_t(curr_cell->energy() * curr_cell->sinTh());
209 exp_E[cellSampling] = Float_t((it.second)->expectedEnergyLoss());
210 LayerHit[cellSampling]++;
211 ATH_MSG_VERBOSE(" Layer : " << cellSampling << " Energy = " << curr_cell->energy()
212 << " Exp : " << (it.second)->expectedEnergyLoss());
213 }
214 }
215
216 // sum cells per layer and fill samples per layer
217
218 for (int i = CaloSampling::PreSamplerB; i < CaloSampling::CaloSample::Unknown; i++) {
219 if (LayerHit[i] > 0) {
220 sample = static_cast<CaloSampling::CaloSample>(i);
221 result.emplace_back(sample, meas_E[i], exp_E[i], meas_Et[i]);
222 ATH_MSG_DEBUG(" Layer : " << sample << " Energy = " << meas_E[i] << " nCells : " << LayerHit[i] << " Exp: " << exp_E[i]);
223 }
224 }
225
226 return result;
227}
228
229// - end getDeposits
230
232// getCaloCellsForLayer
234std::vector<const CaloCell*> TrackDepositInCaloTool::getCaloCellsForLayer(const CaloDetDescrManager* caloDDM,
235 const CaloDetDescriptor* descr,
236 const Trk::TrackParameters* parEntrance,
237 const Trk::TrackParameters* parExit,
238 const CaloCellContainer* caloCellCont) const {
239 if (descr->is_tile()) {
240 // --- Tile implemention is lengthy and therefore put in seperate function
241 // ---
242 return getCaloCellsForTile(caloDDM, descr, parEntrance, parExit, caloCellCont);
243 } else {
244 // --- LAr implementation is short, quick and simple ---
245 const CaloCell* cellEntrance =
246 getClosestCellLAr(caloDDM, parEntrance, descr, caloCellCont);
247 const CaloCell* cellExit =
248 getClosestCellLAr(caloDDM, parExit, descr, caloCellCont);
249 std::vector<const CaloCell*> result;
250 result.push_back(cellEntrance);
251 if (cellEntrance != cellExit) {
252 result.push_back(cellExit);
253 }
254 return result;
255 }
256}
257
259// getCaloCellsForTile
261std::vector<const CaloCell*> TrackDepositInCaloTool::getCaloCellsForTile(const CaloDetDescrManager* caloDDM,
262 const CaloDetDescriptor* descr,
263 const Trk::TrackParameters* parEntrance,
264 const Trk::TrackParameters* parExit,
265 const CaloCellContainer* caloCellCont) const {
266 /*
267 ...to be written...
268 */
269 ATH_MSG_VERBOSE("in getCaloCellsForTileLayer()...");
270
271 std::vector<const CaloCell*> result{};
272 // --- Get all the relevant kinematical variables ---
273 double phiPar = parEntrance->position().phi();
274 double phiParEntrance = phiPar;
275 double zParEntrance = parEntrance->position().z();
276 double phiParExit = parExit->position().phi();
277 double zParExit = parExit->position().z();
278 double diffZPar = zParExit - zParEntrance;
279 double etaPar = parEntrance->position().eta();
280 // --- Determine granularity ---
281 double etaWidth = 2 * (descr->calo_eta_max() - descr->calo_eta_min()) / descr->n_eta();
282 double etaMin = etaPar - etaWidth;
283 double etaMax = etaPar + etaWidth;
284 double phiWidth = (descr->calo_phi_max() - descr->calo_phi_min()) / descr->n_phi();
285 // TODO: HOW TO DEAL WITH PHI ~ PI?
286 double phiMin = phiPar - phiWidth;
287 double phiMax = phiPar + phiWidth;
288 // --- Fill vecHash ---
289 CaloCell_ID::CaloSample sample = descr->getSampling();
290
291 std::vector<IdentifierHash> vecHash;
292 caloDDM->cellsInZone(etaMin, etaMax, phiMin, phiMax, sample, vecHash);
293
294 // --- Iterate and find closest to track (around 12-15 elements in loop) ---
295 std::map<double, const CaloCell*> neighbourMap0;
296 std::map<double, const CaloCell*> neighbourMap1;
297
298 for (const IdentifierHash& id : vecHash) {
299 const CaloCell* cell = caloCellCont->findCell(id);
300 if (!cell) continue;
301 const CaloDetDescrElement* dde = cell->caloDDE();
302 if (!dde) continue;
303
304 double dPhiCell = dde->dphi();
305 double phiCellMin = dde->phi() - dPhiCell / 2;
306 double phiCellMax = phiCellMin + dPhiCell;
307 if (!(phiParEntrance > phiCellMin && phiParExit < phiCellMax) && !(phiParExit > phiCellMin && phiParExit < phiCellMax)) {
308 continue;
309 }
310
311 // --- There are two z dimensions for the BC cells ---
312 double zCellMin0{0}, zCellMax0{0}, zCellMin1{0}, zCellMax1{0};
313 TileCellDim* cellDim = m_tileDDM->get_cell_dim(cell->ID());
314 if (!cellDim) {
315 ATH_MSG_WARNING("TileCellDim object not found for cell " << cell->ID());
316 continue;
317 }
318 // --- This is valid for the BC cells ---
319 if (cellDim->getNRows() == 6) {
320 zCellMin0 = cellDim->getZMin(0);
321 zCellMax0 = cellDim->getZMax(0);
322 zCellMin1 = cellDim->getZMin(3);
323 zCellMax1 = cellDim->getZMax(3);
324 } else {
325 zCellMin0 = cellDim->getZMin(0);
326 zCellMax0 = cellDim->getZMax(0);
327 zCellMin1 = zCellMin0;
328 zCellMax1 = zCellMax0;
329 }
330
331 // --- Check wether entrance parameters are within cell acceptance at entrance ---
332 // --- The equal signs (>=, <=) are very important for the boundary cells ---
333 if (zParEntrance >= zCellMin0 && zParEntrance <= zCellMax0 && phiParEntrance > phiCellMin && phiParEntrance < phiCellMax) {
334 result.push_back(cell);
335 continue;
336 }
337 // --- Check wether exit parameters are within cell acceptance at exit ---
338 if (zParExit >= zCellMin1 && zParExit <= zCellMax1 && phiParExit > phiCellMin && phiParExit < phiCellMax) {
339 result.push_back(cell);
340 continue;
341 }
342 // --- Check wether it crosses a cell ---
343 if (diffZPar > 0) {
344 if (zParEntrance < zCellMin0 && zParExit > zCellMax1) {
345 result.push_back(cell);
346 continue;
347 }
348 } else {
349 if (zParEntrance > zCellMax0 && zParExit < zCellMin1) {
350 result.push_back(cell);
351 continue;
352 }
353 }
354 }
355 return result;
356}
357
359// extrapolateToEntraceOfLayer
361std::unique_ptr<const Trk::TrackParameters> TrackDepositInCaloTool::extrapolateToEntranceOfLayer(const EventContext& ctx,
362 const Trk::TrackParameters* par,
363 const CaloDetDescriptor* descr) const {
364 // --- Initialization ---
365 std::unique_ptr<const Trk::TrackParameters> paramEntrance;
366 bool checkBoundary = true;
368
369 std::unique_ptr<Trk::Surface> surfEntrance{createSurface(descr, Entrance)};
370 if (!surfEntrance) {
371 ATH_MSG_DEBUG("Error in extrapolateToBeginOfLayer()");
372 return nullptr;
373 }
374 // --- Try to extrapolate to entrance ---
375 paramEntrance = m_extrapolator->extrapolate(ctx, *par, *surfEntrance, Trk::alongMomentum, !checkBoundary, muonHypo);
376 if (!paramEntrance) {
377 ATH_MSG_DEBUG("Extrapolation to entrance failed without boundary check.");
378 return nullptr;
379 }
380 const Amg::Vector3D& posVecEntrance = paramEntrance->position();
381 // --- If the parameters are not on surface, extrapolate to side of calorimeter ---
382 if (surfEntrance->isOnSurface(posVecEntrance, checkBoundary)) {
383 ATH_MSG_VERBOSE("Successfully extrapolated to entrance of calo for sample " << descr->getSampling());
384 return paramEntrance;
385 }
386 std::unique_ptr<Trk::Surface> surfInside{createSurface(descr, Inside)};
387 if (surfInside) {
388 std::unique_ptr<const Trk::TrackParameters> paramOnInside{
389 m_extrapolator->extrapolate(ctx, *paramEntrance, *surfInside, Trk::alongMomentum, checkBoundary, muonHypo)};
390 if (paramOnInside) {
391 ATH_MSG_VERBOSE("Successfully extrapolated to inner side of calo for sample " << descr->getSampling());
392 paramEntrance.swap(paramOnInside);
393 } else {
394 ATH_MSG_DEBUG("Extrapolation to entrance failed!");
395 return nullptr;
396 }
397 }
398 return paramEntrance;
399}
400
402// extrapolateToExitOfLayer
404std::unique_ptr<const Trk::TrackParameters> TrackDepositInCaloTool::extrapolateToExitOfLayer(const EventContext& ctx,
405 const Trk::TrackParameters* par,
406 const CaloDetDescriptor* descr) const {
407 std::unique_ptr<const Trk::TrackParameters> paramExit;
408 bool checkBoundary = true;
410
411 // --- Create surface parallel to layer ---
412 std::unique_ptr<Trk::Surface> surfExit{createSurface(descr, Exit)};
413 if (!surfExit) {
414 ATH_MSG_WARNING("Could not create exit surface.");
415 return nullptr;
416 }
417 // --- Try to extrapolate to exit of layer ---
418 paramExit = m_extrapolator->extrapolate(ctx, *par, *surfExit, Trk::alongMomentum, checkBoundary, muonHypo);
419 if (paramExit) {
420 ATH_MSG_VERBOSE("Extrapolated to exit. ");
421 return paramExit;
422 }
423 // --- Try to extrapolate to side ---
424 std::unique_ptr<Trk::Surface> surfOutside{createSurface(descr, Outside)};
425 if (!surfOutside) { return nullptr; }
426 paramExit = m_extrapolator->extrapolate(ctx, *par, *surfOutside, Trk::alongMomentum, checkBoundary, muonHypo);
427 if (paramExit) {
428 ATH_MSG_VERBOSE("Succesfully extrapolated to outer side of calo for sample " << descr->getSampling());
429 } else {
430 ATH_MSG_VERBOSE("Could not extrapolate to exit of calo.");
431 }
432 return paramExit;
433}
434
436// extrapolateToSolenoid
438std::unique_ptr<const Trk::TrackParameters> TrackDepositInCaloTool::extrapolateToSolenoid(const EventContext& ctx,
439 const Trk::TrackParameters* par,
440 bool oppositeMomentum) const {
442 if (oppositeMomentum) { direction = Trk::oppositeMomentum; }
443
444 // --- First extrapolate to solenoid radius or EndCap disk ---
445 // --- Ownership of the HepTransform3Ds is passed to the Surfaces ---
446 constexpr double halfLengthOfCylinder = 3700;
447 bool checkBoundary = true;
448 Trk::CylinderSurface solenoid(solenoidRadius, halfLengthOfCylinder);
450
451 std::unique_ptr<const Trk::TrackParameters> parAtSolenoid{
452 m_extrapolator->extrapolate(ctx, *par, solenoid, direction, checkBoundary, muonHypo)};
453 if (!parAtSolenoid) {
454 // --- Guess EndCap side by direction ---
455 double zTrans = par->eta() > 0 ? halfLengthOfCylinder : -halfLengthOfCylinder;
456 Trk::DiscSurface disc(Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0., 0., zTrans))), 0, solenoidRadius);
457
458 parAtSolenoid = m_extrapolator->extrapolate(ctx, *par, disc, direction, checkBoundary, muonHypo);
459
460 if (!parAtSolenoid) {
461 ATH_MSG_VERBOSE("extrapolateToSolenoid(): Extrapolation to cap of solenoid failed. Trying opposite side.");
462 Trk::DiscSurface discOpp(Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0., 0., -zTrans))), 0, solenoidRadius);
463 parAtSolenoid = m_extrapolator->extrapolate(ctx, *par, discOpp, direction, checkBoundary, muonHypo);
464 }
465
466 if (parAtSolenoid) { ATH_MSG_VERBOSE("extrapolateToSolenoid(): Extrapolation succeeded for disc-type surface."); }
467
468 } else {
469 ATH_MSG_VERBOSE("extrapolateToSolenoid(): Extrapolation succeeded for cylinder-type surface.");
470 }
471
472 return parAtSolenoid;
473}
474
476// deposits
478std::vector<DepositInCalo> TrackDepositInCaloTool::deposits(const Trk::TrackParameters* par, const CaloCellContainer* cellContainer) const {
479 /*
480 This method retrieves a vector of DepositInCalo (sample, energy, energyloss, et) containing one entry for each
481 calorimeter sample traversed. The method is written for muons which are MIPs, so they don't shower very much. This is the
482 reason why only the one sample is returned that is closest to the muon track.
483 The algorithm for finding the deposits works as follows. First a preselection is done by getTraversedLayers(). This returns
484 a vector of CaloDetDescriptors*. From these CaloDetDescriptors surfaces are built to which the extrapolator extrapolates
485 the track parameters . The extrapolator first tries to hit the entrance surface, but if it fails it will try to hit the
486 sides. From there on, the track is extrapolated to the middle of the Calorimeter and the CaloCell that is closest to this point
487 is retrieved using the function getClosestCell. Eventually the parameters are extrapolated to the exit, or outer side of the
488 sample.
489 */
490 ATH_MSG_DEBUG("In TrackDepositInCaloTool::deposits()");
491 std::vector<DepositInCalo> result;
492 const EventContext& ctx = Gaudi::Hive::currentContext();
493
494 // --- Possible crash prevention ---
495 if (!par) { return result; }
496
498 if (!caloDetDescrMgrHandle.isValid()) {
499 return result;
500 }
501
502 const CaloDetDescrManager* caloDDM = *caloDetDescrMgrHandle;
503
504 const Trk::ParticleHypothesis muonHypo = Trk::muon;
505 bool checkBoundary = true;
506
507 // --- Preselection of track's crossing with detector elements ---
508 std::vector<Amg::Vector3D> extrapolations;
509 std::map<double, const CaloDetDescriptor*> caloInfo;
510 std::unique_ptr<const Trk::TrackParameters> parAtSolenoid = extrapolateToSolenoid(ctx, par);
511 if (parAtSolenoid) {
512 if (getTraversedLayers(caloDDM, parAtSolenoid.get(), caloInfo, extrapolations).isFailure()) {
513 ATH_MSG_WARNING("Failure in finding getTraversedLayers. ");
514 return result;
515 }
516 } else {
517 ATH_MSG_WARNING("Failure in extrapolating to solenoid surface.");
518 return result;
519 }
520 // --- Loop over the cells from preselection ---
521 std::vector<Amg::Vector3D>::iterator itP = extrapolations.begin();
522 for (const std::pair<const double, const CaloDetDescriptor*>& it : caloInfo) {
523 // --- Initialization of variables to be determined below ---
524 double energyEntrance{0}, energyExit{0}, energyDeposit{0}, ETDeposit{0}, energyLoss{0};
525 bool eLossFound = false;
526 const CaloDetDescriptor* descr = it.second;
527 CaloCell_ID::CaloSample sample = descr->getSampling();
528 ATH_MSG_VERBOSE("Analysing crossing of calo sample " << sample << " ");
529
530 // --- Extrapolate to entrance of layer ---
531 std::unique_ptr<const Trk::Surface> surfEntrance{createSurface(descr, Entrance)};
532 if (!surfEntrance) {
533 continue;
534 ATH_MSG_VERBOSE("Could not create entrance surface.");
535 }
536 std::unique_ptr<const Trk::TrackParameters> paramEntrance{
537 m_extrapolator->extrapolate(ctx, *par, *surfEntrance, Trk::alongMomentum, !checkBoundary, muonHypo)};
538 if (!paramEntrance) {
539 ATH_MSG_VERBOSE("Could not extrapolate to entrance of calo.");
540 continue;
541 }
542 const Amg::Vector3D& posVecEntrance = paramEntrance->position();
543 if (!surfEntrance->isOnSurface(posVecEntrance, checkBoundary)) {
544 std::unique_ptr<Trk::Surface> surfInside{createSurface(descr, Inside)};
545 if (surfInside) {
546 std::unique_ptr<const Trk::TrackParameters> paramOnInside{
547 m_extrapolator->extrapolate(ctx, *paramEntrance, *surfInside, Trk::alongMomentum, checkBoundary, muonHypo)};
548 if (paramOnInside) {
549 ATH_MSG_VERBOSE("Succesfully extrapolated to inner side of calo for sample " << sample);
550 paramEntrance.swap(paramOnInside);
551 } else {
552 ATH_MSG_WARNING("Extrapolation failed to inner side of calo " << sample);
553 }
554 } else {
555 ATH_MSG_WARNING("Could not create surface for inside of calo for sample " << sample);
556 }
557 }
558 energyEntrance = calcEnergy(paramEntrance.get(), muonHypo);
559 // --- Extrapolate to middle of layer ---
560 std::unique_ptr<Trk::Surface> surfMiddle{createSurface(descr, Middle)};
561 if (surfMiddle) {
562 std::unique_ptr<const Trk::TrackParameters> paramMiddle{
563 m_extrapolator->extrapolate(ctx, *paramEntrance, *surfMiddle, Trk::alongMomentum, checkBoundary, muonHypo)};
564 if (paramMiddle) {
565 // Get energy:
566 const CaloCell* cell = getClosestCell(caloDDM, paramMiddle.get(), descr, cellContainer);
567 if (cell) {
568 energyDeposit = cell->energy();
569 ETDeposit = cell->et();
570 }
571 // --- Extrapolate to exit of layer ---
572 std::unique_ptr<Trk::Surface> surfExit{createSurface(descr, Exit)};
573 std::unique_ptr<const Trk::TrackParameters> paramExit;
574 if (surfExit) {
575 paramExit = m_extrapolator->extrapolate(ctx, *paramMiddle, *surfExit, Trk::alongMomentum, checkBoundary, muonHypo);
576 if (paramExit) {
577 ATH_MSG_VERBOSE("Extrapolated to exit. ");
578 energyExit = calcEnergy(paramExit.get(), muonHypo);
579 eLossFound = true;
580 } else {
581 // Try to extrapolate to outside
582 std::unique_ptr<Trk::Surface> surfOutside{createSurface(descr, Outside)};
583 if (surfOutside) {
584 paramExit =
585 m_extrapolator->extrapolate(ctx, *paramMiddle, *surfOutside, Trk::alongMomentum, checkBoundary, muonHypo);
586 if (paramExit) {
587 ATH_MSG_VERBOSE("Succesfully extrapolated to outer side of calo for sample " << sample);
588 energyExit = calcEnergy(paramExit.get(), muonHypo);
589 eLossFound = true;
590 } else {
591 ATH_MSG_VERBOSE("Could not extrapolate to exit of calo.");
592 }
593 } else {
594 ATH_MSG_WARNING("Could not create surface for outside of calo for sample " << sample);
595 }
596 }
597 } else {
598 ATH_MSG_WARNING("Could not create exit surface.");
599 }
600
601 } else {
602 ATH_MSG_VERBOSE("Could not extrapolate to middle of calo.");
603 }
604 } else {
605 ATH_MSG_VERBOSE("Could not create middle surface.");
606 }
607
608 energyLoss = eLossFound ? -(energyExit - energyEntrance) : 0;
609 result.emplace_back(sample, energyDeposit, energyLoss, ETDeposit);
610 ATH_MSG_DEBUG("Sample: " << sample << "\tEnergyDeposit: " << energyDeposit << "\tEnergyLoss: " << energyLoss);
611
612 if (m_doHist) {
613 Hists& h = getHists();
614 h.m_hParELossEta->Fill(energyLoss, itP->eta());
615 h.m_hParELossSample->Fill(energyLoss, sample);
616 }
617
618 // itP++;
619 // it++;
620 }
621
622 ATH_MSG_VERBOSE("---TRACKDEPOSITINCALOTOOL---TRACKDEPOSITINCALOTOOL---TRACKDEPOSITINCALOTOOL");
623 return result;
624}
625
627// calcEnergy
630 double mass = Trk::ParticleMasses::mass[particleHypo];
631 if (!par) return 0.;
632 double pX = par->momentum().x();
633 double pY = par->momentum().y();
634 double pZ = par->momentum().z();
635 return std::sqrt(mass * mass + pX * pX + pY * pY + pZ * pZ);
636}
637
639// initializeDetectorInfo()
643 LayerMaps maps;
644
645 ATH_MSG_DEBUG("In CaloTrkMuIdDetStore::initialize()");
646 // Initialize LAr
647 for (const CaloDetDescriptor* descr : caloDDM->calo_descriptors_range()) {
648 if (descr) {
649 CaloCell_ID::CaloSample sample = descr->getSampling();
650 ATH_MSG_VERBOSE("Detector Description element for sample " << sample);
651 if (descr->is_lar_em_barrel()) {
652 ATH_MSG_VERBOSE(" this is a cylindrical detector element.");
653 double thickness = descr->calo_r_max() - descr->calo_r_min();
654 double r = descr->calo_r_min() + thickness / 2.0;
655 ATH_MSG_VERBOSE(" R = " << r);
656 ATH_MSG_VERBOSE(" sign = " << descr->calo_sign());
657 ATH_MSG_VERBOSE(" range_low = " << descr->calo_z_min());
658 ATH_MSG_VERBOSE(" range_high = " << descr->calo_z_max());
659 if (sample != CaloCell_ID::PreSamplerB) maps.m_barrelLayerMap[r].push_back(descr);
660 } else {
661 ATH_MSG_VERBOSE(" this is a disk-like detector element.");
662 double thickness = descr->calo_z_max() - descr->calo_z_min();
663 double z = descr->calo_z_min() + thickness / 2.0;
664 ATH_MSG_VERBOSE(" Z = " << z);
665 ATH_MSG_VERBOSE(" sign = " << descr->calo_sign());
666 ATH_MSG_VERBOSE(" range_low = " << descr->calo_r_min());
667 ATH_MSG_VERBOSE(" range_high = " << descr->calo_r_max());
668 if (sample != CaloCell_ID::PreSamplerE) { maps.m_endCapLayerMap[z].push_back(descr); }
669 }
670 } else
671 ATH_MSG_VERBOSE("CaloDetDescriptor was not available!");
672 }
673
674 ATH_MSG_VERBOSE("Processing tiles... ");
675 for (const CaloDetDescriptor* descr : caloDDM->tile_descriptors_range()) {
676 if (descr) {
677 ATH_MSG_VERBOSE("Detector Description element for sample " << descr->getSampling());
678 if (!descr->is_tile()) { ATH_MSG_VERBOSE("This is not a isTile()==true element."); }
679 CaloCell_ID::CaloSample sample = descr->getSampling();
680 if (sample >= 15 && sample <= 17) {
681 // --- Skip the TileGap detector elements ---
682 continue;
683 }
684 ATH_MSG_VERBOSE(" this is a cylindrical detector element.");
685 double thickness = descr->calo_r_max() - descr->calo_r_min();
686 double r = descr->calo_r_min() + thickness / 2.0;
687 ATH_MSG_VERBOSE(" r = " << r);
688 ATH_MSG_VERBOSE(" sign = " << descr->calo_sign());
689 ATH_MSG_VERBOSE(" range_low = " << descr->calo_z_min());
690 ATH_MSG_VERBOSE(" range_high = " << descr->calo_z_max());
691 maps.m_barrelLayerMap[r].push_back(descr);
692 } else
693 ATH_MSG_VERBOSE("CaloDetDescriptor was not available!");
694 }
695 return maps;
696}
697
699// extrapolateR
701std::unique_ptr<Amg::Vector3D> TrackDepositInCaloTool::extrapolateR(const Amg::Vector3D& initialPosition, double phi0, double theta0,
702 double r) {
703 double x0 = initialPosition.x();
704 double y0 = initialPosition.y();
705 double z0 = initialPosition.z();
706
707 double b = 2 * x0 * std::cos(phi0) + 2 * y0 * std::sin(phi0);
708 double c = x0 * x0 + y0 * y0 - r * r;
709 double det = b * b - 4 * c;
710 double lsin = 0;
711 if (det < 0) {
712 return nullptr;
713 } else
714 lsin = (-b + std::sqrt(det)) / 2;
715
716 double xe = x0 + lsin * std::cos(phi0);
717 double ye = y0 + lsin * std::sin(phi0);
718 double ze = z0 + lsin * std::cos(theta0) / std::sin(theta0);
719
720 if (std::abs(xe * xe + ye * ye - r * r) > 10 && det > 0) {
721 // ATH_MSG_WARNING("ExtrapoateR(): extrapolation did not succeed!");
722 return nullptr;
723 }
724 // ATH_MSG_INFO("ExtrapolateR(): Extrapolation succeeded.");
725 return std::make_unique<Amg::Vector3D>(xe, ye, ze);
726}
727
729// extrapolateZ
731std::unique_ptr<Amg::Vector3D> TrackDepositInCaloTool::extrapolateZ(const Amg::Vector3D& initialPosition, double phi0, double theta0,
732 double z) {
733 double x0 = initialPosition.x();
734 double y0 = initialPosition.y();
735 double z0 = initialPosition.z();
736 double cosTheta0 = std::cos(theta0);
737 if (cosTheta0) {
738 double dist = z - z0;
739 double lambda = dist / cosTheta0;
740 if (lambda < 0) {
741 // ATH_MSG_WARNING("ExtrapolateZ(): extrapolation did not succeed!");
742 return nullptr;
743 }
744 double xe = x0 + lambda * std::sin(theta0) * std::cos(phi0);
745 double ye = y0 + lambda * std::sin(theta0) * std::sin(phi0);
746 double ze = z;
747 // ATH_MSG_INFO("ExtrapolateZ(): Extrapolation succeeded.");
748 return std::make_unique<Amg::Vector3D>(xe, ye, ze);
749 } else {
750 // ATH_MSG_WARNING("ExtrapolateZ(): extrapolation did not succeed!");
751 return nullptr;
752 }
753}
754
756// getTraversedLayers
759 const Trk::TrackParameters* par,
760 std::map<double, const CaloDetDescriptor*>& caloInfo,
761 std::vector<Amg::Vector3D>& extrapolations) const {
762 // Cannot do this in initialize: see ATLASRECTS-5012
763 if (!m_layerMaps.isValid()) {
764 m_layerMaps.set (initializeDetectorInfo (caloDDM));
765 }
766 const LayerMaps& layerMaps = *m_layerMaps.ptr();
767
768 const Trk::TrackParameters* parAtSolenoid = nullptr;
769 // --- To be replaced by a check, possibly extrapolating to solenoid surface if needed ---
770 bool parIsAtSolenoid = true;
771 if (parIsAtSolenoid) parAtSolenoid = par;
772
773 // --- This performs a straight line extrapolation and determines wether it is in calorimeter layer acceptance. ---
774 if (parAtSolenoid) {
775 // ATH_MSG_INFO("Parameters at solenoid are well-defined.");
776
777 double deltaR_solLast = std::abs(parAtSolenoid->position().perp() - par->position().perp());
778 double deltaEta_solLast = std::abs(parAtSolenoid->position().eta() - par->position().eta());
779 if (m_doHist) {
780 Hists& h = getHists();
781 h.m_hDeltaEtaLastPar->Fill(deltaEta_solLast);
782 h.m_hDeltaRadiusLastPar->Fill(deltaR_solLast);
783 }
784
785 const Amg::Vector3D positionAtSolenoid = parAtSolenoid->position();
786 double theta0 = parAtSolenoid->momentum().theta();
787 double phi0 = parAtSolenoid->momentum().phi();
788
789 // --- This Code fragment determines the Barrel crossings ---
790 for (const std::pair<const double, std::vector<const CaloDetDescriptor*>>& mapIt : layerMaps.m_barrelLayerMap) {
791 const double& radius = mapIt.first;
792 std::unique_ptr<Amg::Vector3D> extrapolation = extrapolateR(positionAtSolenoid, phi0, theta0, radius);
793 if (!extrapolation) { continue; }
794 for (const CaloDetDescriptor* descr : mapIt.second) {
795 double zSigned = extrapolation->z() * descr->calo_sign();
796 if (zSigned >= descr->calo_z_min() && zSigned <= descr->calo_z_max()) {
797 double distance = (*extrapolation - positionAtSolenoid).mag();
798 caloInfo[distance] = descr;
799 extrapolations.emplace_back(*extrapolation);
800 }
801 }
802 }
803
804 // This code fragment determines the EndCap crossings
805 for (const std::pair<const double, std::vector<const CaloDetDescriptor*>>& mapIt : layerMaps.m_endCapLayerMap) {
806 const double& zCenter = mapIt.first;
807 for (const CaloDetDescriptor* descr : mapIt.second) {
808 double z = zCenter * descr->calo_sign();
809 std::unique_ptr<Amg::Vector3D> extrapolation = extrapolateZ(positionAtSolenoid, phi0, theta0, z);
810 if (!extrapolation) continue;
811
812 double radius = extrapolation->perp();
813 if (radius >= descr->calo_r_min() && radius <= descr->calo_r_max()) {
814 double distance = (*extrapolation - positionAtSolenoid).mag();
815 caloInfo[distance] = descr;
816 extrapolations.emplace_back(*extrapolation);
817 }
818 }
819 }
820
821 } else {
822 return StatusCode::FAILURE;
823 }
824
825 return StatusCode::SUCCESS;
826}
827
829// createSurface()
832 /*
833 Creates a Calorimeter surface for parameter descr. For barrel layers CaloSurfaceType Entrance, Middle and Exit yield
834 a Trk::CylinderSurface. For CaloSurfaceTypes Inside and Outside the result will be a Trk::DiscSurface. Inside in
835 this case is the smallest abs(z) and Outside the largest abs(z) for the two possible sides. For EndCap layers,
836 Inside is the cylinder surface with smallest radius, and Outside the one with the largest radius. It all makes sense
837 when you realize that CaloTrkMuId extrapolates a track outwards from the Inner Detector. The ownership of the
838 transforms is passed to the Trk::Surface result.
839 */
840 Trk::Surface* res = nullptr;
841 if (descr->is_tile() || descr->is_lar_em_barrel()) {
842 // --- Cylindrical calo elements ---
843 if (type >= Entrance && type <= Exit) {
844 double thickness = descr->calo_r_max() - descr->calo_r_min();
845 double halfLength = (descr->calo_z_max() - descr->calo_z_min()) / 2;
846 double middle = descr->calo_z_min() + halfLength;
847 double radius = type / 2.0 * thickness + descr->calo_r_min();
848 // ATH_MSG_INFO("r = " << radius << " for type " << type << " and sample " << descr->getSampling());
849 // HepGeom::Transform3D* trans = new HepGeom::Translate3D(0,0,descr->calo_sign()*middle);
850 res = new Trk::CylinderSurface(Amg::Transform3D(Amg::Translation3D(0., 0., descr->calo_sign() * middle)), radius, halfLength);
851 return res;
852 } else if (type == Inside || type == Outside) {
853 double offset;
854 if (type == Inside) {
855 offset = descr->calo_z_min() * descr->calo_sign();
856 } else {
857 offset = descr->calo_z_max() * descr->calo_sign();
858 }
859 res = new Trk::DiscSurface(Amg::Transform3D(Amg::Translation3D(0., 0., offset)), descr->calo_r_min(), descr->calo_r_max());
860 return res;
861 } else {
862 ATH_MSG_WARNING("Type error in CaloTrkMuIdDetStore::createSurface().");
863 return nullptr;
864 }
865 } else {
866 // --- Disc-like calo elements (EndCap) ---
867 if (type >= Entrance && type <= Exit) {
868 double thickness = descr->calo_z_max() - descr->calo_z_min();
869 double offset = descr->calo_sign() * (thickness * type / 2.0 + descr->calo_z_min());
870 res = new Trk::DiscSurface(Amg::Transform3D(Amg::Translation3D(0., 0., offset)), descr->calo_r_min(), descr->calo_r_max());
871 return res;
872 } else if (type == Inside || type == Outside) {
873 double radius;
874 if (type == Inside) {
875 radius = descr->calo_r_min();
876 } else {
877 radius = descr->calo_r_max();
878 }
879 double halfLength = (descr->calo_z_max() - descr->calo_z_min()) / 2.0;
880 double offset = descr->calo_sign() * (descr->calo_z_min() + halfLength);
881 res = new Trk::CylinderSurface(Amg::Transform3D(Amg::Translation3D(0., 0., offset)), radius, halfLength);
882 return res;
883 } else {
884 ATH_MSG_WARNING("Type error in CaloTrkMuIdDetStore::createSurface().");
885 return nullptr;
886 }
887 }
888 return nullptr;
889}
890
892// getClosestCell()
894const CaloCell*
896 const Trk::TrackParameters* par,
897 const CaloDetDescriptor* descr,
898 const CaloCellContainer* caloCellCont) const
899{
900 /*
901 Get closest cell near the TrackParameters par. For LAr this can be done using the get_element function of the
902 CaloDetDescrManager. This should be really fast since it is nothing more than a sequence of lookups.
903 For the non-projective tile cells one has to select cells in a certain (eta,phi) region and then select the one
904 that is closest to the track.
905 */
906
907 const CaloCell* cell = nullptr;
908 if (descr->is_tile()) {
909 cell = getClosestCellTile(caloDDM, par, descr, caloCellCont);
910 } else {
911 cell = getClosestCellLAr(caloDDM, par, descr, caloCellCont);
912 }
913 return cell;
914}
915
917// getClosestCellLAr()
919const CaloCell*
921 const Trk::TrackParameters* par,
922 const CaloDetDescriptor* descr,
923 const CaloCellContainer* caloCellCont)
924{
925 CaloCell_ID::CaloSample sample = descr->getSampling();
926 // ATH_MSG_INFO("Sampling = " << sample);
927 const CaloDetDescrElement* cellDescr = caloDDM->get_element(sample, par->position().eta(), par->position().phi());
928 if (cellDescr) {
929 IdentifierHash hash = cellDescr->calo_hash();
930 const CaloCell* cell = caloCellCont->findCell(hash);
931 return cell;
932 }
933 return nullptr;
934}
935
937// getClosestCellTile()
939const CaloCell*
941 const CaloDetDescrManager* caloDDM,
942 const Trk::TrackParameters* par,
943 const CaloDetDescriptor* descr,
944 const CaloCellContainer* caloCellCont) const
945{
946 std::map<double, const CaloCell*> neighbourMap;
947 const CaloCell* result = nullptr;
948 // --- Determine granularity ---
949 double etaPar = par->position().eta();
950 double phiPar = par->position().phi();
951 double etaWidth = 2 * (descr->calo_eta_max() - descr->calo_eta_min()) / descr->n_eta();
952 double etaMin = etaPar - etaWidth;
953 double etaMax = etaPar + etaWidth;
954 double phiWidth = (descr->calo_phi_max() - descr->calo_phi_min()) / descr->n_phi();
955 // TODO: HOW TO DEAL WITH PHI ~ PI?
956 double phiMin = phiPar - phiWidth;
957 double phiMax = phiPar + phiWidth;
958 // --- Fill vecHash ---
959 CaloCell_ID::CaloSample sample = descr->getSampling();
960
961 // Cannot do this in initialize: see ATLASRECTS-5012
962
963 std::vector<IdentifierHash> vecHash;
964 caloDDM->cellsInZone(etaMin, etaMax, phiMin, phiMax, sample, vecHash);
965
966 // --- Iterate and find closest to track (around 12-15 elements in loop) ---
967 double dR2Min{ 999 };
968 for (const IdentifierHash& id : vecHash) {
969 const CaloCell* cell = caloCellCont->findCell(id);
970 if (!cell)
971 continue;
972
973 const CaloDetDescrElement* dde = cell->caloDDE();
974 if (!dde)
975 continue;
976 const double etaCell = dde->eta();
977 const double phiCell = dde->phi();
978 const double dEta = etaPar - etaCell;
979 const double dPhi = xAOD::P4Helpers::deltaPhi(phiPar, phiCell);
980 const double dR2 = dEta * dEta + dPhi * dPhi;
981 neighbourMap[sqrt(dR2)] = cell;
982 if (dR2 < dR2Min) {
983 dR2Min = dR2;
984 result = cell;
985 }
986 }
987
988 // --- Show deposits near this track (only if debugMode is on) ---
989 if (msgLevel(MSG::VERBOSE)) {
990 ATH_MSG_INFO("SAMPLE = " << sample);
991 for (const std::pair<const double, const CaloCell*>& mapIt : neighbourMap) {
992 const CaloCell* cell = mapIt.second;
993 double distance = mapIt.first;
994 if (cell) {
995 ATH_MSG_VERBOSE("dR2 = " << distance << ", energy = " << cell->energy());
996 } else {
997 ATH_MSG_VERBOSE("dR2 = " << distance << ", NULL pointer!");
998 }
999 }
1000 }
1001 return result;
1002}
1003
1005// Book Histograms
1008 ATH_MSG_DEBUG("Booking the ROOT Histos");
1009 if (SG::getNSlots() > 1) {
1010 ATH_MSG_FATAL("Filling histograms not supported in MT jobs.");
1011 return StatusCode::FAILURE;
1012 }
1013 ATH_CHECK( m_histSvc.retrieve() );
1014
1015 m_h = std::make_unique<Hists>();
1016 ATH_CHECK( m_h->book (*m_histSvc) );
1017 return StatusCode::SUCCESS;
1018}
1019
1020StatusCode TrackDepositInCaloTool::Hists::book (ITHistSvc& histSvc)
1021{
1022 m_hDepositLayer12 = new TH1F("hDepositLayer12", "hDepositLayer12", 40, 0, 4000);
1023 m_hDepositLayer13 = new TH1F("hDepositLayer13", "hDepositLayer13", 40, 0, 4000);
1024 m_hDepositLayer14 = new TH1F("hDepositLayer14", "hDepositLayer14", 40, 0, 4000);
1025 m_hParELossEta = new TH2F("hParELossEta", "Parametrized eLoss vs eta", 40, 0, 4000, 30, -3, 3);
1026 m_hParELossSample = new TH2F("hParELossSample", "Parametrized eLoss vs sample", 40, 0, 4000, 21, 0, 21);
1027 m_hDeltaEtaLastPar = new TH1F("hDeltaEtaLastPar", "hDeltaEtaLastPar", 50, -2, 2);
1028 m_hDeltaRadiusLastPar = new TH1F("hDeltaRadiusLastPar", "hDeltaRadiusLastPar", 50, 0, 5000);
1029 m_hDepositsInCore = new TH1F("hDepositsInCore", "hDepositsInCore", 50, 0, 5000);
1030 m_hDepositsInCone = new TH1F("hDepositsInCone", "hDepositsInCone", 50, 0, 5000);
1031 m_hDistDepositsTile = new TH2F("hDistDepositsTile", "hDistDepositsTile", 30, 0.0, 0.3, 30, 0, 4000);
1032 m_hDistDepositsHEC = new TH2F("hDistDepositsHEC", "hDistDepositsHEC", 30, 0.0, 0.3, 30, 0, 4000);
1033
1034 m_hEMB1vsdPhi = new TH2F("hEMB1vsdPhi", "hEMB1vsdPhi", 50, -M_PI, M_PI, 50, 0, 500);
1035 m_hEMB2vsdPhi = new TH2F("hEMB2vsdPhi", "hEMB2vsdPhi", 50, -M_PI, M_PI, 50, 0, 500);
1036 m_hEMB3vsdPhi = new TH2F("hEMB3vsdPhi", "hEMB3vsdPhi", 50, -M_PI, M_PI, 50, 0, 500);
1037 m_hEMB1vsdEta = new TH2F("hEMB1vsdEta", "hEMB1vsdEta", 50, -M_PI, M_PI, 50, 0, 500);
1038 m_hEMB2vsdEta = new TH2F("hEMB2vsdEta", "hEMB2vsdEta", 50, -M_PI, M_PI, 50, 0, 500);
1039 m_hEMB3vsdEta = new TH2F("hEMB3vsdEta", "hEMB3vsdEta", 50, -M_PI, M_PI, 50, 0, 500);
1040
1041#define H_CHECK(X) if((X).isFailure()) return StatusCode::FAILURE
1042 H_CHECK( histSvc.regHist("/AANT/CaloTrkMuId/hDepositLayer12", m_hDepositLayer12) );
1043 H_CHECK( histSvc.regHist("/AANT/CaloTrkMuId/hDepositLayer13", m_hDepositLayer13) );
1044 H_CHECK( histSvc.regHist("/AANT/CaloTrkMuId/hDepositLayer14", m_hDepositLayer14) );
1045 H_CHECK( histSvc.regHist("/AANT/CaloTrkMuId/hParELossSample", m_hParELossSample) );
1046 H_CHECK( histSvc.regHist("/AANT/CaloTrkMuId/hParELossEta", m_hParELossEta) );
1047 H_CHECK( histSvc.regHist("/AANT/DetStore/hDeltaEtaLastPar", m_hDeltaEtaLastPar) );
1048 H_CHECK( histSvc.regHist("/AANT/DetStore/hDeltaRadiusLastPar", m_hDeltaRadiusLastPar) );
1049 H_CHECK( histSvc.regHist("/AANT/DetStore/hDepositsInCore", m_hDepositsInCore) );
1050 H_CHECK( histSvc.regHist("/AANT/DetStore/hDepositsInCone", m_hDepositsInCone) );
1051 H_CHECK( histSvc.regHist("/AANT/DetStore/hDistDepositsTile", m_hDistDepositsTile) );
1052 H_CHECK( histSvc.regHist("/AANT/DetStore/hDistDepositsHEC", m_hDistDepositsHEC) );
1053
1054 H_CHECK( histSvc.regHist("/AANT/DetStore/hEMB1vsdPhi", m_hEMB1vsdPhi) );
1055 H_CHECK( histSvc.regHist("/AANT/DetStore/hEMB2vsdPhi", m_hEMB2vsdPhi) );
1056 H_CHECK( histSvc.regHist("/AANT/DetStore/hEMB3vsdPhi", m_hEMB3vsdPhi) );
1057 H_CHECK( histSvc.regHist("/AANT/DetStore/hEMB1vsdEta", m_hEMB1vsdEta) );
1058 H_CHECK( histSvc.regHist("/AANT/DetStore/hEMB2vsdEta", m_hEMB2vsdEta) );
1059 H_CHECK( histSvc.regHist("/AANT/DetStore/hEMB3vsdEta", m_hEMB3vsdEta) );
1060#undef H_CHECK
1061
1062 return StatusCode::SUCCESS;
1063}
1064
1066// Get reference to histograms.
1068
1071{
1072 // We earlier checked that no more than one thread is being used.
1073 Hists* h ATLAS_THREAD_SAFE = m_h.get();
1074 return *h;
1075}
1076
1077
1079// Functions below are under development, these are not used yet.
1081bool TrackDepositInCaloTool::isInsideDomain(double position, double domainCenter, double domainWidth, bool phiVariable) {
1082 double halfWidth = domainWidth / 2;
1083 if (phiVariable) {
1084 if (std::abs(std::abs(domainCenter) - M_PI) < domainWidth) {
1085 position += M_PI;
1086 domainCenter += M_PI;
1087 if (position > M_PI) { position -= 2 * M_PI; }
1088 if (domainCenter > M_PI) { domainCenter -= 2 * M_PI; }
1089 }
1090 }
1091 double boundLow = domainCenter - halfWidth;
1092 double boundHigh = domainCenter + halfWidth;
1093 if (position < boundLow) return false;
1094 if (position > boundHigh) return false;
1095 return true;
1096}
1097
1099 const CaloDetDescrElement* dde = cell->caloDDE();
1100 if (!dde) return false;
1101 if (dde->is_tile()) {
1102 if (!isInsideDomain(position.z(), dde->z(), dde->dz())) return false;
1103 } else {
1104 if (!isInsideDomain(position.eta(), dde->eta(), dde->eta())) return false;
1105 }
1106 if (!isInsideDomain(position.phi(), dde->phi(), dde->dphi(), true)) { return false; }
1107 // if (!isInsideDomain(position.r(), dde->r(), dde->dr()))
1108 // return false;
1109 return true;
1110}
1111
1112// inCell
1113// an alternative version of crossedPhi from CaloCellHelpers, which has a bug
1114
1116 bool result = std::abs(CaloPhiRange::diff(pos.phi(), cell->phi())) < cell->caloDDE()->dphi() / 2;
1117 if (cell->caloDDE()->getSubCalo() != CaloCell_ID::TILE)
1118 result &= std::abs(pos.eta() - cell->eta()) < cell->caloDDE()->deta() / 2;
1119 else if (cell->caloDDE()->getSampling() != CaloCell_ID::TileBar1) // still need to deal with tilebar1
1120 result &= std::abs(pos.z() - cell->z()) < cell->caloDDE()->dz() / 2;
1121 return result;
1122}
1123
1125 double diff_x = p1.x() - p2.x();
1126 double diff_y = p1.y() - p2.y();
1127 double diff_z = p1.z() - p2.z();
1128 return std::hypot(diff_x, diff_y, diff_z);
1129}
#define M_PI
Scalar mag() const
mag method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Maintain a set of objects, one per slot.
Definition of CaloDetDescriptor.
DataVector< Trk::CaloExtension > CaloExtensionCollection
CaloPhiRange class declaration.
std::pair< std::vector< unsigned int >, bool > res
#define H_CHECK(X)
#define z
#define ATLAS_THREAD_SAFE
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)
const ServiceHandle< StoreGateSvc > & detStore() const
Header file for AthHistogramAlgorithm.
Container class for CaloCell.
const CaloCell * findCell(const IdentifierHash theHash) const
fast find method given identifier hash.
CaloSampling::CaloSample CaloSample
Definition CaloCell_ID.h:53
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
double energy() const
get energy (data member)
Definition CaloCell.h:327
const CaloDetDescrElement * caloDDE() const
get pointer to CaloDetDescrElement (data member)
Definition CaloCell.h:321
virtual double sinTh() const override final
get sin(theta) (through CaloDetDescrElement)
Definition CaloCell.h:389
virtual bool badcell() const
check is cell is dead
Definition CaloCell.cxx:144
This class groups all DetDescr information related to a CaloCell.
CaloCell_ID::CaloSample getSampling() const
cell sampling
const CaloDetDescrElement * get_element(const Identifier &cellId) const
get element by its identifier
void cellsInZone(double eta_min, double eta_max, double phi_min, double phi_max, std::vector< IdentifierHash > &cell_list) const
the only client is CaloCellList class
calo_descr_range calo_descriptors_range() const
Range over descriptors.
calo_descr_range tile_descriptors_range() const
Range over tile descriptors.
This class provides the client interface for accessing the detector description information common to...
This is a base class for LAr and Tile Descriptors The primary goal is to speed up loops over all the ...
static double diff(double phi1, double phi2)
simple phi1 - phi2 calculation, but result is fixed to respect range.
static constexpr unsigned int getNumberOfSamplings()
Get number of available samplings.
This is a "hash" representation of an Identifier.
double getZMax(unsigned int index) const
unsigned int getNRows() const
Definition TileCellDim.h:25
double getZMin(unsigned int index) const
std::unique_ptr< const Trk::TrackParameters > extrapolateToEntranceOfLayer(const EventContext &ctx, const Trk::TrackParameters *par, const CaloDetDescriptor *descr) const
ToolHandle< Trk::IExtrapolator > m_extrapolator
std::unique_ptr< const Trk::TrackParameters > extrapolateToExitOfLayer(const EventContext &ctx, const Trk::TrackParameters *par, const CaloDetDescriptor *descr) const
static bool inCell(const CaloCell *cell, const Amg::Vector3D &pos)
std::vector< DepositInCalo > deposits(const Trk::TrackParameters *par, const CaloCellContainer *cellContainer) const override
std::unique_ptr< const Trk::TrackParameters > extrapolateToSolenoid(const EventContext &ctx, const Trk::TrackParameters *par, bool oppositeMomentum=false) const
std::vector< DepositInCalo > getDeposits(const Trk::TrackParameters *par, const CaloCellContainer *caloCellCont) const override
Fills the vector of DepositInCalo using TrackParameters as input.
static std::unique_ptr< Amg::Vector3D > extrapolateR(const Amg::Vector3D &initialPosition, double phi0, double theta0, double r)
Extrapolate track to cylinder surface along straight line.
TrackDepositInCaloTool(const std::string &type, const std::string &name, const IInterface *pInterface)
LayerMaps initializeDetectorInfo(const CaloDetDescrManager *caloDDM) const
std::vector< const CaloCell * > getCaloCellsForTile(const CaloDetDescrManager *caloDDM, const CaloDetDescriptor *descr, const Trk::TrackParameters *parEntrance, const Trk::TrackParameters *parExit, const CaloCellContainer *caloCellCont) const
static std::unique_ptr< Amg::Vector3D > extrapolateZ(const Amg::Vector3D &initialPosition, double phi0, double theta0, double z)
Extrapolate track to disc surface along straight line.
CxxUtils::CachedValue< LayerMaps > m_layerMaps
Trk::Surface * createSurface(const CaloDetDescriptor *descr, CaloSurfaceType type) const override
Creates a Trk::Surface for a calorimeter region that is described by CaloDetDescr.
ToolHandle< Rec::IParticleCaloCellAssociationTool > m_caloCellAssociationTool
bool m_doHist
Flag to write histograms to track performance.
ToolHandle< Trk::IParticleCaloExtensionTool > m_caloExtensionTool
const CaloCell * getClosestCellTile(const CaloDetDescrManager *caloDDM, const Trk::TrackParameters *par, const CaloDetDescriptor *descr, const CaloCellContainer *caloCellCont) const
StatusCode getTraversedLayers(const CaloDetDescrManager *caloDDM, const Trk::TrackParameters *par, std::map< double, const CaloDetDescriptor * > &caloInfo, std::vector< Amg::Vector3D > &extrapolations) const
This function determines which calorimeter regions the tracks traverses.
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloDetDescrMgrKey
ServiceHandle< ITHistSvc > m_histSvc
std::vector< const CaloCell * > getCaloCellsForLayer(const CaloDetDescrManager *caloDDM, const CaloDetDescriptor *descr, const Trk::TrackParameters *parEntrance, const Trk::TrackParameters *parExit, const CaloCellContainer *caloCellCont) const
static double distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
StatusCode initialize() override
double calcEnergy(const Trk::TrackParameters *par, const Trk::ParticleHypothesis &particleHypo) const override
Calculate the energy using .
StatusCode bookHistos()
Create histograms and register them to HistSvc.
static const CaloCell * getClosestCellLAr(const CaloDetDescrManager *caloDDM, const Trk::TrackParameters *par, const CaloDetDescriptor *descr, const CaloCellContainer *caloCellCont)
static bool isInsideCell(const Amg::Vector3D &position, const CaloCell *cell)
const TileDetDescrManager * m_tileDDM
const CaloCell * getClosestCell(const CaloDetDescrManager *caloDDM, const Trk::TrackParameters *par, const CaloDetDescriptor *descr, const CaloCellContainer *cellContainer) const
Retrieve the CaloCell for which its center is closest to the position of the particle.
static bool isInsideDomain(double position, double domainCenter, double domainWidth, bool phiVariable=false)
bool m_doExtr
Flag to perform extrapolations using m_extrapolator.
std::unique_ptr< Hists > m_h
Tracking class to hold the extrapolation through calorimeter Layers Both the caloEntryLayerIntersecti...
const TrackParameters * caloEntryLayerIntersection() const
access to intersection with the calorimeter entry layer return nullptr if the intersection failed
Class for a CylinderSurface in the ATLAS detector.
Class for a DiscSurface in the ATLAS detector.
Definition DiscSurface.h:54
const Amg::Vector3D & momentum() const
Access method for the momentum.
const Amg::Vector3D & position() const
Access method for the position.
Abstract Base Class for tracking surfaces.
int r
Definition globals.cxx:22
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
Eigen::Translation< double, 3 > Translation3D
void entryExitLayerMap(const Trk::CaloExtension &extension, EntryExitLayerMap &result, const LayersToSelect *selection=nullptr)
std::map< CaloSampling::CaloSample, double > ScalarLayerMap
void eLossLayerMap(const Trk::CaloExtension &extension, ScalarLayerMap &result)
std::map< CaloSampling::CaloSample, std::pair< Amg::Vector3D, Amg::Vector3D > > EntryExitLayerMap
size_t getNSlots()
Return the number of event slots.
constexpr double mass[PARTICLEHYPOTHESES]
the array of masses
PropDirection
PropDirection, enum for direction of the propagation.
@ oppositeMomentum
@ alongMomentum
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.
ParametersBase< TrackParametersDim, Charged > TrackParameters
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
TrackParticle_v1 TrackParticle
Reference the current persistent version:
StatusCode book(ITHistSvc &histSvc)
CaloLayerMap m_barrelLayerMap
< std::map of distance versus descriptor for cylindrical calo regions