|
| 1 | +// Copyright 2019-2026 CERN and copyright holders of ALICE O2. |
| 2 | +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. |
| 3 | +// All rights not expressly granted are reserved. |
| 4 | +// |
| 5 | +// This software is distributed under the terms of the GNU General Public |
| 6 | +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". |
| 7 | +// |
| 8 | +// In applying this license CERN does not waive the privileges and immunities |
| 9 | +// granted to it by virtue of its status as an Intergovernmental Organization |
| 10 | +// or submit itself to any jurisdiction. |
| 11 | +/// |
| 12 | + |
| 13 | +#include <algorithm> |
| 14 | +#include <cmath> |
| 15 | +#include <format> |
| 16 | +#include <limits> |
| 17 | + |
| 18 | +#include "ITStracking/TrackerTraitsMC.h" |
| 19 | +#include "ITStracking/TuneExt.h" |
| 20 | +#include "CommonUtils/TreeStreamRedirector.h" |
| 21 | +#include "CommonConstants/MathConstants.h" |
| 22 | +#include "Steer/MCKinematicsReader.h" |
| 23 | + |
| 24 | +#include "Framework/Logger.h" |
| 25 | + |
| 26 | +namespace o2::its |
| 27 | +{ |
| 28 | + |
| 29 | +static o2::utils::TreeStreamRedirector* gDBG{nullptr}; |
| 30 | +static o2::steer::MCKinematicsReader* gMCReader{nullptr}; |
| 31 | + |
| 32 | +template <int NLayers> |
| 33 | +void TrackerTraitsMC<NLayers>::computeLayerTracklets(const int iteration, int iVertex) |
| 34 | +{ |
| 35 | + if (!gDBG) { |
| 36 | + gDBG = new o2::utils::TreeStreamRedirector("its_tune.root"); |
| 37 | + } |
| 38 | + if (!gMCReader) { |
| 39 | + gMCReader = new o2::steer::MCKinematicsReader("collisioncontext.root"); |
| 40 | + } |
| 41 | + |
| 42 | + // Create all tracklets we find in this iteration and dump them. |
| 43 | + const std::string treeName = std::format("trklt_{}", iteration); |
| 44 | + TrackerTraits<NLayers>::computeLayerTracklets(iteration, iVertex); |
| 45 | + this->createTrackletMC(); |
| 46 | + const auto topology = this->mTimeFrame->getTrackingTopologyView(); |
| 47 | + for (int transitionId{0}; transitionId < topology.nTransitions; ++transitionId) { |
| 48 | + const auto& transition = topology.getTransition(transitionId); |
| 49 | + for (int iTrklt{0}; iTrklt < this->mTimeFrame->getTracklets()[transitionId].size(); ++iTrklt) { |
| 50 | + const auto& lbl = this->mTimeFrame->getTrackletsLabel(transitionId)[iTrklt]; |
| 51 | + const auto trklt = this->mTimeFrame->getTracklets()[transitionId][iTrklt]; |
| 52 | + const auto& firstCluster = this->mTimeFrame->getClusters()[transition.fromLayer][trklt.firstClusterIndex]; |
| 53 | + const auto& secondCluster = this->mTimeFrame->getClusters()[transition.toLayer][trklt.secondClusterIndex]; |
| 54 | + const float deltaPhi = std::abs(firstCluster.phi - secondCluster.phi); |
| 55 | + TrackletMC trkltMC{ |
| 56 | + .tgl = trklt.tanLambda, |
| 57 | + .phi = trklt.phi, |
| 58 | + .rIn = firstCluster.radius, |
| 59 | + .zIn = firstCluster.zCoordinate, |
| 60 | + .phiIn = firstCluster.phi, |
| 61 | + .rOut = secondCluster.radius, |
| 62 | + .zOut = secondCluster.zCoordinate, |
| 63 | + .phiOut = secondCluster.phi, |
| 64 | + .dr = secondCluster.radius - firstCluster.radius, |
| 65 | + .dz = secondCluster.zCoordinate - firstCluster.zCoordinate, |
| 66 | + .dPhi = std::min(deltaPhi, static_cast<float>(o2::constants::math::TwoPI) - deltaPhi), |
| 67 | + .ok = lbl.isValid(), |
| 68 | + }; |
| 69 | + float dcaXY = std::numeric_limits<float>::max(), dcaZ = std::numeric_limits<float>::max(); |
| 70 | + if (lbl.isValid()) { |
| 71 | + const auto& eve = gMCReader->getMCEventHeader(lbl.getSourceID(), lbl.getEventID()); |
| 72 | + const float dx = secondCluster.xCoordinate - firstCluster.xCoordinate; |
| 73 | + const float dy = secondCluster.yCoordinate - firstCluster.yCoordinate; |
| 74 | + const float dz = secondCluster.zCoordinate - firstCluster.zCoordinate; |
| 75 | + trkltMC.tglEvent = (firstCluster.zCoordinate - eve.GetZ()) / firstCluster.radius; |
| 76 | + trkltMC.deltaZEvent = std::abs((trkltMC.tglEvent * (secondCluster.radius - firstCluster.radius)) + firstCluster.zCoordinate - secondCluster.zCoordinate); |
| 77 | + const float dxy2 = math_utils::hypot(dx, dy); |
| 78 | + if (dxy2 > constants::Tolerance) { |
| 79 | + const float t = ((eve.GetX() - firstCluster.xCoordinate) * dx + (eve.GetY() - firstCluster.yCoordinate) * dy) / dxy2; |
| 80 | + const float xAtDCA = firstCluster.xCoordinate + t * dx; |
| 81 | + const float yAtDCA = firstCluster.yCoordinate + t * dy; |
| 82 | + const float zAtDCA = firstCluster.zCoordinate + t * dz; |
| 83 | + const float curDCAx = xAtDCA - eve.GetX(); |
| 84 | + const float curDCAy = yAtDCA - eve.GetY(); |
| 85 | + dcaXY = math_utils::hypot(curDCAx, curDCAy); |
| 86 | + dcaZ = zAtDCA - eve.GetZ(); |
| 87 | + trkltMC.dXY = dcaXY; |
| 88 | + trkltMC.dZ = dcaZ; |
| 89 | + } |
| 90 | + const auto* mcTrk = gMCReader->getTrack(lbl); |
| 91 | + if (mcTrk) { |
| 92 | + trkltMC.prim = mcTrk->isPrimary(); |
| 93 | + } |
| 94 | + } |
| 95 | + (*gDBG) << treeName.c_str() |
| 96 | + << "from=" << transition.fromLayer |
| 97 | + << "to=" << transition.toLayer |
| 98 | + << "trklt=" << trkltMC |
| 99 | + << "\n"; |
| 100 | + } |
| 101 | + } |
| 102 | +} |
| 103 | + |
| 104 | +template <int NLayers> |
| 105 | +void TrackerTraitsMC<NLayers>::computeLayerCells(const int iteration) |
| 106 | +{ |
| 107 | + TrackerTraits<NLayers>::computeLayerCells(iteration); |
| 108 | +} |
| 109 | + |
| 110 | +template <int NLayers> |
| 111 | +void TrackerTraitsMC<NLayers>::findCellsNeighbours(const int iteration) |
| 112 | +{ |
| 113 | + TrackerTraits<NLayers>::findCellsNeighbours(iteration); |
| 114 | +} |
| 115 | + |
| 116 | +template <int NLayers> |
| 117 | +void TrackerTraitsMC<NLayers>::findRoads(const int iteration) |
| 118 | +{ |
| 119 | + TrackerTraits<NLayers>::findRoads(iteration); |
| 120 | + |
| 121 | + if (this->mTrkParams.size() - 1 == iteration) { |
| 122 | + gDBG->Close(); |
| 123 | + } |
| 124 | +} |
| 125 | + |
| 126 | +template class TrackerTraitsMC<7>; |
| 127 | + |
| 128 | +} // namespace o2::its |
0 commit comments