ATLAS Offline Software
Loading...
Searching...
No Matches
TRTTimeCorrection.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "TRTTimeCorrection.h"
6
7//TRT detector information:
11
12#include "TRTDigSettings.h"
13
15//For speed of light:
16#include "CLHEP/Units/PhysicalConstants.h"
17
18#include "Identifier/Identifier.h"
19#include "GaudiKernel/IService.h"
20
21
22//__________________________________________________________________________________________________________
24 const InDetDD::TRT_DetectorManager* detmgr,
25 const TRT_ID* trt_id,
26 const ITRT_CalDbTool* calDbTool)
27 : AthMessaging("TRTTimeCorrection"),
28 m_settings(digset), m_detmgr(detmgr), m_trt_id(trt_id),
29 m_subdetectorMask(0x00200000), m_right5Bits(0x0000001F),
30 m_shift5Bits(5), m_shift10Bits(10), m_shift15Bits(15), m_notInitVal(-999999.0), m_trtcaldbtool(calDbTool)
31{
32 Initialize();
33}
34
35
36//__________________________________________________________________________________________________________
38
39//__________________________________________________________________________________________________________
41
42 m_signalPropagationSpeed = m_settings->signalPropagationSpeed() ;
43 m_lengthDeadRegion = m_settings->lengthOfDeadRegion();
44 m_maxVertexDisplacement = m_settings->maxVertexDisplacement();
45 m_timeShiftPhiSectSymmetry = m_settings->timeshiftsSymmetricForPhiSectors();
46 m_getT0FromData = m_settings->getT0FromData();
47
49 ATH_MSG_ERROR("Could not find TRT_CalDbTool => cannot use t0 of data.");
50 m_getT0FromData=false;
51 }
52
53 const InDetDD::TRT_Numerology *numerology(m_detmgr->getNumerology());
54
55 const unsigned int nbarrelphi(m_timeShiftPhiSectSymmetry ? 1 : numerology->getNBarrelPhi());
56 const unsigned int nendcapphi(m_timeShiftPhiSectSymmetry ? 1 : numerology->getNEndcapPhi());
57
58 //Initialize barrel max timeshift arrays:
59 m_timeShiftForBarrelStraws.resize(nbarrelphi);
60 for (auto & timeShiftForBarrelStraw : m_timeShiftForBarrelStraws) {
61 timeShiftForBarrelStraw.resize(numerology->getNBarrelRings());
62 for (unsigned int iRing = 0; iRing < timeShiftForBarrelStraw.size(); ++iRing) {
63 timeShiftForBarrelStraw[iRing].resize(numerology->getNBarrelLayers(iRing));
64 for (unsigned int iLayer = 0; iLayer < timeShiftForBarrelStraw[iRing].size(); ++iLayer) {
65 if (m_detmgr->getBarrelElement(0,iRing,0,iLayer)) {
66 unsigned int nstraws_in_layer = m_detmgr->getBarrelElement(0,iRing,0,iLayer)->nStraws();
67 timeShiftForBarrelStraw[iRing][iLayer].assign(nstraws_in_layer,m_notInitVal);
68 }
69 }
70 }
71 }
72
73 //Initialize endcap max timeshift arrays:
74 m_timeShiftForEndCapPlanes.resize(nendcapphi);
75 for (auto & timeShiftForEndCapPlane : m_timeShiftForEndCapPlanes) {
76 timeShiftForEndCapPlane.resize(numerology->getNEndcapWheels());
77 for (unsigned int iWheel = 0; iWheel < timeShiftForEndCapPlane.size(); ++iWheel) {
78 timeShiftForEndCapPlane[iWheel].assign(numerology->getNEndcapLayers(iWheel),m_notInitVal);
79 }
80 }
81
82 //Initialize barrel direct/reflected distances array
85 for (unsigned int iRing = 0; iRing < m_directDistsForBarrelLayers.size(); ++iRing) {
86 m_directDistsForBarrelLayers[iRing].assign(numerology->getNBarrelLayers(iRing),m_notInitVal);
87 m_reflectedDistsForBarrelLayers[iRing].assign(numerology->getNBarrelLayers(iRing),m_notInitVal);
88 };
89
90 //Initialize endcap direct/reflected distances array
93
94}
95
96//__________________________________________________________________________________________________________
97double TRTTimeCorrection::TimeShift(const int& strawID, const InDetDD::TRT_DetElementContainer* detElements) {
98
99 //TODO: Use hit id helpers (but resolve efficiency issues first).
100
101 double timeshift=0.;
102
103 //Layer and phi index are needed for both endcap and barrel:
104 const unsigned int iLayer((strawID >> m_shift5Bits) & m_right5Bits);
105 const unsigned int iPhi(m_timeShiftPhiSectSymmetry ? 0 : ( (strawID >> m_shift10Bits) & m_right5Bits ));
106
107 if (strawID & m_subdetectorMask) {
108
109 //===// EndCap //===//
110
111 const unsigned int iWheel((strawID >> m_shift15Bits) & m_right5Bits);
112
113 //Sanity check:
114 if (iPhi>=m_timeShiftForEndCapPlanes.size()||
115 iWheel>=m_timeShiftForEndCapPlanes[iPhi].size()||
116 iLayer>=m_timeShiftForEndCapPlanes[iPhi][iWheel].size()) {
118 ATH_MSG_ERROR("TimeCorrection::TimeShift: (iWheel,iLayer) = ("
119 << iWheel << ", " << iLayer << ") out of bounds! Returning 0.");
120 } else {
121 ATH_MSG_ERROR("TimeCorrection::TimeShift: (iPhi,iWheel,iLayer) = ("
122 << iPhi << ", " << iWheel << ", " << iLayer << ") out of bounds! Returning 0.");
123 }
124 return 0.0;
125 }
126
127 timeshift = m_timeShiftForEndCapPlanes[iPhi][iWheel][iLayer];
128
129 if (timeshift==m_notInitVal) {
130 //We need to initialize
131 timeshift = calculateTimeShift_EndCap(iPhi,iWheel,iLayer,strawID,detElements);
132 m_timeShiftForEndCapPlanes[iPhi][iWheel][iLayer] = timeshift;
133 }
134
135 } else {
136
137 //===// Barrel //===//
138
139 const unsigned int iRing((strawID >> m_shift15Bits) & m_right5Bits);
140 const unsigned int iStraw(strawID & m_right5Bits);
141
142 //Sanity check:
143 if (iPhi>=m_timeShiftForBarrelStraws.size()||
144 iRing>=m_timeShiftForBarrelStraws[iPhi].size()||
145 iLayer>=m_timeShiftForBarrelStraws[iPhi][iRing].size()||
146 iStraw>=m_timeShiftForBarrelStraws[iPhi][iRing][iLayer].size()) {
148 ATH_MSG_ERROR("TimeCorrection::TimeShift: (iRing,iLayer,iStraw) = ("
149 << iRing << ", " << iLayer << ", " << iStraw
150 << ") out of bounds! Returning 0.");
151 } else {
152 ATH_MSG_ERROR("TimeCorrection::TimeShift: (iPhi,iRing,iLayer,iStraw) = ("
153 << iPhi << ", " << iRing << ", " << iLayer << ", " << iStraw
154 << ") out of bounds! Returning 0.");
155 }
156 return 0.0;
157 }
158
159 timeshift = m_timeShiftForBarrelStraws[iPhi][iRing][iLayer][iStraw];
160
161 if (timeshift==m_notInitVal) {
162 //We need to initialize
163 timeshift = calculateTimeShift_Barrel(iPhi,iRing,iLayer,iStraw,strawID,detElements);
164 m_timeShiftForBarrelStraws[iPhi][iRing][iLayer][iStraw] = timeshift;
165 }
166
167 }
168
169 return timeshift;
170}
171
172//__________________________________________________________________________________________________________
173double TRTTimeCorrection::calculateTimeShift_Barrel( const unsigned int& iPhi,
174 const unsigned int& iRing,
175 const unsigned int& iLayer,
176 const unsigned int& iStraw,
177 const int strawID,
178 const InDetDD::TRT_DetElementContainer* detElements) {
179
180 const InDetDD::TRT_BarrelElement * barrel_element(detElements->getBarrelDetElement(0/*positive*/,
181 iRing, iPhi, iLayer ));
182
183 //Sanity checks:
184 if (!barrel_element) {
185 ATH_MSG_ERROR("calculateTimeShift_Barrel: Could not get element for iRing = "
186 << iRing <<" and iLayer = "<<iLayer<<". Timeshift becomes 0.");
187 return 0.0;
188 }
189
190 if (iStraw >= barrel_element->nStraws()) {
191 ATH_MSG_ERROR("calculateTimeShift_Barrel: Trying to access iStraw "
192 << iStraw <<" in an element with "<<barrel_element->nStraws()<<" straws (iRing="
193 << iRing <<",iLayer="<<iLayer<<"). Timeshift becomes 0.");
194 return 0.0;
195 }
196
197 //Straw endpoints for the straw lying along the z-axis:
198 Amg::Vector3D strawend1(0,0, barrel_element->strawLength()*0.5 );
199 Amg::Vector3D strawend2(0,0, -(barrel_element->strawLength()*0.5) );
200
201 //And here put into their proper global place:
202 strawend1 = barrel_element->strawTransform(iStraw) * strawend1;
203 strawend2 = barrel_element->strawTransform(iStraw) * strawend2;
204
205 return calculateTimeShiftFromStrawEnds(strawend1,strawend2,strawID);
206
207}
208
209//__________________________________________________________________________________________________________
210double TRTTimeCorrection::calculateTimeShift_EndCap( const unsigned int& iPhi,
211 const unsigned int& iWheel,
212 const unsigned int& iLayer,
213 const int strawID,
214 const InDetDD::TRT_DetElementContainer* detElements) {
215
216 const InDetDD::TRT_EndcapElement * ec_element(detElements->getEndcapDetElement(0/*positive*/,
217 iWheel, iLayer, iPhi ));
218
219 //Sanity check:
220 if (!ec_element) {
221 ATH_MSG_ERROR("calculateTimeShift_EndCap: Could not get element for iWheel = "
222 << iWheel <<" and iLayer = "<<iLayer<<". Timeshift becomes 0.");
223 return 0.0;
224 }
225
226 //Straw endpoints for the straw lying along the z-axis:
227 Amg::Vector3D strawend1(0,0, ec_element->strawLength() * 0.5 );
228 Amg::Vector3D strawend2(0,0, ec_element->strawLength() * (-0.5) );
229
230 //And here put into their proper global place:
231 strawend1 = ec_element->strawTransform(0) * strawend1;
232 strawend2 = ec_element->strawTransform(0) * strawend2;
233
234 return calculateTimeShiftFromStrawEnds(strawend1,strawend2,strawID); //,m_lvl
235
236}
237
238//__________________________________________________________________________________________________________
240 const Amg::Vector3D& strawend2_globalcoord,
241 const int strawID ) {
242
243 //The two (hopefully relevant) extreme points of the vertex region:
244 Amg::Vector3D vertexExtension1( m_settings->timeOffsetCalcVertexX(),
245 m_settings->timeOffsetCalcVertexY(),
246 m_settings->timeOffsetCalcVertexZ() + m_maxVertexDisplacement);
247 Amg::Vector3D vertexExtension2( m_settings->timeOffsetCalcVertexX(),
248 m_settings->timeOffsetCalcVertexY(),
249 m_settings->timeOffsetCalcVertexZ() - m_maxVertexDisplacement);
250
251 //Minimum distance between vertex region and the straw ends:
252 // const double mindisttoend1(std::min(strawend1_globalcoord.distance(vertexExtension1),
253 // strawend1_globalcoord.distance(vertexExtension2)));
254 const double mindisttoend1(std::min((strawend1_globalcoord-vertexExtension1).mag(),
255 (strawend1_globalcoord-vertexExtension2).mag()));
256 // const double mindisttoend2(std::min(strawend2_globalcoord.distance(vertexExtension1),
257 // strawend2_globalcoord.distance(vertexExtension2)));
258 const double mindisttoend2(std::min((strawend2_globalcoord-vertexExtension1).mag(),
259 (strawend2_globalcoord-vertexExtension2).mag()));
260
261 //Just a sanity check here:
262 if ( (mindisttoend2<mindisttoend1) == m_settings->electronicsAreAtFarEnd() ) {
263 ATH_MSG_WARNING("It would seem that the local z-coordinate of a test straw grows TOWARDS"
264 <<" the electronics ends. This will give trouble elsewhere!!");
265 }
266
267 double shift = 1.0; // 1 ns (negative) overall shift for the whole TRT detector. Now set in stone.
268 // Used to be set with overallT0Shift() & overallT0ShiftShortBarrel()
269 // Note: if you change this then you need to set ToolSvc.InDetTRT_DriftFunctionTool.MCTuningShift
270
271 if (m_settings->getT0FromData()) {
272 bool identifierOK;
273 const Identifier idStraw(getIdentifier(strawID, identifierOK));
274 if (identifierOK) {
275 shift = m_trtcaldbtool->getT0(idStraw);
276 } else {
277 ATH_MSG_ERROR("Attempt to use t0 from data failed: TRTCalDbSvc was not able to supply t0 for straw with identifier: "
278 << idStraw << ". Please set getT0FromData=false in jobOptions and run again");
279 }
280 }
281
282 if (m_settings->electronicsAreAtFarEnd())
283 return std::max(mindisttoend1,mindisttoend2) / (m_settings->distanceToTimeFactor() * CLHEP::c_light) - shift;
284 else
285 return std::min(mindisttoend1,mindisttoend2) / (m_settings->distanceToTimeFactor() * CLHEP::c_light) - shift;
286
287}
288
289//__________________________________________________________________________________________________________
290void TRTTimeCorrection::PropagationTime(const int& strawID, const double& meanZ,
291 double& propagationTime1, double& propagationTime2) {
292
293 double direct_distance, reflect_distance;
294
295 if (strawID & m_subdetectorMask) {
296
297 //===// EndCap //===//
298 const unsigned int iWheel((strawID >> m_shift15Bits) & m_right5Bits);
299 direct_distance = m_directDistsForEndCapWheels[iWheel];
300 reflect_distance = m_reflectedDistsForEndCapWheels[iWheel];
301
302 if (direct_distance==m_notInitVal) {
303 //We need to initialize
304 calculateSignalDists_EndCap(iWheel,direct_distance,reflect_distance);
305 m_directDistsForEndCapWheels[iWheel] = direct_distance;
306 m_reflectedDistsForEndCapWheels[iWheel] = reflect_distance;
307 };
308
309 //Z is counted positive AWAY from the electronics:
310 propagationTime1 = (direct_distance + meanZ) / m_signalPropagationSpeed;
311 propagationTime2 = (reflect_distance - meanZ) / m_signalPropagationSpeed;
312
313 } else {
314
315 //===// Barrel //===//
316 const unsigned int iRing((strawID >> m_shift15Bits) & m_right5Bits);
317 const unsigned int iLayer((strawID >> m_shift5Bits) & m_right5Bits);
318 direct_distance = m_directDistsForBarrelLayers[iRing][iLayer];
319 reflect_distance = m_reflectedDistsForBarrelLayers[iRing][iLayer];
320
321 if (direct_distance==m_notInitVal) {
322 //We need to initialize
323 calculateSignalDists_Barrel(iRing,iLayer,direct_distance,reflect_distance);
324 m_directDistsForBarrelLayers[iRing][iLayer] = direct_distance;
325 m_reflectedDistsForBarrelLayers[iRing][iLayer] = reflect_distance;
326 };
327
328 //Z is counted positive AWAY from the electronics:
329 propagationTime1 = (direct_distance + meanZ) / m_signalPropagationSpeed;
330 propagationTime2 = (reflect_distance - meanZ) / m_signalPropagationSpeed;
331
332 }
333
334 }
335
336//__________________________________________________________________________________________________________
337void TRTTimeCorrection::calculateSignalDists_Barrel(const unsigned int& iRing, const unsigned int& iLayer,
338 double& direct_dist, double& reflect_dist ) const {
339
340 //We need to calculate the distance along the wire that the signal
341 //has to travel before it reaches the electronics. Both if it goes
342 //directly to the electronics and if it goes via a reflection in the
343 //other end of the wire.
344 //
345 //The signal starts in the middle of the active region.
346 //
347 //In addition to the length of the active gas, the signal also has
348 //to go through the little dead region at the end.
349
350 const InDetDD::TRT_BarrelElement * barrel_element(m_detmgr->getBarrelElement(0,//positive,
351 iRing,//moduleIndex,
352 0,//int phiIndex,
353 iLayer));//strawLayerIndex
354
355 direct_dist = 0.5*barrel_element->strawLength() + m_lengthDeadRegion;
356 reflect_dist = 1.5*barrel_element->strawLength() + 3*m_lengthDeadRegion;
357}
358
359//__________________________________________________________________________________________________________
361 double& direct_dist,
362 double& reflect_dist ) const {
363
364 //For an explanation, please read the comment in calculateSignalDists_Barrel
365
366 const InDetDD::TRT_EndcapElement * ec_element(m_detmgr->getEndcapElement(0,//positive,
367 iWheel,//wheelIndex,
368 0,//strawLayerIndex,
369 0));//phiIndex
370
371 direct_dist = 0.5*ec_element->strawLength() + m_lengthDeadRegion;
372 reflect_dist = 1.5*ec_element->strawLength() + 3*m_lengthDeadRegion;
373}
374
375//_____________________________________________________________________________
377 bool & statusok)
378{
379 statusok = true;
380
381 Identifier IdStraw;
382 Identifier IdLayer;
383
384 const int mask(0x0000001F);
385 const int word_shift(5);
386 int trtID, ringID, moduleID, layerID, strawID;
387 int wheelID, planeID, sectorID;
388
389 const InDetDD::TRT_BarrelElement *barrelElement;
390 const InDetDD::TRT_EndcapElement *endcapElement;
391
392 if ( !(hitID & 0x00200000) ) { // barrel
393 strawID = hitID & mask;
394 hitID >>= word_shift;
395 layerID = hitID & mask;
396 hitID >>= word_shift;
397 moduleID = hitID & mask;
398 hitID >>= word_shift;
399 ringID = hitID & mask;
400 trtID = hitID >> word_shift;
401
402 barrelElement =
403 m_detmgr->getBarrelElement(trtID, ringID, moduleID, layerID);
404 if ( barrelElement ) {
405
406 IdLayer = barrelElement->identify();
407 IdStraw = m_trt_id->straw_id(IdLayer, strawID);
408 } else {
409 ATH_MSG_ERROR("Could not find detector element for barrel identifier with "
410 << "(ipos,iring,imod,ilayer,istraw) = ("
411 << trtID << ", " << ringID << ", " << moduleID << ", "
412 << layerID << ", " << strawID << ")");
413 statusok = false;
414 }
415 } else { // endcap
416 strawID = hitID & mask;
417 hitID >>= word_shift;
418 planeID = hitID & mask;
419 hitID >>= word_shift;
420 sectorID = hitID & mask;
421 hitID >>= word_shift;
422 wheelID = hitID & mask;
423 trtID = hitID >> word_shift;
424
425 // change trtID (which is 2/3 for endcaps) to use 0/1 in getEndcapElement
426 if (trtID == 3) trtID = 0;
427 else trtID = 1;
428
429 endcapElement =
430 m_detmgr->getEndcapElement(trtID, wheelID, planeID, sectorID);
431
432 if ( endcapElement ) {
433 IdLayer = endcapElement->identify();
434 IdStraw = m_trt_id->straw_id(IdLayer, strawID);
435 } else {
436 ATH_MSG_ERROR("Could not find detector element for endcap identifier with "
437 << "(ipos,iwheel,isector,iplane,istraw) = ("
438 << trtID << ", " << wheelID << ", " << sectorID << ", "
439 << planeID << ", " << strawID << ")");
440 ATH_MSG_ERROR("If this happens very rarely, don't be alarmed (it is a Geant4 'feature')");
441 ATH_MSG_ERROR("If it happens a lot, you probably have misconfigured geometry in the sim. job.");
442 statusok = false;
443 }
444
445 }
446
447 return IdStraw;
448}
Scalar mag() const
mag method
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
abstract interface to TRT calibration constants
Extended TRT_BaseElement to describe a TRT readout element, this is a planar layer with n ( order of ...
virtual const double & strawLength() const override final
Get the length of the straws (active length):
unsigned int nStraws() const
Number of straws in the element.
virtual Identifier identify() const override final
identifier of this detector element:
const Amg::Transform3D & strawTransform(unsigned int straw) const
Straw transform - fast access in array, in Tracking frame: Amg.
Class to hold different TRT detector elements structures.
const TRT_EndcapElement * getEndcapDetElement(unsigned int positive, unsigned int wheelIndex, unsigned int strawLayerIndex, unsigned int phiIndex) const
const TRT_BarrelElement * getBarrelDetElement(unsigned int positive, unsigned int moduleIndex, unsigned int phiIndex, unsigned int strawLayerIndex) const
The Detector Manager for all TRT Detector elements, it acts as the interface to the detector elements...
Extended class of a TRT_BaseElement to describe a readout elment in the endcap.
virtual const double & strawLength() const override
Active straw length.
Helper class to organize the straw elements on TRT readout elements.
unsigned int getNEndcapWheels() const
unsigned int getNEndcapPhi() const
unsigned int getNBarrelPhi() const
unsigned int getNBarrelRings() const
unsigned int getNBarrelLayers(unsigned int iMod) const
unsigned int getNEndcapLayers(unsigned int iWheel) const
Class containing parameters and settings used by TRT digitization.
TRTTimeCorrection(const TRTDigSettings *digset, const InDetDD::TRT_DetectorManager *detmgr, const TRT_ID *, const ITRT_CalDbTool *)
std::vector< std::vector< double > > m_directDistsForBarrelLayers
Cached distances.
void calculateSignalDists_EndCap(const unsigned int &iWheel, double &direct_dist, double &reflect_dist) const
Calculate the distance along the wire the signal travels before reaching the electronics.
const unsigned int m_subdetectorMask
std::vector< std::vector< double > > m_reflectedDistsForBarrelLayers
Cached distances.
const TRTDigSettings * m_settings
double calculateTimeShift_Barrel(const unsigned int &iPhi, const unsigned int &iRing, const unsigned int &iLayer, const unsigned int &iStraw, const int strawID, const InDetDD::TRT_DetElementContainer *detElements)
Time shift for barrel straws.
std::vector< double > m_directDistsForEndCapWheels
Cached distances.
std::vector< std::vector< std::vector< double > > > m_timeShiftForEndCapPlanes
Cached timeshifts.
const TRT_ID * m_trt_id
const unsigned int m_shift10Bits
const double m_notInitVal
Value used to denote an uninitialized value.
const unsigned int m_right5Bits
void PropagationTime(const int &strawID, const double &meanZ, double &propagationTime1, double &propagationTime2)
Calculates the time between the signal reaching the wire and when it reaches the electronics.
std::vector< double > m_reflectedDistsForEndCapWheels
Cached distances.
void calculateSignalDists_Barrel(const unsigned int &iRing, const unsigned int &iLayer, double &direct_dist, double &reflect_dist) const
Calculate the distance along the wire the signal travels before reaching the electronics.
const ITRT_CalDbTool * m_trtcaldbtool
double TimeShift(const int &strawID, const InDetDD::TRT_DetElementContainer *detElements)
Returns the time it would take to travel at light-speed from (0,0,0) to the farthest end of the wire ...
Identifier getIdentifier(int hitID, bool &statusok)
double calculateTimeShift_EndCap(const unsigned int &iPhi, const unsigned int &iWheel, const unsigned int &iLayer, const int strawID, const InDetDD::TRT_DetElementContainer *detElements)
Time shift for end cap straws.
const unsigned int m_shift5Bits
double calculateTimeShiftFromStrawEnds(const Amg::Vector3D &strawend1_globalcoord, const Amg::Vector3D &strawend2_globalcoord, const int strawID)
Time shift from straw endpoints in global system.
const unsigned int m_shift15Bits
std::vector< std::vector< std::vector< std::vector< double > > > > m_timeShiftForBarrelStraws
Cached timeshifts.
const InDetDD::TRT_DetectorManager * m_detmgr
This is an Identifier helper class for the TRT subdetector.
Definition TRT_ID.h:82
Eigen::Matrix< double, 3, 1 > Vector3D