StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StTrsChargeSegment.cc
1 /***************************************************************************
2  *
3  * $Id: StTrsChargeSegment.cc,v 1.43 2011/07/18 21:30:31 genevb Exp $
4  *
5  * Author: brian May 18, 1998
6  *
7  ***************************************************************************
8  *
9  * Description: Input charge segment...much like a g2t_tpc_hit but
10  * with added functionality
11  *
12  ***************************************************************************
13  *
14  *
15  * $Log: StTrsChargeSegment.cc,v $
16  * Revision 1.43 2011/07/18 21:30:31 genevb
17  * Unify GEANT PID discrimination to StarClassLibrary
18  *
19  * Revision 1.42 2011/01/18 14:40:15 fisyak
20  * Clean up TpcDb interfaces and Tpc coordinate transformation
21  *
22  * Revision 1.41 2009/11/03 14:34:19 fisyak
23  * Remove default in zFromTB
24  *
25  * Revision 1.40 2005/12/12 21:00:12 perev
26  * 3 random generators ==> 1
27  *
28  * Revision 1.39 2004/04/08 20:51:39 perev
29  * bug fix low limit must be -10, not 10.
30  *
31  * Revision 1.38 2004/04/07 18:58:57 perev
32  * Cleanup
33  *
34  * Revision 1.37 2003/12/24 13:44:52 fisyak
35  * Add (GEANT) track Id information in Trs; propagate it via St_tpcdaq_Maker; account interface change in StTrsZeroSuppressedReaded in StMixerMaker
36  *
37  * Revision 1.36 2003/09/02 17:59:19 perev
38  * gcc 3.2 updates + WarnOff
39  *
40  * Revision 1.35 2002/04/26 06:05:26 long
41  * add triton and correct charge for he3
42  *
43  * Revision 1.34 2002/04/25 21:40:23 long
44  * add he3,he4,deuteron
45  *
46  * Revision 1.33 2002/04/25 21:37:03 long
47  * *** empty log message ***
48  *
49  * Revision 1.32 2001/11/21 01:53:42 long
50  * adding log message for 3/2001 long;
51  *
52  * adding:
53  *
54  * if(aMiniSegment.position().z()>0)
55  * listOfMiniSegments->push_back(aMiniSegment); //HL,03/2001 protect against
56  * negative z.
57  *
58  * Revision 1.31 2001/03/14 23:43:39 long
59  * *** empty log message ***
60  *
61  * Revision 1.30 2001/03/07 20:22:56 long
62  * *** empty log message ***
63  *
64  * Revision 1.29 2000/11/23 02:08:49 lbarnby
65  * More protection against Nan
66  *
67  * Revision 1.28 2000/11/09 19:23:09 lbarnby
68  * Cernlib entry point changed (dstlan->dislan) Fix for optimization bug, prevent use of nan. Proper robust solution still required.
69  *
70  * Revision 1.27 2000/07/30 02:59:23 long
71  * *** empty log message ***
72  *
73  * Revision 1.26 2000/07/30 02:38:36 long
74  * comment out numberofLevel
75  *
76  * Revision 1.25 2000/06/23 00:12:40 snelling
77  * Removed dependence on local files now pointed to StDbUtilities
78  *
79  * Revision 1.24 2000/02/24 16:19:07 long
80  * take away straight line model due to changes made by GEANT on de<0 case
81  *
82  *Revision 1.24 2000/02/20 16:22:33 long
83  * take away straight line model due to changes made by GEANT on de<0 case
84  *
85  * Revision 1.23 2000/02/10 01:21:49 calderon
86  * Switch to use StTpcDb.
87  * Coordinates checked for consistency.
88  * Fixed problems with StTrsIstream & StTrsOstream.
89  *
90  * Revision 1.22 2000/01/31 20:38:33 lasiuk
91  * namespace for HP (random_shuffle)
92  *
93  * Revision 1.21 2000/01/10 23:14:30 lasiuk
94  * Include MACROS for compatiblity with SUN CC5
95  *
96  * Revision 1.20 1999/12/08 02:10:42 calderon
97  * Modified to eliminate warnings on Linux.
98  *
99  * Revision 1.19 1999/11/12 01:42:15 long
100  * delete "fabs((magDb->at(mSector12Position)).z())>0.01)" because it is not needed
101  *
102  * Revision 1.18 1999/10/22 15:51:47 calderon
103  * Remove ifdefs for erf. Problem is solved by loading libm at the
104  * macro level.
105  *
106  * Revision 1.17 1999/10/22 00:00:13 calderon
107  * -added macro to use Erf instead of erf if we have HP and Root together.
108  * -constructor with char* for StTrsDedx so solaris doesn't complain
109  * -remove mZeros from StTrsDigitalSector. This causes several files to
110  * be modified to conform to the new data format, so only mData remains,
111  * access functions change and digitization procedure is different.
112  *
113  * Revision 1.16 1999/10/04 16:22:33 long
114  * straight line model in case of de<0
115  *
116  * Revision 1.15 1999/09/24 01:23:30 fisyak
117  * Reduced Include Path
118  *
119  * Revision 1.14 1999/07/20 02:18:06 lasiuk
120  * remove CVS merge conflicts
121  *
122  * Revision 1.13 1999/07/19 21:37:42 lasiuk
123  * - constructor arguments reordered for increased speed
124  * - tssSplit() and associated parameterizations from
125  * tss are included (requires linking with cernlib)
126  * - introduce static random number generators
127  * - whichGEANTParticle() introduced for g2t input
128  *
129  * Revision 1.12 1999/06/16 14:26:52 fisyak
130  * Add flags for egcs on Solaris
131  *
132  * Revision 1.11 1999/03/16 02:00:40 lasiuk
133  * use STL in ionization generation;
134  * do not always use betaGamma as a scale factor;
135  * still a problem with the neutrals depositing energy
136  *
137  * Revision 1.10 1999/03/15 13:49:30 lasiuk
138  * field is initialized with Tesla in the data base!
139  *
140  * Revision 1.9 1999/03/02 17:51:45 lasiuk
141  * geant PID
142  *
143  * Revision 1.8 1999/02/28 20:15:17 lasiuk
144  * splitting test/add muon to pid
145  *
146  * Revision 1.7 1999/02/18 21:18:33 lasiuk
147  * rotate() mods to StTpcCoordinateTranform
148  *
149  * Revision 1.6 1999/02/16 18:15:41 fisyak
150  * Check in the latest updates to fix them
151  *
152  * Revision 1.5 1999/02/12 01:26:37 lasiuk
153  * Limit debug output
154  *
155  * Revision 1.4 1999/02/10 18:02:24 lasiuk
156  * verbose output and ostream
157  *
158  * Revision 1.3 1999/01/28 02:50:28 lasiuk
159  * beta gamma for particle mass
160  *
161  * Revision 1.2 1999/01/15 10:59:11 lasiuk
162  * remove g2t pointer
163  * add pid member; add systemofunits; mv access fcts to .hh
164  * add ostream operator
165  *
166  **************************************************************************/
167 #include "StTrsChargeSegment.hh"
168 
169 #include <algorithm>
170 #if defined(__SUNPRO_CC) && __SUNPRO_CC < 0x500
171 #include <ospace/stl/src/randgen.cpp>
172 #endif
173 
174 #ifndef ST_NO_NAMESPACES
175 using std::random_shuffle;
176 #endif
177 
178 #include "StPhysicalHelix.hh"
179 #include "StParticleTable.hh"
180 #include "StParticleDefinition.hh"
181 
182 #include "StDbUtilities/StTpcCoordinateTransform.hh"
183 #include "StTrsDeDx.hh"
184 #include "StTrsRandom.hh"
185 #include "TMath.h"
186 // Need a CERNLIB routine for tssSplit
187 extern "C" float dislan_(float &x);
188 float dislan(float x) { return (x<-10.)? 0.:dislan_(x);}
189 
190 HepJamesRandom StTrsChargeSegment::mEngine;
191 RandFlat StTrsChargeSegment::mFlatDistribution(mEngine);
192 
193 StTrsChargeSegment::StTrsChargeSegment()
194  : mPosition(0,0,0),
195  mSector12Position(mPosition),
196  mMomentum(0,0,0),
197  mId(0),
198  mDE(0),
199  mDs(0),
200  mPid(0),
201  mNumberOfElectrons(-1),
202  mSectorOfOrigin(0)
203 
204 { /* nopt */ }
205 
206 StTrsChargeSegment::StTrsChargeSegment(StThreeVector<double>& pos,
208  int id,
209  double de,
210  double ds,
211  int pid,
212  double ne)
213  : mPosition(pos),
214  mSector12Position(mPosition),
215  mMomentum(mom),
216  mId(id),
217  mDE(de),
218  mDs(ds),
219  mPid(pid), // default is -1
220  mNumberOfElectrons(ne), //default is -1
221  mSectorOfOrigin(0)
222 { /* nopt */ }
223 
224 StTrsChargeSegment::~StTrsChargeSegment() {/* nopt */ }
225 
226 
227 void StTrsChargeSegment::whichGEANTParticle(double& particleMass, int& charge)
228 {
229  StParticleDefinition* pDef = StParticleTable::instance()->findParticleByGeantId(mPid);
230  if (pDef) {
231  particleMass = pDef->mass();
232  charge = (int) (pDef->charge());
233  } else {
234  // Probably uncharged, but DO NOT BREAK IT!
235  cout << "Mass is Undefined (" << mPid << ")" << endl;
236  particleMass = 0*GeV;
237  charge = 0;
238  //subSegments = 1;
239  }
240 }
241 
242 #ifndef ST_NO_TEMPLATE_DEF_ARGS
243 void StTrsChargeSegment::split(StTrsDeDx* gasDb,
244  StMagneticField* magDb,
245  int subSegments,
246  list<StTrsMiniChargeSegment>* listOfMiniSegments)
247 #else
248 void StTrsChargeSegment::split(StTrsDeDx* gasDb,
249  StMagneticField* magDb,
250  int subSegments,
251  list<StTrsMiniChargeSegment,allocator<StTrsMiniChargeSegment> >* listOfMiniSegments)
252 #endif
253 {
254 #ifndef ST_NO_NAMESPACES
255  using namespace units;
256 #endif
257 
258 #ifndef ST_NO_TEMPLATE_DEF_ARGS
259  vector<int> ionization(StTrsDeDx::numberOfElectrons);
260  vector<float> theIonization;
261 
262 #else
263  vector<int, allocator<int> > ionization(StTrsDeDx::numberOfElectrons);
264  vector<float, allocator<float> > theIonization;
265 #endif
266 
267 
268  //
269  // Calculate the number of electrons in complete segment
270  //
271  if (mNumberOfElectrons<0)
272  mNumberOfElectrons = (mDE)/(gasDb->W());
273 
274 // PR(mDE/eV);
275 // PR(gasDb->W());
276 // PR(mNumberOfElectrons);
277  //
278  // Only do costly initialization if you
279  // break into more than one subsegment
280  //
281  double particleMass;
282  int charge;
283 
284  if(subSegments>1) {
285  //
286  // PID are GEANT3 Conventions
287  // Must get from pid structures
288  whichGEANTParticle(particleMass, charge);
289 
290  }
291 
292  //
293  // Double Check
294  if(subSegments > 1) { // if an uncharged particle deposits energy, do not split it
295 
296  // what is the subsegment length?
297 
298  double deltaS = mDs/static_cast<double>(subSegments);
299 
300  // set the segment length in the gasDb:
301  gasDb->setPadLength(deltaS*centimeter);
302 
303  //
304  // theIonization
305  //
306  theIonization.clear();
307 
308  // number of segments to split given by command line argument (default 1):
309  // should be related to mNumberOfElectrons
310 
311  double ionizationLeft = mNumberOfElectrons;
312 
313  for(int ii=0; ii<(subSegments-1); ii++) {
314  //
315  // generate electrons
316  double betaGamma = abs(mMomentum)/particleMass;
317  // PR(betaGamma);
318  if(betaGamma>3)
319  gasDb->electrons(ionization, betaGamma);
320  else
321  gasDb->electrons(ionization); // betaGamma = 3
322 
323  // Don't generate too much ionization
324  if(ionization[StTrsDeDx::total] > ionizationLeft) {
325  theIonization.push_back(ionizationLeft);
326  }
327  else {
328  theIonization.push_back(ionization[StTrsDeDx::total]);
329  }
330 
331  ionizationLeft -= theIonization.back();
332 // PR(ionizationLeft);
333 
334  } // loop over subsegments
335  theIonization.push_back(ionizationLeft);
336 
337  //copy(theIonization.begin(),theIonization.end(), ostream_iterator<float>(cout,","));
338  random_shuffle(theIonization.begin(), theIonization.end(),StTrsRandom::inst());
339  //cout << endl;
340  //copy(theIonization.begin(), theIonization.end(), ostream_iterator<float>(cout,","));
341 
342  //To decompose track use the helix parameterization.
343  //StPhysicalHelix(p,x,B,+/-)
344  // Need some track info from pid:
345 
347  track(mMomentum,
348  mSector12Position,
349  (magDb->at(mSector12Position)).z(), //*tesla NOT now!
350  charge);
351 
352 // PR(particleMass/GeV);
353 // PR(mMomentum.mag());
354 
355  //
356  // calculate the offset to the start position
357  //
358  double newPosition = -mDs/2. + deltaS/2.;
359  //PR(newPosition);
360 
361  //
362  // loop over all subSegments and distribute charge
363  //
364 
365  //cout << "ionization.size() " << (ionization.size()) << endl;
366 // PR(subSegments);
367  for(int i=0; i<subSegments; i++) {
368  // Take the electrons from the vector
369 
370  // If there is no Ionization, take the next
371  if(!theIonization[i]) {
372  newPosition += deltaS;
373  continue;
374  }
375 
376  //PR(newPosition);
377  //PR(track.at(newPosition));
378 
379  StTrsMiniChargeSegment aMiniSegment(track.at(newPosition),
380  theIonization[i],
381  deltaS, mId);
382  listOfMiniSegments->push_back(aMiniSegment);
383 
384  newPosition += deltaS;
385  // PR(newPosition);
386  } // loop over subsegments
387 
388  } // if (subsegments > 1) ---> allows us to skip the helix construction
389  else if(subSegments == 1) {
390  StTrsMiniChargeSegment aSingleMiniSegment(mPosition,
391  mNumberOfElectrons,
392  mDs, mId);
393 
394  if(aSingleMiniSegment.position().z()>0)listOfMiniSegments->push_back(aSingleMiniSegment);
395 // PR(mPosition);
396 // PR(mNumberOfElectrons);
397  }
398 
399 }
400 #ifndef ST_NO_TEMPLATE_DEF_ARGS
401 void StTrsChargeSegment::tssSplit(StTrsDeDx* gasDb,
402  StMagneticField* magDb,
403  int numberOfLevels ,
404  list<StTrsMiniChargeSegment>* listOfMiniSegments)
405 #else
406 void StTrsChargeSegment::tssSplit(StTrsDeDx* gasDb,
407  StMagneticField* magDb,
408  int numberOfLevels ,
409  list<StTrsMiniChargeSegment,allocator<StTrsMiniChargeSegment> >* listOfMiniSegments)
410 #endif
411 {
412 #ifndef ST_NO_NAMESPACES
413  using namespace units;
414 #endif
415 
416  //
417  // Calculate the numser of electrons in complete segment
418  //
419 
420  if (mNumberOfElectrons<0)
421  // mNumberOfElectrons = (mDE)/(gasDb->W());
422 
423 
424  mNumberOfElectrons = fabs(mDE)/(gasDb->W());//HL,9/10/99
425 
426 
427 
428 
429 
430  //PR(mDE/eV);
431  //PR(gasDb->W());
432  //PR(mNumberOfElectrons);
433 
434  // int numberOfLevels =
435  // static_cast<int>(::log(static_cast<double>(subSegments))/M_LN2 + .999);
436 
437  // numberOfLevels++; // take care of the zero!
438 
439  double totalNumberOfSubSegments = ::pow(2.,(numberOfLevels-1));
440 
441 #ifndef ST_NO_TEMPLATE_DEF_ARGS
442  vector<double> tmp;
443  vector<vector<double> > ionizationSegments;
444 
445 #else
446  vector<double, allocator<double> > tmp;
447  typedef vector<double, allocator<double> > iSegs;
448  vector<iSegs , allocator<iSegs> > ionizationSegments;
449 #endif
450 
451  //
452  // Minimum ioinizing is a 3GeV proton!
453  //
454 
455  double minimumIonizingdEdx =
456  gasDb->betheBlochTSS(3.*GeV,1,.938*GeV);
457  //PR(minimumIonizingdEdx/(keV/centimeter));
458  int ii,jj; // cntrs
459  for(ii=0; ii<numberOfLevels; ii++)
460  ionizationSegments.push_back(tmp);
461 
462  //
463  // Fill dE/dx of complete segment
464  //
465  ionizationSegments[0].push_back(this->numberOfElectrons());
466 
467  //
468  // Must Determine the particle mass!
469  double particleMass;
470  int charge;
471  whichGEANTParticle(particleMass, charge);
472 
473  //PR(this->momentum());
474  //PR(particleMass/MeV);
475 
476 
477  if(charge != 0) {
478  double numberOfSubSegmentsInCurrentLevel;
479  double numberOfSubSegmentsInPreviousLevel;
480 
481  double dEdxBethe =
482  gasDb->betheBlochTSS(abs(this->momentum()),charge,particleMass);
483  //PR(dEdxBethe/(MeV/centimeter));
484 
485  double mip = dEdxBethe/minimumIonizingdEdx;
486 
487  double xBinary;
488 
489  for(ii=1; ii<numberOfLevels; ii++) {
490  numberOfSubSegmentsInCurrentLevel = 1<<(ii);
491  float dL = mDs/numberOfSubSegmentsInCurrentLevel;
492  //PR(dL/centimeter);
493 
494  // In this level you must create "numberOfSubSegments" subsegments
495  // Loop over the existing ones...
496  numberOfSubSegmentsInPreviousLevel = 1<<(ii-1);
497  for(jj=0; jj<numberOfSubSegmentsInPreviousLevel; jj++) {
498  double parentdEdx = ionizationSegments[(ii-1)][jj];
499 
500  double lengthOfSegmentToBeSplit = dL*2.;
501  double dEAverage = dEdxBethe*(lengthOfSegmentToBeSplit);
502 
503  double dErelave =
504  (parentdEdx*gasDb->W())/dEAverage;
505 
506  //PR(lengthOfSegmentToBeSplit);
507  //PR(dErelave);
508  //PR(mip);
509 
510  // Must pass the length of segment in the units of centimeters!
511 
512  xBinary = binaryPartition((lengthOfSegmentToBeSplit/centimeter),
513  dErelave,mip);
514  //PR(xBinary);
515  ionizationSegments[ii].push_back(xBinary*parentdEdx);
516  ionizationSegments[ii].push_back((1.-xBinary)*parentdEdx);
517  }
518  } // levels
519 
520  // --> Added here!
521 
522  //
523  // Distribution on a helix
524  //
525 
526  double deltaS =
527  mDs/static_cast<double>(totalNumberOfSubSegments);
528 
529  //To decompose track use the helix parameterization.
530  //StPhysicalHelix(p,x,B,+/-)
531  // Need some track info from pid:
532 
533 
535  track(mMomentum,
536  mSector12Position,
537  (magDb->at(mSector12Position)).z(), //*tesla NOT now!
538  charge);
539 
540  //PR(particleMass/GeV);
541  //PR(mMomentum.mag());
542 
543  //
544  // calculate the offset to the start position
545  //
546  double newPosition = -mDs/2. + deltaS/2.;
547 
548  //
549  // loop over all subSegments and distribute charge
550  //
551 
552  for(unsigned int i=0; i<ionizationSegments[(numberOfLevels-1)].size(); i++) {
553  // Take the electrons from the vector
554  StTrsMiniChargeSegment aMiniSegment(track.at(newPosition),
555  ionizationSegments[(numberOfLevels-1)][i],
556  deltaS, mId);
557  if(aMiniSegment.position().z()>0)listOfMiniSegments->push_back(aMiniSegment); //HL,03/2001 protect against negative z.
558 
559  newPosition += deltaS;
560  } // loop over subsegments
561 
562 
563 
564 
565  } // charge !=0
566  else {
567  //
568  // Not sure what to do with this?
569  //
570  StTrsMiniChargeSegment aBadMiniSegment(mPosition,
571  mNumberOfElectrons,
572  mDs, mId);
573 
574  }
575 }
576 
577 // Add member functions necessary for tssSplit
578 double StTrsChargeSegment::sigmaParameter(double l, double derelave, double xmip, int index) const
579 {
580  double beta[2] = {1.0, 2.0};
581  double b[2] = {0.0, -0.02};
582  double gamma[2] = {.0041, .0052};
583  double c[2] = {-1.02, -1.02};
584  double delta[2] = {-.022,-.0058};
585  double d[2] = {-1.88, -1.92};
586 
587  double a = ::pow(xmip,delta[index])+d[index]+b[index]*derelave;
588  double alpha = (::pow(xmip,gamma[index])+c[index])/(::pow(derelave,beta[index]));
589  return (::pow(l,alpha)+a);
590 }
591 
592 double StTrsChargeSegment::meanParameter(double l, double derelave, double xmip, int index) const
593 {
594  double a[2] = {0.367, 0.267};
595  double alpha[2] = {.05, .1};
596  double beta[2] = {.2, 1.0};
597  double gamma[2] = {.0423, .0852};
598 
599  return ( (a[index]*::pow(l,gamma[index])*::pow(xmip,alpha[index]))/(::pow(derelave,beta[index])) );
600 }
601 
602 double StTrsChargeSegment::xReflectedGauss(double x0, double sig) const
603 {
604  double granularity = .001;
605  double root2Sigma = M_SQRT2*sig;
606  double denom = TMath::Erf((1.-x0)/root2Sigma) + TMath::Erf(x0/root2Sigma);
607  double testValue = mFlatDistribution.shoot();
608 
609  double xlo =0.;
610  double xhi = 1.;
611 
612  double x,p;
613  do {
614  x = .5*(xlo+xhi);
615  p =.5*(1. + (TMath::Erf((x-x0)/root2Sigma) + TMath::Erf((x+x0-1)/root2Sigma))/denom);
616  if( (fabs(testValue-p)<granularity) || (fabs(xhi-xlo)<1.e-7)) {
617  return x;
618  }
619  else if (testValue>p) {
620  xlo = x;
621  }
622  else {
623  xhi = x;
624  }
625  } while(true);
626 }
627 
628 double StTrsChargeSegment::xReflectedLandau(double x0, double sig) const
629 {
630  // uses dislan_() from CERNLIB
631  double granularity = .001;
632 
633  float arg3 = (1.-x0)/sig;
634  float arg4 = -x0/sig;
635 
636  float dlan3 = dislan(arg3);
637  float dlan4 = dislan(arg4);
638 
639  double denom = dlan3 - dlan4;
640 
641  double testValue = mFlatDistribution.shoot();
642 
643  double xlo =0.;
644  double xhi = 1.;
645 
646  float arg1, arg2;
647  float dlan1, dlan2;
648 
649  int counter=0;
650  double x,p;
651  do {
652  x = .5*(xlo+xhi);
653  arg1 = (x-x0)/sig;
654  arg2 = (1.-x-x0)/sig;
655  dlan1 = dislan(arg1);
656  dlan2 = dislan(arg2);
657  if (isnan(dlan1)) dlan1=0;
658  p = .5*(1. + (dlan1 - dlan2)/denom);
659  if( (fabs(testValue-p)<granularity) ) {
660  return x;
661  }
662  else if (testValue>p) {
663  xlo = x;
664  }
665  else {
666  xhi = x;
667  }
668  if(counter++ == 100){
669  cout << "Probable race condition in loop in StTrsChargeSegement::xReflectedLandau" << endl;
670  PR(arg1); PR(arg2); PR(arg3); PR(arg4);
671  return x;
672  }
673  } while(true);
674 }
675 
676 double StTrsChargeSegment::binaryPartition(double l, double derelave, double xmip) const
677 {
678  int index;
679  if(derelave<1.)
680  index = 0; // f2c indices
681  else
682  index = 1;
683 
684  double x0 = fabs(meanParameter(l,derelave,xmip,index));
685  double sig = fabs(sigmaParameter(l,derelave,xmip,index));
686 
687  if(x0>1) x0 = .001;
688  if(sig>1) sig = 1.0;
689 
690  double value;
691  if(index == 0) {
692  value = xReflectedGauss(x0,sig);
693  }
694  else {
695  value = xReflectedLandau(x0,sig);
696  }
697  return value;
698 }
699 
700 
701 // Non-member
702 ostream& operator<<(ostream& os, const StTrsChargeSegment& seg)
703 {
704  return os << "(Pos:" << seg.position() << ", mon:" << seg.momentum()
705  << ", id:" << seg.id()
706  << ", dE:" << seg.dE()
707  << ", dS:" << seg.ds()
708  << ", pid:" << seg.pid()
709  << ")";
710 }