StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StETofGeometry.cxx
1 /***************************************************************************
2  *
3  * $Id: StETofGeometry.cxx,v 1.4 2019/12/10 16:03:46 fseck Exp $
4  *
5  * Author: Florian Seck, April 2018
6  ***************************************************************************
7  *
8  * Description: Collection of geometry classes for the eTOF:
9  * - StETofNode: generic eTOF geometry object initialized via
10  * TGeoManager
11  * - StETofGeomModule, StETofGeomCounter inherit from StETofNode
12  * - StETofGeometry builds the geometry and features all
13  * necessary methods to match track helices with eTOF hits
14  *
15  ***************************************************************************
16  *
17  * $Log: StETofGeometry.cxx,v $
18  * Revision 1.4 2019/12/10 16:03:46 fseck
19  * added handling of StPicoHelix in extrapolation & step-wise extrapolation in changing magnetic field
20  *
21  * Revision 1.3 2019/04/23 23:48:58 fseck
22  * added support for StPicoHelix and fixed bug in sectorAtPhi() leading to inefficiencies
23  *
24  * Revision 1.2 2019/02/19 20:20:14 fseck
25  * update after second part of eTOF code review
26  *
27  * Revision 1.1 2018/07/25 14:34:40 jeromel
28  * First version, reviewed Raghav+Jerome
29  *
30  *
31  ***************************************************************************/
32 #include <algorithm>
33 #include <fstream>
34 
35 #include "TGeoManager.h"
36 #include "TGeoVolume.h"
37 #include "TGeoPhysicalNode.h"
38 #include "TGeoMatrix.h"
39 #include "TGeoBBox.h"
40 
41 #include "StETofUtil/StETofGeometry.h"
42 #include "StMessMgr.h"
43 
44 #include "StETofHit.h"
45 #include "StMuDSTMaker/COMMON/StMuETofHit.h"
46 #include "StPicoEvent/StPicoETofHit.h"
47 
48 #include "tables/St_etofAlign_Table.h"
49 
50 #include "StarMagField.h"
51 
52 #include "StMaker.h"
53 
55 //
56 // StETofNode
57 // ==========
58 //
60 
61 StETofNode::StETofNode( const TGeoPhysicalNode& gpNode )
62 : mSafetyMarginX( 0. ),
63  mSafetyMarginY( 0. ),
64  mDebug( false )
65 {
66 
67  mGeoMatrix = static_cast< TGeoHMatrix* > ( gpNode.GetMatrix() );
68  mBox = static_cast< TGeoBBox* > ( gpNode.GetShape() );
69 
70  buildMembers();
71 }
72 
73 StETofNode::StETofNode( const TGeoPhysicalNode& gpNode, const float& dx, const float& dy, const StThreeVectorD alignment = { 0, 0, 0 } )
74 : mSafetyMarginX( 0. ),
75  mSafetyMarginY( 0. ),
76  mDebug( false )
77 {
78  mGeoMatrix = static_cast< TGeoHMatrix* > ( gpNode.GetMatrix() );
79 
80  mBox = static_cast< TGeoBBox* > ( gpNode.GetShape() );
81 
82  // resize mBox with dx and dy
83  float dz = mBox->GetDZ();
84  mBox->SetBoxDimensions( dx, dy, dz );
85 
86  // modified buildMembers() method. PW;
87  // build member variables: mMinEta, mMaxEta, mMinPhi, mMaxPhi, mCenter, mNormal
88  double xl[3] = { -alignment.x(), -alignment.y(), -alignment.z() };
89  //z alignment is positive to reflect the correct direction in which z has to be moved in global coordinates. x and y are negative to match the numbers from hit-intersection
90  double xm[3];
91  local2Master( xl, xm );
92 
93  mCenter = StThreeVectorD( xm[ 0 ], xm[ 1 ], xm[ 2 ] );
94  mGeoMatrix->SetDx(xm[ 0 ]);
95  mGeoMatrix->SetDy(xm[ 1 ]);
96  mGeoMatrix->SetDz(xm[ 2 ]);
97  //correct counter rotation is implemented in .XML
98 
99  LOG_DEBUG << "StETofNode::Created physical node at: "<< xm[ 0 ]<<","<< xm[ 1 ]<<"," << xm[ 2 ]<<" with alignments: "<< alignment.x()<<","<< alignment.y()<<"," << alignment.z()<< endm;//debug PW.
100 
101  mNormal = calcXYPlaneNormal();
102 
103  mEtaMin = calcEta( -1. );
104  mEtaMax = calcEta( 1. );
105 
106  mPhiMin = calcPhi( -1, -1. );
107  mPhiMax = calcPhi( -1, 1. );
108 
109  if( mDebug ) print();
110 }
111 
112 void
113 StETofNode::convertPos( StETofNode* from, const double* pos_from, StETofNode* to, double* pos_to )
114 {
115  if( to == 0 ) {
116  from->local2Master( pos_from, pos_to );
117  }
118  else {
119  double xg[ 3 ];
120  from->local2Master( pos_from, xg );
121  to->master2Local( xg, pos_to );
122  }
123 }
124 
125 
126 void
127 StETofNode::local2Master( const double* local, double* master )
128 {
129  // transformation from local cooridinates into global coordinates
130  mGeoMatrix->LocalToMaster( local, master );
131 }
132 
133 
134 void
135 StETofNode::master2Local( const double* master, double* local )
136 {
137  // transformation from global cooridinates into local coordinates
138  mGeoMatrix->MasterToLocal( master, local );
139 }
140 
141 
143 StETofNode::calcCenterPos()
144 {
145  // calculate center position of the node in global coordinates
146  double xl[3] = { 0, 0, 0 }; //can change centers here, but might not change actual box dimensions
147  double xm[3];
148 
149  local2Master( xl, xm );
150 
151  return StThreeVectorD( xm[ 0 ], xm[ 1 ], xm[ 2 ] );
152 }
153 
154 
156 StETofNode::calcXYPlaneNormal()
157 {
158  // calculate the normal vector to the local XY-plane
159  // i.e. the global representation of the local unit vector (0,0,1)
160 
161  double xl[ 3 ] = { 0, 0, 1 };
162  double xm[ 3 ];
163 
164  // transform to global coordinates
165  local2Master( xl, xm );
166 
167  StThreeVectorD norm( xm[ 0 ], xm[ 1 ], xm[ 2 ] );
168 
169  // subtract vector pointing to the center
170  norm -= mCenter;
171 
172  return norm;
173 }
174 
175 
176 double
177 StETofNode::calcEta( const double& rel_local_x )
178 {
179  // calculate min (relative local x = -1) / max (relative local x = 1) eta at the edges of the node
180  double xl[3] = { 0, 0, 0 };
181  double xm[3];
182 
183  if( fabs( rel_local_x ) <= 1. && rel_local_x != 0. ) {
184  double dx = mBox->GetDX();
185  xl[ 0 ] = dx * rel_local_x;
186  }
187 
188  local2Master( xl, xm );
189  return StThreeVectorD( xm[ 0 ], xm[ 1 ], xm[ 2 ] ).pseudoRapidity();
190 }
191 
192 
193 double
194 StETofNode::calcPhi( const double& rel_local_x, const double& rel_local_y )
195 {
196  // calculate min (relative local y = -1) / max (relative local y = 1) phi at the edges of the node
197  // set rel_local_x to -1 to get the lower edge (largest span of the node in phi)
198  double xl[3] = { 0, 0, 0 };
199  double xm[3];
200 
201  if( fabs( rel_local_x ) <= 1. && rel_local_x != 0. ) {
202  double dx = mBox->GetDX();
203  xl[ 0 ] = dx * rel_local_x;
204  }
205  if( fabs( rel_local_y ) <= 1. && rel_local_y != 0. ) {
206  double dy = mBox->GetDY();
207  xl[ 1 ] = dy * rel_local_y;
208  }
209 
210  local2Master( xl, xm );
211  return StThreeVectorD( xm[ 0 ], xm[ 1 ], xm[ 2 ] ).phi();
212 }
213 
214 
215 void
216 StETofNode::buildMembers()
217 {
218  // build member variables: mMinEta, mMaxEta, mMinPhi, mMaxPhi, mCenter, mNormal
219  mCenter = calcCenterPos();
220  mNormal = calcXYPlaneNormal();
221 
222  mEtaMin = calcEta( -1. );
223  mEtaMax = calcEta( 1. );
224 
225  mPhiMin = calcPhi( -1, -1. );
226  mPhiMax = calcPhi( -1, 1. );
227 
228  if( mDebug ) print();
229 }
230 
231 
232 void
233 StETofNode::setSafetyMargins( const double* margins )
234 {
235  if (!margins) {
236  mSafetyMarginX = 0;
237  mSafetyMarginY = 0;
238  return;
239  }
240 
241  if( margins[ 0 ] < 0 || margins[ 1 ] < 0 ) {
242  LOG_DEBUG << "StETofNode::setSafetyMargins() -- WARNING: input values are negative" << endm;
243  }
244  mSafetyMarginX = margins[ 0 ];
245  mSafetyMarginY = margins[ 1 ];
246 }
247 
248 
249 bool
250 StETofNode::isLocalPointIn( const double* local )
251 {
252  // returns true if point in local coordinates is inside the node's volume
253  //return mBox->Contains( local );
254 
255  if ( fabs( local[ 0 ] ) > mBox->GetDX() + mSafetyMarginX ) return false;
256  if ( fabs( local[ 1 ] ) > mBox->GetDY() + mSafetyMarginY ) return false;
257  if ( fabs( local[ 2 ] ) > mBox->GetDZ() ) return false;
258 
259  return true;
260 }
261 
262 
263 bool
264 StETofNode::isGlobalPointIn( const StThreeVectorD& global )
265 {
266  // returns true if point in global coordinates is inside the node's volume
267  double xm[ 3 ] = { global.x(), global.y(), global.z() };
268  double xl[ 3 ];
269 
270  master2Local( xm, xl );
271 
272  return isLocalPointIn( xl );
273 }
274 
275 bool
276 StETofNode::isGlobalPointIn( const TVector3& global )
277 {
278  // returns true if point in global coordinates is inside the node's volume
279  double xm[ 3 ] = { global.x(), global.y(), global.z() };
280  double xl[ 3 ];
281 
282  master2Local( xm, xl );
283 
284  return isLocalPointIn( xl );
285 }
286 
287 bool
288 StETofNode::helixCross( const StHelixD& helix, double& pathLength, StThreeVectorD& cross, double& theta )
289 {
290  // check if helix goes through this node
291  // and return path length of helix before crossing this node
292  float maxPathLength = 1000;
293 
294  bool isInside = false;
295  pathLength = -1.;
296 
297  // find intersection between helix & the node's XY-plane
298  pathLength = helix.pathLength( mCenter, mNormal );
299 
300  if( pathLength > 0 && pathLength < maxPathLength ) {
301  cross = helix.at( pathLength );
302  theta = mNormal.angle( -helix.cat( pathLength ) );
303  }
304 
305  // check if the intersection point is really inside the node
306  isInside = isGlobalPointIn( cross );
307 
308  return isInside;
309 }
310 
311 
312 bool
313 StETofNode::helixCross( const StPicoHelix& helix, double& pathLength, TVector3& cross, double& theta )
314 {
315  // check if helix goes through this node
316  // and return path length of helix before crossing this node
317  float maxPathLength = 1000;
318 
319  bool isInside = false;
320  pathLength = -1.;
321 
322  // find intersection between helix & the node's XY-plane
323  TVector3 center( mCenter.x(), mCenter.y(), mCenter.z() );
324  TVector3 normal( mNormal.x(), mNormal.y(), mNormal.z() );
325  pathLength = helix.pathLength( center, normal ); //pathlength at the crossing with counter plane defined by counter center and normal vector
326 
327  if( pathLength > 0 && pathLength < maxPathLength ) {
328  cross = helix.at( pathLength );
329  theta = normal.Angle( -helix.cat( pathLength ) );
330  }
331 
332  // check if the intersection point is really inside the node
333  isInside = isGlobalPointIn( cross );
334 
335  return isInside;
336 }
337 
338 
339 void
340 StETofNode::print( const Option_t* opt ) const
341 {
342  double* trans = mGeoMatrix->GetTranslation();
343  double* rotMat = mGeoMatrix->GetRotationMatrix();
344 
345  LOG_INFO << " -------- "
346  << "\nBox dimension: " << mBox->GetDX() << " : " << mBox->GetDY() << " : " << mBox->GetDZ()
347  << "\ncenter pos: " << mCenter.x() << " : " << mCenter.y() << " : " << mCenter.z()
348  << "\ncenter phi: " << mCenter.phi() << ", eta: " << mCenter.pseudoRapidity()
349  << "\nphi range: " << mPhiMin << " : " << mPhiMax
350  << "\teta range: " << mEtaMin << " : " << mEtaMax
351  << "\nXYplane normal: " << mNormal.x() << " : " << mNormal.y() << " : " << mNormal.z()
352  << "\ntrans [0-2] = " << trans[ 0 ] << " " << trans[ 1 ] << " " << trans[ 2 ]
353  << "\nrotMat[0-2] = " << rotMat[ 0 ] << " " << rotMat[ 1 ] << " " << rotMat[ 2 ]
354  << "\nrotMat[3-5] = " << rotMat[ 3 ] << " " << rotMat[ 4 ] << " " << rotMat[ 5 ]
355  << "\nrotMat[6-8] = " << rotMat[ 6 ] << " " << rotMat[ 7 ] << " " << rotMat[ 8 ]
356  << "\n ------------------------------------------------ " << endm;
357 }
358 
359 
360 
361 
362 
364 //
365 // StETofGeomModule
366 // ================
367 //
369 
370 StETofGeomModule::StETofGeomModule( const TGeoPhysicalNode& gpNode, const int moduleId )
371 : StETofNode( gpNode ),
372  mModuleIndex( moduleId ),
373  mDebug( false )
374 {
375  mSector = calcSector( moduleId );
376  mPlane = calcPlane( moduleId );
377 
378  mETofCounter.reserve( eTofConst::nCounters );
379 
380  if( mDebug ) print();
381 }
382 
383 void
384 StETofGeomModule::addCounter( const TGeoPhysicalNode& gpNode, const float& dx, const float& dy, const int moduleId, const int counterId, const double* safetyMargins = initializer_list<double>({0, 0}).begin(), const StThreeVectorD alignment = {0,0,0} )
385 {
386  StETofGeomCounter* counter = new StETofGeomCounter( gpNode, dx, dy, moduleId, counterId, alignment );
387 
388  counter->setSafetyMargins( safetyMargins );
389 
390  mETofCounter.push_back( counter );
391 }
392 
393 
395 StETofGeomModule::counter( const unsigned int i ) const
396 {
397  if( mETofCounter.size() <= i || i < 0 ) {
398  LOG_ERROR << "Counter not defined" << endm;
399  return nullptr;
400  }
401 
402  return mETofCounter[ i ];
403 }
404 
405 void
406 StETofGeomModule::clearCounters()
407 {
408  for( size_t i=0; i<mETofCounter.size(); i++ ) {
409  LOG_DEBUG << "deleting counter (" << i << ")" << endm;
410  delete mETofCounter[ i ];
411  }
412  mETofCounter.clear();
413 }
414 
415 
416 int
417 StETofGeomModule::calcSector( const int moduleId )
418 {
419  // calculate sector from moduleId
420  // moduleId = (plane - 1) + 3 * (sector - 13)
421  return ( moduleId / eTofConst::nPlanes ) + eTofConst::sectorStart;
422 }
423 
424 
425 int
426 StETofGeomModule::calcPlane( const int moduleId )
427 {
428  // calculate plane from moduleId
429  // moduleId = (plane - 1) + 3 * (sector - 13)
430  return ( moduleId % eTofConst::nPlanes ) + eTofConst::zPlaneStart;
431 }
432 
433 
434 void
435 StETofGeomModule::print( const Option_t* opt ) const
436 {
437  LOG_INFO << "StETofGeomModule, module# = " << mModuleIndex << " sector = " << mSector << " plane = " << mPlane << endm;
438  StETofNode::print( opt );
439 }
440 
441 
442 
443 
444 
446 //
447 // StETofGeomCounter
448 // =================
449 //
451 
452 StETofGeomCounter::StETofGeomCounter( const TGeoPhysicalNode& gpNode, const int moduleId, const int counterId )
453 : StETofNode( gpNode ),
454  mModuleIndex( moduleId ),
455  mCounterIndex( counterId ),
456  mDebug( false )
457 {
458  mSector = calcSector( moduleId );
459  mPlane = calcPlane( moduleId );
460 
461  createGeomStrips();
462 
463  if( mDebug ) print();
464 }
465 
466 
467 StETofGeomCounter::StETofGeomCounter( const TGeoPhysicalNode& gpNode, const float& dx, const float& dy, const int moduleId, const int counterId, const StThreeVectorD alignment = { 0, 0, 0 } )
468 : StETofNode( gpNode, dx, dy, alignment ),
469  mModuleIndex( moduleId ),
470  mCounterIndex( counterId ),
471  mDebug( false )
472 {
473  mSector = calcSector( moduleId );
474  mPlane = calcPlane( moduleId );
475 
476  createGeomStrips();
477 
478  if( mDebug ) print();
479 }
480 
481 int
482 StETofGeomCounter::calcSector( const int moduleId )
483 {
484  // calculate sector from moduleId
485  // moduleId = (plane - 1) + 3 * (sector - 13)
486  return ( moduleId / eTofConst::nPlanes ) + eTofConst::sectorStart;
487 }
488 
489 
490 int
491 StETofGeomCounter::calcPlane( const int moduleId )
492 {
493  // calculate plane from moduleId
494  // moduleId = (plane - 1) + 3 * (sector - 13)
495  return ( moduleId % eTofConst::nPlanes ) + eTofConst::zPlaneStart;
496 }
497 
498 
499 void
500 StETofGeomCounter::createGeomStrips()
501 {
502  // divide the counter into strips
503  float counterDx = this->box()->GetDX();
504  float stripPitch = 2 * counterDx / eTofConst::nStrips;
505 
506  for( int i=0; i<=eTofConst::nStrips; i++) {
507  mStripX[ i ] = stripPitch * i - counterDx;
508  }
509 }
510 
511 
512 int
513 StETofGeomCounter::findStrip( const double* local )
514 {
515  // look up the strip the local point is in
516  int iStrip = -999;
517 
518  // only care about the local X coordinate
519  double xl[ 3 ] = { local[ 0 ], 0. ,0. };
520 
521  if( isLocalPointIn( xl ) ) {
522  for( int i=0; i<eTofConst::nStrips; i++ ) {
523  if( mStripX[ i ] <= xl[ 0 ] && xl[ 0 ] <= mStripX[ i+1 ] ) {
524  iStrip = i+1;
525  break;
526  }
527  }
528  if( xl[ 0 ] < mStripX[ 0 ] ) iStrip = 0;
529  if( xl[ 0 ] > mStripX[ eTofConst::nStrips ] ) iStrip = 33;
530  }
531 
532  return iStrip;
533 }
534 
535 
536 void
537 StETofGeomCounter::print( const Option_t* opt ) const
538 {
539  LOG_INFO << "StETofGeomCounter, module# = " << mModuleIndex << " sector = " << mSector << " plane = " << mPlane << " counter = " << mCounterIndex + 1 << endm;
540  StETofNode::print( opt );
541 }
542 
543 
544 
545 
546 
548 //
549 // StETofGeometry
550 // ==============
551 //
553 
554 StETofGeometry::StETofGeometry( const char* name, const char* title )
555 : TNamed( name, title ),
556  mNValidModules( 0 ),
557  mInitFlag( false ),
558  mDebug( false ),
559  mStarBField( nullptr ),
560  mFileNameAlignParam("")
561 {
562 
563 }
564 
565 
566 StETofGeometry::~StETofGeometry()
567 {
568  reset();
569 }
570 
571 
572 void
573 StETofGeometry::init( TGeoManager* geoManager, const double* safetyMargins, const bool useHelixSwimmer )
574 {
575  if( !geoManager ) {
576  LOG_ERROR << " *** StETofGeometry::Init - cannot find TGeoManager *** " << endm;
577  return;
578  }
579 
580  LOG_DEBUG << " +++ geoManager : " << geoManager << endm;
581 
582  mNValidModules = 0;
583 
584  if ( !mFileNameAlignParam.empty() ) {
585  readAlignmentParameters();
586  } else {
587  readAlignmentDatabase();
588  }
589 
590  if( mAlignmentParameters.size() != eTofConst::nCounters * eTofConst::nModules ){
591  LOG_ERROR << "StETofGeometry::Init(...) - Wrong size of counter alignment vector. Either incomplete alignment file or non-existant database table." << endm;
592  return;
593  }
594 
595  int iCounterAlignment = 0;
596  // loop over sectors
597  for( int sector = eTofConst::sectorStart; sector <= eTofConst::sectorStop; sector++ ) {
598  // loop over planes
599  for( int plane = eTofConst::zPlaneStart; plane <= eTofConst::zPlaneStop; plane++ ) {
600  std::string geoPath( formTGeoPath( geoManager, plane, sector ) );
601 
602  if( geoPath.empty() ) {
603  LOG_INFO << "StETofGeometry::Init(...) - cannot find path to ETOF module "
604  "(id " << plane << sector << "). Skipping..." << endm;
605  continue;
606  }
607  mNValidModules++;
608 
609  const TGeoPhysicalNode* gpNode = geoManager->MakePhysicalNode( geoPath.c_str() );
610 
611  int moduleId = calcModuleIndex( sector, plane );
612 
613  mETofModule[ mNValidModules-1 ] = new StETofGeomModule( *gpNode, moduleId );
614 
615 
616  // load the counters of the modules
617  // loop over counters
618  for( int counter = eTofConst::counterStart; counter <= eTofConst::counterStop; counter++ ) {
619  std::string geoPath( formTGeoPath( geoManager, plane, sector, counter ) );
620 
621  if( geoPath.empty() ) {
622  LOG_DEBUG << "StETofGeometry::Init(...) - cannot find path to ETOF counter "
623  "(id " << plane << sector << ", " << counter << "). Skipping..." << endm;
624  continue;
625  }
626 
627  const TGeoPhysicalNode* gpNode = geoManager->MakePhysicalNode( geoPath.c_str() );
628 
629  //get the gas gap dimensions
630  int gap = 1;
631  std::string geoPathActiveVolume( formTGeoPath( geoManager, plane, sector, counter, gap ) );
632 
633  if( geoPathActiveVolume.empty() ) {
634  LOG_DEBUG << "StETofGeometry::Init(...) - cannot find path to ETOF counter gas gap (for active area evaluation)"
635  "(id " << plane << sector << ", " << counter << "). Skipping..." << endm;
636  continue;
637  }
638 
639  const TGeoPhysicalNode* gpNodeActiveVolume = geoManager->MakePhysicalNode( geoPathActiveVolume.c_str() );
640 
641  const TGeoBBox* activeVolume = static_cast< TGeoBBox* > ( gpNodeActiveVolume->GetShape() );
642 
643  float dx = activeVolume->GetDX();
644  float dy = activeVolume->GetDY();
645 
646  LOG_DEBUG << activeVolume->GetDX() << " " << activeVolume->GetDY() << " " << activeVolume->GetDZ() << endm;
647 
648  int counterId = counter - eTofConst::counterStart;
649  mETofModule[ mNValidModules-1 ]->addCounter( *gpNode, dx, dy, moduleId, counterId, safetyMargins, mAlignmentParameters.at(iCounterAlignment) );
650  iCounterAlignment++;
651  } // end of loop over counters
652 
653  } // end of loop over planes
654  } // end of loop over sectors
655 
656  LOG_INFO << "amount of valid modules: " << mNValidModules << endm;
657 
658 
659  // ----------------------
660  if( useHelixSwimmer ) {
661  // get magnetic field map
662  if( !StarMagField::Instance() ) {
663  LOG_INFO << " no StMagField available ... " << endm;
664  }
665  else {
666  mStarBField = StarMagField::Instance();
667  LOG_INFO << " ... initializing magnetic field from StarMagField: fScale = " << mStarBField->GetFactor() << endm;
668  }
669  }
670  // ----------------------
671 
672 
673  // finished initializing geometry
674  setInitFlag( true );
675 }
676 
677 
678 void
679 StETofGeometry::reset()
680 {
681  for( size_t i=0; i<mNValidModules; i++ ) {
682  LOG_DEBUG << "for ETofModule (" << i << ")" << endm;
683  mETofModule[ i ]->clearCounters();
684 
685  LOG_DEBUG << "deleting ETofModule (" << i << ")" << endm;
686  delete mETofModule[ i ];
687  mETofModule[ i ] = 0;
688  }
689  LOG_INFO << "StETofGeometry cleared up ...." << endm;
690 
691  mNValidModules = 0;
692  mAlignmentParameters.clear();
693  mInitFlag = false;
694 
695  mStarBField = nullptr;
696 }
697 
698 
704 std::string
705 StETofGeometry::formTGeoPath( const TGeoManager* geoManager, int plane, int sector, int counter )
706 {
707  std::ostringstream geoPath;
708 
709  geoPath << "/HALL_1/CAVE_1/MagRefSys_1/ETOF_" << plane << sector;
710 
711  bool found = geoManager->CheckPath( geoPath.str().c_str() );
712 
713  if( !found ) {
714  geoPath.str("");
715  geoPath.clear();
716 
717  geoPath << "/HALL_1/CAVE_1/ETOF_" << plane << sector;
718  }
719 
720  // go deeper if counter is requested
721  if( counter >= 1 ) {
722  geoPath << "/EGAS_1/ECOU_" << counter;
723  }
724 
725  found = geoManager->CheckPath( geoPath.str().c_str() );
726 
727  return found ? geoPath.str() : "";
728 }
729 
730 
731 std::string
732 StETofGeometry::formTGeoPath( const TGeoManager* geoManager, int plane, int sector, int counter, int gap )
733 {
734  std::ostringstream geoPath;
735 
736  geoPath << "/HALL_1/CAVE_1/MagRefSys_1/ETOF_" << plane << sector;
737 
738  bool found = geoManager->CheckPath( geoPath.str().c_str() );
739 
740  if( !found ) {
741  geoPath.str("");
742  geoPath.clear();
743 
744  geoPath << "/HALL_1/CAVE_1/ETOF_" << plane << sector;
745  }
746 
747  // go deeper if counter is requested
748  if( counter >= 1 ) {
749  geoPath << "/EGAS_1/ECOU_" << counter;
750  }
751  if( gap >= 1 ) {
752  geoPath << "/EGAP_" << gap;
753  }
754 
755  found = geoManager->CheckPath( geoPath.str().c_str() );
756 
757  return found ? geoPath.str() : "";
758 }
759 
760 
761 int
762 StETofGeometry::calcModuleIndex( const int& sector, const int& plane )
763 {
764  // calculate module index from sector (13 -- 24) and plane (1 -- 3)
765  return (plane - eTofConst::zPlaneStart ) + eTofConst::nPlanes * ( sector - eTofConst::sectorStart );
766 }
767 
768 
769 int
770 StETofGeometry::calcVolumeIndex( const int& sector, const int& plane, const int& counter, const int& strip )
771 {
772  // calculate volume Id
773  int idMultiplier[ 3 ] = { 10000, 1000, 100 };
774  int id = sector * idMultiplier[ 0 ] + plane * idMultiplier[ 1 ] + counter * idMultiplier[ 2 ] + strip;
775 
776  return id;
777 }
778 
779 void
780 StETofGeometry::decodeVolumeIndex( const int& volumeId, int& sector, int& plane, int& counter, int& strip )
781 {
782  // decode volume Id
783  int idMultiplier[ 3 ] = { 10000, 1000, 100 };
784 
785  sector = volumeId / idMultiplier[ 0 ];
786  plane = ( volumeId % idMultiplier[ 0 ] ) / idMultiplier[ 1 ];
787  counter = ( volumeId % idMultiplier[ 1 ] ) / idMultiplier[ 2 ];
788  strip = volumeId % idMultiplier[ 2 ];
789 }
790 
791 
792 StETofNode*
793 StETofGeometry::findETofNode( const int moduleId, const int counterId )
794 {
795  int iModule = -1;
796  int iCounter = -1;
797 
798  for( unsigned int i=0; i<mNValidModules; i++ ) {
799  if( mETofModule[ i ]->moduleIndex() == moduleId ) {
800  iModule = i;
801  break;
802  }
803  }
804 
805  if( iModule == -1 ) {
806  LOG_ERROR << "ETOF volume for moduleId " << moduleId << " and counter " << counterId << " is not loaded ..." << endm;
807  return nullptr;
808  }
809 
810  int nValidCounters = mETofModule[ iModule ]->numberOfCounters();
811 
812  for( int j=0; j<nValidCounters; j++ ) {
813  if( mETofModule[ iModule ]->counter( j )->counterIndex() == counterId ) {
814  iCounter = j;
815  break;
816  }
817  }
818 
819  if( iCounter == -1 ) {
820  LOG_ERROR << "ETOF volume for moduleId " << moduleId << " and counter " << counterId << " is not loaded ..." << endm;
821  return nullptr;
822  }
823 
824  return mETofModule[ iModule ]->counter( iCounter );
825 }
826 
827 void
828 StETofGeometry::pointMaster2local( const int moduleId, const int counterId, const double* master, double* local )
829 {
830  local[ 0 ] = 0;
831  local[ 1 ] = 0;
832  local[ 2 ] = 0;
833 
834  if( !findETofNode( moduleId, counterId ) ) {
835  LOG_ERROR << "ETOF volume of a hit is not loaded in the geometry" << endm;
836  return;
837  }
838 
839  findETofNode( moduleId, counterId )->master2Local( master, local );
840 }
841 
842 
843 void
844 StETofGeometry::hitLocal2Master( const int moduleId, const int counterId, const double* local, double* master )
845 {
846  master[ 0 ] = 0;
847  master[ 1 ] = 0;
848  master[ 2 ] = 0;
849 
850  if( !findETofNode( moduleId, counterId ) ) {
851  LOG_ERROR << "ETOF volume of a hit is not loaded in the geometry" << endm;
852  return;
853  }
854 
855  findETofNode( moduleId, counterId )->local2Master( local, master );
856 }
857 
859 StETofGeometry::hitLocal2Master( StETofHit* hit )
860 {
861  // local to global coordinate conversion
862  // -------------------------------------
863  double xl[ 3 ] = { hit->localX(), hit->localY(), 0. };
864  double xg[ 3 ] = { 0., 0., 0. };
865 
866  int moduleId = calcModuleIndex( hit->sector(), hit->zPlane() );
867  int counterId = hit->counter() - 1;
868 
869  if( !findETofNode( moduleId, counterId ) ) {
870  LOG_ERROR << "ETOF volume of a hit is not loaded in the geometry" << endm;
871  return StThreeVectorD( 0., 0., 0. );
872  }
873 
874  findETofNode( moduleId, counterId )->local2Master( xl, xg );
875 
876  return StThreeVectorD( xg[ 0 ], xg[ 1 ], xg[ 2 ] );
877 }
878 
880 StETofGeometry::hitLocal2Master( StMuETofHit* hit )
881 {
882  return hitLocal2Master( ( StETofHit* ) hit );
883 }
884 
885 
886 TVector3
887 StETofGeometry::hitLocal2Master( StPicoETofHit* hit )
888 {
889  // local to global coordinate conversion
890  // -------------------------------------
891  double xl[ 3 ] = { hit->localX(), hit->localY(), 0. };
892  double xg[ 3 ] = { 0., 0., 0. };
893 
894  int moduleId = calcModuleIndex( hit->sector(), hit->zPlane() );
895  int counterId = hit->counter() - 1;
896 
897  if( !findETofNode( moduleId, counterId ) ) {
898  LOG_ERROR << "ETOF volume of a hit is not loaded in the geometry" << endm;
899  return TVector3( 0., 0., 0. );
900  }
901 
902  findETofNode( moduleId, counterId )->local2Master( xl, xg );
903 
904  return TVector3( xg[ 0 ], xg[ 1 ], xg[ 2 ] );
905 }
906 
907 
909 StETofGeometry::helixCrossPlane( const StHelixD& helix, const double& z )
910 {
911  if( isDebugOn() ) {
912  LOG_INFO << "zplane:" << z << endm;
913  }
914 
915  // XY plane at z
916  StThreeVectorD r( 0, 0, z );
917 
918  // normal to XY plane
919  StThreeVectorD n( 0, 0, 1 );
920 
921  if( isDebugOn() )
922  logPoint( "( outer- ) helix origin" , helix.origin() );
923 
924  double s = helix.pathLength( r, n );
925  if( s<0. || s>4000. ) return StThreeVectorD( -999., -999., 999. );
926 
927  StThreeVectorD point = helix.at( s );
928  if( point.perp() > 300. ) return StThreeVectorD( -999., -999., 999. );
929 
930  if( isDebugOn() ) {
931  LOG_INFO << "pathLength @ ETOF plane = " << s << endm;
932  logPoint( "intersection", point );
933  }
934 
935  return point;
936 }
937 
939 StETofGeometry::helixCrossETofPlane( const StHelixD& helix )
940 {
941  return helixCrossPlane( helix, eTofConst::zplanes[ 1 ] );
942 }
943 
944 
945 void
946 StETofGeometry::helixSwimmer( const StPhysicalHelixD& helix, StPhysicalHelixD& helixSwimmer, const double& z, double& pathlength )
947 {
948  helixSwimmer = helix;
949 
950  // normal to XY plane
951  StThreeVectorD n( 0., 0., 1. );
952 
953  double zTpcEdge = -220.;
954  if( z > zTpcEdge ) return;
955 
956  // --1-- extrapolate helix to TPC edge
957  double s = helix.pathLength( StThreeVectorD( 0., 0., zTpcEdge ), n );
958  if( s<0. || s>4000. ) {
959  return;
960  }
961 
962  pathlength = s;
963 
964  StThreeVectorD posTpcEdge = helix.at( s );
965  //if( posTpcEdge.perp() > 300. ) false;
966 
967  double bField = getFieldZ( posTpcEdge ) * kilogauss;
968  StThreeVectorD momTpcEdge = helix.momentumAt( s, bField );
969  int charge = helix.charge( bField );
970 
971  // --2-- step through the volume between TPC and eTOF
972  const int nSteps = 10;
973  double stepWidth = ( z - zTpcEdge ) / nSteps; //cm
974 
975  StThreeVectorD posInStep = posTpcEdge;
976  StThreeVectorD momInStep = momTpcEdge;
977 
978  for( int i=0; i<nSteps; i++ ) {
979  double zInStep = zTpcEdge + stepWidth * ( i+1 );
980 
981  bField = getFieldZ( posInStep ) * kilogauss;
982  StPhysicalHelixD helixInStep( momInStep, posInStep, bField, charge );
983 
984  s = helixInStep.pathLength( StThreeVectorD( 0., 0., zInStep ), n );
985  if( s<0. || s>4000. ) {
986  return;
987  }
988 
989  posInStep = helixInStep.at( s );
990  //if( posInStep.perp() > 300. ) return false;
991 
992  momInStep = helixInStep.momentumAt( s, bField );
993 
994  pathlength += s;
995 
996  if( mDebug ) {
997  logPoint( "ideal", helix.at( pathlength ) );
998  logPoint( "swimmer", helixInStep.at( s ) );
999 
1000  LOG_INFO << " pt: " << momInStep.perp() << " helix curvature: " << helixInStep.curvature() << " radius: " << 1./ helixInStep.curvature() << endm;
1001  LOG_INFO << "stepWidth: " << stepWidth << " bField: " << bField << " pathLength: " << s << " mom phi:" << momInStep.phi() << endm;
1002  }
1003  }
1004 
1005  helixSwimmer = StPhysicalHelixD( momInStep, posInStep, bField, charge );
1006 }
1007 
1008 
1009 
1014 std::vector< int >
1016 {
1017  StThreeVectorD point = helixCrossPlane( helix, eTofConst::zplanes[ 1 ] );
1018 
1019  if( fabs( point.x() + 999 ) < 1e-5 ) {
1020  std::vector< int > r;
1021  return r;
1022  }
1023 
1024  LOG_DEBUG << "track phi @ ETOF= " << point.phi() << endm;
1025 
1026  return sectorAtPhi( point.phi() );
1027 }
1028 
1029 std::vector< int >
1030 StETofGeometry::sectorAtPhi( const double& angle )
1031 {
1032  float phi = angle + ( M_PI / 24 ); // offset phi by 7.5 degree so center slices in the middle of a sector
1033 
1034  // make phi bounded by [0, 2pi]
1035  if ( phi < 0. ) phi += 2. * M_PI;
1036 
1037  // 15 degree slice; half of an ETOF sector
1038  double slice = M_PI / 12.;
1039 
1040  // sector 21 at phi = 0
1041  // sector 24 at phi = pi/2
1042  // sector 15 at phi = pi
1043  // sector 18 at phi = 3pi/2
1044  vector< int > sectorId = { 21, 22, 23, 24, 13, 14, 15, 16, 17, 18, 19, 20 };
1045 
1046  double iSlice = phi / slice;
1047  int sectorA = -1;
1048  int sectorB = -1;
1049  int intSlice = ( int ) iSlice;
1050 
1051  int indexA = ( intSlice / 2 ) % sectorId.size(); // prevent index out of range
1052 
1053  // in this case the track falls into a 15 degree slice in the center of the sector, only matches with this sector
1054  if( intSlice % 2 == 0 ) {
1055  sectorA = sectorId[ indexA ];
1056  } else {
1057  // in this case the track is in the 15 degree slice overlap of two sector
1058  int indexB = ( indexA + 1 ) % sectorId.size(); // prevent index out of range
1059 
1060  sectorA = sectorId[ indexA ];
1061  sectorB = sectorId[ indexB ];
1062  }
1063  if ( isDebugOn() ) {
1064  LOG_INFO << "phi = " << phi << ", iSlice = " << iSlice << ", SectorA: " << sectorA << ", SectorB: " << sectorB << endm;
1065  }
1066 
1067  vector< int > r = { sectorA };
1068  if( sectorB >= 13 )
1069  r.push_back( sectorB );
1070 
1071  return r;
1072 }
1073 
1074 
1079 void
1080 StETofGeometry::helixCrossCounter( const StPhysicalHelixD& helix, vector< int >& idVec, vector< StThreeVectorD >& crossVec, vector< StThreeVectorD >& localVec, vector< double >& thetaVec, vector< double >& pathLenVec )
1081 {
1082  // estimate which sector(s) the track crossed
1083  vector< int > sectorsCrossed = helixCrossSector( helix );
1084 
1085  if( sectorsCrossed.size() == 0 ) return;
1086 
1087  if( sectorsCrossed.size() == 1 ) LOG_DEBUG << "sector crossed: " << sectorsCrossed[ 0 ] << endm;
1088  if( sectorsCrossed.size() == 2 ) LOG_DEBUG << "sectors crossed: " << sectorsCrossed[ 0 ] << ", " << sectorsCrossed[ 1 ] << endm;
1089 
1090  // loop over all modules
1091  for( unsigned int i=0; i<mNValidModules; i++ ) {
1092  if( !mETofModule[ i ] ) continue;
1093 
1094  // only search in modules of crossed sectors
1095  int iSector = mETofModule[ i ]->sector();
1096  auto found = std::find( std::begin( sectorsCrossed ), std::end( sectorsCrossed ), iSector );
1097 
1098  if( found == std::end( sectorsCrossed ) ) continue;
1099 
1100  LOG_DEBUG << iSector << " " << mETofModule[ i ]->plane() << endm;
1101 
1102  double module_pathLen;
1103  double module_theta;
1104  StThreeVectorD module_cross;
1105 
1106  bool helixCrossedModule = mETofModule[ i ]->helixCross( helix, module_pathLen, module_cross, module_theta );
1107 
1108  module_theta *= 180. / M_PI;
1109 
1110 
1111  if( mDebug && helixCrossedModule ) {
1112  LOG_INFO << " -----------" << "\nmoduleId:"<< mETofModule[ i ]->moduleIndex() << " helix_crossed: " << helixCrossedModule
1113  << " sector: " << mETofModule[ i ]->sector() << " plane: " << mETofModule[ i ]->plane() << endm;
1114  LOG_INFO << "pathLength: " << module_pathLen << " absolute impact angle: " << module_theta << " degree" << endm;
1115  logPoint( "crossing point" , module_cross );
1116  LOG_INFO << "cross.eta: " << module_cross.pseudoRapidity() << endm;
1117  }
1118 
1119 
1120  // only search for intersections of counters with the helix if the module was crossed
1121  if( !helixCrossedModule ) continue;
1122 
1123  // get helix swimmer
1124  StPhysicalHelixD swimmerHelix;
1125  double swimmerPathLen;
1126 
1127  if( mStarBField ) {
1128  // get swimmer helix 5 cm in front of the module
1129  helixSwimmer( helix, swimmerHelix, mETofModule[ i ]->centerPos().z() + 5., swimmerPathLen );
1130  }
1131 
1132  // loop over counters
1133  int nValidCounters = mETofModule[ i ]->numberOfCounters();
1134  for( int j=0; j<nValidCounters; j++ ) {
1135  double pathLen;
1136  double theta;
1137  StThreeVectorD cross;
1138 
1139  bool helixCrossedCounter = false;
1140 
1141  if( mStarBField ) {
1142  // use helix swimmer
1143  helixCrossedCounter = mETofModule[ i ]->counter( j )->helixCross( swimmerHelix, pathLen, cross, theta );
1144  pathLen += swimmerPathLen;
1145  if( mDebug ) LOG_DEBUG << " using swimmer helix" << endm;
1146  }
1147  else {
1148  // use ideal helix
1149  helixCrossedCounter = mETofModule[ i ]->counter( j )->helixCross( helix, pathLen, cross, theta );
1150  if( mDebug ) LOG_DEBUG << " using ideal helix" << endm;
1151  }
1152 
1153  if( helixCrossedCounter ) {
1154  theta *= 180. / M_PI;
1155 
1156  double global[ 3 ];
1157  double local [ 3 ];
1158 
1159  global[ 0 ] = cross.x();
1160  global[ 1 ] = cross.y();
1161  global[ 2 ] = cross.z();
1162 
1163  mETofModule[ i ]->counter( j )->master2Local( global, local );
1164  int strip = mETofModule[ i ]->counter( j )->findStrip( local );
1165 
1166  int sector = mETofModule[ i ]->sector();
1167  int plane = mETofModule[ i ]->plane();
1168  int counter = mETofModule[ i ]->counter( j )->counterIndex() + 1;
1169 
1170  int volumeIndex = calcVolumeIndex( sector, plane, counter, strip );
1171 
1172  idVec.push_back( volumeIndex );
1173  crossVec.push_back( cross );
1174  localVec.push_back( StThreeVectorD( local[ 0 ], local[ 1 ], local[ 2 ] ) );
1175  thetaVec.push_back( theta );
1176  pathLenVec.push_back( pathLen );
1177 
1178  if( mDebug ) {
1179  LOG_INFO << " -----------" << "\ncounterId: " << mETofModule[ i ]->counter( j )->counterIndex() << endm;
1180  LOG_INFO << "pathLength: " << pathLen << " impact angle: " << theta << " degree" << endm;
1181  logPoint( "crossing point" , cross );
1182  LOG_INFO << "cross.eta: " << cross.pseudoRapidity() << "\n" << endm;
1183  LOG_INFO << "localX: " << local[ 0 ] << " localY: " << local[ 1 ] << " localZ: " << local[ 2 ] << endm;
1184  LOG_INFO << "Strip: " << strip << " * * * " << endm;
1185  }
1186  }
1187 
1188  } // end loop over counters
1189  } // end loop over modules
1190 }
1191 
1192 
1193 void
1194 StETofGeometry::logPoint( const char* text, const StThreeVectorD& point )
1195 {
1196  LOG_INFO << text << " at (" << point.x() << ", " << point.y() << ", " << point.z() << ")" << endm;
1197 }
1198 
1199 
1201 StETofGeometry::module( const unsigned int i )
1202 {
1203  if( isInitDone() && i < mNValidModules ) {
1204  return mETofModule[ i ];
1205  }
1206  else return nullptr;
1207 }
1208 
1209 
1210 
1211 TVector3
1212 StETofGeometry::helixCrossETofPlane( const StPicoHelix& helix )
1213 {
1214  return helixCrossPlane( helix, eTofConst::zplanes[ 1 ] );
1215 }
1216 
1217 
1218 
1219 TVector3
1220 StETofGeometry::helixCrossPlane( const StPicoHelix& helix, const double& z )
1221 {
1222  TVector3 r( 0, 0, z );
1223 
1224  // Normal to ETOF plane
1225  TVector3 n( 0, 0, 1 );
1226 
1227  if( isDebugOn() )
1228  logPoint( "( outer- ) helix origin" , helix.origin() );
1229 
1230  double s = helix.pathLength( r, n );
1231  TVector3 point = helix.at( s );
1232 
1233  if( isDebugOn() ) {
1234  LOG_INFO << "pathLength @ z = " << s << endm;
1235  logPoint( "intersection", point );
1236  }
1237 
1238  return point;
1239 }
1240 
1241 
1242 
1243 void
1244 StETofGeometry::helixSwimmer( const StPicoPhysicalHelix& helix, StPicoPhysicalHelix& helixSwimmer, const double& z, double& pathlength )
1245 {
1246  helixSwimmer = helix;
1247 
1248  // normal to XY plane
1249  TVector3 n( 0., 0., 1. );
1250 
1251  double zTpcEdge = -220.;
1252  if( z > zTpcEdge ) return;
1253 
1254  // --1-- extrapolate helix to TPC edge
1255  double s = helix.pathLength( TVector3( 0., 0., zTpcEdge ), n );
1256  if( s<0. || s>4000. ) {
1257  return;
1258  }
1259 
1260  pathlength = s;
1261 
1262  TVector3 posTpcEdge = helix.at( s );
1263  //if( posTpcEdge.perp() > 300. ) false;
1264 
1265  double bField = getFieldZ( posTpcEdge ) * kilogauss;
1266  TVector3 momTpcEdge = helix.momentumAt( s, bField );
1267  int charge = helix.charge( bField );
1268 
1269  // --2-- step through the volume between TPC and eTOF
1270  const int nSteps = 10;
1271  double stepWidth = ( z - zTpcEdge ) / nSteps; //cm
1272 
1273  TVector3 posInStep = posTpcEdge;
1274  TVector3 momInStep = momTpcEdge;
1275 
1276  for( int i=0; i<nSteps; i++ ) {
1277  double zInStep = zTpcEdge + stepWidth * ( i+1 );
1278 
1279  bField = getFieldZ( posInStep ) * kilogauss;
1280  StPicoPhysicalHelix helixInStep( momInStep, posInStep, bField, charge );
1281 
1282  s = helixInStep.pathLength( TVector3( 0., 0., zInStep ), n );
1283  if( s<0. || s>4000. ) {
1284  return;
1285  }
1286 
1287  posInStep = helixInStep.at( s );
1288  //if( posInStep.perp() > 300. ) return false;
1289 
1290  momInStep = helixInStep.momentumAt( s, bField );
1291 
1292  pathlength += s;
1293 
1294  if( mDebug ) {
1295  logPoint( "ideal", helix.at( pathlength ) );
1296  logPoint( "swimmer", helixInStep.at( s ) );
1297 
1298  LOG_INFO << " pt: " << momInStep.Perp() << " helix curvature: " << helixInStep.curvature() << " radius: " << 1./ helixInStep.curvature() << endm;
1299  LOG_INFO << "stepWidth: " << stepWidth << " bField: " << bField << " pathLength: " << s << " mom phi:" << momInStep.Phi() << endm;
1300  }
1301  }
1302 
1303  helixSwimmer = StPicoPhysicalHelix( momInStep, posInStep, bField, charge );
1304 }
1305 
1306 
1307 
1312 std::vector< int >
1314 {
1315  TVector3 point = helixCrossETofPlane( helix );
1316 
1317  LOG_DEBUG << "track phi @ ETOF= " << point.Phi() << endm;
1318 
1319  return sectorAtPhi( point.Phi() );
1320 }
1321 
1322 
1327 void
1328 StETofGeometry::helixCrossCounter( const StPicoPhysicalHelix& helix, vector< int >& idVec, vector< TVector3 >& crossVec, vector< TVector3 >& localVec, vector< double >& thetaVec )
1329 {
1330  // estimate which sector(s) the track crossed
1331  vector< int > sectorsCrossed = helixCrossSector( helix );
1332 
1333  if( sectorsCrossed.size() == 1 ) LOG_DEBUG << "sector crossed: " << sectorsCrossed[ 0 ] << endm;
1334  if( sectorsCrossed.size() == 2 ) LOG_DEBUG << "sectors crossed: " << sectorsCrossed[ 0 ] << ", " << sectorsCrossed[ 1 ] << endm;
1335 
1336  // loop over all modules
1337  for( unsigned int i=0; i<mNValidModules; i++ ) {
1338  if( !mETofModule[ i ] ) continue;
1339 
1340  // only search in modules of crossed sectors
1341  int iSector = mETofModule[ i ]->sector();
1342  auto found = std::find( std::begin( sectorsCrossed ), std::end( sectorsCrossed ), iSector );
1343 
1344  if( found == std::end( sectorsCrossed ) ) continue;
1345 
1346  LOG_DEBUG << iSector << " " << mETofModule[i]->plane() << endm;
1347 
1348  double module_pathLen;
1349  double module_theta;
1350  TVector3 module_cross;
1351 
1352  bool helixCrossedModule = mETofModule[ i ]->helixCross( helix, module_pathLen, module_cross, module_theta );
1353 
1354  module_theta = fabs( module_theta * 180. / M_PI );
1355 
1356 
1357  if( mDebug && helixCrossedModule ) {
1358  LOG_INFO << " -----------" << "\nmoduleId:"<< mETofModule[ i ]->moduleIndex() << " helix_crossed: " << helixCrossedModule
1359  << " sector: " << mETofModule[ i ]->sector() << " plane: " << mETofModule[ i ]->plane() << endm;
1360  LOG_INFO << "pathLength: " << module_pathLen << " absolute impact angle: " << module_theta << " degree" << endm;
1361  logPoint( "crossing point" , module_cross );
1362  LOG_INFO << "cross.eta: " << module_cross.PseudoRapidity() << endm;
1363  }
1364 
1365 
1366  // only search for intersections of counters with the helix if the module was crossed
1367  if( !helixCrossedModule ) continue;
1368 
1369 
1370  // get helix swimmer
1371  StPicoPhysicalHelix swimmerHelix;
1372  double swimmerPathLen;
1373 
1374  if( mStarBField ) {
1375  // get swimmer helix 5 cm in front of the module
1376  helixSwimmer( helix, swimmerHelix, mETofModule[ i ]->centerPos().z() + 5., swimmerPathLen );
1377  }
1378 
1379  // loop over counters
1380  int nValidCounters = mETofModule[ i ]->numberOfCounters();
1381  for( int j=0; j<nValidCounters; j++ ) {
1382  double pathLen;
1383  double theta;
1384  TVector3 cross;
1385 
1386  bool helixCrossedCounter = false;
1387 
1388  if( mStarBField ) {
1389  // use helix swimmer
1390  helixCrossedCounter = mETofModule[ i ]->counter( j )->helixCross( swimmerHelix, pathLen, cross, theta );
1391  pathLen += swimmerPathLen;
1392  if( mDebug ) LOG_DEBUG << " using swimmer helix" << endm;
1393  }
1394  else {
1395  // use ideal helix
1396  helixCrossedCounter = mETofModule[ i ]->counter( j )->helixCross( helix, pathLen, cross, theta );
1397  if( mDebug ) LOG_DEBUG << " using ideal helix" << endm;
1398  }
1399 
1400  theta = fabs( theta * 180. / M_PI );
1401 
1402  if( helixCrossedCounter ) {
1403  double global[ 3 ];
1404  double local [ 3 ];
1405 
1406  global[ 0 ] = cross.x();
1407  global[ 1 ] = cross.y();
1408  global[ 2 ] = cross.z();
1409 
1410  mETofModule[ i ]->counter( j )->master2Local( global, local );
1411  int strip = mETofModule[ i ]->counter( j )->findStrip( local );
1412 
1413  int sector = mETofModule[ i ]->sector();
1414  int plane = mETofModule[ i ]->plane();
1415  int counter = mETofModule[ i ]->counter( j )->counterIndex() + 1;
1416 
1417  int volumeIndex = calcVolumeIndex( sector, plane, counter, strip );
1418 
1419  idVec.push_back( volumeIndex );
1420  crossVec.push_back( cross );
1421  localVec.push_back( TVector3( local[ 0 ], local[ 1 ], local[ 2 ] ) );
1422  thetaVec.push_back( theta );
1423 
1424  if( mDebug ) {
1425  LOG_INFO << " -----------" << "\ncounterId: " << mETofModule[ i ]->counter( j )->counterIndex() << endm;
1426  LOG_INFO << "pathLength: " << pathLen << " absolute impact angle: " << theta << " degree" << endm;
1427  logPoint( "crossing point" , cross );
1428  LOG_INFO << "cross.eta: " << cross.PseudoRapidity() << "\n" << endm;
1429  LOG_INFO << "localX: " << local[ 0 ] << " localY: " << local[ 1 ] << " localZ: " << local[ 2 ] << endm;
1430  LOG_INFO << "Strip: " << strip << " * * * " << endm;
1431  }
1432  }
1433 
1434  } // end loop over counters
1435  } // end loop over modules
1436 }
1437 
1438 
1439 void
1440 StETofGeometry::logPoint( const char* text, const TVector3& point )
1441 {
1442  LOG_INFO << text << " at (" << point.x() << ", " << point.y() << ", " << point.z() << ")" << endm;
1443 }
1444 
1446 StETofGeometry::getField( const StThreeVectorD& pos ) {
1447  if( !mStarBField ) {
1448  return StThreeVectorD( -999., -999., -999. );
1449  }
1450 
1451  double B[ 3 ] = { 0, 0, 0 };
1452  double X[ 3 ] = { pos.x(), pos.y(), pos.z() };
1453  mStarBField->BField( X, B );
1454 
1455  return StThreeVectorD( B[ 0 ], B[ 1 ], B[ 2 ] );
1456 }
1457 
1458 TVector3
1459 StETofGeometry::getField( const TVector3& pos ) {
1460  if( !mStarBField ) {
1461  return TVector3( -999., -999., -999. );
1462  }
1463 
1464  double B[ 3 ] = { 0, 0, 0 };
1465  double X[ 3 ] = { pos.X(), pos.Y(), pos.Z() };
1466  mStarBField->BField( X, B );
1467 
1468  return TVector3( B[ 0 ], B[ 1 ], B[ 2 ] );
1469 }
1470 
1471 
1472 double
1473 StETofGeometry::getFieldZ( const StThreeVectorD& pos ) {
1474  StThreeVectorD bField = getField( pos );
1475  return bField.z();
1476 }
1477 
1478 double
1479 StETofGeometry::getFieldZ( const TVector3& pos ) {
1480  TVector3 bField = getField( pos );
1481  return bField.Z();
1482 }
1483 
1484 double
1485 StETofGeometry::getFieldZ( const double& x, const double& y, const double& z ) {
1486  if( !mStarBField ) {
1487  return -999.;
1488  }
1489 
1490  double B[ 3 ] = { 0, 0, 0 };
1491  double X[ 3 ] = { x, y, z };
1492 
1493  mStarBField->BField( X, B );
1494 
1495  return B[ 2 ];
1496 }
1497 
1498 void
1499 StETofGeometry::readAlignmentParameters(){
1500  LOG_INFO << "etofAlignParam: filename provided --> use parameter file: " << mFileNameAlignParam << endm;
1501 
1502  //add check for no alignment set here.
1503 
1504  ifstream paramFile;
1505  paramFile.open( mFileNameAlignParam );
1506 
1507  if( !paramFile.is_open() ) {
1508  LOG_INFO << "unable to get the alignments parameters from file --> file does not exist" << endm;
1509  return;
1510  }
1511 
1512  StThreeVectorD counterAlignmentParameter;
1513  float tempX;
1514  float tempY;
1515  float tempZ;
1516  while( paramFile >> tempX >> tempY >> tempZ ) {
1517  counterAlignmentParameter = StThreeVectorD( tempX, tempY, tempZ );
1518  mAlignmentParameters.push_back( counterAlignmentParameter );
1519  }
1520 
1521  paramFile.close();
1522 
1523  if( mAlignmentParameters.size() != 108 ) {
1524  LOG_WARN << "parameter file for alignments has not the right amount of entries: " << mAlignmentParameters.size() << " instead of 108 !!!!" << endm;
1525  return;
1526  }
1527 }
1528 
1529 void
1530 StETofGeometry::readAlignmentDatabase(){
1531  LOG_INFO << "No etof alignment file provided --> use database: " << endm;
1532 
1533  //add check for no alignment set here.
1534 
1535  TDataSet* dbDataSet = StMaker::GetChain()->GetDataBase("Geometry/etof/etofAlign");
1536  if( !dbDataSet ) {
1537  LOG_ERROR << "unable to get the dataset from the database" << endm;
1538  return;
1539  }
1540 
1541  St_etofAlign* etofAlign = static_cast< St_etofAlign * > ( dbDataSet->Find( "etofAlign" ) );
1542  if( !etofAlign ) {
1543  LOG_ERROR << "unable to get the align params from the database" << endm;
1544  return;
1545  }
1546 
1547  etofAlign_st* table = etofAlign->GetTable();
1548  StThreeVectorD counterAlignmentParameter;
1549  float tempX;
1550  float tempY;
1551  float tempZ;
1552 
1553  for( int iCounter = 0; iCounter < eTofConst::nCounters * eTofConst::nModules; iCounter++){
1554  tempX = table->detectorAlignX[iCounter];
1555  tempY = table->detectorAlignY[iCounter];
1556  tempZ = table->detectorAlignZ[iCounter];
1557  StThreeVectorD counterAlignmentParameter = StThreeVectorD( tempX, tempY, tempZ );
1558  mAlignmentParameters.push_back( counterAlignmentParameter );
1559  //LOG_INFO <<" Setting alignment parameters for counter "<< iCounter << " X: "<< tempX << " Y: "<< tempY <<" Z: "<< tempZ << endm;
1560  }
1561 }
TVector3 momentumAt(Double_t, Double_t) const
Return momemtum at S.
Float_t localX() const
Return local X coordinate (cm) across strips w.r.t. center of eTOF counter volume.
Definition: StPicoETofHit.h:49
Int_t zPlane() const
Definition: StPicoETofHit.h:43
void helixCrossCounter(const StPhysicalHelixD &helix, std::vector< int > &idVec, std::vector< StThreeVectorD > &crossVec, std::vector< StThreeVectorD > &localVec, std::vector< double > &thetaVec, std::vector< double > &pathLenVec)
std::string formTGeoPath(const TGeoManager *geoManager, int plane, int sector, int counter=-1)
Int_t sector() const
Return eTOF sector number (equal to TPC sector numbering)
Definition: StPicoETofHit.h:39
std::vector< int > helixCrossSector(const StHelixD &helix)
pair< Double_t, Double_t > pathLength(Double_t r) const
path length at given r (cylindrical r)
const TVector3 & origin() const
Return origin of the helix = starting point.
Definition: StPicoHelix.h:213
pair< double, double > pathLength(double r) const
path length at given r (cylindrical r)
Definition: StHelix.cc:351
unsigned int counter() const
Counter.
Definition: StETofHit.h:191
const StThreeVector< double > & origin() const
-sign(q*B);
Definition: StHelix.hh:224
Helis parametrization for the particle.
Int_t charge(Double_t) const
Return charge of a particle.
unsigned int zPlane() const
ZPlane.
Definition: StETofHit.h:190
double localX() const
X-position.
Definition: StETofHit.h:198
Stores eTOF hit information.
Definition: StPicoETofHit.h:19
Int_t counter() const
Definition: StPicoETofHit.h:47
double localY() const
Y-position.
Definition: StETofHit.h:199
Helix parametrization that uses ROOT TVector3.
Definition: StPicoHelix.h:38
unsigned int sector() const
Sector.
Definition: StETofHit.h:189
Float_t localY() const
Return local Y coordinate (cm) along strips w.r.t. center of eTOF counter volume. ...
Definition: StPicoETofHit.h:51
virtual TDataSet * Find(const char *path) const
Definition: TDataSet.cxx:362