ATLAS Offline Software
Loading...
Searching...
No Matches
MuonClusterOnTrackCreator.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// AlgTool used for MuonClusterOnTrack object production
8
10
11#include <cmath>
12#include <sstream>
13
23#include "TrkSurfaces/Surface.h"
24#include "GaudiKernel/PhysicalConstants.h"
25
26namespace {
27 constexpr double SIG_VEL = 4.80000; // ns/m
28 constexpr double C_VEL = 1./ Gaudi::Units::c_light; // ns/m
29}
30namespace Muon {
31 //================================================================================
33 ATH_CHECK(m_idHelperSvc.retrieve());
34
35 ATH_CHECK(m_clusterBuilderToolMM.retrieve(DisableTool{m_calibToolNSW.empty()}));
36 ATH_CHECK(m_calibToolNSW.retrieve(DisableTool{m_calibToolNSW.empty()}));
37 return StatusCode::SUCCESS;
38 }
39
40 //================================================================================
42 const Amg::Vector3D& GP) const {
43 MuonClusterOnTrack* MClT = nullptr;
44
45 // check whether PrepRawData has detector element, if not there print warning
47
48 ATH_MSG_VERBOSE("Create ROT from "<<m_idHelperSvc->toString(RIO.identify())<<".");
49
50 // in RIO_OnTrack the local param and cov should have the same dimension
52
53 if (RIO.localCovariance().cols() > 1 || (m_idHelperSvc->isTgc(RIO.identify()) && m_idHelperSvc->measuresPhi(RIO.identify()))) {
54 ATH_MSG_VERBOSE("Making 2-dim local parameters: " << m_idHelperSvc->toString(RIO.identify()));
55 } else {
56 Trk::DefinedParameter radiusPar(RIO.localPosition().x(), Trk::locX);
57 locpar = Trk::LocalParameters(radiusPar);
58 ATH_MSG_VERBOSE("Making 1-dim local parameters: " << m_idHelperSvc->toString(RIO.identify()));
59 }
60
61 Amg::Vector2D lp{Amg::Vector2D::Zero()};
62 double positionAlongStrip{0};
63 double positionAlongZ{0};
64
65 const Trk::Surface& rio_surface = EL->surface(RIO.identify());
66 if (!rio_surface.globalToLocal(GP, GP, lp)) {
67 Amg::Vector3D lpos = rio_surface.transform().inverse() * GP;
68 ATH_MSG_WARNING("Extrapolated GlobalPosition not on detector surface! Distance " << lpos.z());
69 lp[Trk::locX] = lpos.x();
70 lp[Trk::locY] = lpos.y();
71 positionAlongZ = lpos.z();
72 }
73
74 positionAlongStrip = lp[Trk::locY];
75
76 Amg::MatrixX loce = RIO.localCovariance();
77 ATH_MSG_DEBUG("All: new err matrix is " << loce);
78 switch (m_idHelperSvc->technologyIndex(RIO.identify())) {
80 case RPC: {
81 //***************************
82 // RPC: cast to RpcPrepData
83 //***************************
84 const RpcPrepData* MClus = static_cast<const RpcPrepData*>(&RIO);
85 const bool measphi = m_idHelperSvc->measuresPhi(RIO.identify());
86
87 if ((m_doFixedErrorRpcEta && !measphi) ||
88 (m_doFixedErrorRpcPhi && measphi) ) {
89 const double fixedError = measphi ? m_fixedErrorRpcPhi
91 Amg::MatrixX mat(1, 1);
92 mat(0, 0) = fixedError * fixedError;
93 loce = mat;
94 }
95
97 Amg::Vector3D clusPos = re->stripPos(RIO.identify());
98
99 // let's correct rpc time subtracting delay due to the induced electric signal propagation along strip
100 double timeAlongStrip = 0;
101 if (!measphi) {
102 timeAlongStrip = re->distanceToEtaReadout(GP) / 1000. * SIG_VEL;
103 } else {
104 timeAlongStrip = re->distanceToPhiReadout(GP) / 1000. * SIG_VEL;
105 }
106 if (positionAlongZ) timeAlongStrip = 0; // no correction if extrapolated GlobalPosition not on detector surface!
107
108 // let's evaluate the average delay due to the induced electric signal propagation along strip
109 double assignedTimFromPrd = 0;
110 if (!measphi) {
111 assignedTimFromPrd = re->distanceToEtaReadout(clusPos) / 1000. * SIG_VEL;
112 } else {
113 assignedTimFromPrd = re->distanceToPhiReadout(clusPos) / 1000. * SIG_VEL;
114 }
115
116 // let's evaluate [real TOF - nominal TOF]
117 double real_TOF_onRPCgap = GP.mag() / 1000. * C_VEL;
118 double nominal_TOF_onRPCgap = clusPos.mag() / 1000. * C_VEL;
119
120 // let's evaluate the total time correction
121 double correct_time_tot = real_TOF_onRPCgap
122 - nominal_TOF_onRPCgap
123 + timeAlongStrip
124 - assignedTimFromPrd;
125
126 MClT = new RpcClusterOnTrack(MClus, std::move(locpar), std::move(loce),
127 positionAlongStrip, MClus->time() - correct_time_tot);
128
129 ATH_MSG_DEBUG(" correct_time_along_strip " << timeAlongStrip << " assignedTimFromPrd "
130 << assignedTimFromPrd << " real_TOF_onRPCgap " << real_TOF_onRPCgap
131 << " nominal_TOF_onRPCgap " << nominal_TOF_onRPCgap << " MClus->time() "
132 << MClus->time() << " correct_time_tot " << correct_time_tot);
133 break;
134
135 } case TGC: {
136
137 //***************************
138 // TGC: cast to TgcPrepData
139 //***************************
140
141 const TgcPrepData* MClus = static_cast<const TgcPrepData*>(&RIO);
142 const TgcIdHelper& idHelper{m_idHelperSvc->tgcIdHelper()};
143
144 // calculation of 2D error matrix for TGC phi strips
145 if (idHelper.measuresPhi(RIO.identify())) {
146 const int stripNo = idHelper.channel(RIO.identify());
147 const int gasGap = idHelper.gasGap(RIO.identify());
148
149 const MuonGM::TgcReadoutElement* ele = MClus->detectorElement();
150
151 double stripLength = ele->stripLength();
152 double stripWidth = std::abs(ele->stripPitch(gasGap, stripNo, lp[Trk::locZ]));
153 const Amg::Vector3D lStripDir = ele->transform(RIO.identify()).inverse().linear()*
154 ele->stripDir(RIO.identify());
155
156 Amg::MatrixX mat(2, 2);
157
158 double phistereo = lStripDir.phi() - 90.*Gaudi::Units::deg;
159 double Sn = std::sin(phistereo);
160 double Sn2 = Sn * Sn;
161 double Cs2 = 1. - Sn2;
162
163 double V0 = stripWidth * stripWidth / 12;
165 double V1 = stripLength * stripLength / 12;
166 mat(0, 0) = (Cs2 * V0 + Sn2 * V1);
167 mat.fillSymmetric(1, 0, (Sn * std::sqrt(Cs2) * (V0 - V1)));
168 mat(1, 1) = (Sn2 * V0 + Cs2 * V1);
169 loce = mat;
170 } else {
172 Amg::MatrixX mat(1, 1);
174 loce = mat;
175 }
176 }
177
178 MClT = new TgcClusterOnTrack(MClus, std::move(locpar), std::move(loce),
179 positionAlongStrip);
180 break;
181
182 } case STGC: {
183
184 //***************************
185 // sTGC: cast to sTgcPrepData
186 //***************************
187
188 const sTgcPrepData* MClus = static_cast<const sTgcPrepData*>(&RIO);
189 Amg::Vector2D localPos(lp[Trk::locX], lp[Trk::locY]);
190
191 // Dont make RIO On tracks for sTGC wires in inner Q1
192 if (m_idHelperSvc->stgcIdHelper().channelType(MClus->identify()) == sTgcIdHelper::Wire &&
193 MClus->detectorElement()->isEtaZero(MClus->identify(), lp)) {
194 ATH_MSG_DEBUG("sTgcReadoutElement with isEtaZero() ?! "
195 <<m_idHelperSvc->toString(MClus->identify()));
196 return nullptr;
197 }
198 // Wires are already considered in the above check. Dont remove them here
199 if (!rio_surface.insideBounds(localPos) &&
200 m_idHelperSvc->stgcIdHelper().channelType(MClus->identify()) != sTgcIdHelper::Wire) {
201 ATH_MSG_DEBUG("sTgc measurement "<<m_idHelperSvc->toString(MClus->identify())
202 <<" out of bounds. "<<Amg::toString(localPos));
203 return nullptr;
204 }
205 MClT = new sTgcClusterOnTrack(MClus, std::move(locpar),
206 std::move(loce), positionAlongStrip);
207 break;
208
209 } case MM:{
210 //***************************
211 // MM: cast to MMPrepData
212 //***************************
213 const MMPrepData* mmPRD = static_cast<const MMPrepData*>(&RIO);
214 MClT = new MMClusterOnTrack(mmPRD, std::move(locpar), std::move(loce),
215 positionAlongStrip, {}, {});
216 break;
217 } default:
218 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Measurement not supported:"
219 <<m_idHelperSvc->toString(RIO.identify()));
220 }
221
222 return MClT;
223 }
224
225
226 //================================================================================
230
231 //================================================================================
232 MuonClusterOnTrack* MuonClusterOnTrackCreator::correct(const Trk::PrepRawData& RIO, const Trk::TrackParameters& TP, const EventContext& /*ctx*/ ) const {
233 return correct(RIO, TP.position(), TP.momentum().unit());
234 }
235
236 //================================================================================
238 ATH_MSG_VERBOSE("Apply calibration correction to "<<RIO);
239
240 switch (m_idHelperSvc->technologyIndex(RIO.identify())) {
242 case MM:
243 return calibratedClusterMMG(RIO, GP, GD);
244 case STGC: {
245 if (!m_idHelperSvc->measuresPhi(RIO.identify())){
246 return calibratedClusterSTG(RIO, GP, GD);
247 }
248 return createRIO_OnTrack(RIO, GP);
249 } default:
250 return createRIO_OnTrack(RIO, GP);
251 }
252 }
253
254
255 //================================================================================
257 const EventContext& ctx{Gaudi::Hive::currentContext()};
258 // Make sure RIO has a detector element
259 const MuonGM::MMReadoutElement* mmEL = static_cast<const MuonGM::MMReadoutElement*>(RIO.detectorElement());
260 if (!mmEL) {
261 ATH_MSG_WARNING("RIO does not have associated detectorElement! Skipping cluster calibration");
262 return nullptr;
263 }
264
265 Amg::MatrixX loce = RIO.localCovariance();
267
268 // * Local cluster coordinates to feed to the calibration tools
269 Amg::Vector2D lp{Amg::Vector2D::Zero()};
270
271 // get localY from the seeded position
272 const Trk::PlaneSurface& rio_surface = mmEL->surface(RIO.identify());
273 if (!rio_surface.globalToLocal(GP, GP, lp)) {
274 Amg::Vector3D lpos = rio_surface.transform().inverse() * GP;
275 ATH_MSG_WARNING("Extrapolated GlobalPosition not on detector surface! Distance " << lpos.z());
276 lp[Trk::locX] = lpos.x();
277 lp[Trk::locY] = lpos.y();
278 }
279 // set localX from the cluster parameters
280 lp[Trk::locX] = locpar[Trk::locX];
281
282 // * B-Field correction
283 // calibrate the input strips
284 const MMPrepData* mmPRD = static_cast<const MMPrepData*>(&RIO);
285
286 std::vector<NSWCalib::CalibratedStrip> calibratedStrips;
287 StatusCode sc = m_calibToolNSW->calibrateClus(ctx, mmPRD, GP, calibratedStrips);
288 if (sc != StatusCode::SUCCESS) {
289 ATH_MSG_WARNING("Could not calibrate the MM Cluster in the RIO on track creator");
290 return nullptr;
291 }
292
293 // calibrate the cluster position along the precision coordinate (updates lp.x())
294 IMMClusterBuilderTool::RIO_Author rotAuthor = m_clusterBuilderToolMM->getCalibratedClusterPosition(ctx,
295 calibratedStrips,
296 NswClustering::toLocal(*mmPRD, GD),
297 lp, loce);
298
299 if (rotAuthor == IMMClusterBuilderTool::RIO_Author::unKnownAuthor) {
300 ATH_MSG_WARNING("Could not calibrate the MM Cluster in the RIO on track creator");
301 return nullptr;
302 }
303
304 // * Correct the local cluster coordinates for as-built conditions and B-lines (returns a new 3D vector)
305 Amg::Vector3D localposition3D{Amg::Vector3D::Zero()};
306 if (!mmEL->spacePointPosition(RIO.identify(), lp, localposition3D)){
307 ATH_MSG_WARNING("Application of final as-built parameters failed for channel "<<m_idHelperSvc->toString(RIO.identify())<<" local pos = ("<<lp.x()<<"/"<<lp.y()<<").");
308 }
309
310 // Get the direction of the track in the local coordinate system and use it to project
311 // the actual hit position onto the nominal surface (locZ = 0), where the intersection
312 // of the track is considered. This "effective" position provides a more accurate residual.
314 rio_surface.globalToLocalDirection(GD, ld);
315 double a_impact = ld.angleXZ() < 0 ? -M_PI_2 - ld.angleXZ() : M_PI_2 - ld.angleXZ();
316 double x_projected = localposition3D.x() - std::tan(a_impact) * localposition3D.z();
317
318 // * Set the value of the local parameter (locX) after applying conditions
319 // The position along strip will be set from the seed (there is no better
320 // estimate than that; not used in the track fits anyway)
321 locpar[Trk::locX] = x_projected;
322
323 ATH_MSG_VERBOSE("generating MMClusterOnTrack in MMClusterBuilder");
324 MMClusterOnTrack* cluster = new MMClusterOnTrack(mmPRD, std::move(locpar), std::move(loce), lp[Trk::locY], {}, {});
325 cluster->setAuthor(rotAuthor);
326
327 return cluster;
328 }
329
330
331 //================================================================================
333
334 // Make sure RIO has a detector element
335 const MuonGM::sTgcReadoutElement* stgEL = static_cast<const MuonGM::sTgcReadoutElement*>(RIO.detectorElement());
336 if (!stgEL) {
337 ATH_MSG_WARNING("RIO does not have associated detectorElement! Skipping cluster calibration");
338 return nullptr;
339 }
340
341 Amg::MatrixX loce = RIO.localCovariance();
342 // > 1 in case we want to keep pads in the future ?
344
345
346 // * Local cluster coordinates to feed to the calibration tools
347 Amg::Vector2D lp{ Amg::Vector2D::Zero() };
348
349 // get local y from the seeded position
350 const Trk::PlaneSurface& rio_surface = stgEL->surface(RIO.identify());
351 if (!rio_surface.globalToLocal(GP, GP, lp)) {
352 Amg::Vector3D lpos = rio_surface.transform().inverse() * GP;
353 ATH_MSG_WARNING("Extrapolated GlobalPosition not on detector surface! Distance " << lpos.z());
354 lp[Trk::locX] = lpos.x();
355 lp[Trk::locY] = lpos.y();
356 }
357 // set local x from the cluster parameters
358 lp[Trk::locX] = locpar[Trk::locX];
359
360 // * Correct the local coordinates for as-built conditions and b-lines
361 Amg::Vector3D localposition3D { Amg::Vector3D::Zero() };
362 stgEL->spacePointPosition(RIO.identify(), lp[Trk::locX], lp[Trk::locY], localposition3D);
363
364 // Get the direction of the track in the local coordinate system and use it to project
365 // the actual hit position onto the nominal surface (locZ = 0), where the intersection
366 // of the track is considered. This "effective" position provides a more accurate residual.
368 rio_surface.globalToLocalDirection(GD, ld);
369 double a_impact = ld.angleXZ() < 0 ? -M_PI_2 - ld.angleXZ() : M_PI_2 - ld.angleXZ();
370 double x_projected = localposition3D.x() - std::tan(a_impact) * localposition3D.z();
371
372 // * Set the value of the local parameter (locX) after applying conditions
373 // The position along strip will be set from the seed (there is no better
374 // estimate than that; not used in the track fits anyway)
375 locpar[Trk::locX] = x_projected;
376
377 const sTgcPrepData* stgPRD = static_cast<const sTgcPrepData*>(&RIO);
378 ATH_MSG_VERBOSE("generating sTgcClusterOnTrack in MuonClusterBuilder");
379 MuonClusterOnTrack* cluster = new sTgcClusterOnTrack(stgPRD, std::move(locpar), std::move(loce), lp[Trk::locY]);
380
381 return cluster;
382 }
383} // namespace Muon
const boost::regex re(r_e)
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t sc
An MMReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station con...
virtual bool spacePointPosition(const Identifier &phiId, const Identifier &etaId, Amg::Vector2D &pos) const override final
space point position for a given pair of phi and eta identifiers The LocalPosition is expressed in th...
virtual const Trk::PlaneSurface & surface() const override
access to chamber surface (phi orientation), uses the first gas gap
virtual const Amg::Transform3D & transform() const override
Return local to global transform.
An RpcReadoutElement corresponds to a single RPC module; therefore typicaly a barrel muon station con...
A TgcReadoutElement corresponds to a single TGC chamber; therefore typically a TGC station contains s...
Amg::Vector3D stripDir(int gasGap, int strip) const
Returns the direction of a strip.
double stripLength() const
Returns the length of each strip which is equal to the height of the chamber.
double stripPitch(int gasGap, int strip) const
Returns the pitch of the given strip in gasGap i.
An sTgcReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station c...
virtual bool spacePointPosition(const Identifier &phiId, const Identifier &etaId, Amg::Vector2D &pos) const override final
space point position for a given pair of phi and eta identifiers The LocalPosition is expressed in th...
bool isEtaZero(const Identifier &id, const Amg::Vector2D &localPosition) const
is eta=0 of QL1 or QS1?
MMClusterOnTrack::Author RIO_Author
Refinement of the cluster position after the cluster calibration loop is ran with a complete external...
Class to represent calibrated clusters formed from TGC strips.
Class to represent MM measurements.
Definition MMPrepData.h:22
virtual StatusCode initialize() override
Gaudi::Property< double > m_fixedErrorTgcEta
MuonClusterOnTrack * calibratedClusterMMG(const Trk::PrepRawData &RIO, const Amg::Vector3D &GP, const Amg::Vector3D &GD) const
virtual MuonClusterOnTrack * createRIO_OnTrack(const Trk::PrepRawData &RIO, const Amg::Vector3D &GP) const override
Create new Muon::MuonClusterOnTrack from a Trk::PrepRawData and a predicted Trk::TrackParameter.
virtual MuonClusterOnTrack * correct(const Trk::PrepRawData &RIO, const Trk::TrackParameters &TP, const EventContext &) const override
Create new Muon::MuonClusterOnTrack from a Trk::PrepRawData and the predicted Trk::TrackParameter at ...
Gaudi::Property< double > m_fixedErrorRpcEta
Gaudi::Property< double > m_fixedErrorRpcPhi
ToolHandle< Muon::INSWCalibTool > m_calibToolNSW
MuonClusterOnTrack * calibratedClusterSTG(const Trk::PrepRawData &RIO, const Amg::Vector3D &GP, const Amg::Vector3D &GD) const
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
ToolHandle< Muon::IMMClusterBuilderTool > m_clusterBuilderToolMM
Gaudi::Property< double > m_fixedErrorTgcPhi
Base class for Muon cluster RIO_OnTracks.
Class to represent calibrated clusters formed from RPC strips.
Class to represent RPC measurements.
Definition RpcPrepData.h:35
virtual const MuonGM::RpcReadoutElement * detectorElement() const override final
Returns the detector element corresponding to this PRD.
float time() const
Returns the time.
Class to represent calibrated clusters formed from TGC strips.
Class to represent TGC measurements.
Definition TgcPrepData.h:32
virtual const MuonGM::TgcReadoutElement * detectorElement() const override final
Returns the detector element corresponding to this PRD The pointer will be zero if the det el is not ...
Class to represent calibrated clusters formed from TGC strips.
Class to represent sTgc measurements.
virtual const MuonGM::sTgcReadoutElement * detectorElement() const override final
Returns the detector element corresponding to this PRD.
int channel(const Identifier &id) const override
int gasGap(const Identifier &id) const override
get the hashes
bool measuresPhi(const Identifier &id) const override
represents the three-dimensional global direction with respect to a planar surface frame.
const Amg::Vector3D & momentum() const
Access method for the momentum.
const Amg::Vector3D & position() const
Access method for the position.
Class for a planaer rectangular or trapezoidal surface in the ATLAS detector.
virtual bool globalToLocal(const Amg::Vector3D &glob, const Amg::Vector3D &mom, Amg::Vector2D &loc) const override final
Specified for PlaneSurface: GlobalToLocal method without dynamic memory allocation - boolean checks i...
void globalToLocalDirection(const Amg::Vector3D &glodir, Trk::LocalDirection &locdir) const
This method transforms the global direction to a local direction wrt the plane.
virtual const TrkDetElementBase * detectorElement() const =0
return the detector element corresponding to this PRD The pointer will be zero if the det el is not d...
const Amg::Vector2D & localPosition() const
return the local position reference
Identifier identify() const
return the identifier
const Amg::MatrixX & localCovariance() const
return const ref to the error matrix
Abstract Base Class for tracking surfaces.
virtual bool globalToLocal(const Amg::Vector3D &glob, const Amg::Vector3D &mom, Amg::Vector2D &loc) const =0
Specified by each surface type: GlobalToLocal method without dynamic memory allocation - boolean chec...
virtual bool insideBounds(const Amg::Vector2D &locpos, double tol1=0., double tol2=0.) const =0
virtual methods to be overwritten by the inherited surfaces
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
This is the base class for all tracking detector elements with read-out relevant information.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
This module defines the arguments passed from the BATCH driver to the BATCH worker.
TechnologyIndex
enum to classify the different layers in the muon spectrometer
Amg::Vector3D toLocal(const Amg::Transform3D &toLocalTrans, const Amg::Vector3D &dir)
Rotates a direction vector into a local frame: x-axis : Parallell to the radial direction of the dete...
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
Definition TgcBase.h:6
@ locY
local cartesian
Definition ParamDefs.h:38
@ locX
Definition ParamDefs.h:37
@ locZ
local cylindrical
Definition ParamDefs.h:42
std::pair< double, ParamDefs > DefinedParameter
Typedef to of a std::pair<double, ParamDefs> to identify a passed-through double as a specific type o...
ParametersBase< TrackParametersDim, Charged > TrackParameters