ATLAS Offline Software
Loading...
Searching...
No Matches
SCTLorentzMonAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "SCTLorentzMonAlg.h"
6
14
15#include <cmath>
16#include <memory>
17#include <vector>
18
19SCTLorentzMonAlg::SCTLorentzMonAlg(const std::string& name, ISvcLocator* pSvcLocator)
20 :AthMonitorAlgorithm(name,pSvcLocator) {
21}
22
24 ATH_CHECK(detStore()->retrieve(m_pSCTHelper, "SCT_ID"));
25 ATH_CHECK(m_trackSummaryTool.retrieve());
26 ATH_CHECK(m_tracksName.initialize());
27 ATH_CHECK(m_SCTDetEleCollKey.initialize());
28 ATH_CHECK(m_assoTool.retrieve(DisableTool{!m_rejectSharedHits} ));
29
30 ATH_CHECK(m_holeSearchTool.retrieve());
31 ATH_MSG_INFO("Retrieved hole search tool " << m_holeSearchTool);
32
33 if ( m_beamSpotKey.initialize().isFailure() ) {
34 ATH_MSG_WARNING("Failed to retrieve beamspot service " << m_beamSpotKey << " - will use nominal beamspot at (0,0,0)");
35 m_hasBeamCondSvc = false;
36 }
37 else {
38 m_hasBeamCondSvc = true;
39 ATH_MSG_DEBUG("Retrieved service " << m_beamSpotKey);
40 }
41
42
44}
45
46StatusCode SCTLorentzMonAlg::fillHistograms(const EventContext& ctx) const {
47 static const int layer100[] = {
48 2, 2, 3, 2, 2, 2, 0, 2, 3, 2, 0, 2, 3, 2, 3, 2, 0, 2, 3, 0, 2, 0, 2, 3, 2, 2, 2, 0, 0, 0, 0, 0, 0, 3, 0, 3, 2, 0, 2,
49 2, 0, 3, 3, 3, 0, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 3, 3, 2, 2, 2, 2, 2, 3, 3, 2, 3, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 3, 3,
50 2, 3, 2, 3, 3, 2, 3, 2, 2, 2, 2, 2, 2, 2
51 };
52 static const int phi100[] = {
53 29, 29, 6, 13, 23, 13, 14, 29, 9, 29, 14, 29, 9, 29, 39, 32, 21, 32, 13, 22, 32, 22, 32, 13, 32, 32, 32, 20, 20, 20,
54 20, 20, 20, 13, 21, 17, 33, 5, 33, 33, 31, 6, 19, 47, 21, 37, 37, 37, 37, 33, 37, 37, 24, 33, 33, 47, 19, 33, 33,
55 37, 37, 37, 55, 9, 38, 24, 37, 38, 8, 9, 9, 26, 38, 38, 38, 38, 39, 39, 38, 11, 45, 54, 54, 24, 31, 14, 47, 45, 47,
56 47, 47, 47
57 };
58 static const int eta100[] = {
59 3, -4, -6, 2, 6, 3, -5, -1, 6, -2, -6, -5, 5, -3, 2, 6, -3, 5, 5, 3, 4, 2, 2, 2, -1, -3, -4, 1, -1, -2, -3, -4, 4,
60 -1, -5, 6, 2, 4, 3, 1, 6, -2, 6, 3, -6, -1, 2, 1, 3, -5, 4, 5, -3, -4, -3, -5, -2, -1, -2, -3, -2, -4, -3, 2, 3, -6,
61 -5, 4, 6, 1, -6, 1, 1, -5, -4, -3, -3, -5, -2, 1, 5, 5, 4, 4, 5, 4, -1, -5, 3, 4, 1, -5
62 };
63 constexpr unsigned int layer100_n{sizeof(layer100) / sizeof(*layer100)};
64 constexpr unsigned int phi100_n{sizeof(phi100) / sizeof(*phi100)};
65 constexpr unsigned int eta100_n{sizeof(eta100) / sizeof(*eta100)};
66 constexpr bool theseArraysAreEqualInLength{(layer100_n == phi100_n) and (phi100_n == eta100_n)};
67 static_assert(theseArraysAreEqualInLength, "Coordinate arrays for <100> wafers are not of equal length");
68
69 ATH_MSG_DEBUG("enters fillHistograms");
70
72 const InDetDD::SiDetectorElementCollection* elements{sctDetEle.retrieve()};
73 if (elements==nullptr) {
74 ATH_MSG_WARNING(m_SCTDetEleCollKey.fullKey() << " could not be retrieved");
75 return StatusCode::SUCCESS;
76 }
78 if (not tracks.isValid()) {
79 ATH_MSG_WARNING(" TrackCollection not found: Exit SCTLorentzTool" << m_tracksName.key());
80 return StatusCode::SUCCESS;
81 }
82
83 // Prepare AssociationTool
84 std::unique_ptr<Trk::PRDtoTrackMap> prd_to_track_map;
86 prd_to_track_map = m_assoTool->createPRDtoTrackMap();
87 for (const Trk::Track* track : *tracks) {
88 ATH_CHECK( m_assoTool->addPRDs(*prd_to_track_map,*track) );
89 }
90 }
91
92 float beamSpotX = 0.;
93 float beamSpotY = 0.;
94 float beamSpotZ = 0.;
95 float beamTiltX = 0.;
96 float beamTiltY = 0.;
97
98 if (m_hasBeamCondSvc) {
99 auto beamSpotHandle = SG::ReadCondHandle(m_beamSpotKey, ctx);
100 Amg::Vector3D bpos = beamSpotHandle->beamPos();
101 beamSpotX = bpos.x();
102 beamSpotY = bpos.y();
103 beamSpotZ = bpos.z();
104 beamTiltX = beamSpotHandle->beamTilt(0);
105 beamTiltY = beamSpotHandle->beamTilt(1);
106 ATH_MSG_DEBUG ("Beamspot: x0 = " << beamSpotX << ", y0 = " << beamSpotY << ", z0 = " << beamSpotZ << ", tiltX = " << beamTiltX << ", tiltY = " << beamTiltY);
107 }
108
109 for (const Trk::Track* track: *tracks) {
110 if (track==nullptr) {
111 ATH_MSG_ERROR("no pointer to track!!!");
112 continue;
113 }
114
115 if (track->perigeeParameters() == nullptr) {
116 continue;
117 }
118 // Get a track with holes
119 std::unique_ptr<const Trk::Track> trackWithHoles(m_holeSearchTool->getTrackWithHoles(*track));
120
121 if (not trackWithHoles) {
122 ATH_MSG_WARNING("trackWithHoles pointer is invalid");
123 continue;
124 }
125
126 ATH_MSG_VERBOSE("Found " << trackWithHoles->trackStateOnSurfaces()->size() << " states on track");
127
128 // Get pointer to track state on surfaces
129 const Trk::TrackStates* trackStates{trackWithHoles->trackStateOnSurfaces()};
130 if (trackStates==nullptr) {
131 ATH_MSG_WARNING("for current track, TrackStateOnSurfaces == Null, no data will be written for this track");
132 continue;
133 }
134
135 const Trk::TrackSummary* summary{trackWithHoles->trackSummary()};
136 std::unique_ptr<Trk::TrackSummary> mySummary;
137 if (summary==nullptr) {
138 mySummary = m_trackSummaryTool->summary(ctx, *trackWithHoles);
139 summary = mySummary.get();
140 if (summary==nullptr) {
141 ATH_MSG_WARNING("Trk::TrackSummary is null and cannot be created by " << m_trackSummaryTool.name());
142 continue;
143 }
144 }
145
146 for (const Trk::TrackStateOnSurface* tsos: *trackStates) {
147 int nStrip = 0;
148 Identifier sct_id(0);
149
151 // This is hit.
152 const InDet::SiClusterOnTrack* clus{dynamic_cast<const InDet::SiClusterOnTrack*>(tsos->measurementOnTrack())};
153 if (clus) { // Is it a SiCluster? If yes...
154 // Reject shared hits if you want
155 if (prd_to_track_map and prd_to_track_map->isShared(*(clus->prepRawData())) ) {
156 continue;
157 }
158
159 const InDet::SiCluster* RawDataClus{dynamic_cast<const InDet::SiCluster*>(clus->prepRawData())};
160 if (RawDataClus==nullptr) {
161 continue; // Continue if dynamic_cast returns null
162 }
163 if (RawDataClus->detectorElement()->isSCT()) {
164 sct_id = clus->identify();
165 // find cluster size
166 const std::vector<Identifier>& rdoList{RawDataClus->rdoList()};
167 nStrip = static_cast<int>(rdoList.size());
168 } else {
169 continue;
170 }
171 } else {
172 // This is not an Si cluster.
173 continue;
174 }
175 } else if (tsos->type(Trk::TrackStateOnSurface::Hole)) {
176 // This is a hole.
177 const Trk::MeasurementBase* mesb{tsos->measurementOnTrack()};
178 if (mesb and mesb->associatedSurface().associatedDetectorElement()) {
180 } else if (tsos->trackParameters()) {
181 sct_id = tsos->trackParameters()->associatedSurface().associatedDetectorElementIdentifier();
182 } else {
183 // sct_id wasn't correctly retrieved.
184 continue;
185 }
186 } else {
187 continue;
188 }
189
190 if (!m_pSCTHelper->is_sct(sct_id)) {
191 continue;
192 }
193
194 const int bec{m_pSCTHelper->barrel_ec(sct_id)};
195 const int layer{m_pSCTHelper->layer_disk(sct_id)};
196 const int side{m_pSCTHelper->side(sct_id)};
197 const int eta{m_pSCTHelper->eta_module(sct_id)};
198 const int phi{m_pSCTHelper->phi_module(sct_id)};
199
200 // Check if the silicon surface is 100.
201 SiliconSurface surface{surface111};
202 for (unsigned int i{0}; i < layer100_n; i++) {
203 if ((layer100[i] == layer) and (eta100[i] == eta) and (phi100[i] == phi)) {
204 surface = surface100;
205 break;
206 }
207 }
208
209 const Trk::TrackParameters* trkp{dynamic_cast<const Trk::TrackParameters*>(tsos->trackParameters())};
210 if (trkp==nullptr) {
211 ATH_MSG_WARNING(" Null pointer to MeasuredTrackParameters");
212 continue;
213 }
214
215 const Trk::Perigee* perigee{track->perigeeParameters()};
216
217 if (perigee) {
218 // Get angle to wafer surface
219 float phiToWafer{90.f};
220 float thetaToWafer(90.f);
221 float sinAlpha{0.f}; // for barrel, which is the only thing considered here
222 float pTrack[3]; // 3 is for x, y, z.
223 pTrack[0] = trkp->momentum().x();
224 pTrack[1] = trkp->momentum().y();
225 pTrack[2] = trkp->momentum().z();
226 float etaTrack = trkp->eta();
227
228 int iflag{findAnglesToWaferSurface(pTrack, sinAlpha, sct_id, elements, thetaToWafer, phiToWafer)};
229 if (iflag < 0) {
230 ATH_MSG_WARNING("Error in finding track angles to wafer surface");
231 continue; // Let's think about this (later)... continue, break or return?
232 }
233
234 float beamX = 0;
235 float beamY = 0;
236 float d0bscorr = -999;
237
238 // correct the track parameters for the beamspot position
239 beamX = beamSpotX + tan(beamTiltX) * (perigee->parameters()[Trk::z0]-beamSpotZ);
240 beamY = beamSpotY + tan(beamTiltY) * (perigee->parameters()[Trk::z0]-beamSpotZ);
241 d0bscorr = perigee->parameters()[Trk::d0] - ( -sin(perigee->parameters()[Trk::phi])*beamX + cos(perigee->parameters()[Trk::phi])*beamY );
242
243
244 // The cuts for the physics runs follow ATL-COM-INDET-2021-011.
245 if (trkp->momentum().perp() > 500. and
246 summary->get(Trk::numberOfSCTHits) > 6 and
248 (std::abs(d0bscorr) < 1. and trackWithHoles->perigeeParameters()->parameters()[Trk::qOverP] < 0.)
249 )
250 ) {
251 // Fill profile
252 std::string xVar{"phiToWafer"};
253 std::string yVar{"nStrip"};
254 if(bec == 0){ // Barrel
255 xVar += "_" + std::to_string(layer);
256 yVar += "_" + std::to_string(layer);
257 if(surface == surface100){
258 xVar += "_100";
259 yVar += "_100";
260 }
261 if(surface == surface111){
262 xVar += "_111";
263 yVar += "_111";
264 }
265 } else { // Endcaps
266 if (bec == -2) {
267 xVar += "_ECC";
268 yVar += "_ECC";
269 } else {
270 xVar += "_ECA";
271 yVar += "_ECA";
272 }
273 xVar += std::to_string(layer);
274 yVar += std::to_string(layer);
275 if (eta == 0) {
276 xVar += "_outer";
277 yVar += "_outer";
278 } else if (eta == 1) {
279 xVar += "_middle";
280 yVar += "_middle";
281 } else {
282 xVar += "_inner";
283 yVar += "_inner";
284 }
285 } // Common for barrel and endcaps
286 if(side == side0){
287 xVar += "_0";
288 yVar += "_0";
289 }
290 if(side == side1){
291 xVar += "_1";
292 yVar += "_1";
293 }
294
295 auto phiToWaferAcc{Monitored::Scalar<float>(xVar, phiToWafer)};
296 auto nStripAcc{Monitored::Scalar<int>(yVar, nStrip)};
297 auto isCentralAcc{Monitored::Scalar<bool>("isCentral", (std::abs(etaTrack) < 0.5))};
298 fill("SCTLorentzMonitor", phiToWaferAcc, nStripAcc, isCentralAcc);
299 }// end if passesCuts
300 } // end if SCT..
301 }// end of loop on TrackStatesonSurface (they can be SiClusters, TRTHits,..)
302 } // end of loop on tracks
303
304 return StatusCode::SUCCESS;
305}
306
307int
308SCTLorentzMonAlg::findAnglesToWaferSurface(const float (&vec)[3], // 3 is for x, y, z.
309 const float& sinAlpha, const Identifier& id,
311 float& theta, float& phi) const {
312 int iflag{-1};
313
314 phi = 90.;
315 theta = 90.;
316
317 const Identifier waferId{m_pSCTHelper->wafer_id(id)};
318 const IdentifierHash waferHash{m_pSCTHelper->wafer_hash(waferId)};
319 const InDetDD::SiDetectorElement* element{elements->getDetectorElement(waferHash)};
320 if (element==nullptr) {
321 ATH_MSG_ERROR("findAnglesToWaferSurface: failed to find detector element for id=" <<
322 m_pSCTHelper->show_to_string(id));
323 return iflag;
324 }
325
326 float cosAlpha{std::sqrt(1.0f - sinAlpha * sinAlpha)};
327 double phix{ cosAlpha * element->phiAxis().x() + sinAlpha * element->phiAxis().y()};
328 double phiy{-sinAlpha * element->phiAxis().x() + cosAlpha * element->phiAxis().y()};
329
330 double pNormal{vec[0] * element->normal().x() + vec[1] * element->normal().y() + vec[2] * element->normal().z()};
331 double pEta{ vec[0] * element->etaAxis().x() + vec[1] * element->etaAxis().y() + vec[2] * element->etaAxis().z()};
332 double pPhi{ vec[0] * phix + vec[1] * phiy + vec[2] * element->phiAxis().z()};
333
334 if (pPhi < 0.) {
335 phi = -90.;
336 }
337 if (pEta < 0.) {
338 theta = -90.;
339 }
340 if (pNormal != 0.) {
341 phi = std::atan(pPhi / pNormal) / CLHEP::deg;
342 theta = std::atan(pEta / pNormal) / CLHEP::deg;
343 }
344 iflag = 1;
345 return iflag;
346}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
std::vector< size_t > vec
Header file to be included by clients of the Monitored infrastructure.
This is an Identifier helper class for the SCT subdetector.
const ServiceHandle< StoreGateSvc > & detStore() const
virtual StatusCode initialize() override
initialize
DataType_t dataType() const
Accessor functions for the data type.
AthMonitorAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
This is a "hash" representation of an Identifier.
Class to hold the SiDetectorElement objects to be put in the detector store.
const SiDetectorElement * getDetectorElement(const IdentifierHash &hash) const
Class to hold geometrical description of a silicon detector element.
virtual const Amg::Vector3D & normal() const override final
Get reconstruction local normal axes in global frame.
RIO_OnTrack base class for Silicon detector in the InnerDetector.
virtual const InDetDD::SiDetectorElement * detectorElement() const override final
return the detector element corresponding to this PRD The pointer will be zero if the det el is not d...
Declare a monitored scalar variable.
ToolHandle< Trk::ITrackSummaryTool > m_trackSummaryTool
int findAnglesToWaferSurface(const float(&vec)[3], const float &sinAlpha, const Identifier &id, const InDetDD::SiDetectorElementCollection *elements, float &theta, float &phi) const
virtual StatusCode fillHistograms(const EventContext &ctx) const override final
adds event to the monitoring histograms
const SCT_ID * m_pSCTHelper
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_SCTDetEleCollKey
SCTLorentzMonAlg(const std::string &name, ISvcLocator *pSvcLocator)
ToolHandle< Trk::ITrackHoleSearchTool > m_holeSearchTool
BooleanProperty m_rejectSharedHits
SG::ReadHandleKey< TrackCollection > m_tracksName
Name of the Track collection to use.
ToolHandle< Trk::IPRDtoTrackMapTool > m_assoTool
SG::ReadCondHandleKey< InDet::BeamSpotData > m_beamSpotKey
virtual StatusCode initialize() override final
initialize
const_pointer_type retrieve()
virtual bool isValid() override final
Can the handle be successfully dereferenced?
This class is the pure abstract base class for all fittable tracking measurements.
virtual const Surface & associatedSurface() const =0
Interface method to get the associated Surface.
double eta() const
Access method for pseudorapidity - from momentum.
const Amg::Vector3D & momentum() const
Access method for the momentum.
const std::vector< Identifier > & rdoList() const
return the List of rdo identifiers (pointers)
virtual const Trk::PrepRawData * prepRawData() const =0
returns the PrepRawData (also known as RIO) object to which this RIO_OnTrack is associated.
Identifier identify() const
return the identifier -extends MeasurementBase
const TrkDetElementBase * associatedDetectorElement() const
return associated Detector Element
represents the track state (measurement, material, fit parameters and quality) at a surface.
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
@ Hole
A hole on the track - this is defined in the following way.
A summary of the information contained by a track.
virtual Identifier identify() const =0
Identifier.
Eigen::Matrix< double, 3, 1 > Vector3D
DataVector< const Trk::TrackStateOnSurface > TrackStates
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
@ qOverP
perigee
Definition ParamDefs.h:67
@ phi
Definition ParamDefs.h:75
@ d0
Definition ParamDefs.h:63
@ z0
Definition ParamDefs.h:64
ParametersBase< TrackParametersDim, Charged > TrackParameters
void fill(H5::Group &out_file, size_t iterations)