ATLAS Offline Software
SiLorentzAngleTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "SiLorentzAngleTool.h"
6 
7 #include <algorithm>
8 #include <limits>
9 
10 #include "GaudiKernel/SystemOfUnits.h"
11 
17 
18 SiLorentzAngleTool::SiLorentzAngleTool(const std::string& type, const std::string& name, const IInterface* parent):
19  base_class(type, name, parent),
20  m_condData{"SCTSiLorentzAngleCondData"}
21 {
22  declareProperty("IgnoreLocalPos", m_ignoreLocalPos = false,
23  "Treat methods that take a local position as if one called the methods without a local position");
24  // YOU NEED TO USE THE SAME PROPERTIES AS USED IN Pixel/SCTSiLorentzAngleCondAlg!!!
25  declareProperty("DetectorName", m_detectorName="Pixel", "Detector name (Pixel, SCT or PLR)");
26  declareProperty("NominalField", m_nominalField = 2.0834*Gaudi::Units::tesla);
27  declareProperty("UseMagFieldCache", m_useMagFieldCache = true);
28  declareProperty("SiLorentzAngleCondData", m_condData, "Key of input SiLorentzAngleCondData");
29 }
30 
32 
33  ATH_MSG_DEBUG("SiLorentzAngleTool Initialized");
34 
35  if ((m_detectorName not_eq "Pixel") and (m_detectorName not_eq "SCT") and (m_detectorName not_eq "PLR")) {
36  ATH_MSG_FATAL("Invalid detector name: " << m_detectorName << ". Must be Pixel, SCT or PLR.");
37  return StatusCode::FAILURE;
38  }
39 
40  // Read Cond Handle
43 
44  // MagneticFieldCache
45  if (not m_useMagFieldCache) {
46  ATH_MSG_DEBUG("Not using Magnetic Field cache - Will be using Nominal Field!");
47  }
49 
50  return StatusCode::SUCCESS;
51 }
52 
54  return StatusCode::SUCCESS;
55 }
56 
57 double SiLorentzAngleTool::getLorentzShift(const IdentifierHash& elementHash, const EventContext& ctx) const {
58  const SiLorentzAngleCondData* condData{getCondData(ctx)};
59  if (condData) {
60  return condData->getLorentzShift(elementHash);
61  }
62  return s_invalidValue;
63 }
64 
65 double SiLorentzAngleTool::getLorentzShift(const IdentifierHash& elementHash, const Amg::Vector2D& locPos) const {
66  if (m_ignoreLocalPos) return getLorentzShift(elementHash, Gaudi::Hive::currentContext());
67  // The cache is used to store the results. The cache is therefore invalidated if we specify a position.
68  return getValue(elementHash, locPos, LorentzShift);
69 }
70 
71 double SiLorentzAngleTool::getLorentzShiftEta(const IdentifierHash& elementHash) const {
72  const SiLorentzAngleCondData* condData{getCondData(Gaudi::Hive::currentContext())};
73  if (condData) {
74  return condData->getLorentzShiftEta(elementHash);
75  }
76  return s_invalidValue;
77 }
78 
79 double SiLorentzAngleTool::getLorentzShiftEta(const IdentifierHash& elementHash, const Amg::Vector2D& locPos) const {
80  if (m_ignoreLocalPos) return getLorentzShiftEta(elementHash);
81  // The cache is used to store the results. The cache is therefore invalidated if we specify a position.
82  return getValue(elementHash, locPos, LorentzShiftEta);
83 }
84 
85 double SiLorentzAngleTool::getTanLorentzAngle(const IdentifierHash& elementHash, const EventContext& ctx) const {
86  const SiLorentzAngleCondData* condData{getCondData(ctx)};
87  if (condData) {
88  return condData->getTanLorentzAngle(elementHash);
89  }
90  return s_invalidValue;
91 }
92 
93 double SiLorentzAngleTool::getTanLorentzAngle(const IdentifierHash& elementHash, const Amg::Vector2D& locPos) const {
94  if (m_ignoreLocalPos) return getTanLorentzAngle(elementHash, Gaudi::Hive::currentContext());
95  // The cache is used to store the results. The cache is therefore invalidated if we specify a position.
96  return getValue(elementHash, locPos, TanLorentzAngle);
97 }
98 
100  const SiLorentzAngleCondData* condData{getCondData(Gaudi::Hive::currentContext())};
101  if (condData) {
102  return condData->getTanLorentzAngleEta(elementHash);
103  }
104  return s_invalidValue;
105 }
106 
107 double SiLorentzAngleTool::getTanLorentzAngleEta(const IdentifierHash& elementHash, const Amg::Vector2D& locPos) const {
108  if (m_ignoreLocalPos) return getTanLorentzAngleEta(elementHash);
109  // The cache is used to store the results. The cache is therefore invalidated if we specify a position.
110  return getValue(elementHash, locPos, TanLorentzAngleEta);
111 }
112 
113 double SiLorentzAngleTool::getBiasVoltage(const IdentifierHash& elementHash) const {
114  const SiLorentzAngleCondData* condData{getCondData(Gaudi::Hive::currentContext())};
115  if (condData) {
116  return condData->getBiasVoltage(elementHash);
117  }
118  return s_invalidValue;
119 }
120 
121 double SiLorentzAngleTool::getTemperature(const IdentifierHash& elementHash) const {
122  const SiLorentzAngleCondData* condData{getCondData(Gaudi::Hive::currentContext())};
123  if (condData) {
124  return condData->getTemperature(elementHash);
125  }
126  return s_invalidValue;
127 }
128 
129 double SiLorentzAngleTool::getDepletionVoltage(const IdentifierHash& elementHash) const {
130  const SiLorentzAngleCondData* condData{getCondData(Gaudi::Hive::currentContext())};
131  if (condData) {
132  return condData->getDepletionVoltage(elementHash);
133  }
134  return s_invalidValue;
135 }
136 
137 double SiLorentzAngleTool::getValue(const IdentifierHash& elementHash, const Amg::Vector2D& locPos, Variable variable) const {
139  ATH_MSG_WARNING("getValue with Variable=" << variable << " is not available");
140  return s_invalidValue;
141  }
142 
143  double temperature{getTemperature(elementHash)};
144  double deplVoltage{getDepletionVoltage(elementHash)};
145  double biasVoltage{getBiasVoltage(elementHash)};
146 
147  // Calculate depletion depth. If biasVoltage is less than depletionVoltage
148  // the detector is not fully depleted and we need to take this into account.
149  // We take absolute values just in case voltages are signed.
150  const InDetDD::SiDetectorElement* element{getDetectorElement(elementHash)};
151  double depletionDepth{element->thickness()};
152  if (deplVoltage==0.0) ATH_MSG_WARNING("Depletion voltage in "<<__FILE__<<" is zero, which might be a bug.");
153  if (std::abs(biasVoltage) < std::abs(deplVoltage)) {
154  depletionDepth *= sqrt(std::abs(biasVoltage / deplVoltage));
155  }
156  double meanElectricField{0.};
157  if (depletionDepth) {
158  meanElectricField = biasVoltage / depletionDepth;
159  }
160  double mobility{0.};
161  InDet::SiliconProperties siProperties;
162  siProperties.setConditions(temperature, meanElectricField);
163  mobility = siProperties.signedHallMobility(element->carrierType());
164  // Get magnetic field.
165  Amg::Vector3D pointvec{element->globalPosition(locPos)};
166  Amg::Vector3D magneticField{getMagneticField(pointvec)};
167 
168  double correctionFactor{getCorrectionFactor()};
169 
170  // The angles are in the hit frame. This is because that is what is needed by the digization and also
171  // gives a more physical sign of the angle (ie dosen't flip sign when the detector is flipped).
172  // The hit depth axis is pointing from the readout side to the backside if m_design->readoutSide() < 0
173  // The hit depth axis is pointing from the backside to the readout side if m_design->readoutSide() > 0
175  double tanLorentzAnglePhi{element->design().readoutSide()*mobility*element->hitDepthDirection()*element->hitPhiDirection()*(element->normal().cross(magneticField)).dot(element->phiAxis())};
176  if (variable==TanLorentzAngle) {
177  return correctionFactor*tanLorentzAnglePhi;
178  }
179  // This gives the effective correction in the reconstruction frame hence the extra hitPhiDirection()
180  // as the angle above is in the hit frame.
181  double lorentzCorrectionPhi{-0.5*element->hitPhiDirection()*tanLorentzAnglePhi*depletionDepth};
182  return correctionFactor*lorentzCorrectionPhi;
183  }
184 
185  // The Lorentz eta shift very small and so can be ignored, but we include it for completeness.
186  // It is < ~0.1 um in the pixel.
187  // In the SCT its largest in the stereo side of the barrel modules where it is about 0.3 micron along the strip.
189  double tanLorentzAngleEta{element->design().readoutSide()*mobility*element->hitDepthDirection()*element->hitEtaDirection()*(element->normal().cross(magneticField)).dot(element->etaAxis())};
191  return correctionFactor*tanLorentzAngleEta;
192  }
193  double lorentzCorrectionEta{-0.5*element->hitPhiDirection()*tanLorentzAngleEta*depletionDepth};
194  return correctionFactor*lorentzCorrectionEta;
195  }
196 
197  ATH_MSG_WARNING("You should not see this message. Something is wrong in getValue");
198  return s_invalidValue;
199 }
200 
202 {
203  const SiLorentzAngleCondData* condData{getCondData(Gaudi::Hive::currentContext())};
204  if (condData) {
205  return condData->getCorrectionFactor();
206  }
207  return s_invalidValue;
208 }
209 
211  // Get the magnetic field.
212  bool useMagFieldCache{m_useMagFieldCache};
213  MagField::AtlasFieldCache fieldCache;
214  if (useMagFieldCache) {
215  SG::ReadCondHandle<AtlasFieldCacheCondObj> readHandle{m_fieldCondObjInputKey, Gaudi::Hive::currentContext()};
216  const AtlasFieldCacheCondObj* fieldCondObj{*readHandle};
217  if (fieldCondObj == nullptr) {
218  ATH_MSG_ERROR("SCTSiLorentzAngleCondAlg : Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCondObjInputKey.key());
219  useMagFieldCache = false;
220  } else {
221  fieldCondObj->getInitializedCache(fieldCache);
222  }
223  }
224  if (useMagFieldCache) {
225  ATH_MSG_VERBOSE("Getting magnetic field from magnetic field service.");
226  double field[3];
227  double point[3];
228  point[0] = pointvec[0];
229  point[1] = pointvec[1];
230  point[2] = pointvec[2];
231  fieldCache.getField(point, field);
232  return Amg::Vector3D(field[0], field[1], field[2]);
233  } else {
234  ATH_MSG_VERBOSE("Using Nominal Field");
235  return Amg::Vector3D(0., 0., m_nominalField);
236  }
237 }
238 
239 const SiLorentzAngleCondData* SiLorentzAngleTool::getCondData(const EventContext& ctx) const {
241  if (handle.isValid()) {
242  const SiLorentzAngleCondData* data{*handle};
243  return data;
244  }
245  ATH_MSG_WARNING(m_condData.key() << " cannot be retrieved.");
246  return nullptr;
247 }
248 
251  const InDetDD::SiDetectorElementCollection* elements{nullptr};
252  if (handle.isValid()) elements = *handle;
253  if (elements!=nullptr) return elements->getDetectorElement(waferHash);
254 
255  ATH_MSG_WARNING(m_detEleCollKey.key() << " cannot be retrieved.");
256  return nullptr;
257 }
258 
259 const double SiLorentzAngleTool::s_invalidValue{std::numeric_limits<double>::quiet_NaN()};
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
SiLorentzAngleTool::getValue
double getValue(const IdentifierHash &elementHash, const Amg::Vector2D &locPos, Variable variable) const
Definition: SiLorentzAngleTool.cxx:137
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
SiLorentzAngleTool::getMagneticField
Amg::Vector3D getMagneticField(const Amg::Vector3D &pointvec) const
Definition: SiLorentzAngleTool.cxx:210
InDetDD::SiDetectorElementCollection
Definition: SiDetectorElementCollection.h:30
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
AtlasFieldCacheCondObj
Definition: AtlasFieldCacheCondObj.h:19
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
SiLorentzAngleCondData::getCorrectionFactor
double getCorrectionFactor() const
Get correction factor.
Definition: SiLorentzAngleCondData.cxx:81
SiLorentzAngleCondData::getLorentzShiftEta
double getLorentzShiftEta(const IdentifierHash &elementHash) const
Get the Lorentz shift correction in the local y (etaDist) direction Assumes the center of the detecto...
Definition: SiLorentzAngleCondData.cxx:45
SiLorentzAngleTool::m_detectorName
std::string m_detectorName
Definition: SiLorentzAngleTool.h:97
SiLorentzAngleCondData
Definition: SiLorentzAngleCondData.h:22
SiLorentzAngleCondData::getTanLorentzAngleEta
double getTanLorentzAngleEta(const IdentifierHash &elementHash) const
Get tan af the Lorentz angle in the local y (etaDist) direction Assumes the center of the detector an...
Definition: SiLorentzAngleCondData.cxx:57
SiLorentzAngleTool::m_fieldCondObjInputKey
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCondObjInputKey
Definition: SiLorentzAngleTool.h:103
SiLorentzAngleTool::getCondData
const SiLorentzAngleCondData * getCondData(const EventContext &ctx) const
Definition: SiLorentzAngleTool.cxx:239
ReadOfcFromCool.field
field
Definition: ReadOfcFromCool.py:48
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
SiLorentzAngleCondData::getTanLorentzAngle
double getTanLorentzAngle(const IdentifierHash &elementHash) const
Get tan af the Lorentz angle in the local x (phiDist) direction Assumes the center of the detector an...
Definition: SiLorentzAngleCondData.cxx:51
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
AthenaAttributeList.h
SiLorentzAngleCondData::getBiasVoltage
double getBiasVoltage(const IdentifierHash &elementHash) const
Get bias voltage.
Definition: SiLorentzAngleCondData.cxx:63
SiLorentzAngleTool::getCorrectionFactor
double getCorrectionFactor() const
Definition: SiLorentzAngleTool.cxx:201
SiLorentzAngleTool.h
SiLorentzAngleTool::m_detEleCollKey
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_detEleCollKey
Definition: SiLorentzAngleTool.h:102
SiLorentzAngleTool::m_condData
SG::ReadCondHandleKey< SiLorentzAngleCondData > m_condData
Definition: SiLorentzAngleTool.h:101
SiLorentzAngleTool::getTanLorentzAngle
virtual double getTanLorentzAngle(const IdentifierHash &elementHash, const EventContext &ctx) const override
Get tan af the Lorentz angle in the local x (phiDist) direction Assumes the center of the detector an...
Definition: SiLorentzAngleTool.cxx:85
SiLorentzAngleTool::SiLorentzAngleTool
SiLorentzAngleTool(const std::string &type, const std::string &name, const IInterface *parent)
Definition: SiLorentzAngleTool.cxx:18
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
InDetDD::SolidStateDetectorElementBase::thickness
double thickness() const
SiLorentzAngleTool::getTemperature
virtual double getTemperature(const IdentifierHash &elementHash) const override
Get temperature.
Definition: SiLorentzAngleTool.cxx:121
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
SiLorentzAngleTool::getTanLorentzAngleEta
virtual double getTanLorentzAngleEta(const IdentifierHash &elementHash) const override
Get tan af the Lorentz angle in the local y (etaDist) direction Assumes the center of the detector an...
Definition: SiLorentzAngleTool.cxx:99
AtlasFieldCache.h
SiLorentzAngleCondData::getDepletionVoltage
double getDepletionVoltage(const IdentifierHash &elementHash) const
Get depletion voltage.
Definition: SiLorentzAngleCondData.cxx:75
test_pyathena.parent
parent
Definition: test_pyathena.py:15
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
python.selection.variable
variable
Definition: selection.py:33
SiLorentzAngleTool::LorentzShift
@ LorentzShift
Definition: SiLorentzAngleTool.h:88
SiLorentzAngleTool::TanLorentzAngle
@ TanLorentzAngle
Definition: SiLorentzAngleTool.h:88
SiLorentzAngleTool::getLorentzShiftEta
virtual double getLorentzShiftEta(const IdentifierHash &elementHash) const override
Get the Lorentz shift correction in the local y (etaDist) direction Assumes the center of the detecto...
Definition: SiLorentzAngleTool.cxx:71
dot.dot
def dot(G, fn, nodesToHighlight=[])
Definition: dot.py:5
SiLorentzAngleTool::m_ignoreLocalPos
bool m_ignoreLocalPos
Definition: SiLorentzAngleTool.h:100
SiLorentzAngleTool::initialize
virtual StatusCode initialize() override
Service init.
Definition: SiLorentzAngleTool.cxx:31
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
SiLorentzAngleTool::TanLorentzAngleEta
@ TanLorentzAngleEta
Definition: SiLorentzAngleTool.h:88
IdentifierHash.h
python.SystemOfUnits.tesla
int tesla
Definition: SystemOfUnits.py:228
InDetDD::SiDetectorElement
Definition: SiDetectorElement.h:109
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
InDet::SiliconProperties
Definition: SiliconProperties.h:24
InDet::SiliconProperties::signedHallMobility
double signedHallMobility(InDetDD::CarrierType carrier) const
Definition: SiliconProperties.cxx:114
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Variable
Wrapper around a histogram which allows for some additional filling patterns and data manipulation.
Definition: Trigger/TrigCost/TrigCostAnalysis/src/Variable.h:39
SiDetectorElement.h
SiLorentzAngleTool::m_nominalField
double m_nominalField
Definition: SiLorentzAngleTool.h:98
SiLorentzAngleTool::s_invalidValue
static const double s_invalidValue
Definition: SiLorentzAngleTool.h:105
SiLorentzAngleTool::finalize
virtual StatusCode finalize() override
Service finalize.
Definition: SiLorentzAngleTool.cxx:53
SiLorentzAngleTool::LorentzShiftEta
@ LorentzShiftEta
Definition: SiLorentzAngleTool.h:88
SiLorentzAngleTool::getDepletionVoltage
virtual double getDepletionVoltage(const IdentifierHash &elementHash) const override
Get depletion voltage.
Definition: SiLorentzAngleTool.cxx:129
SiLorentzAngleTool::getBiasVoltage
virtual double getBiasVoltage(const IdentifierHash &elementHash) const override
Get bias voltage.
Definition: SiLorentzAngleTool.cxx:113
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
MagField::AtlasFieldCache
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h)
Definition: AtlasFieldCache.h:43
SiLorentzAngleCondData::getLorentzShift
double getLorentzShift(const IdentifierHash &elementHash) const
Get the Lorentz shift correction in the local x (phiDist) direction Assumes the center of the detecto...
Definition: SiLorentzAngleCondData.cxx:39
MagField::AtlasFieldCache::getField
void getField(const double *ATH_RESTRICT xyz, double *ATH_RESTRICT bxyz, double *ATH_RESTRICT deriv=nullptr)
get B field value at given position xyz[3] is in mm, bxyz[3] is in kT if deriv[9] is given,...
Definition: AtlasFieldCache.cxx:42
SiLorentzAngleTool::m_useMagFieldCache
bool m_useMagFieldCache
Definition: SiLorentzAngleTool.h:99
IdentifierHash
This is a "hash" representation of an Identifier. This encodes a 32 bit index which can be used to lo...
Definition: IdentifierHash.h:25
SiLorentzAngleTool::getLorentzShift
virtual double getLorentzShift(const IdentifierHash &elementHash, const EventContext &ctx) const override
Get the Lorentz shift correction in the local x (phiDist) direction Assumes the center of the detecto...
Definition: SiLorentzAngleTool.cxx:57
InDetDD::SiDetectorElementCollection::getDetectorElement
const SiDetectorElement * getDetectorElement(const IdentifierHash &hash) const
Definition: SiDetectorElementCollection.cxx:15
SiLorentzAngleTool::getDetectorElement
const InDetDD::SiDetectorElement * getDetectorElement(const IdentifierHash &waferHash) const
Definition: SiLorentzAngleTool.cxx:249
InDet::SiliconProperties::setConditions
void setConditions(double temperature, double electricField)
Definition: SiliconProperties.cxx:71
SiliconProperties.h
SiLorentzAngleCondData::getTemperature
double getTemperature(const IdentifierHash &elementHash) const
Get temperature.
Definition: SiLorentzAngleCondData.cxx:69