ATLAS Offline Software
Loading...
Searching...
No Matches
TRT_HitCollectionCnv_p3.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
9
10#include <cmath>
11
12// CLHEP
13#include "CLHEP/Geometry/Point3D.h"
14#include "CLHEP/Units/SystemOfUnits.h"
15
16// Gaudi
17#include "GaudiKernel/MsgStream.h"
18
19// Athena
22
23// Transient(Geant) to Persistent(Disk)
25{
26
27 /*
28 Spring 2009
29 Andrew Beddall - lossy TRT G4hit compression [p3]
30
31 In p1, p2 versions, GEANT hits are persistified on disk as floats.
32 In this p3 version, floats are compressed to "integers"/"short-floats" before persistifying.
33 The saving is about 75%; see http://cern.ch/beddall/TRThitCompression/
34
35 Spring 2008
36 Rob Duxfield - lossless TRT G4hit compression [p2]
37
38 Finds hits belonging to a "string" (in which the end point of one hit is
39 the same as the start point of the next) and persistifies the end point
40 of each hit plus the start point of the first hit in each string.
41 */
42
43 // The original units from the hit simulation are indicated in comments;
44 // they are all in CLHEP units except for hitEne which is in keV.
45 // I sometimes make use of CLHEP scales *CLHEP::mm and *CLHEP::ns (both=1) for clarity (I hope!).
46 // See also https://twiki.cern.ch/twiki/bin/view/Atlas/TrtSoftware#Production_of_Hits
47
48 static const double dRcut = 1.0e-7*CLHEP::mm;
49 static const double dTcut = 1.0*CLHEP::ns; // redundant?
50
51 // if (log.level() <= MSG::DEBUG) log << MSG::DEBUG << "In TRT_HitCollectionCnv_p3::transToPers()" << endmsg;
52
53 int lastBarcode = -1;
54 int lastId = -1;
55 double lastT = 0.0*CLHEP::ns;
56 unsigned int idx = 0;
57 unsigned int endBC = 0;
58 unsigned int endId = 0;
59 unsigned int endHit = 0;
60 HepGeom::Point3D<double> lastEnd(0.0, 0.0, 0.0); // mm
61
62 for (TRTUncompressedHitCollection::const_iterator it = transCont->begin(); it != transCont->end(); ++it) {
63
65
66 if ( trtHit->particleLink().barcode() != lastBarcode || idx - endBC > 65500) { // max unsigned short = 65535;
67 // store barcode once for set of consecutive hits with same barcode
68 lastBarcode = trtHit->particleLink().barcode();
69 using barcodeType = decltype(persCont->m_barcode)::value_type;
70 persCont->m_barcode.push_back(static_cast<barcodeType>(lastBarcode));
71 if ( idx > 0 ) {
72 persCont->m_nBC.push_back(idx - endBC);
73 endBC = idx;
74 }
75 }
76
77 if ( (int)trtHit->GetParticleEncoding() != lastId || idx - endId > 65500) { // max unsigned short = 65535;
78 // store id once for set of consecutive hits with same id
79 lastId = trtHit->GetParticleEncoding();
80 persCont->m_id.push_back(lastId);
81 if ( idx > 0 ) {
82 persCont->m_nId.push_back(idx - endId);
83 endId = idx;
84 }
85 }
86
87 const HepGeom::Point3D<double> hitStart(trtHit->GetPreStepX(), trtHit->GetPreStepY(), trtHit->GetPreStepZ()); // mm
88
89 const double meanTime = trtHit->GetGlobalTime(); // ns // Time of flight from the I.P. to the center of the hit.
90 const double dTLast = fabs(meanTime - lastT); // |d(meantime)| between the previous hit and the current one.
91 const double dRLast = lastEnd.distance(hitStart); // Distance between end of previous hit and start of current one;
92 // this is zero if the hit is a continuation of the same particle in the same straw.
93
94 // Begin a new string if the current and previous hits are disconnected;
95 // it looks like dTcut is redundant (but not sure about this).
96 if ( dRLast >= dRcut || dTLast >= dTcut ) {
97
98 // if ( dRLast < dRcut) std::cout << "AJBdTLastTriggeredNewString " << dRLast << " " << dTLast << std::endl;
99
101 // new hit string //
103
104 //
105 // Persistify string *strawId* using 24 bits.
106 // Assumes 0 <= strawId <= 16,777,215 (strawId appears to be < 4,000,000)
107 //
108 const unsigned int strawId = trtHit->GetHitID();
109 persCont->m_strawId1b.push_back( (unsigned char)(strawId % 256) ); // 8 bits
110 persCont->m_strawId2b.push_back( (unsigned short)(strawId / 256) ); // 16 bits
111 if ( strawId>16777215 )
112 log << MSG::WARNING << "TRT_HitCollectionCnv: strawId > 2^24-1 cannot be persistified correctly! " << endmsg;
113
114 //
115 // Persistify string start radius using 1 bit (istartRflag) or 8 bits (startR)
116 // Note that the smallest value of R is the wire radius (0.0155 mm)
117 //
118 // R will be flagged as 2 mm if it is within 0.1 um of the straw wall => max error = 0.1 um,
119 // otherwise compress with 8 bits => max error = 3.9 um (0.078 ns), RMS error = 1.1 um (0.022 ns)
120 //
121 const double startR = sqrt( hitStart.x()*hitStart.x() + hitStart.y()*hitStart.y() ); // mm
122 unsigned short istartRflag;
123 if ( startR > 1.9999*CLHEP::mm ) {
124 istartRflag=1; // persistify as a 1-bit flag
125 }
126 else {
127 istartRflag=0; // compress to 8 bits with a span of 2 mm
128 persCont->m_startR.push_back( (unsigned char)(startR/(2.0*CLHEP::mm)*256.0) );
129 }
130
131 //
132 // Persistify string *startPhi* using 8 bits (min=-pi, max=+pi)
133 // Max. error = 12 mrad (< 24 um, 0.48 ns); RMS error = 7 mrad (< 14 um, 0.28 ns)
134 //
135 const double startPhi = atan2( hitStart.y(), hitStart.x() ); // returns range -pi to +pi rad
136 persCont->m_startPhi.push_back( (unsigned char)( (startPhi+M_PI)/(2.0*M_PI)*256.0 ) );
137
138 //
139 // Persistify *startZ* using a 4 bits (min = -365 mm, max= +365 mm)
140 // Max. error = 25 mm (25e-3/(0.75c) = 0.111 ns * 2 reflect = 0.222 ns)
141 // RMS error = 14 mm (14e-3/(0.75c) = 0.062 ns * 2 reflect = 0.124 ns)
142 // Also the 1-bit *istartRflag* is packed into this variable.
143 //
144 // Note:
145 // In the digi code we need to allow for something like 22.5 mm outside straw.
146 // Also because we have short straws,
147 // short straws are about < +-180 mm, long straws are about < +-350 mm
148 // The following compressions can give a large "out of straw" value;
149 // *don't* use these: (2.0), 32.0, 128.0, 256.0.
150
151 unsigned char istartZ = (unsigned char)( (hitStart.z()+365.0*CLHEP::mm)/(730.0*CLHEP::mm)*16.0 );
152 istartZ = (istartZ << 1) | istartRflag;
153 persCont->m_startZ.push_back( istartZ );
154
155 if ( idx > 0 ) {
156 persCont->m_nHits.push_back( idx - endHit );
157 endHit = idx;
158 }
159 /*
160 // Validation output
161 std::cout.precision(15);
162 std::cout << "AJBTtoPstrawId " << strawId << std::endl;
163 std::cout << "AJBTtoPstartR " << startR << std::endl;
164 std::cout << "AJBTtoPstartPhi " << startPhi << std::endl;
165 std::cout << "AJBTtoPstartX " << hitStart.x() << std::endl;
166 std::cout << "AJBTtoPstartY " << hitStart.y() << std::endl;
167 std::cout << "AJBTtoPstartZ " << hitStart.z() << std::endl;
168 */
169 } // end of "begin new hit string"
170
172 // Now for the end hits //
174
175 const HepGeom::Point3D<double> hitEnd(trtHit->GetPostStepX(), trtHit->GetPostStepY(), trtHit->GetPostStepZ()); // mm
176 const HepGeom::Point3D<double> hitLength = (hitEnd - hitStart);
177
178 //
179 // Here both *kinEne* (kinetic energy of the particle causing the hit) and
180 // *steplength* (g4hit length) are persistified using a 15-bit "short float"
181 // (9 bit unsigned mantissa, 6 bit unsigned exponent).
182 // This stores values in the range 0.51*2^0 = 0.51 to 1.00*2^63 = 9.2e18.
183 // I enforce the limits 1.0 and 9.0e18; see below.
184 // Max relative error = 0.0010, RMS = 0.0004
185 //
186 // Notes:
187 //
188 // - G4 gives kinEne in MeV; I sometimes see values ~ 1e-7 MeV (100 meV) [float round-off?]
189 // So I multiply by 1e9 and store in units of meV => range 1.0 meV to 9.0e18 meV (9000 TeV!)
190 // - About 1 in 10000 hits have steplength ~ 1e-7 mm [float round-off?]
191 // so again I multiply by 1e9 and store in units of pm => range 1.0 pm to 9.0e18 pm (9000 km)
192 // - The mantissa has maximum 9 bits, the exponent has maximum 6 bits,
193 // Note: a rare condition causes an 10-bit mantissa (mantissa=512).
194 //
195 double kinEne = trtHit->GetKineticEnergy() * 1.0e9; // nano Mev = meV.
196 double steplength = hitLength.distance() * 1.0e9; // nano mm = pm.
197 if ( kinEne < 1.0 ) kinEne=1.0; // Keep the value
198 if ( steplength < 1.0 ) steplength=1.0; // well within the
199 if ( kinEne > 9.0e18 ) kinEne=9.0e18; // range of the
200 if ( steplength > 9.0e18 ) steplength=9.0e18; // short float.
201 const unsigned int kexponent = (unsigned int)ceil(log10(kinEne)/0.30102999566398);
202 const unsigned int sexponent = (unsigned int)ceil(log10(steplength)/0.30102999566398);
203 const unsigned int kmantissa = (unsigned int)(kinEne/pow(2.0,kexponent)*1024) - 512;
204 const unsigned int smantissa = (unsigned int)(steplength/pow(2.0,sexponent)*1024) - 512;
205 persCont->m_kinEne.push_back( (kmantissa << 6) | kexponent );
206 persCont->m_steplength.push_back( (smantissa << 6) | sexponent );
207
208 //
209 // Persistify hit end radius using 1 bit (iendRflag) or 8 bits (endR).
210 // Note that the smallest value of R is the wire radius (0.0155 mm)
211 //
212 // R will be flagged as 2 mm if it is within 0.1 um of the straw wall => max error = 0.1 um,
213 // otherwise compress with 8 bits. The errors are as for startR, but can increased greatly
214 // after steplength preservation in PtoT.
215 //
216 const double endR = sqrt( hitEnd.x()*hitEnd.x() + hitEnd.y()*hitEnd.y() ); // mm
217 unsigned short iendRflag;
218 if ( endR > 1.9999*CLHEP::mm ) {
219 iendRflag=1; // persistify as a 1-bit flag
220 }
221 else {
222 iendRflag=0; // compress to 8 bits with a span of 2 mm
223 persCont->m_endR.push_back( (unsigned char)(endR/(2.0*CLHEP::mm)*256.0) );
224 }
225
226 //
227 // Persistify string *endPhi* using 8 bits (min=-pi, max=+pi)
228 // The errors are as for startPhi, but are very different after steplength
229 // preservation in PtoT.
230 //
231 const double endPhi = atan2( hitEnd.y(), hitEnd.x() ); // returns range -pi to +pi rad
232 persCont->m_endPhi.push_back( (unsigned char)( (endPhi+M_PI)/(2.0*M_PI)*256.0 ) );
233
234 //
235 // Persistify hit *meanTime* using 10 bits (min=0.,span=75 ns)
236 // with float overflow for meanTime >= 75ns (the tail of the distribution).
237 // Max. error = 0.037 ns; RMS error = 0.021 ns.
238 // Also the 1-bit *iendRflag* and 1-bit *idZsign* are packed into this variable.
239 //
240 unsigned short idZsign = (hitLength.z()>0.0) ? 1 : 0; // flag the sign of dZ
241 unsigned short imeanTime = ( meanTime < 75.0*CLHEP::ns ) ? (unsigned short)(meanTime/(75.0*CLHEP::ns)*1024.0) : 1023;
242 if ( imeanTime == 1023 ) persCont->m_meanTimeof.push_back( (float)meanTime ); // "overflow flag"
243 imeanTime = (imeanTime << 2) | (idZsign << 1) | iendRflag;
244 persCont->m_meanTime.push_back( imeanTime );
245
246 //
247 // Persistify hit *hitEne* (the energy deposited by the hit in keV) using a float but only for photons
248 // (relatively very few of these). Digitisation does not use hitEne for charged particles.
249 //
250 if ( lastId == 22 ||
251 (int)(abs(lastId)/100000) == 41 ||
252 (int)(abs(lastId)/10000000) == 1
253 ) persCont->m_hitEne.push_back( (float)(trtHit->GetEnergyDeposit()) ); // keV
254
255 lastEnd = hitEnd;
256 lastT = meanTime;
257 ++idx;
258 /*
259 // Validation output
260 std::cout.precision(15);
261 std::cout << "AJBTtoPendR " << endR << std::endl;
262 std::cout << "AJBTtoPendPhi " << endPhi << std::endl;
263 std::cout << "AJBTtoPendX " << hitEnd.x() << std::endl;
264 std::cout << "AJBTtoPendY " << hitEnd.y() << std::endl;
265 std::cout << "AJBTtoPendZ " << hitEnd.z() << std::endl;
266 std::cout << "AJBTtoPmeanTime " << meanTime << std::endl;
267 std::cout << "AJBTtoPkinEne " << trtHit->kineticEnergy << std::endl;
268 std::cout << "AJBTtoPhitEne " << trtHit->energyDeposit << std::endl;
269 std::cout << "AJBTtoPsteplength " << hitLength.distance() << std::endl;
270 */
271 }
272
273 persCont->m_nBC.push_back(idx - endBC);
274 persCont->m_nId.push_back(idx - endId);
275 persCont->m_nHits.push_back( idx - endHit );
276
277} // transToPers
278
279
280// Create Transient
282 std::unique_ptr<TRTUncompressedHitCollection> trans(std::make_unique<TRTUncompressedHitCollection>("DefaultCollectionName",persObj->m_nHits.size()));
283 persToTrans(persObj, trans.get(), log);
284 return(trans.release());
285} //createTransient
286
287
288// Persistent(Disk) to Transient
290{
291
292 // if (log.level() <= MSG::DEBUG) log << MSG::DEBUG << "In TRT_HitCollectionCnv_p3::persToTrans()" << endmsg;
293
294 // some values are read less than once per hit, these need counters.
295 unsigned int meanTimeofCount=0, startRCount=0, endRCount=0, hitEneCount=0;
296 unsigned int idxBC=0, idxId=0, endHit=0, endBC=0, endId=0;
297
298 // Assume that all Hits should be linked to the hard-scatter GenEvent
300 const int event_number = HepMcParticleLink::getEventNumberAtPosition (0, sg);
301
302 //
303 // loop over strings - index [i]
304 //
305
306 for ( unsigned int i = 0; i < persCont->m_nHits.size(); i++ ) {
307
308 if ( persCont->m_nHits[i] ) { // at least one hit in the string
309
310 const unsigned int startHit = endHit;
311 endHit += persCont->m_nHits[i];
312
313 //
314 // string strawId
315 //
316 const unsigned int i1 = persCont->m_strawId1b[i]; // 8 bits
317 const unsigned int i2 = persCont->m_strawId2b[i]; // 16 bits
318 const unsigned int strawId = i2*256+i1; // => 24 bits (0 to 16,777,215)
319
320 //
321 // string startPhi
322 //
323 const unsigned int istartPhi = persCont->m_startPhi[i]; // 8 bits
324 const double startPhi = -M_PI + (istartPhi+0.5)*2.0*M_PI/256.0; // rad (min = -pi, max = +pi)
325
326 //
327 // string startZ
328 //
329 const unsigned int istartZ = persCont->m_startZ[i] >> 1; // 4 bits
330 double startZ = -365.0*CLHEP::mm + (istartZ+0.5)*730.0*CLHEP::mm/16.0; // (min = -365 mm, max = +365 mm)
331
332 //
333 // start Rflag
334 //
335 const unsigned int istartRflag = persCont->m_startZ[i] & 1; // 1 bit
336
337 //
338 // string startR
339 //
340 double startR;
341 if ( istartRflag == 1 ) {
342 startR = 2.0*CLHEP::mm; // 1 bit
343 }
344 else {
345 const unsigned int istartR = persCont->m_startR[startRCount++]; // 8 bits
346 startR = (istartR+0.5)*2.0*CLHEP::mm/256.0; // (range 0 - 2 mm)
347 if ( startR < 0.0155*CLHEP::mm ) startR = 0.0155*CLHEP::mm; // The wire radius
348 }
349
350 //
351 // string startX, startY (derived from R,Phi)
352 //
353 double startX = startR*cos(startPhi);
354 double startY = startR*sin(startPhi);
355 /*
356 // Validation output
357 std::cout.precision(15);
358 std::cout << "AJBPtoTstrawId " << strawId << std::endl;
359 std::cout << "AJBPtoTstartR " << startR << std::endl;
360 std::cout << "AJBPtoTstartPhi " << startPhi << std::endl;
361 std::cout << "AJBPtoTstartX " << startX << std::endl;
362 std::cout << "AJBPtoTstartY " << startY << std::endl;
363 std::cout << "AJBPtoTstartZ " << startZ << std::endl;
364 std::cout << "AJBPtoTnHits " << persCont->m_nHits[i] << std::endl;
365 */
366 //
367 // loop over end hits in the string - index [j]
368 //
369
370 for ( unsigned int j = startHit; j < endHit; j++ ) {
371
372 if ( j >= endBC + persCont->m_nBC[idxBC] ) endBC += persCont->m_nBC[idxBC++];
373 if ( j >= endId + persCont->m_nId[idxId] ) endId += persCont->m_nId[idxId++];
374
375 //
376 // hit meanTime
377 //
378 const unsigned int imeanTime = persCont->m_meanTime[j] >> 2; // 10 bits
379 double meanTime = (imeanTime+0.5)*75.0*CLHEP::ns/1024.0; // (min = 0.0 ns, max = 75.0 ns)
380 if ( imeanTime == 1023 ) meanTime = (double)persCont->m_meanTimeof[meanTimeofCount++]; // ns, 32-bit float overflow
381
382 //
383 // dZ sign
384 //
385 const unsigned int idZsign = (persCont->m_meanTime[j] >> 1 ) & 1; // 1 bit
386
387 //
388 // endR flag
389 //
390 const unsigned int iendRflag = persCont->m_meanTime[j] & 1; // 1 bit
391
392 //
393 // hit energy deposited in keV (only relevant for photons) 32-bit float
394 //
395 const double hitEne = ( persCont->m_id[idxId] == 22 ||
396 (int)(abs(persCont->m_id[idxId])/100000) == 41 ||
397 (int)(abs(persCont->m_id[idxId])/10000000) == 1
398 ) ? (double)persCont->m_hitEne[hitEneCount++] : 0.0;
399
400 //
401 // hit endPhi (can be modified later during "steplength preservation")
402 //
403 const unsigned int iendPhi = persCont->m_endPhi[j]; // 8 bits
404 double endPhi = -M_PI + (iendPhi+0.5)*2.0*M_PI/256.0; // rad (min = -pi, max = +pi)
405
406 //
407 // string endR (can be modified later during "steplength preservation")
408 //
409 double endR;
410 if ( iendRflag==1 ) {
411 endR = 2.0*CLHEP::mm; // 1 bit
412 }
413 else {
414 const unsigned int iendR = persCont->m_endR[endRCount++];
415 endR = (iendR+0.5)*2.0*CLHEP::mm/256.0; // 8 bits
416 if ( endR < 0.0155*CLHEP::mm ) endR = 0.0155*CLHEP::mm; // the wire radius
417 }
418
419 //
420 // hit endX, endY (derived from R,Phi)
421 //
422 double endX = endR*cos(endPhi); // can be modified later during "steplength preservation"
423 double endY = endR*sin(endPhi); // can be modified later during "steplength preservation"
424
425 // Save the (o)riginal endX, endY values for the next hit start because
426 // they might get shrunk to fit the g4 steplength of the current hit.
427 double endXo = endX;
428 double endYo = endY;
429
430 //
431 // g4 step length of the hit, m_steplength, and
432 // kinetic energy of the hit, m_kinEne, are both 15-bit short floats.
433 // Note: a rare condition causes a 16-bit short float (mantissa=512).
434 //
435 const int kmantissa = persCont->m_kinEne[j] >> 6; // 9 bits (expected)
436 const int smantissa = persCont->m_steplength[j] >> 6;
437 const int kexponent = persCont->m_kinEne[j] & 0x3F; // 6 bits
438 const int sexponent = persCont->m_steplength[j] & 0x3F;
439 const double kinEne = (kmantissa+512.5)/1024 * pow(2.0,kexponent) / 1.0e9; // MeV
440 double g4steplength = (smantissa+512.5)/1024 * pow(2.0,sexponent) / 1.0e9; // mm
441 if ( idZsign==0 ) g4steplength = -g4steplength;
442
443 //
444 // Preserving the steplength of the hit by setting endZ or shrinking dX,dY.
445 //
446 double dX = endX-startX;
447 double dY = endY-startY;
448 double dZ;
449 double dXY2 = dX*dX+dY*dY;
450 double dL2 = g4steplength*g4steplength;
451 if ( dL2 > dXY2 ) { // define dZ such that steplength = g4steplength
452 dZ = sqrt(dL2-dXY2);
453 if (g4steplength<0.0) dZ=-dZ;
454 }
455 else { // dL2 < dXY2 // shrink dX,dY such that dXY = g4steplength
456 dX = dX * sqrt(dL2/dXY2); // this includes the cases where dL2=0!
457 dY = dY * sqrt(dL2/dXY2);
458 dZ = 0.0*CLHEP::mm;
459 endX = startX + dX;
460 endY = startY + dY;
461 //endR = sqrt( endX*endX + endY*endY ); // for validation information
462 //endPhi = atan2(endY,endX); // for validation information
463 }
464 double endZ = startZ + dZ;
465 //dX = endX-startX; // for validation information
466 //dY = endY-startY; // for validation information
467 /*
468 // Validation output
469 std::cout.precision(15);
470 std::cout << "AJBPtoTendR " << endR << std::endl;
471 std::cout << "AJBPtoTendPhi " << endPhi << std::endl;
472 std::cout << "AJBPtoTendX " << endX << std::endl;
473 std::cout << "AJBPtoTendY " << endY << std::endl;
474 std::cout << "AJBPtoTendZ " << endZ << std::endl;
475 std::cout << "AJBPtoTmeanTime " << meanTime << std::endl;
476 std::cout << "AJBPtoTkinEne " << kinEne << std::endl;
477 std::cout << "AJBPtoThitEne " << hitEne << std::endl;
478 std::cout << "AJBPtoTsteplength " << sqrt(dX*dX+dY*dY+dZ*dZ) << std::endl;
479 */
480 //
481 // Notes:
482 // - All units are CLHEP, except hitEne which is in keV.
483 // - For charged particles kinEne is *zero*!
484 //
485
487 if ( HepMC::BarcodeBased::is_truth_suppressed_pileup(static_cast<int>(persCont->m_barcode[idxBC])) ) {
489 }
490 transCont->Emplace( strawId, partLink, persCont->m_id[idxId],
491 kinEne, hitEne, startX, startY, startZ,
492 endX, endY, endZ, meanTime );
493 //
494 // End of this hit becomes the start of the next;
495 // use the original (uncorrected) values for X,Y
496 // but the derived value for Z.
497 //
498 startX = endXo; startY = endYo; startZ = endZ;
499
500 }
501 } // nhits>0
502 } // straw loop
503} // persToTrans
#define M_PI
#define endmsg
@ EBC_PU_SUPPRESSED
AtlasHitsVector< TRTUncompressedHit > TRTUncompressedHitCollection
constexpr int pow(int base, int exp) noexcept
const_iterator begin() const
void Emplace(Args &&... args)
const_iterator end() const
static IProxyDict * store()
Fetch the current store.
virtual void transToPers(const TRTUncompressedHitCollection *transCont, TRT_HitCollection_p3 *persCont, MsgStream &log)
virtual void persToTrans(const TRT_HitCollection_p3 *persCont, TRTUncompressedHitCollection *transCont, MsgStream &log)
virtual TRTUncompressedHitCollection * createTransient(const TRT_HitCollection_p3 *persObj, MsgStream &log)
std::vector< unsigned short > m_kinEne
std::vector< unsigned char > m_startPhi
std::vector< unsigned char > m_endR
std::vector< unsigned char > m_startR
std::vector< unsigned int > m_barcode
std::vector< unsigned short > m_meanTime
std::vector< unsigned char > m_endPhi
std::vector< unsigned short > m_nBC
std::vector< int > m_id
std::vector< unsigned short > m_nId
std::vector< unsigned short > m_strawId2b
std::vector< float > m_meanTimeof
std::vector< unsigned short > m_steplength
std::vector< unsigned char > m_strawId1b
std::vector< unsigned char > m_startZ
std::vector< unsigned short > m_nHits
std::vector< float > m_hitEne
bool is_truth_suppressed_pileup(const T &p)
Method to establish if a particle (or barcode) corresponds to truth-suppressed pile-up.