ATLAS Offline Software
Loading...
Searching...
No Matches
PixelSiLorentzAngleCondAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include "GaudiKernel/PhysicalConstants.h"
9
13
14PixelSiLorentzAngleCondAlg::PixelSiLorentzAngleCondAlg(const std::string& name, ISvcLocator* pSvcLocator):
15 ::AthCondAlgorithm(name, pSvcLocator)
16{
17}
18
20 ATH_MSG_DEBUG("PixelSiLorentzAngleCondAlg::initialize()");
21
22 const PixelID* idHelper{nullptr};
23 ATH_CHECK(detStore()->retrieve(idHelper, m_pixelIDName.value()));
24
25 m_maxHash = idHelper->wafer_hash_max();
26
27 ATH_CHECK(m_readKeyTemp.initialize());
28 ATH_CHECK(m_readKeyHV.initialize());
29 ATH_CHECK(m_writeKey.initialize());
30
31 ATH_CHECK(m_siPropertiesTool.retrieve());
32
35
36 ATH_CHECK(m_pixelDetEleCollKey.initialize());
37
38 if(m_disable3D) ATH_MSG_INFO("Running with Lorentz correction disabled for 3D pixels");
39
40 return StatusCode::SUCCESS;
41}
42
44StatusCode
45PixelSiLorentzAngleCondAlg::execute(const EventContext& ctx) const {
47
48 ATH_MSG_DEBUG("PixelSiLorentzAngleCondAlg::execute()");
49
51 if (writeHandle.isValid()) {
52 ATH_MSG_DEBUG("CondHandle " << writeHandle.fullKey() << " is already valid." << " In theory this should not be called, but may happen" << " if multiple concurrent events are being processed out of order.");
53 return StatusCode::SUCCESS;
54 }
55
56 // Read Cond Handle (temperature)
58 const PixelDCSTempData* readCdoTemp(*readHandleTemp);
59 if (readCdoTemp==nullptr) {
60 ATH_MSG_FATAL("Null pointer to the read conditions object");
61 return StatusCode::FAILURE;
62 }
63 writeHandle.addDependency(readHandleTemp);
64 ATH_MSG_DEBUG("Input is " << readHandleTemp.fullKey() << " with the range of " << readHandleTemp.getRange());
65
66 // Read Cond Handle (HV)
68 const PixelDCSHVData* readCdoHV(*readHandleHV);
69 if (readCdoHV==nullptr) {
70 ATH_MSG_FATAL("Null pointer to the read conditions object");
71 return StatusCode::FAILURE;
72 }
73 writeHandle.addDependency(readHandleHV);
74 ATH_MSG_DEBUG("Input is " << readHandleHV.fullKey() << " with the range of " << readHandleHV.getRange());
75
76 // Field cache object for field calculations
80 // Get field cache object
82 const AtlasFieldCacheCondObj* fieldCondObj{*readHandleField};
83
84 if (fieldCondObj == nullptr) {
85 ATH_MSG_ERROR("PixelSiLorentzAngleCondAlg: Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCondObjInputKey.key());
86 return StatusCode::FAILURE;
87 }
88 //WL: The previous implementation didn't intersect the range of this readHanlde.
89 //I suspect that was a bug.
90 writeHandle.addDependency(readHandleField);
91 fieldCondObj->getInitializedCache (fieldCache);
93
94 if (m_useMagFieldDcs) {
95 // Read Cond Handle (B field sensor)
97 const CondAttrListCollection* readCdoBFieldSensor(*readHandleBFieldSensor);
98 if (readCdoBFieldSensor==nullptr) {
99 ATH_MSG_FATAL("Null pointer to the read conditions object");
100 return StatusCode::FAILURE;
101 }
102 writeHandle.addDependency(readHandleBFieldSensor);
103 ATH_MSG_DEBUG("Input is " << readHandleBFieldSensor.fullKey() << " with the range of " << readHandleBFieldSensor.getRange() );
104
105 }//end if useMagFieldDcs
106 }//end if useMagFieldSvc
107
108
110 const InDetDD::SiDetectorElementCollection* elements(pixelDetEle.retrieve());
111 if (elements==nullptr) {
112 ATH_MSG_FATAL(m_pixelDetEleCollKey.fullKey() << " could not be retrieved");
113 return StatusCode::FAILURE;
114 }
115 writeHandle.addDependency(pixelDetEle);
116
117 // Construct the output Cond Object and fill it in
118 std::unique_ptr<SiLorentzAngleCondData> writeCdo{std::make_unique<SiLorentzAngleCondData>()};
119 const PixelID::size_type wafer_hash_max = m_maxHash;
120 writeCdo->resize(wafer_hash_max);
121 for (PixelID::size_type hash = 0; hash < wafer_hash_max; hash++) {
122 const IdentifierHash elementHash = static_cast<IdentifierHash::value_type>(hash);
123
124 double temperature = readCdoTemp->getTemperature(elementHash)+273.15;
125 double deplVoltage = 0.0*CLHEP::volt;
126 double biasVoltage = readCdoHV->getBiasVoltage(elementHash)*CLHEP::volt;
127
128 ATH_MSG_DEBUG("Pixel Hash = " << elementHash << " Temperature = " << temperature << " [deg K], BiasV = " << biasVoltage << " DeplV = " << deplVoltage);
129
130 const InDetDD::SiDetectorElement* element = elements->getDetectorElement(elementHash);
131 double depletionDepth = element->thickness();
132 if (std::fabs(biasVoltage) < std::fabs(deplVoltage)) {
133 depletionDepth *= std::sqrt(std::fabs(biasVoltage/deplVoltage));
134 }
135
136 const InDetDD::PixelModuleDesign* p_design = dynamic_cast<const InDetDD::PixelModuleDesign*>(&element->design());
137
138 if (not p_design){
139 ATH_MSG_FATAL("Dynamic cast to PixelModuleDesign* failed in PixelSiLorentzAngleCondAlg::execute");
140 return StatusCode::FAILURE;
141 }
142 double forceLorentzToZero = 1.0;
143 if ((p_design->getReadoutTechnology()==InDetDD::PixelReadoutTechnology::FEI4 && p_design->numberOfCircuits()==1 && p_design->rowsPerCircuit()>100) // IBL 3D
144 || (m_disable3D && p_design->is3D())) { // ITk L0 + L0.5
145 forceLorentzToZero = 0.0;
146 }
147
148 const InDet::SiliconProperties &siProperties = m_siPropertiesTool->getSiProperties(elementHash, ctx);
149 double mobility = siProperties.signedHallMobility(element->carrierType());
150
151 // Get magnetic field. This first checks that field cache is valid.
152 Amg::Vector3D magneticField = getMagneticField(fieldCache,element);
153
154 // The angles are in the hit frame. This is because that is what is needed by the digization and also
155 // gives a more physical sign of the angle (ie dosen't flip sign when the detector is flipped).
156 // The hit depth axis is pointing from the readout side to the backside if m_design->readoutSide() < 0
157 // The hit depth axis is pointing from the backside to the readout side if m_design->readoutSide() > 0
158 double tanLorentzAnglePhi = forceLorentzToZero*element->design().readoutSide()*mobility*element->hitDepthDirection()*element->hitPhiDirection()*(element->normal().cross(magneticField)).dot(element->phiAxis());
159 writeCdo->setTanLorentzAngle(elementHash, tanLorentzAnglePhi);
160
161 // This gives the effective correction in the reconstruction frame hence the extra hitPhiDirection()
162 // as the angle above is in the hit frame.
163 double lorentzCorrectionPhi = -0.5*element->hitPhiDirection()*tanLorentzAnglePhi*depletionDepth;
164 writeCdo->setLorentzShift(elementHash, lorentzCorrectionPhi);
165
166 // The Lorentz eta shift very small and so can be ignored, but we include it for completeness.
167 double tanLorentzAngleEta = forceLorentzToZero*element->design().readoutSide()*mobility*element->hitDepthDirection()*element->hitEtaDirection()*(element->normal().cross(magneticField)).dot(element->etaAxis());
168 writeCdo->setTanLorentzAngleEta(elementHash, tanLorentzAngleEta);
169 double lorentzCorrectionEta = -0.5*element->hitPhiDirection()*tanLorentzAngleEta*depletionDepth;
170 writeCdo->setLorentzShiftEta(elementHash, lorentzCorrectionEta);
171
172 // Monitoring value
173 writeCdo->setBiasVoltage(elementHash, biasVoltage/CLHEP::volt);
174 writeCdo->setTemperature(elementHash, temperature-273.15);
175 writeCdo->setDepletionVoltage(elementHash, deplVoltage/CLHEP::volt);
176
177 ATH_MSG_DEBUG("Hash = " << elementHash << " tanPhi = " << lorentzCorrectionPhi << " shiftPhi = " << writeCdo->getLorentzShift(elementHash) << " Factor = 1.0 Depletion depth = " << depletionDepth);
178 ATH_MSG_DEBUG("Hash = " << elementHash << " tanPhi = " << lorentzCorrectionPhi << " shiftPhi = " << writeCdo->getLorentzShift(elementHash) << "Depletion depth = " << depletionDepth);
179 ATH_MSG_VERBOSE("Temperature (C), bias voltage, depletion voltage: " << temperature-273.15 << ", " << biasVoltage/CLHEP::volt << ", " << deplVoltage/CLHEP::volt);
180 ATH_MSG_VERBOSE("Depletion depth: " << depletionDepth/CLHEP::mm);
181 ATH_MSG_VERBOSE("Mobility (cm2/V/s): " << mobility/(CLHEP::cm2/CLHEP::volt/CLHEP::s));
182 ATH_MSG_VERBOSE("Magnetic Field (tesla): " << "(" << magneticField.x()/CLHEP::tesla << "," << magneticField.y()/CLHEP::tesla << "," << magneticField.z()/CLHEP::tesla << ")");
183 ATH_MSG_VERBOSE("LorentzShift, tanLorentzAngle = " << writeCdo->getLorentzShift(elementHash) << ", " << writeCdo->getTanLorentzAngle(elementHash));
184 ATH_MSG_VERBOSE("LorentzShiftEta, tanLorentzAngleEta = " << writeCdo->getLorentzShiftEta(elementHash) << ", " << writeCdo->getTanLorentzAngleEta(elementHash));
185 }
186
187 // Record the output cond object
188 if (writeHandle.record(std::move(writeCdo)).isFailure()) {
189 ATH_MSG_FATAL("Could not record SiLorentzAngleCondData " << writeHandle.key() << " with EventRange " << writeHandle.getRange() << " into Conditions Store");
190 return StatusCode::FAILURE;
191 }
192
193 ATH_MSG_DEBUG("recorded new CDO " << writeHandle.key() << " with range " << writeHandle.getRange() << " into Conditions Store");
194
195 return StatusCode::SUCCESS;
196}
197
199 ATH_MSG_DEBUG("PixelSiLorentzAngleCondAlg::finalize()");
200 return StatusCode::SUCCESS;
201}
202
204 if (m_useMagFieldCache) {
205 ATH_MSG_VERBOSE("Getting magnetic field from MT magnetic field service.");
206 double field[3]; //in/out parameter
207 fieldCache.getField(element->center().data(), field);
208 return Amg::Vector3D(field[0], field[1], field[2]);
209 }
210 else {
211 ATH_MSG_VERBOSE("Using Nominal Field");
212 return Amg::Vector3D(0., 0., m_nominalField);
213 }
214}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
This is an Identifier helper class for the Pixel subdetector.
const ServiceHandle< StoreGateSvc > & detStore() const
Base class for conditions algorithms.
void getInitializedCache(MagField::AtlasFieldCache &cache) const
get B field cache for evaluation as a function of 2-d or 3-d position.
This class is a collection of AttributeLists where each one is associated with a channel number.
This is a "hash" representation of an Identifier.
unsigned int value_type
int readoutSide() const
ReadoutSide.
Class used to describe the design of a module (diode segmentation and readout scheme)
PixelReadoutTechnology getReadoutTechnology() const
int rowsPerCircuit() const
Number of cell rows per circuit:
int numberOfCircuits() const
Total number of circuits:
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 SiDetectorDesign & design() const override final
access to the local description (inline):
InDetDD::CarrierType carrierType() const
carrier type for readout.
double hitPhiDirection() const
See previous method.
virtual const Amg::Vector3D & normal() const override final
Get reconstruction local normal axes in global frame.
virtual const Amg::Vector3D & center() const override final
Center in global coordinates.
double hitDepthDirection() const
Directions of hit depth,phi,eta axes relative to reconstruction local position axes (LocalPosition).
double hitEtaDirection() const
See previous method.
double signedHallMobility(InDetDD::CarrierType carrier) const
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h)
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,...
float getBiasVoltage(const int chanNum) const
float getTemperature(int chanNum) const
This is an Identifier helper class for the Pixel subdetector.
Definition PixelID.h:67
size_type wafer_hash_max() const
Definition PixelID.cxx:801
Identifier::size_type size_type
Definition PixelID.h:71
Gaudi::Property< std::string > m_pixelIDName
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_pixelDetEleCollKey
virtual StatusCode execute(const EventContext &ctx) const override
SG::ReadCondHandleKey< PixelDCSHVData > m_readKeyHV
Amg::Vector3D getMagneticField(MagField::AtlasFieldCache &m_fieldCache, const InDetDD::SiDetectorElement *element) const
SG::WriteCondHandleKey< SiLorentzAngleCondData > m_writeKey
SG::ReadCondHandleKey< CondAttrListCollection > m_readKeyBFieldSensor
virtual StatusCode finalize() override
ToolHandle< ISiPropertiesTool > m_siPropertiesTool
virtual StatusCode initialize() override
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCondObjInputKey
PixelSiLorentzAngleCondAlg(const std::string &name, ISvcLocator *pSvcLocator)
SG::ReadCondHandleKey< PixelDCSTempData > m_readKeyTemp
const_pointer_type retrieve()
const DataObjID & fullKey() const
const EventIDRange & getRange()
const std::string & key() const
void addDependency(const EventIDRange &range)
const EventIDRange & getRange() const
StatusCode record(const EventIDRange &range, T *t)
record handle, with explicit range DEPRECATED
const DataObjID & fullKey() const
Eigen::Matrix< double, 3, 1 > Vector3D