ATLAS Offline Software
Loading...
Searching...
No Matches
SiHitCollectionCnv_p4.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
10
11#include <cmath>
12
13//CLHEP
14#include "CLHEP/Geometry/Point3D.h"
15// Gaudi
16#include "GaudiKernel/MsgStream.h"
17#include "GaudiKernel/ThreadLocalContext.h"
18
19// Athena
22
23// * * * stolen from eflowRec * * * //
24inline double phicorr(double a)
25{
26 if (a <= -M_PI)
27 {
28 return a+(2*M_PI*floor(-(a-M_PI)/(2*M_PI)));
29 }
30 else if (a > M_PI)
31 {
32 return a-(2*M_PI*floor((a+M_PI)/(2*M_PI)));
33 }
34 else
35 {
36 return a;
37 }
38}
39
40// * * * stolen from eflowRec * * * //
41inline double cycle(double a, double b)
42{
43 double del = b-a;
44 if (del > M_PI)
45 {
46 return a+2.0*M_PI;
47 }
48 else if (del < -M_PI)
49 {
50 return a-2.0*M_PI;
51 }
52 else
53 {
54 return a;
55 }
56}
57
58
59const double SiHitCollectionCnv_p4::m_persEneUnit = 1.0e-5;
60const double SiHitCollectionCnv_p4::m_persLenUnit = 1.0e-5;
61const double SiHitCollectionCnv_p4::m_persAngUnit = 1.0e-5;
62const double SiHitCollectionCnv_p4::m_2bHalfMaximum = pow(2.0, 15.0);
63const int SiHitCollectionCnv_p4::m_2bMaximum = (unsigned short)(-1);
64
65
66void SiHitCollectionCnv_p4::transToPers(const SiHitCollection* transCont, SiHitCollection_p4* persCont, MsgStream &log)
67{
68 // Finds hits belonging to a "string" (in which the end point of one hit is the same as the start point of the next) and
69 // persistifies the end point of each hit plus the start point of the first hit in each string.
70 //
71 // Further compression is achieved by optimising the storage of the position vectors:- start (x,y,z) and (theta,phi) of
72 // first hit are stored as floats, (delta_theta,delta_phi) relative to the fisrst hit are stored as 2 byte numbers and
73 // used to specify the hit direction. All hit lengths are stored as 2 byte numbers.
74 //
75 // Additional savings are achieved by storing the energy loss for each hit as a 2 byte number and only storing the mean
76 // time of the first hit per string.
77 //
78 // See http://indico.cern.ch/getFile.py/access?contribId=11&resId=2&materialId=slides&confId=30893 for more info.
79
80 static const double dRcut = 1.0e-7;
81 static const double dTcut = 1.0;
82
84 int lastIndex{-1};
85 int lastTruthId{-1};
86 int lastId = -1;
87 double stringFirstTheta = 0.0;
88 double stringFirstPhi = 0.0;
89 double lastT = 0.0;
90 double persSumE = 0.0;
91 double transSumE = 0.0;
92 unsigned int idx = 0;
93 unsigned int endTruthID = 0;
94 unsigned int endId = 0;
95 unsigned int endHit = 0;
96 HepGeom::Point3D<double> lastTransEnd(0.0, 0.0, 0.0);
97 HepGeom::Point3D<double> lastPersEnd(0.0, 0.0, 0.0);
98
99 for (SiHitCollection::const_iterator it = transCont->begin(); it != transCont->end(); ++it) {
100
102 const HepMcParticleLink * currentLink = &(siHit->particleLink());
103 const int truthId = currentLink->id();
104 const char truthSupp= currentLink->getTruthSuppressionTypeAsChar();
105 int index{0};
107 proxy).at(0) != 0) {
108 index = currentLink->eventIndex();
109 }
110
111 if ( lastTruthId != truthId || lastIndex != index || (idx-endTruthID)==USHRT_MAX ) {
112 lastTruthId = truthId;
113 lastIndex = index;
114 const unsigned short persIndex = static_cast<unsigned short>(index);
115 if (static_cast<HepMcParticleLink::index_type>(lastIndex) != static_cast<HepMcParticleLink::index_type>(persIndex)) {
116 log << MSG::WARNING << "Attempting to persistify an eventIndex larger than max unsigned short!" << endmsg;
117 }
118 // store truthId and eventIndex once for set of consecutive hits
119 // with the same truthId and eventIndex.
120 persCont->m_truthID.push_back(static_cast<unsigned long>(truthId));
121 persCont->m_mcEvtIndex.push_back(persIndex);
122 persCont->m_truthSupp.push_back(truthSupp); // TODO include this in the equality check above?
123 if (idx > 0) {
124 persCont->m_nTruthID.push_back(idx - endTruthID);
125 endTruthID = idx;
126 }
127 }
128
129 if ( ( (int)siHit->identify() != lastId ) || (idx-endId)==USHRT_MAX) {
130
131 // store SiHitIdentifier once for set of consecutive hits with
132 // the same SiHitIdentifier
133
134 lastId = siHit->identify();
135 persCont->m_id.push_back(lastId);
136
137 if (idx > 0) {
138 persCont->m_nId.push_back(idx - endId);
139 endId = idx;
140 }
141 }
142
143 HepGeom::Point3D<double> st = siHit->localStartPosition();
144 HepGeom::Point3D<double> en = siHit->localEndPosition();
145
146 const double dx = st.x() - lastTransEnd.x();
147 const double dy = st.y() - lastTransEnd.y();
148 const double dz = st.z() - lastTransEnd.z();
149 const double t = siHit->meanTime();
150
151 const double dRLast = sqrt(dx * dx + dy * dy + dz * dz); // dR between end of previous hit and start of current one
152 const double dTLast = fabs(t - lastT);
153
154 CLHEP::Hep3Vector direction(0.0, 0.0, 0.0);
155 double theta = 0.0;
156 double phi = 0.0;
157 bool startNewString = (dRLast >= dRcut || dTLast >= dTcut || (idx - endHit) == USHRT_MAX);
158
159 if (!startNewString) {
160
161 // hit is part of existing string
162
163 direction = CLHEP::Hep3Vector( en.x() - lastPersEnd.x(), en.y() - lastPersEnd.y(), en.z() - lastPersEnd.z() );
164
165 theta = direction.theta();
166 phi = phicorr( direction.phi() );
167
168 const int dTheta_2b = (int)( (theta - stringFirstTheta) / m_persAngUnit + m_2bHalfMaximum + 0.5 );
169 const int dPhi_2b = (int)( (cycle(phi, stringFirstPhi) - stringFirstPhi) / m_persAngUnit + m_2bHalfMaximum + 0.5 );
170
171 if ( dTheta_2b < m_2bMaximum && dTheta_2b >= 0 && dPhi_2b < m_2bMaximum && dPhi_2b >= 0) {
172 persCont->m_dTheta.push_back(dTheta_2b);
173 persCont->m_dPhi.push_back(dPhi_2b);
174 theta = stringFirstTheta + ( (double)dTheta_2b - m_2bHalfMaximum ) * m_persAngUnit;
175 phi = stringFirstPhi + ( (double)dPhi_2b - m_2bHalfMaximum ) * m_persAngUnit;
176 phi = phicorr(phi);
177 }
178 else {
179 startNewString = true;
180 }
181 }
182
183 if (startNewString) {
184
185 // begin new hit string
186
187 direction = CLHEP::Hep3Vector( en.x() - st.x(), en.y() - st.y(), en.z() - st.z() );
188
189 theta = direction.theta();
190 phi = phicorr( direction.phi() );
191
192 persCont->m_hit1_meanTime.push_back(t);
193 persCont->m_hit1_x0.push_back(st.x());
194 persCont->m_hit1_y0.push_back(st.y());
195 persCont->m_hit1_z0.push_back(st.z());
196 persCont->m_hit1_theta.push_back(theta);
197 persCont->m_hit1_phi.push_back(phi);
198
199 lastPersEnd = HepGeom::Point3D<double>(st.x(), st.y(), st.z());
200
201 stringFirstTheta = theta;
202 stringFirstPhi = phi;
203
204 if (idx > 0) {
205 persCont->m_nHits.push_back(idx - endHit);
206 endHit = idx;
207 }
208 }
209
210 lastTransEnd = HepGeom::Point3D<double>(en.x(), en.y(), en.z());
211 transSumE += siHit->energyLoss();
212
213 const int eneLoss_2b = (int)((transSumE - persSumE) / m_persEneUnit + 0.5); // calculated to allow recovery sum over
214 // whole hit string to chosen precision
215
216 const int hitLength_2b = (int)(direction.mag() / m_persLenUnit + 0.5); // calculated to give the correct position to
217 // the chosen precision, NOT the length of the
218 // hit (small difference in practice).
219 double eneLoss = 0.0;
220
221 if (eneLoss_2b >= m_2bMaximum) {
222 eneLoss = siHit->energyLoss();
223 persCont->m_hitEne_2b.push_back(m_2bMaximum);
224 persCont->m_hitEne_4b.push_back(eneLoss);
225 }
226 else {
227 eneLoss = eneLoss_2b * m_persEneUnit;
228 persCont->m_hitEne_2b.push_back(eneLoss_2b);
229 }
230
231 double length = 0.0;
232
233 if (hitLength_2b >= m_2bMaximum) {
234 length = direction.mag();
235 persCont->m_hitLength_2b.push_back(m_2bMaximum);
236 persCont->m_hitLength_4b.push_back(direction.mag());
237 }
238 else {
239 length = hitLength_2b * m_persLenUnit;
240 persCont->m_hitLength_2b.push_back(hitLength_2b);
241 }
242
243 CLHEP::Hep3Vector persDir(length, 0.0, 0.0);
244 persDir.setTheta(theta);
245 persDir.setPhi(phi);
246
247 lastPersEnd = (CLHEP::Hep3Vector)lastPersEnd + persDir;
248 persSumE += eneLoss;
249 lastT = t;
250
251 ++idx;
252 }
253
254 persCont->m_nTruthID.push_back(idx - endTruthID);
255 persCont->m_nId.push_back(idx - endId);
256 persCont->m_nHits.push_back(idx - endHit);
257#ifdef ENABLE_SANITY_CHECKS
258 // Sanity check
259 const unsigned int init(0);
260 const unsigned int transContSize = transCont->size();
261 if (std::accumulate(persCont->m_nTruthID.begin(), persCont->m_nTruthID.end(), init)!=transContSize) {
262 log << MSG::ERROR << "transToPers: sum of entries of persCont->m_nTruthID (" << std::accumulate(persCont->m_nTruthID.begin(), persCont->m_nTruthID.end(), init) << ") does not match transient container size = " << transContSize << endmsg;
263 }
264 if (std::accumulate(persCont->m_nId.begin(), persCont->m_nId.end(), init)!=transContSize) {
265 log << MSG::ERROR << "transToPers: sum of entries of persCont->m_nId (" << std::accumulate(persCont->m_nId.begin(), persCont->m_nId.end(), init) << ") does not match transient container size = " << transContSize << endmsg;
266 }
267 if (std::accumulate(persCont->m_nHits.begin(), persCont->m_nHits.end(), init)!=transContSize) {
268 log << MSG::ERROR << "transToPers: sum of entries of persCont->m_nHits (" << std::accumulate(persCont->m_nHits.begin(), persCont->m_nHits.end(), init) << ") does not match transient container size = " << transContSize << endmsg;
269 }
270#endif
271}
272
273
275 std::unique_ptr<SiHitCollection> trans(std::make_unique<SiHitCollection>("DefaultCollectionName",persObj->m_nHits.size()));
276 persToTrans(persObj, trans.get(), log);
277 return(trans.release());
278}
279
280
281#ifdef ENABLE_SANITY_CHECKS
282void SiHitCollectionCnv_p4::persToTrans(const SiHitCollection_p4* persCont, SiHitCollection* transCont, MsgStream &log)
283#else
284void SiHitCollectionCnv_p4::persToTrans(const SiHitCollection_p4* persCont, SiHitCollection* transCont, MsgStream &/*log*/)
285#endif
286{
287 const EventContext& ctx = Gaudi::Hive::currentContext();
288#ifdef ENABLE_SANITY_CHECKS
289 // Sanity check
290 const unsigned int transContSize = persCont->m_hitEne_2b.size(); // this vector has one entry per transient SiHit, so its size can be used as a proxy for the transient Container size
291 const unsigned int init(0);
292 if (std::accumulate(persCont->m_nTruthID.begin(), persCont->m_nTruthID.end(), init)!=transContSize) {
293 log << MSG::ERROR << "persToTrans: sum of entries of persCont->m_nTruthID (" << std::accumulate(persCont->m_nTruthID.begin(), persCont->m_nTruthID.end(), init) << ") does not match transient container size = " << transContSize << endmsg;
294 }
295 if (std::accumulate(persCont->m_nId.begin(), persCont->m_nId.end(), init)!=transContSize) {
296 log << MSG::ERROR << "persToTrans: sum of entries of persCont->m_nId (" << std::accumulate(persCont->m_nId.begin(), persCont->m_nId.end(), init) << ") does not match transient container size = " << transContSize << endmsg;
297 }
298 if (std::accumulate(persCont->m_nHits.begin(), persCont->m_nHits.end(), init)!=transContSize) {
299 log << MSG::ERROR << "persToTrans: sum of entries of persCont->m_nHits (" << std::accumulate(persCont->m_nHits.begin(), persCont->m_nHits.end(), init) << ") does not match transient container size = " << transContSize << endmsg;
300 }
301#endif
302
303 unsigned int hitCount = 0;
304 unsigned int angleCount = 0;
305 unsigned int idxTruthID = 0;
306 unsigned int idxId = 0;
307 unsigned int idxEne4b = 0;
308 unsigned int idxLen4b = 0;
309 unsigned int endHit = 0;
310 unsigned int endTruthID = 0;
311 unsigned int endId = 0;
312
313 for (unsigned int i = 0; i < persCont->m_nHits.size(); i++) {
314
315 if (persCont->m_nHits[i]) {
316
317 const unsigned int start = endHit;
318 endHit += persCont->m_nHits[i];
319
320 const double t0 = persCont->m_hit1_meanTime[i];
321 const double theta0 = persCont->m_hit1_theta[i];
322 const double phi0 = persCont->m_hit1_phi[i];
323 HepGeom::Point3D<double> endLast(persCont->m_hit1_x0[i], persCont->m_hit1_y0[i], persCont->m_hit1_z0[i]);
324
325 for (unsigned int j = start; j < endHit; j++) {
326
327 if (j >= endTruthID + persCont->m_nTruthID[idxTruthID])
328 endTruthID += persCont->m_nTruthID[idxTruthID++];
329
330 if (j >= endId + persCont->m_nId[idxId])
331 endId += persCont->m_nId[idxId++];
332
333 const double eneLoss_2b = persCont->m_hitEne_2b[hitCount];
334 const double hitLength_2b = persCont->m_hitLength_2b[hitCount];
335
336 const double eneLoss = (eneLoss_2b < m_2bMaximum) ? eneLoss_2b * m_persEneUnit : persCont->m_hitEne_4b[idxEne4b++];
337 const double length = (hitLength_2b < m_2bMaximum) ? hitLength_2b * m_persLenUnit : persCont->m_hitLength_4b[idxLen4b++];
338
339 const double dTheta = (j > start) ? ((double)persCont->m_dTheta[angleCount] - m_2bHalfMaximum) * m_persAngUnit : 0.0;
340 const double dPhi = (j > start) ? ((double)persCont->m_dPhi[angleCount] - m_2bHalfMaximum) * m_persAngUnit : 0.0;
341
342 const double meanTime = t0;
343 const double theta = theta0 + dTheta;
344 const double phi = phicorr(phi0 + dPhi);
345
346 CLHEP::Hep3Vector r(length, 0.0, 0.0);
347 r.setTheta(theta);
348 r.setPhi(phi);
349
350 HepGeom::Point3D<double> endThis( endLast + r );
351
353 if (persCont->m_mcEvtIndex[idxTruthID] == 0) {
355 }
356 HepMcParticleLink partLink( persCont->m_truthID[idxTruthID], persCont->m_mcEvtIndex[idxTruthID], flag, HepMcParticleLink::IS_ID, ctx );
358 transCont->Emplace( endLast, endThis, eneLoss, meanTime, partLink, persCont->m_id[idxId] );
359
360 endLast = std::move(endThis);
361
362 ++hitCount;
363 if (j > start) ++angleCount;
364 }
365 }
366 }
367}
#define M_PI
Scalar phi() const
phi method
Scalar theta() const
theta method
#define endmsg
double length(const pvec &v)
static Double_t a
static Double_t t0
double phicorr(double a)
double cycle(double a, double b)
double phicorr(double a)
double cycle(double a, double b)
AtlasHitsVector< SiHit > SiHitCollection
CONT::const_iterator const_iterator
const_iterator begin() const
void Emplace(Args &&... args)
size_type size() const
const_iterator end() const
static const double m_persLenUnit
virtual void transToPers(const SiHitCollection *transCont, SiHitCollection_p4 *persCont, MsgStream &log)
static const double m_2bHalfMaximum
virtual void persToTrans(const SiHitCollection_p4 *persCont, SiHitCollection *transCont, MsgStream &log)
static const double m_persEneUnit
virtual SiHitCollection * createTransient(const SiHitCollection_p4 *persObj, MsgStream &log)
static const double m_persAngUnit
std::vector< unsigned short > m_hitEne_2b
std::vector< char > m_truthSupp
std::vector< float > m_hit1_y0
std::vector< float > m_hitEne_4b
std::vector< unsigned short > m_dTheta
std::vector< float > m_hit1_z0
std::vector< float > m_hit1_phi
std::vector< float > m_hitLength_4b
std::vector< unsigned short > m_dPhi
std::vector< unsigned short > m_nHits
std::vector< unsigned short > m_hitLength_2b
std::vector< float > m_hit1_meanTime
std::vector< float > m_hit1_x0
std::vector< float > m_hit1_theta
std::vector< unsigned long > m_truthID
std::vector< unsigned short > m_nTruthID
std::vector< unsigned long > m_id
std::vector< unsigned short > m_nId
std::vector< unsigned short > m_mcEvtIndex
TH1F * trans(TH1F *h, bool t=false)
int r
Definition globals.cxx:22
IProxyDict * proxyDictFromEventContext()
Return the IProxyDict for this thread's current context.
constexpr int pow(int x)
Definition conifer.h:27
Definition index.py:1
Some out-of-line helpers for ExtendedEventContext.