ATLAS Offline Software
Loading...
Searching...
No Matches
xMuonHitAnalysis.cxx
Go to the documentation of this file.
1
2/*
3 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
4*/
5#include "xMuonHitAnalysis.h"
6
9#include "GaudiKernel/SystemOfUnits.h"
11
12#include <format>
13#include <TH1F.h>
14#include <TH2F.h>
15namespace MuonValR4{
18 const std::string& basePath,
19 const TechIdx_t techIdx,
20 const int stIdent):
21 identifier{stIdent} {
22
23 auto registerHisto = [&](TH1* h) {
24 h->Sumw2();
25 h->StatOverflows();
26
27 std::string stName = "Inclusive";
28 if (stIdent >= 0) {
29 switch (techIdx) {
30 case TechIdx_t::MDT:
31 case TechIdx_t::RPC: {
33 break;
34 } case TechIdx_t::TGC: {
35 stName = idHelperSvc->tgcIdHelper().stationNameString(stIdent);
36 break;
37 } case TechIdx_t::STGC: {
38 stName = idHelperSvc->stgcIdHelper().stationNameString(stIdent);
39 break;
40 } case TechIdx_t::MM: {
41 stName = idHelperSvc->mmIdHelper().stationNameString(stIdent);
42 break;
43 } default:
44 break;
45 }
46 }
47 const std::string histPath = std::format("/{}/Station_{}/{}",
48 basePath, stName, h->GetName());
49 histSvc->regHist(histPath, h).ignore();
50 return h;
51 };
52 h_dirTheta = registerHisto(new TH1F("dirTheta", "local direction; #theta [deg]", 180, 0, 180));
53 h_dirPhi = registerHisto(new TH1F("dirPhi", "local direction; #phi [deg]", 360, -180, 180));
54 h_energy = registerHisto(new TH1F("energy", "kinetic energy; e[GeV]", 150, 0, 150));
55 h_deposit = registerHisto(new TH1F("energyDeposit", "energy deposit; e[GeV]", 20, 0, 2));
56 h_pdgId = registerHisto(new TH1F("pdgId", "Particle data ID; pdgId",31, -15.5, 15.5));
57
58 switch (techIdx) {
59 case TechIdx_t::TGC: {
60 h_stationPhi = registerHisto(new TH1F("stationPhi", "StationPhi;stationPhi",48, 0.5, 48.5));
61 h_stationEta = registerHisto(new TH1F("stationEta", "StationEta;stationEta",11, -5.5, 5.5));
62 h_localHitPos = registerHisto(new TH2F("localHitPosXY", "hit position;x [mm]; y[mm]",
63 240, -1200, 1200, 240, -1200, 1200));
64 h_localHitZ = registerHisto(new TH1F("localHitPosZ", "position in gas gap;z [mm]", 20, -5, 5));
65
66 constexpr double r = 12. * Gaudi::Units::m;
67 constexpr double z = 14 * Gaudi::Units::m;
68 h_globHitXY = registerHisto(new TH2F("hitXY", "hitXY;x [mm]; y[mm];entries", 240, -r,r, 240,-r,r));
69 h_globHitRZ = registerHisto(new TH2F("hitRZ", "hitRz;r [mm]; z[mm];entries", 1200, 0, r, 2200,-z,z));
70 break;
71 } case TechIdx_t::RPC: {
72 h_stationPhi = registerHisto(new TH1F("stationPhi", "StationPhi;stationPhi",8, 0.5, 8.5));
73 h_stationEta = registerHisto(new TH1F("stationEta", "StationEta;stationEta",17, -8.5, 8.5));
74 h_localHitPos = registerHisto(new TH2F("localHitPosXY", "hit position;x [mm]; y[mm]",
75 70, -1400, 1400, 70, -1400, 1400));
76 h_localHitZ = registerHisto(new TH1F("localHitPosZ", "position in gas gap;z [mm]", 11, -0.5, 0.5));
77 constexpr double r = 12. * Gaudi::Units::m;
78 constexpr double z = 12 * Gaudi::Units::m;
79 h_globHitXY = registerHisto(new TH2F("hitXY", "hitXY;x [mm]; y[mm];entries", 240, -r,r, 240,-r,r));
80 h_globHitRZ = registerHisto(new TH2F("hitRZ", "hitRz;r [mm]; z[mm];entries", 1200, 0, r, 600,-z,z));
81
82 break;
83 } case TechIdx_t::MDT: {
84 h_stationPhi = registerHisto(new TH1F("stationPhi", "StationPhi;stationPhi",8, 0.5, 8.5));
85 h_stationEta = registerHisto(new TH1F("stationEta", "StationEta;stationEta",17, -8.5, 8.5));
86 h_localHitPos = registerHisto(new TH1F("localHitPosR", "hit position;r [mm]", 61, -15, 15));
87 h_localHitZ = registerHisto(new TH1F("localHitPosZ", "position in gas gap;z [mm]", 310, -3100, 3100));
88 constexpr double r = 12. * Gaudi::Units::m;
89 constexpr double z = 22 * Gaudi::Units::m;
90 h_globHitXY = registerHisto(new TH2F("hitXY", "hitXY;x [mm]; y[mm];entries", 2400, -r,r, 2400,-r,r));
91 h_globHitRZ = registerHisto(new TH2F("hitRZ", "hitRz;r [mm]; z[mm];entries", 1200, 0, r, 2200,-z,z));
92
93 break;
94 } case TechIdx_t::MM: {
95 h_stationPhi = registerHisto(new TH1F("stationPhi", "StationPhi;stationPhi",8, 0.5, 8.5));
96 h_stationEta = registerHisto(new TH1F("stationEta", "StationEta;stationEta",5, -2.5, 2.5));
97 h_localHitPos = registerHisto(new TH2F("localHitPosXY", "hit position;x [mm]; y[mm]",
98 480, -1200, 1200, 480, -2400, 2400));
99 h_localHitZ = registerHisto(new TH1F("localHitPosZ", "position in gas gap;z [mm]", 11, -0.5, 0.5));
100 constexpr double r = 5 * Gaudi::Units::m;
101 constexpr double z = 8. *Gaudi::Units::m;
102 h_globHitXY = registerHisto(new TH2F("hitXY", "hitXY;x [mm]; y[mm];entries", 1000, -r,r, 1000,-r,r));
103 h_globHitRZ = registerHisto(new TH2F("hitRZ", "hitRz;r [mm]; z[mm];entries", 500, 0, r, 160, -z, z));
104
105 break;
106 } case TechIdx_t::STGC: {
107 h_stationPhi = registerHisto(new TH1F("stationPhi", "StationPhi;stationPhi",8, 0.5, 8.5));
108 h_stationEta = registerHisto(new TH1F("stationEta", "StationEta;stationEta",7, -3.5, 3.5));
109 h_localHitPos = registerHisto(new TH2F("localHitPosXY", "hit position;x [mm]; y[mm]",
110 440, -1100, 1100, 440, -1100, 1100));
111 h_localHitZ = registerHisto(new TH1F("localHitPosZ", "position in gas gap;z [mm]", 11, -0.5, 0.5));
112 constexpr double r = 5 * Gaudi::Units::m;
113 constexpr double z = 8. *Gaudi::Units::m;
114 h_globHitXY = registerHisto(new TH2F("hitXY", "hitXY;x [mm]; y[mm];entries", 1000, -r,r, 1000,-r,r));
115 h_globHitRZ = registerHisto(new TH2F("hitRZ", "hitRz;r [mm]; z[mm];entries", 500, 0, r, 160, -z, z));
116 break;
117 } default:
118 break;
119 }
120 }
121
122
124 ATH_CHECK(m_inputKey.initialize());
125 ATH_CHECK(m_geoCtxKey.initialize());
126 ATH_CHECK(m_idHelperSvc.retrieve());
127 ATH_CHECK(detStore()->retrieve(m_detMgr));
128 std::set<int> histIds{-1};
129 TechIdx_t techIdx{static_cast<TechIdx_t>(1*m_techIdx)};
130 using namespace Muon::MuonStationIndex;
131 switch (techIdx) {
132 case TechIdx_t::MDT: {
133 for (int s = 0 ; s < toInt(StIdx_t::StIndexMax); ++s){
134 histIds.insert(s);
135 }
136 break;
137 } case TechIdx_t::RPC: {
138 for (int s = 0 ; s < toInt(StIdx_t::BE); ++s){
139 histIds.insert(s);
140 }
141 break;
142 } case TechIdx_t::TGC: {
143 const auto& idHelper{m_idHelperSvc->tgcIdHelper()};
144 std::for_each(idHelper.module_begin(), idHelper.module_end(),
145 [&histIds, &idHelper](const Identifier& id) {
146 histIds.insert(idHelper.stationName(id));
147 });
148 break;
149 } case TechIdx_t::STGC: {
150 const auto& idHelper{m_idHelperSvc->stgcIdHelper()};
151 std::for_each(idHelper.module_begin(), idHelper.module_end(),
152 [&histIds, &idHelper](const Identifier& id) {
153 histIds.insert(idHelper.stationName(id));
154 });
155 break;
156 } case TechIdx_t::MM: {
157 const auto& idHelper{m_idHelperSvc->mmIdHelper()};
158 std::for_each(idHelper.module_begin(), idHelper.module_end(),
159 [&histIds, &idHelper](const Identifier& id) {
160 histIds.insert(idHelper.stationName(id));
161 });
162 break;
163 } default:
164 ATH_MSG_FATAL("Invalid technology index parsed "<<m_techIdx);
165 return StatusCode::FAILURE;
166 }
167 for (int id : histIds) {
168 m_histos.emplace_back(m_idHelperSvc.get(), histSvc(), m_path, techIdx, id);
169 }
170 return StatusCode::SUCCESS;
171 }
173 const EventContext& ctx{Gaudi::Hive::currentContext()};
174 const xAOD::MuonSimHitContainer* simHits{nullptr};
175 const ActsTrk::GeometryContext* gctx{nullptr};
176 ATH_CHECK(SG::get(simHits, m_inputKey, ctx));
177 if (simHits->empty()) {
178 ATH_MSG_DEBUG("No hits recorded in the event "<<m_inputKey.fullKey());
179 return StatusCode::SUCCESS;
180 }
181 ATH_CHECK(SG::get(gctx, m_geoCtxKey, ctx));
182
183 xAOD::ChamberViewer viewer{*simHits, m_idHelperSvc.get(),
185 do{
186 const Identifier refId{viewer.at(0)->identify()};
187 const TechIdx_t techIdx = m_idHelperSvc->technologyIndex(refId);
188
189 const int stIdx = (techIdx == TechIdx_t::TGC || techIdx == TechIdx_t::STGC ||
190 techIdx == TechIdx_t::MM ? m_idHelperSvc->stationName(refId)
191 : toInt(m_idHelperSvc->stationIndex(refId)));
192 const int stationEta = m_idHelperSvc->stationEta(refId);
193 const int stationPhi = m_idHelperSvc->stationPhi(refId);
194
195 std::vector<unsigned> fillMe{};
196 for (unsigned h = 0; h<m_histos.size(); ++h) {
197 if (m_histos[h].identifier == -1 ||
198 m_histos[h].identifier == stIdx){
199 fillMe.push_back(h);
200 }
201 }
202 for (const xAOD::MuonSimHit* hit : viewer) {
203 const Identifier& hitId{hit->identify()};
204 const MuonGMR4::MuonReadoutElement* re = m_detMgr->getReadoutElement(hitId);
205 const double theta = hit->localDirection().theta();
206 const double phi = hit->localDirection().phi();
207 double signedR{0.};
208 IdentifierHash layHash{re->layerHash(hitId)};
209 if (techIdx ==TechIdx_t::MDT) {
210 signedR = Amg::lineDistance<3>(Amg::Vector3D::Zero(),
211 Amg::Vector3D::UnitZ(),
212 xAOD::toEigen(hit->localPosition()),
213 xAOD::toEigen(hit->localDirection()));
214 layHash = re->measurementHash(hitId);
215 }
216 const Amg::Vector3D globPos{re->localToGlobalTrans(*gctx,layHash)*
217 xAOD::toEigen(hit->localPosition())};
218
219 for (unsigned h : fillMe) {
220 m_histos[h].h_dirTheta->Fill(theta / Gaudi::Units::deg);
221 m_histos[h].h_dirPhi->Fill(phi / Gaudi::Units::deg);
222 m_histos[h].h_energy->Fill(hit->kineticEnergy()/ Gaudi::Units::GeV);
223 m_histos[h].h_deposit->Fill(hit->energyDeposit() / Gaudi::Units::GeV);
224 m_histos[h].h_pdgId->Fill(hit->pdgId());
225 m_histos[h].h_stationPhi->Fill(stationPhi);
226 m_histos[h].h_stationEta->Fill(stationEta);
227 if (techIdx == TechIdx_t::MDT) {
228 m_histos[h].h_localHitPos->Fill(signedR);
229 } else {
230 m_histos[h].h_localHitPos->Fill(hit->localPosition().x(),
231 hit->localPosition().y());
232 }
233 m_histos[h].h_localHitZ->Fill(hit->localPosition().z());
234 m_histos[h].h_globHitXY->Fill(globPos.x(), globPos.y());
235 m_histos[h].h_globHitRZ->Fill(globPos.perp(), globPos.z());
236 }
237 }
238 } while(viewer.next());
239 return StatusCode::SUCCESS;
240 }
241
242}
const boost::regex re(r_e)
Scalar phi() const
phi method
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_DEBUG(x)
Handle class for reading from StoreGate.
#define z
const ServiceHandle< StoreGateSvc > & detStore() const
Header file for AthHistogramAlgorithm.
const ServiceHandle< ITHistSvc > & histSvc() const
The standard THistSvc (for writing histograms and TTrees and more to a root file) Returns (kind of) a...
bool empty() const noexcept
Returns true if the collection is empty.
This is a "hash" representation of an Identifier.
The MuonReadoutElement is an abstract class representing the geometry representing the muon detector.
const std::string & stationNameString(const int &index) const
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Service handle of the IdHelperSvc.
SG::ReadHandleKey< ActsTrk::GeometryContext > m_geoCtxKey
std::vector< HistoSet > m_histos
Gaudi::Property< std::string > m_path
Gaudi::Property< int > m_techIdx
const MuonGMR4::MuonDetectorManager * m_detMgr
MuonSimHit.
SG::ReadHandleKey< xAOD::MuonSimHitContainer > m_inputKey
virtual StatusCode execute() override final
Muon::MuonStationIndex::TechnologyIndex TechIdx_t
Muon::MuonStationIndex::StIndex StIdx_t
virtual StatusCode initialize() override final
Interface for Helper service that creates muon Identifiers and can be used to print Identifiers.
virtual const MmIdHelper & mmIdHelper() const =0
access to CscIdHelper
virtual const sTgcIdHelper & stgcIdHelper() const =0
access to TgcIdHelper
virtual const TgcIdHelper & tgcIdHelper() const =0
access to TgcIdHelper
bool next() noexcept
Loads the hits from the next chamber.
const_ref at(const std::size_t idx) const
Returns the i-the measurement from the current chamber.
int r
Definition globals.cxx:22
double lineDistance(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
: Calculates the shortest distance between two lines
Eigen::Matrix< double, 3, 1 > Vector3D
Lightweight algorithm to read xAOD MDT sim hits and (fast-digitised) drift circles from SG and fill a...
constexpr int toInt(const EnumType enumVal)
const std::string & stName(StIndex index)
convert StIndex into a string
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
@ Chamber
View ends if the moduleHash changes.
MuonSimHit_v1 MuonSimHit
Defined the version of the MuonSimHit.
Definition MuonSimHit.h:12
MuonSimHitContainer_v1 MuonSimHitContainer
Define the version of the pixel cluster container.
TH1 * h_dirPhi
Local phi direction of the hit.
TH1 * h_deposit
Energy deposit of the hit.
TH1 * h_localHitPos
Local position of the hit (signed radius) / pos in x-y plane.
TH1 * h_stationEta
Station eta of the hit.
HistoSet(const Muon::IMuonIdHelperSvc *idHelperSvc, const ServiceHandle< ITHistSvc > &histSvc, const std::string &basePath, const TechIdx_t techIdx, const int stIdent)
Helper struct to define histograms spectrometer region.
TH1 * h_stationPhi
Station phi of the hit.
TH1 * h_localHitZ
Local z-hit position.
TH1 * h_globHitXY
Global hit position (x-y) plane.
int identifier
Identifier (Either the stationIndex (Mdt/Rpc) or stationName (Tgc/Mm/sTgc))
TH1 * h_dirTheta
Local theta direction of the hit.
TH1 * h_globHitRZ
Global hit position (r-z) plane.