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