ATLAS Offline Software
Loading...
Searching...
No Matches
PixelDistortionAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6#include "GaudiKernel/EventIDRange.h"
7
8// Random Number Generation
10#include "CLHEP/Random/RandomEngine.h"
11
12#include "CLHEP/Random/RandGaussZiggurat.h"
14#include "CLHEP/Units/SystemOfUnits.h"
16#include <cmath>
17
18#include <cstdint>
19#include <istream>
20#include <map>
21#include <string>
22
23PixelDistortionAlg::PixelDistortionAlg(const std::string& name, ISvcLocator* pSvcLocator):
24 ::AthCondAlgorithm(name, pSvcLocator)
25{
26}
27
29 ATH_MSG_DEBUG("PixelDistortionAlg::initialize()");
30
31 ATH_CHECK(detStore()->retrieve(m_pixelID,"PixelID"));
32
33 ATH_CHECK(m_rndmSvc.retrieve());
34 ATH_CHECK(m_readKey.initialize());
35 ATH_CHECK(m_writeKey.initialize());
36
37 return StatusCode::SUCCESS;
38}
39
40StatusCode PixelDistortionAlg::execute(const EventContext& ctx) const {
41 ATH_MSG_DEBUG("PixelDistortionAlg::execute(const EventContext& ctx) const");
42
44 if (writeHandle.isValid()) {
45 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.");
46 return StatusCode::SUCCESS;
47 }
48
49 // Construct the output Cond Object and fill it in
50 std::unique_ptr<PixelDistortionData> writeCdo(std::make_unique<PixelDistortionData>());
51
52
53
54 constexpr int nmodule_max = 2048;
55 std::unordered_map<uint32_t,std::vector<float>> distortionMap;
56 std::unordered_map<uint32_t,unsigned long long> ids;
57 if (m_distortionInputSource==0) { // no bow correction
58 ATH_MSG_DEBUG("No bow correction");
59 writeCdo -> setVersion(m_distortionVersion);
60 for (int i=0; i<nmodule_max; i++) {
61 distortionMap[i].push_back(0.0);
62 distortionMap[i].push_back(0.0);
63 distortionMap[i].push_back(0.0);
64 }
65 }
66 else if (m_distortionInputSource==1) { // constant bow
67 ATH_MSG_DEBUG("Using constant pixel distortions ");
68 writeCdo -> setVersion(m_distortionVersion);
69 for (int i=0; i<nmodule_max; i++) {
70 distortionMap[i].push_back(0.1); // 1/mm
71 distortionMap[i].push_back(0.1); // 1/mm
72 distortionMap[i].push_back(2.0*std::atan(0.0005)/CLHEP::degree); // convert to degree
73 }
74 }
75 else if (m_distortionInputSource==2) { // read from file
76 const std::string &file_name = m_inputFileName;
77 if (file_name.empty()) {
78 ATH_MSG_ERROR("Distortion filename is empty not found! No pixel distortion will be applied.");
79 return StatusCode::FAILURE;
80 }
81
82 ATH_MSG_DEBUG("Reading pixel distortions from file: " << file_name);
83 writeCdo -> setVersion(m_distortionVersion);
84
85 if (file_name[0] != '/') {
86 PathResolver::find_file(file_name, "DATAPATH");
87 }
88 std::ifstream input(file_name);
89 if (!input.good()) {
90 ATH_MSG_ERROR("Cannot open " << file_name);
91 return StatusCode::FAILURE;
92 }
93
94 int distosize;
95 if (m_distortionVersion < 2) distosize = 3;
96 else distosize = 441;
97
98 while (!input.eof()) {
99 unsigned int idmod{};
100 unsigned int hashID {};
101 float data{};
102
103 if (m_distortionVersion == 1) {
104 input >> idmod;
105 hashID = idmod;
106 } else {
107 input >> std::hex >> idmod >> std::dec;
108 hashID = m_pixelID->wafer_hash((Identifier)idmod);
109 }
110 //Values read in from file should be tested to ensure they are within sensible limits
111 //we assume however that the file is a trusted source.
112 //coverity[TAINTED_SCALAR]
113 Identifier modId = m_pixelID->wafer_id((IdentifierHash)hashID);
114 ids[hashID] = modId.get_compact();
115 ATH_MSG_DEBUG("Identifier = 0x" << std::hex << ids[hashID] << std::dec);
116
117 std::stringstream s;
118 for (int i = 0; i < distosize; ++i) {
119 input >> data;
120 s << data << " ";
121 distortionMap[hashID].push_back(data);
122 }
123 ATH_MSG_DEBUG(s.str());
124 }
125 input.close();
126 }
127 else if (m_distortionInputSource==3) { // random generation
128 ATH_MSG_DEBUG("Using random pixel distortions");
129 writeCdo -> setVersion(m_distortionVersion);
130
131 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this);
132 CLHEP::HepRandomEngine *rndmEngine = rngWrapper->getEngine(ctx);
133 //these numbers could become properties, but seems unnecessary now (they are the same in all cases):
134 constexpr double distortionMeanR{0.12/CLHEP::meter};
135 constexpr double distortionRMSR{0.08};
136 constexpr double distortionMeanTwist{-0.0005};
137
138 for (int i=0; i<nmodule_max; i++) {
139 float r1 = CLHEP::RandGaussZiggurat::shoot(rndmEngine,distortionMeanR,distortionRMSR);
140 float r2 = CLHEP::RandGaussZiggurat::shoot(rndmEngine,r1,distortionRMSR/10.);//to implement a correlation between distortions on 2 sides of the module
141 float twist = CLHEP::RandGaussZiggurat::shoot(rndmEngine,distortionMeanTwist,distortionMeanTwist);
142 distortionMap[i].push_back(r1*CLHEP::meter); // convert to 1/mm
143 distortionMap[i].push_back(r2*CLHEP::meter); // convert to 1/mm
144 distortionMap[i].push_back(2.0*std::atan(twist)/CLHEP::degree); // convert to degree
145 }
146 }
147 else if (m_distortionInputSource==4) { // read from database here
148 ATH_MSG_DEBUG("Using pixel distortions from database");
150 const DetCondCFloat* readCdo = *readHandle;
151 if (readCdo==nullptr) {
152 ATH_MSG_FATAL("Null pointer to the read conditions object");
153 return StatusCode::FAILURE;
154 }
155 // Get the validitiy range
156 ATH_MSG_DEBUG("Size of DetCondCFloat " << readHandle.fullKey() << " readCdo->size()= " << readCdo->size());
157
158 int version = 0;
159 if (readCdo->tag()=="/Indet/PixelDist") {
160 version = 0; // For reproducing bug in earlier versions for backward compatibility
161 ATH_MSG_INFO("Detected old version of pixel distortions data.");
162 }
163 else {
164 bool gotVersion = false;
165 // Get version number, expecting string to have the form /Indet/PixelDist_v#
166 // If not recongnized will default to latest version.
167 std::string baseStr = "/Indet/PixelDist_v";
168 if (readCdo->tag().compare(0,baseStr.size(),baseStr)==0) {
169 std::istringstream istr(readCdo->tag().substr(baseStr.size()));
170 int version_tmp = 0;
171 istr >> version_tmp;
172 if (istr.eof()) { // Should be have read whole stream if its a number
173 version = version_tmp;
174 gotVersion = true;
175 }
176 }
177 if (!gotVersion) {
178 ATH_MSG_WARNING("Unable to determine version number of pixel distortions data. Version string: " << readCdo->tag());
179 }
180 }
181 writeCdo -> setVersion(version);
182 ATH_MSG_DEBUG("Distortions data version = " << version);
183
184 int distosize = readCdo->size();
185
186 for (int i=0; i<nmodule_max; i++) {
187 if (readCdo->find(m_pixelID->wafer_id(IdentifierHash(i)))) {
188 Identifier modId = m_pixelID->wafer_id((IdentifierHash)i);
189 const float *disto = readCdo->find(modId);
190 ids[i] = modId.get_compact();
191
192 ATH_MSG_DEBUG("Identifier = 0x" << std::hex << ids[i] << std::dec);
193 std::stringstream s;
194 for (int j = 0; j < distosize; ++j) {
195 distortionMap[i].push_back(disto[j]);
196 s << disto[j] << " ";
197 }
198 ATH_MSG_DEBUG(s.str());
199 }
200 }
201 }
202 writeCdo -> setDistortionMap(distortionMap);
203 writeCdo -> setIds(ids);
204
205 if (m_writeToFile) {
206 std::ofstream* outfile = new std::ofstream("output_distortion.txt");
207 for (int i=0; i<nmodule_max; i++) {
208 if (!distortionMap[i].empty()) {
209 if (m_distortionVersion==0) {
210 *outfile << m_pixelID->wafer_id(IdentifierHash(i)) << " " << distortionMap[i].at(0) << " " << distortionMap[i].at(1) << " " << distortionMap[i].at(2) << std::endl;
211 }
212 else if (m_distortionVersion>0) {
213 *outfile << i << " " << distortionMap[i].at(0) << " " << distortionMap[i].at(1) << " " << distortionMap[i].at(2) << std::endl;
214 }
215 }
216 }
217 outfile->close();
218 delete outfile;
219 }
220
221 const EventIDBase start{EventIDBase::UNDEFNUM, EventIDBase::UNDEFEVT, 0, 0, EventIDBase::UNDEFNUM, EventIDBase::UNDEFNUM};
222 const EventIDBase stop {EventIDBase::UNDEFNUM, EventIDBase::UNDEFEVT, EventIDBase::UNDEFNUM-1, EventIDBase::UNDEFNUM-1, EventIDBase::UNDEFNUM, EventIDBase::UNDEFNUM};
223 const EventIDRange rangeW{start, stop};
224
225 if (writeHandle.record(rangeW, std::move(writeCdo)).isFailure()) {
226 ATH_MSG_FATAL("Could not record PixelDistortionData " << writeHandle.key() << " with EventRange " << rangeW << " into Conditions Store");
227 return StatusCode::FAILURE;
228 }
229 ATH_MSG_DEBUG("recorded new CDO " << writeHandle.key() << " with range " << rangeW << " into Conditions Store");
230
231 return StatusCode::SUCCESS;
232}
233
#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_WARNING(x)
#define ATH_MSG_DEBUG(x)
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
This is an Identifier helper class for the Pixel subdetector.
static const Attributes_t empty
A wrapper class for event-slot-local random engines.
Definition RNGWrapper.h:56
CLHEP::HepRandomEngine * getEngine(const EventContext &ctx) const
Retrieve the random engine corresponding to the provided EventContext.
Definition RNGWrapper.h:134
const ServiceHandle< StoreGateSvc > & detStore() const
Base class for conditions algorithms.
DetCondCFloat is a class to hold sets of Identifiers and arrays of floats for detector element specif...
const std::string & tag() const
const float * find(const Identifier &ident) const
int size() const
This is a "hash" representation of an Identifier.
value_type get_compact() const
Get the compact id.
static std::string find_file(const std::string &logical_file_name, const std::string &search_path)
Gaudi::Property< int > m_distortionVersion
virtual StatusCode execute(const EventContext &ctx) const override
PixelDistortionAlg(const std::string &name, ISvcLocator *pSvcLocator)
Gaudi::Property< std::string > m_inputFileName
SG::ReadCondHandleKey< DetCondCFloat > m_readKey
ServiceHandle< IAthRNGSvc > m_rndmSvc
Random number service.
SG::WriteCondHandleKey< PixelDistortionData > m_writeKey
virtual StatusCode initialize() override
Gaudi::Property< bool > m_writeToFile
const PixelID * m_pixelID
Gaudi::Property< int > m_distortionInputSource
const DataObjID & fullKey() const
const std::string & key() const
StatusCode record(const EventIDRange &range, T *t)
record handle, with explicit range DEPRECATED
const DataObjID & fullKey() const