ATLAS Offline Software
SCTSiLorentzAngleCondAlg.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
10 // Local include
12 
13 // Athena includes
14 #include "InDetIdentifier/SCT_ID.h"
17 
18 // Gaudi include
19 #include "GaudiKernel/PhysicalConstants.h"
20 
21 // STL include
22 
23 SCTSiLorentzAngleCondAlg::SCTSiLorentzAngleCondAlg(const std::string& name, ISvcLocator* pSvcLocator):
24  ::AthReentrantAlgorithm(name, pSvcLocator),
25  m_maxHash{0}
26 {
27 }
28 
30 {
31  if (m_siConditionsTool.empty()) m_sctDefaults.setValue(true);
32 
33  if (not m_sctDefaults.value()) {
34  // SCTSiliconConditionsTool
35  ATH_CHECK(m_siConditionsTool.retrieve());
36  } else {
37  m_siConditionsTool.disable();
38  }
39  // Read Cond handle
40  ATH_CHECK(m_readKeyTemp.initialize((not m_sctDefaults.value()) and (not m_useGeoModel.value())));
41  ATH_CHECK(m_readKeyHV.initialize((not m_sctDefaults.value()) and (not m_useGeoModel.value())));
42 
44 
46 
47  // Write Cond Handle
49 
50  // Get maximum hash for vector sizes. We need the idhelper for this.
51  const SCT_ID* idHelper{nullptr};
52  ATH_CHECK(detStore()->retrieve(idHelper, "SCT_ID"));
53  m_maxHash = idHelper->wafer_hash_max();
54 
55  return StatusCode::SUCCESS;
56 }
57 
58 StatusCode SCTSiLorentzAngleCondAlg::execute(const EventContext& ctx) const
59 {
60  // Write Cond Handle
62  // Do we have a valid Write Cond Handle for current time?
63  if (writeHandle.isValid()) {
64  ATH_MSG_DEBUG("CondHandle " << writeHandle.fullKey() << " is already valid."
65  << " In theory this should not be called, but may happen"
66  << " if multiple concurrent events are being processed out of order.");
67  return StatusCode::SUCCESS;
68  }
69 
70  // Get SCT_DetectorElementCollection
72  const InDetDD::SiDetectorElementCollection* elements(sctDetEle.retrieve());
73  if (elements==nullptr) {
74  ATH_MSG_FATAL(m_SCTDetEleCollKey.fullKey() << " could not be retrieved");
75  return StatusCode::FAILURE;
76  }
77  writeHandle.addDependency(sctDetEle); // Run-LB IOV
78 
79  if ((not m_sctDefaults.value()) and (not m_useGeoModel.value())) {
80  // Read Cond Handle (temperature)
82  const SCT_DCSFloatCondData* readCdoTemp{*readHandleTemp};
83  if (readCdoTemp==nullptr) {
84  ATH_MSG_FATAL("Null pointer to the read conditions object");
85  return StatusCode::FAILURE;
86  }
87  writeHandle.addDependency(readHandleTemp);
88  ATH_MSG_INFO("Input is " << readHandleTemp.fullKey() << " with the range of " << readHandleTemp.getRange());
89 
90  // Read Cond Handle (HV)
92  const SCT_DCSFloatCondData* readCdoHV{*readHandleHV};
93  if (readCdoHV==nullptr) {
94  ATH_MSG_FATAL("Null pointer to the read conditions object");
95  return StatusCode::FAILURE;
96  }
97  writeHandle.addDependency(readHandleHV);
98  ATH_MSG_INFO("Input is " << readHandleHV.fullKey() << " with the range of " << readHandleHV.getRange());
99  }
100 
101  MagField::AtlasFieldCache fieldCache;
102  if (m_useMagFieldCache.value()) {
103  // Get field cache object
105  const AtlasFieldCacheCondObj* fieldCondObj{*readHandle};
106 
107  if (fieldCondObj==nullptr) {
108  ATH_MSG_FATAL("Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCondObjInputKey.key());
109  return StatusCode::FAILURE;
110  }
111  writeHandle.addDependency(readHandle);
112  fieldCondObj->getInitializedCache(fieldCache);
113  }
114 
115  // Construct the output Cond Object and fill it in
116  std::unique_ptr<SiLorentzAngleCondData> writeCdo{std::make_unique<SiLorentzAngleCondData>()};
117  writeCdo->resize(m_maxHash);
118  // SiLorentzAngleCondData myData;
119 
120  for (unsigned int hash{0}; hash<m_maxHash; hash++) {
121  const IdentifierHash elementHash{hash};
122 
123  double temperatureC{0.0};
124  double deplVoltage{0.0};
125  double biasVoltage{0.0};
126 
127  if (m_sctDefaults.value()) {
128  temperatureC = m_temperature.value();
129  deplVoltage = m_deplVoltage.value() * CLHEP::volt;
130  biasVoltage = m_biasVoltage.value() * CLHEP::volt;
131  } else {
132  temperatureC = m_siConditionsTool->temperature(elementHash, ctx);
133  deplVoltage = m_siConditionsTool->depletionVoltage(elementHash, ctx) * CLHEP::volt;
134  biasVoltage = m_siConditionsTool->biasVoltage(elementHash, ctx) * CLHEP::volt;
135  ATH_MSG_DEBUG("SCT Hash = " << elementHash << " Temperature = " << temperatureC << " [deg C], BiasV = " << biasVoltage << " DeplV = " << deplVoltage);
136  }
137 
138  // Protect against invalid temperature
139  if (not ((temperatureC>m_temperatureMin) and (temperatureC<m_temperatureMax))) {
140  temperatureC = m_temperature.value();
141  ATH_MSG_DEBUG("Invalid temperature: " << temperatureC << " C. " << "Setting to " << m_temperature.value() << " C. " << "Detector element hash: " << elementHash);
142  }
143  double temperature{temperatureC + Gaudi::Units::STP_Temperature}; // C -> K
144 
145  // Calculate depletion depth. If biasVoltage is less than depletionVoltage
146  // the detector is not fully depleted and we need to take this into account.
147  // We take absolute values just in case voltages are signed.
148  const InDetDD::SiDetectorElement* element{elements->getDetectorElement(elementHash)};
149  double depletionDepth{element->thickness()};
150  if (deplVoltage==0.0) {
151  ATH_MSG_WARNING("Depletion voltage in "<<__FILE__<<" is zero, which might be a bug.");
152  }
153  if (std::abs(biasVoltage) < std::abs(deplVoltage)) {
154  depletionDepth *= sqrt(std::abs(biasVoltage / deplVoltage));
155  }
156 
157  double meanElectricField{0.};
158  if (depletionDepth>0.) {
159  meanElectricField = biasVoltage / depletionDepth;
160  }
161  InDet::SiliconProperties siProperties;
162  siProperties.setConditions(temperature, meanElectricField);
163  double mobility{siProperties.signedHallMobility(element->carrierType())};
164 
165  // Get magnetic field. This first checks that field cache is valid.
166  Amg::Vector3D magneticField{getMagneticField(fieldCache, element)};
167 
168  // The angles are in the hit frame. This is because that is what is needed by the digization and also
169  // gives a more physical sign of the angle (ie dosen't flip sign when the detector is flipped).
170  // The hit depth axis is pointing from the readout side to the backside if m_design->readoutSide() < 0
171  // The hit depth axis is pointing from the backside to the readout side if m_design->readoutSide() > 0
172  double tanLorentzAnglePhi{element->design().readoutSide() * mobility * element->hitDepthDirection()
173  * element->hitPhiDirection() * (element->normal().cross(magneticField)).dot(element->phiAxis())};
174  writeCdo->setTanLorentzAngle(elementHash, tanLorentzAnglePhi);
175 
176  // This gives the effective correction in the reconstruction frame hence the extra hitPhiDirection()
177  // as the angle above is in the hit frame.
178  double lorentzCorrectionPhi{-0.5 * element->hitPhiDirection() * tanLorentzAnglePhi * depletionDepth};
179  writeCdo->setLorentzShift(elementHash, lorentzCorrectionPhi);
180 
181  // The Lorentz eta shift very small and so can be ignored, but we include it for completeness.
182  // In the SCT its largest in the stereo side of the barrel modules where it is about 0.3 micron along the strip.
183  double tanLorentzAngleEta{element->design().readoutSide() * mobility * element->hitDepthDirection()
184  * element->hitEtaDirection() * (element->normal().cross(magneticField)).dot(element->etaAxis())};
185  writeCdo->setTanLorentzAngleEta(elementHash, tanLorentzAngleEta);
186  double lorentzCorrectionEta{-0.5 * element->hitPhiDirection() * tanLorentzAngleEta * depletionDepth};
187  writeCdo->setLorentzShiftEta(elementHash, lorentzCorrectionEta);
188 
189  // Monitoring value
190  writeCdo->setBiasVoltage(elementHash, biasVoltage/CLHEP::volt);
191  writeCdo->setTemperature(elementHash, temperatureC);
192  writeCdo->setDepletionVoltage(elementHash, deplVoltage/CLHEP::volt);
193 
194  ATH_MSG_DEBUG("Hash = " << elementHash << " tanPhi = " << lorentzCorrectionPhi << " shiftPhi = " << writeCdo->getLorentzShift(elementHash) << "Depletion depth = " << depletionDepth);
195  ATH_MSG_VERBOSE("Temperature (C), bias voltage, depletion voltage: " << temperatureC << ", " << biasVoltage/CLHEP::volt << ", " << deplVoltage/CLHEP::volt);
196  ATH_MSG_VERBOSE("Depletion depth: " << depletionDepth/CLHEP::mm);
197  ATH_MSG_VERBOSE("Mobility (cm2/V/s): " << mobility/(CLHEP::cm2/CLHEP::volt/CLHEP::s));
198  ATH_MSG_VERBOSE("Magnetic Field (tesla): " << "(" << magneticField.x()/CLHEP::tesla << "," << magneticField.y()/CLHEP::tesla << "," << magneticField.z()/CLHEP::tesla << ")");
199  ATH_MSG_VERBOSE("LorentzShift, tanLorentzAngle = " << writeCdo->getLorentzShift(elementHash) << ", " << writeCdo->getTanLorentzAngle(elementHash));
200  ATH_MSG_VERBOSE("LorentzShiftEta, tanLorentzAngleEta = " << writeCdo->getLorentzShiftEta(elementHash) << ", " << writeCdo->getTanLorentzAngleEta(elementHash));
201  }
202 
203  // Record the output cond object
204  if (writeHandle.record(std::move(writeCdo)).isFailure()) {
205  ATH_MSG_FATAL("Could not record SiLorentzAngleCondData " << writeHandle.key()
206  << " with EventRange " << writeHandle.getRange() << " into Conditions Store");
207  return StatusCode::FAILURE;
208  }
209  ATH_MSG_INFO("recorded new CDO " << writeHandle.key() << " with range " << writeHandle.getRange() << " into Conditions Store");
210 
211  return StatusCode::SUCCESS;
212 }
213 
215 {
216  return StatusCode::SUCCESS;
217 }
218 
220 
221  if (m_useMagFieldCache.value()) {
222  Amg::Vector3D pointvec{element->center()};
223 
224  ATH_MSG_VERBOSE("Getting magnetic field from MT magnetic field service.");
225 
226  double point[3];
227  point[0] = pointvec[0];
228  point[1] = pointvec[1];
229  point[2] = pointvec[2];
230  double field[3];
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 }
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
SCTSiLorentzAngleCondAlg::initialize
virtual StatusCode initialize() override final
Definition: SCTSiLorentzAngleCondAlg.cxx:29
SCTSiLorentzAngleCondAlg::m_nominalField
DoubleProperty m_nominalField
Definition: SCTSiLorentzAngleCondAlg.h:65
SCT_DCSFloatCondData
Class for data object used in SCT_DCSConditions{HV,Temp}CondAlg, SCT_DCSConditionsTool,...
Definition: SCT_DCSFloatCondData.h:30
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
SCT_ID.h
This is an Identifier helper class for the SCT subdetector. This class is a factory for creating comp...
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
SCTSiLorentzAngleCondAlg::m_temperatureMin
DoubleProperty m_temperatureMin
Definition: SCTSiLorentzAngleCondAlg.h:61
InDetDD::SiDetectorElementCollection
Definition: SiDetectorElementCollection.h:30
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
AtlasFieldCacheCondObj
Definition: AtlasFieldCacheCondObj.h:19
python.PhysicalConstants.STP_Temperature
float STP_Temperature
Definition: PhysicalConstants.py:119
InDetDD::SolidStateDetectorElementBase::center
virtual const Amg::Vector3D & center() const override final
Center in global coordinates.
SCTSiLorentzAngleCondAlg::m_SCTDetEleCollKey
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_SCTDetEleCollKey
Definition: SCTSiLorentzAngleCondAlg.h:50
SCTSiLorentzAngleCondAlg::finalize
virtual StatusCode finalize() override final
Definition: SCTSiLorentzAngleCondAlg.cxx:214
ReadOfcFromCool.field
field
Definition: ReadOfcFromCool.py:48
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
SCTSiLorentzAngleCondAlg::m_temperature
DoubleProperty m_temperature
Definition: SCTSiLorentzAngleCondAlg.h:60
SCTSiLorentzAngleCondAlg::m_maxHash
unsigned int m_maxHash
Definition: SCTSiLorentzAngleCondAlg.h:70
AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::detStore
const ServiceHandle< StoreGateSvc > & detStore() const
The standard StoreGateSvc/DetectorStore Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:95
AthReentrantAlgorithm
An algorithm that can be simultaneously executed in multiple threads.
Definition: AthReentrantAlgorithm.h:83
SCTSiLorentzAngleCondAlg::m_useMagFieldCache
BooleanProperty m_useMagFieldCache
Definition: SCTSiLorentzAngleCondAlg.h:66
SCTSiLorentzAngleCondAlg::execute
virtual StatusCode execute(const EventContext &ctx) const override final
Definition: SCTSiLorentzAngleCondAlg.cxx:58
SCTSiLorentzAngleCondAlg::SCTSiLorentzAngleCondAlg
SCTSiLorentzAngleCondAlg(const std::string &name, ISvcLocator *pSvcLocator)
Definition: SCTSiLorentzAngleCondAlg.cxx:23
SCTSiLorentzAngleCondAlg::m_readKeyHV
SG::ReadCondHandleKey< SCT_DCSFloatCondData > m_readKeyHV
Definition: SCTSiLorentzAngleCondAlg.h:48
SCTSiLorentzAngleCondAlg::m_sctDefaults
BooleanProperty m_sctDefaults
Definition: SCTSiLorentzAngleCondAlg.h:68
SG::ReadCondHandle::retrieve
const_pointer_type retrieve()
Definition: ReadCondHandle.h:162
python.SystemOfUnits.cm2
int cm2
Definition: SystemOfUnits.py:88
InDetDD::SolidStateDetectorElementBase::thickness
double thickness() const
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
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
python.SystemOfUnits.volt
int volt
Definition: SystemOfUnits.py:204
SCTSiLorentzAngleCondAlg::m_siConditionsTool
ToolHandle< ISiliconConditionsTool > m_siConditionsTool
Definition: SCTSiLorentzAngleCondAlg.h:56
dot.dot
def dot(G, fn, nodesToHighlight=[])
Definition: dot.py:5
SCTSiLorentzAngleCondAlg::getMagneticField
Amg::Vector3D getMagneticField(MagField::AtlasFieldCache &fieldCache, const InDetDD::SiDetectorElement *element) const
Definition: SCTSiLorentzAngleCondAlg.cxx:219
SCTSiLorentzAngleCondAlg.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
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
SiDetectorElement.h
SCTSiLorentzAngleCondAlg::m_useGeoModel
BooleanProperty m_useGeoModel
Definition: SCTSiLorentzAngleCondAlg.h:69
python.SystemOfUnits.mm
int mm
Definition: SystemOfUnits.py:83
SCTSiLorentzAngleCondAlg::m_fieldCondObjInputKey
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCondObjInputKey
Definition: SCTSiLorentzAngleCondAlg.h:52
CaloCondBlobAlgs_fillNoiseFromASCII.hash
dictionary hash
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:109
SCT_ID
Definition: SCT_ID.h:68
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
SCTSiLorentzAngleCondAlg::m_biasVoltage
DoubleProperty m_biasVoltage
Definition: SCTSiLorentzAngleCondAlg.h:64
SCTSiLorentzAngleCondAlg::m_temperatureMax
DoubleProperty m_temperatureMax
Definition: SCTSiLorentzAngleCondAlg.h:62
MagField::AtlasFieldCache
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h)
Definition: AtlasFieldCache.h:43
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
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
SCTSiLorentzAngleCondAlg::m_deplVoltage
DoubleProperty m_deplVoltage
Definition: SCTSiLorentzAngleCondAlg.h:63
SCTSiLorentzAngleCondAlg::m_readKeyTemp
SG::ReadCondHandleKey< SCT_DCSFloatCondData > m_readKeyTemp
Definition: SCTSiLorentzAngleCondAlg.h:47
SG::WriteCondHandle
Definition: WriteCondHandle.h:26
SCTSiLorentzAngleCondAlg::m_writeKey
SG::WriteCondHandleKey< SiLorentzAngleCondData > m_writeKey
Definition: SCTSiLorentzAngleCondAlg.h:54
InDetDD::SiDetectorElementCollection::getDetectorElement
const SiDetectorElement * getDetectorElement(const IdentifierHash &hash) const
Definition: SiDetectorElementCollection.cxx:15
InDet::SiliconProperties::setConditions
void setConditions(double temperature, double electricField)
Definition: SiliconProperties.cxx:71
SiliconProperties.h