CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Geant4ePropagator.cc
Go to the documentation of this file.
1 #include <sstream>
2 
3 //Geant4e
6 
7 //CMSSW
12 
17 
18 //Geant4
19 #include "G4ErrorRunManagerHelper.hh"
20 #include "G4ErrorFreeTrajState.hh"
21 #include "G4ErrorPlaneSurfaceTarget.hh"
22 #include "G4ErrorCylSurfaceTarget.hh"
23 #include "G4ErrorPropagatorData.hh"
24 #include "G4EventManager.hh"
25 #include "G4SteppingControl.hh"
26 #include "G4TransportationManager.hh"
27 #include "G4Box.hh"
28 #include "G4Tubs.hh"
29 #include "G4UImanager.hh"
30 #include "G4GeometryTolerance.hh"
31 #include "G4TransportationManager.hh"
32 #include "G4Field.hh"
33 #include "G4FieldManager.hh"
34 
35 //CLHEP
36 #include "CLHEP/Units/GlobalSystemOfUnits.h"
37 
41  std::string particleName, PropagationDirection dir) :
42  Propagator(dir), theField(field), theParticleName(
43  particleName), theG4eManager(
44  G4ErrorPropagatorManager::GetErrorPropagatorManager()), theG4eData(
45  G4ErrorPropagatorData::GetErrorPropagatorData())
46 {
47  LogDebug("Geant4e") << "Geant4e Propagator initialized";
48 
49  // has to be called here, doing it later will not load the G4 physics list properly when using
50  // the G4 ES Producer. Reason: unclear
52 }
53 
57 {
58  LogDebug("Geant4e") << "Geant4ePropagator::~Geant4ePropagator()" << std::endl;
59 
60  // don't close the g4 Geometry here, because the propagator might have been cloned
61  // but there is only one, globally-shared Geometry
62 }
63 
64 //
66 //
67 
73 {
74  LogDebug("Geant4e") << "ensureGeant4eIsInitilized called" << std::endl;
75  if ( (G4ErrorPropagatorData::GetErrorPropagatorData()->GetState()
76  == G4ErrorState_PreInit) || forceInit )
77  {
78  LogDebug("Geant4e") << "Initializing G4 propagator" << std::endl;
79 
80  G4UImanager::GetUIpointer()->ApplyCommand(
81  "/exerror/setField -10. kilogauss");
82 
83  theG4eManager->InitGeant4e();
84 
85  const G4Field* field =
86  G4TransportationManager::GetTransportationManager()->GetFieldManager()->GetDetectorField();
87  if (field == nullptr)
88  {
89  edm::LogError("Geant4e") << "No G4 magnetic field defined";
90  }
91  LogDebug("Geant4e") << "G4 propagator initialized" << std::endl;
92  }
93  else {
94  LogDebug("Geant4e") << "G4 not in preinit state: " << G4ErrorPropagatorData::GetErrorPropagatorData()->GetState() << std::endl;
95  }
96 
97  // example code uses
98  // G4UImanager::GetUIpointer()->ApplyCommand("/geant4e/limits/stepLength 100 mm");
99  G4UImanager::GetUIpointer()->ApplyCommand(
100  "/geant4e/limits/stepLength 10.0 mm");
101 }
102 
103 template<>
105  const Plane& pDest, bool moveTargetToEndOfSurface) const
106 {
107  //* Get position and normal (orientation) of the destination plane
108  GlobalPoint posPlane = pDest.toGlobal(LocalPoint(0, 0, 0));
109  GlobalVector normalPlane = pDest.toGlobal(LocalVector(0, 0, 1.));
110  normalPlane = normalPlane.unit();
111 
112  //* Transform this into HepGeom::Point3D<double> and HepGeom::Normal3D<double> that define a plane for
113  // Geant4e.
114  // CMS uses cm and GeV while Geant4 uses mm and MeV
115  HepGeom::Point3D<double> surfPos =
117  HepGeom::Normal3D<double> surfNorm =
119 
120  //* Set the target surface
121  return ErrorTargetPair(false,
122  std::make_shared < G4ErrorPlaneSurfaceTarget > (surfNorm, surfPos));
123 }
124 
125 template<>
127  const Cylinder& pDest, bool moveTargetToEndOfSurface) const
128 {
129  //Get Cylinder parameters.
130  //CMS uses cm and GeV while Geant4 uses mm and MeV.
131  // - Radius
132  G4float radCyl = pDest.radius() * cm;
133  // - Position: PositionType & GlobalPoint are Basic3DPoint<float,GlobalTag>
134  G4ThreeVector posCyl = TrackPropagation::globalPointToHep3Vector(
135  pDest.position());
136  // - Rotation: Type in CMSSW is RotationType == TkRotation<T>, T=float
137  G4RotationMatrix rotCyl = TrackPropagation::tkRotationFToHepRotation(
138  pDest.rotation());
139 
140  //DEBUG
142  LogDebug("Geant4e") << "G4e - TkRotation" << rotation;
143  LogDebug("Geant4e") << "G4e - G4Rotation" << rotCyl << "mm";
144 
145  return ErrorTargetPair(!moveTargetToEndOfSurface,
146  std::make_shared < G4ErrorCylSurfaceTarget
147  > (radCyl, posCyl, rotCyl));
148 }
149 
150 template<>
152 {
153  return "Cylinder";
154 }
155 
156 template<>
158 {
159  return "Plane";
160 }
161 
163 {
164  std::string particleName = theParticleName;
165 
166  if (charge > 0)
167  {
168  particleName += "+";
169  }
170  if ( charge < 0)
171  {
172  particleName += "-";
173  }
174 
175  LogDebug("Geant4e") << "G4e - Particle name: " << particleName;
176 
177  return particleName;
178 }
179 
180 template<>
182  Plane const& pDest, GlobalPoint const& cmsInitPos,
183  GlobalVector const& cmsInitMom) const
184 {
185  if (pDest.localZ(cmsInitPos) * pDest.localZ(cmsInitMom) < 0)
186  {
187  mode = G4ErrorMode_PropForwards;
188  LogDebug("Geant4e") << "G4e - Propagator mode is \'forwards\' indirect via the Any direction" << std::endl;
189  }
190  else
191  {
192  mode = G4ErrorMode_PropBackwards;
193  LogDebug("Geant4e") << "G4e - Propagator mode is \'backwards\' indirect via the Any direction" << std::endl;
194  }
195 
196  return true;
197 }
198 
199 template<>
201  Cylinder const& pDest, GlobalPoint const& cmsInitPos,
202  GlobalVector const& cmsInitMom) const
203 {
204  //------------------------------------
205  //For cylinder assume outside is backwards, inside is along
206  //General use for particles from collisions
207  LocalPoint lpos = pDest.toLocal(cmsInitPos);
208  Surface::Side theSide = pDest.side(lpos, 0);
209  if (theSide == SurfaceOrientation::positiveSide)
210  { //outside cylinder
211  mode = G4ErrorMode_PropBackwards;
212  LogDebug("Geant4e") << "G4e - Propagator mode is \'backwards\' indirect via the Any direction";
213  }
214  else
215  { //inside cylinder
216  mode = G4ErrorMode_PropForwards;
217  LogDebug("Geant4e") << "G4e - Propagator mode is \'forwards\' indirect via the Any direction";
218  }
219 
220  return true;
221 }
222 
223 template<class SurfaceType>
225  SurfaceType const& pDest, GlobalPoint const& cmsInitPos,
226  GlobalVector const& cmsInitMom) const
227 {
229  {
230  mode = G4ErrorMode_PropBackwards;
231  LogDebug("Geant4e") << "G4e - Propagator mode is \'backwards\' " << std::endl;
232  }
233  else if (propagationDirection() == alongMomentum)
234  {
235  mode = G4ErrorMode_PropForwards;
236  LogDebug("Geant4e") << "G4e - Propagator mode is \'forwards\'" << std::endl;
237  }
238  else if (propagationDirection() == anyDirection)
239  {
240  if (configureAnyPropagation(mode, pDest, cmsInitPos, cmsInitMom)
241  == false)
242  return false;
243  }
244  else
245  {
246  edm::LogError("Geant4e") << "G4e - Unsupported propagation mode";
247  return false;
248  }
249  return true;
250 }
251 
252 template<class SurfaceType>
253 std::pair<TrajectoryStateOnSurface, double> Geant4ePropagator::propagateGeneric(
254  const FreeTrajectoryState& ftsStart, const SurfaceType& pDest) const
255 {
257  // Construct the target surface
258  //
259  //* Set the target surface
260 
261  ErrorTargetPair g4eTarget_center = transformToG4SurfaceTarget(pDest, false);
262 
263  // * Get the starting point and direction and convert them to CLHEP::Hep3Vector
264  // for G4. CMS uses cm and GeV while Geant4 uses mm and MeV
265  GlobalPoint cmsInitPos = ftsStart.position();
266  GlobalVector cmsInitMom = ftsStart.momentum();
267  bool flipped=false;
269  {
270  // flip the momentum vector as Geant4 will not do this
271  // on it's own in a backward propagation
272  cmsInitMom = -cmsInitMom;
273  flipped = true;
274  }
275 
276  //Set the mode of propagation according to the propagation direction
277  G4ErrorMode mode = G4ErrorMode_PropForwards;
278  if (!configurePropagation(mode, pDest, cmsInitPos, cmsInitMom))
279  return TsosPP(TrajectoryStateOnSurface(), 0.0f);
280 
281  //re-check propagation direction chosen in case of AnyDirection
282  if (mode == G4ErrorMode_PropBackwards && !flipped)
283  cmsInitMom = -cmsInitMom;
284 
285  CLHEP::Hep3Vector g4InitPos = TrackPropagation::globalPointToHep3Vector(
286  cmsInitPos);
287  CLHEP::Hep3Vector g4InitMom = TrackPropagation::globalVectorToHep3Vector(
288  cmsInitMom * GeV);
289 
290  debugReportTrackState("intitial", cmsInitPos, g4InitPos, cmsInitMom,
291  g4InitMom, pDest);
292 
293  //Set the mode of propagation according to the propagation direction
294  //G4ErrorMode mode = G4ErrorMode_PropForwards;
295 
296  //if (!configurePropagation(mode, pDest, cmsInitPos, cmsInitMom))
297  // return TsosPP(TrajectoryStateOnSurface(), 0.0f);
298 
299 
301  //Set the error and trajectories, and finally propagate
302  //
303  G4ErrorTrajErr g4error(5, 1);
304  if (ftsStart.hasError())
305  {
307  initErr = ftsStart.curvilinearError();
309  initErr, ftsStart.charge());
310  LogDebug("Geant4e") << "CMS - Error matrix: " << std::endl
311  << initErr.matrix();
312  } else
313  {
314  LogDebug("Geant4e") << "No error matrix available" << std::endl;
315  return TsosPP(TrajectoryStateOnSurface(), 0.0f);
316  }
317 
318  LogDebug("Geant4e") << "G4e - Error matrix: " << std::endl << g4error;
319 
320  // in CMSSW, the state errors are deflated when performing the backward propagation
321  if (mode == G4ErrorMode_PropForwards)
322  {
323  G4ErrorPropagatorData::GetErrorPropagatorData()->SetStage(
324  G4ErrorStage_Inflation);
325  }
326  else if (mode == G4ErrorMode_PropBackwards)
327  {
328  G4ErrorPropagatorData::GetErrorPropagatorData()->SetStage(
329  G4ErrorStage_Deflation);
330  }
331 
332  G4ErrorFreeTrajState g4eTrajState(generateParticleName(ftsStart.charge()),
333  g4InitPos, g4InitMom, g4error);
334  LogDebug("Geant4e") << "G4e - Traj. State: " << (g4eTrajState);
335 
337  // Propagate
338  int iterations = 0;
339  double finalPathLength = 0;
340 
341  HepGeom::Point3D<double> finalRecoPos;
342 
343  G4ErrorPropagatorData::GetErrorPropagatorData()->SetMode(mode);
344 
345  theG4eData->SetTarget(g4eTarget_center.second.get());
346  LogDebug("Geant4e") << "Running Propagation to the RECO surface" << std::endl;
347 
348  theG4eManager->InitTrackPropagation();
349 
350  bool continuePropagation = true;
351  while (continuePropagation)
352  {
353  iterations++;
354  LogDebug("Geant4e") << std::endl << "step count " << iterations << " step length " << finalPathLength;
355 
356  const int ierr = theG4eManager->PropagateOneStep(&g4eTrajState, mode);
357 
358  if (ierr != 0)
359  {
360  // propagation failed, return invalid track state
361  return TsosPP(TrajectoryStateOnSurface(), 0.0f);
362  }
363 
364  const float thisPathLength = TrackPropagation::g4doubleToCmsDouble(
365  g4eTrajState.GetG4Track()->GetStepLength());
366 
367  LogDebug("Geant4e") << "step Length was " << thisPathLength << " cm, current global position: " << TrackPropagation::hepPoint3DToGlobalPoint( g4eTrajState.GetPosition() ) << std::endl;
368 
369  finalPathLength += thisPathLength;
370 
371  //if (std::fabs(finalPathLength) > 10000.0f)
372  if (std::fabs(finalPathLength) > 200.0f)
373  {
374  LogDebug("Geant4e")
375  << "ERROR: Quitting propagation: path length mega large"
376  << std::endl;
377  theG4eManager->GetPropagator()->InvokePostUserTrackingAction(
378  g4eTrajState.GetG4Track());
379  continuePropagation = false;
380  LogDebug("Geant4e")
381  << "WARNING: Quitting propagation: max path length exceeded, returning invalid state"
382  << std::endl;
383 
384  // reached maximum path length, bail out
385  return TsosPP(TrajectoryStateOnSurface(), 0.0f);
386  }
387 
388  if (theG4eManager->GetPropagator()->CheckIfLastStep(
389  g4eTrajState.GetG4Track()))
390  {
391  theG4eManager->GetPropagator()->InvokePostUserTrackingAction(
392  g4eTrajState.GetG4Track());
393  continuePropagation = false;
394  }
395  }
396 
397  // CMSSW Tracking convention, backward propagations have negative path length
399  finalPathLength = -finalPathLength;
400 
401  // store the correct location for the hit on the RECO surface
402  LogDebug("Geant4e") << "Position on the RECO surface"
403  << g4eTrajState.GetPosition() << std::endl;
404  finalRecoPos = g4eTrajState.GetPosition();
405 
406  theG4eManager->EventTermination();
407 
408  LogDebug("Geant4e") << "Final position of the Track :" << g4eTrajState.GetPosition()
409  << std::endl;
410 
412  // Retrieve the state in the end from Geant4e, convert them to CMS vectors
413  // and points, and build global trajectory parameters.
414  // CMS uses cm and GeV while Geant4 uses mm and MeV
415  //
416  const HepGeom::Vector3D<double> momEnd = g4eTrajState.GetMomentum();
417 
418  // use the hit on the the RECO plane as the final position to be d'accor with the
419  // RecHit measurements
421  finalRecoPos);
423  / GeV;
424 
425  debugReportTrackState("final", posEndGV, finalRecoPos, momEndGV, momEnd,
426  pDest);
427 
428  // Get the error covariance matrix from Geant4e. It comes in curvilinear
429  // coordinates so use the appropiate CMS class
430  G4ErrorTrajErr g4errorEnd = g4eTrajState.GetError();
431 
432  CurvilinearTrajectoryError curvError(
434  ftsStart.charge()));
435 
436  if (mode == G4ErrorMode_PropBackwards)
437  {
438  GlobalTrajectoryParameters endParm(posEndGV, momEndGV,
439  ftsStart.parameters().charge(),
440  &ftsStart.parameters().magneticField());
441 
442  // flip the momentum direction because it has been flipped before running G4's backwards prop
443  momEndGV = -momEndGV;
444  }
445 
446  LogDebug("Geant4e") << "G4e - Error matrix after propagation: "
447  << std::endl << g4errorEnd;
448 
449  LogDebug("Geant4e") << "CMS - Error matrix after propagation: "
450  << std::endl << curvError.matrix();
451 
452  GlobalTrajectoryParameters tParsDest(posEndGV, momEndGV, ftsStart.charge(),
453  theField);
454 
456 
457  side = propagationDirection() == alongMomentum ?
460 
461  return TsosPP(TrajectoryStateOnSurface(tParsDest, curvError, pDest, side),
462  finalPathLength);
463 }
464 
465 //
467 //
468 
475 std::pair<TrajectoryStateOnSurface, double> Geant4ePropagator::propagateWithPath(
476  const FreeTrajectoryState& ftsStart, const Plane& pDest) const
477 {
478  //Finally build the pair<...> that needs to be returned where the second
479  //parameter is the exact path length. Currently calculated with a stepping
480  //action that adds up the length of every step
481  return propagateGeneric(ftsStart, pDest);
482 
483 }
484 
485 std::pair<TrajectoryStateOnSurface, double> Geant4ePropagator::propagateWithPath(
486  const FreeTrajectoryState& ftsStart, const Cylinder& cDest) const
487 {
488  //Finally build the pair<...> that needs to be returned where the second
489  //parameter is the exact path length.
490  return propagateGeneric(ftsStart, cDest);
491 }
492 
493 std::pair<TrajectoryStateOnSurface, double> Geant4ePropagator::propagateWithPath(
494  const TrajectoryStateOnSurface& tsosStart, const Plane& pDest) const
495 {
496  //Finally build the pair<...> that needs to be returned where the second
497  //parameter is the exact path length.
498  const FreeTrajectoryState ftsStart = *tsosStart.freeState();
499  return propagateGeneric(ftsStart, pDest);
500 
501 }
502 
503 std::pair<TrajectoryStateOnSurface, double> Geant4ePropagator::propagateWithPath(
504  const TrajectoryStateOnSurface& tsosStart, const Cylinder& cDest) const
505 {
506  const FreeTrajectoryState ftsStart = *tsosStart.freeState();
507  //Finally build the pair<...> that needs to be returned where the second
508  //parameter is the exact path length.
509  return propagateGeneric(ftsStart, cDest);
510 
511 }
512 
514  HepGeom::Point3D<double> const& surfPos,
515  GlobalVector const& normalPlane,
516  HepGeom::Normal3D<double> const& surfNorm, const Plane& pDest) const
517 {
518  LogDebug("Geant4e") << "G4e - Destination CMS plane position:" << posPlane
519  << "cm\n"
520  << "G4e - (Ro, eta, phi): ("
521  << posPlane.perp() << " cm, " << posPlane.eta()
522  << ", " << posPlane.phi().degrees() << " deg)\n"
523  << "G4e - Destination G4 plane position: "
524  << surfPos << " mm, Ro = " << surfPos.perp()
525  << " mm";
526  LogDebug("Geant4e") << "G4e - Destination CMS plane normal : "
527  << normalPlane << "\n"
528  << "G4e - Destination G4 plane normal : "
529  << normalPlane;
530  LogDebug("Geant4e") << "G4e - Distance from plane position to plane: "
531  << pDest.localZ(posPlane) << " cm";
532 }
533 
534 template<class SurfaceType>
536  GlobalPoint const& cmsInitPos, CLHEP::Hep3Vector const& g4InitPos,
537  GlobalVector const& cmsInitMom, CLHEP::Hep3Vector const& g4InitMom,
538  const SurfaceType& pDest) const
539 {
540  LogDebug("Geant4e") << "G3 -- Current Context: " << currentContext;
541  LogDebug("Geant4e") << "G4e - CMS point position:" << cmsInitPos << "cm\n"
542  << "G4e - (Ro, eta, phi): ("
543  << cmsInitPos.perp() << " cm, "
544  << cmsInitPos.eta() << ", "
545  << cmsInitPos.phi().degrees() << " deg)\n"
546  << "G4e - G4 point position: " << g4InitPos
547  << " mm, Ro = " << g4InitPos.perp() << " mm";
548  LogDebug("Geant4e") << "G4e - CMS momentum :" << cmsInitMom
549  << "GeV\n" << " pt: " << cmsInitMom.perp()
550  << "G4e - G4 momentum : "
551  << g4InitMom << " MeV";
552 }
553 
#define LogDebug(id)
GlobalPoint toGlobal(const Point2DBase< Scalar, LocalTag > lp) const
Definition: Surface.h:114
std::pair< TrajectoryStateOnSurface, double > TsosPP
Local3DVector LocalVector
Definition: LocalVector.h:12
const double GeV
Definition: MathUtil.h:16
T perp() const
Definition: PV3DBase.h:72
virtual PropagationDirection propagationDirection() const
Definition: Propagator.h:155
Geant4ePropagator(const MagneticField *field=0, std::string particleName="mu", PropagationDirection dir=alongMomentum)
const GlobalTrajectoryParameters & parameters() const
HepGeom::Normal3D< double > globalVectorToHepNormal3D(const GlobalVector &p)
void debugReportPlaneSetup(GlobalPoint const &posPlane, HepGeom::Point3D< double > const &surfPos, GlobalVector const &normalPlane, HepGeom::Normal3D< double > const &surfNorm, const Plane &pDest) const
double g4doubleToCmsDouble(const G4double &d)
virtual std::pair< TrajectoryStateOnSurface, double > propagateWithPath(const FreeTrajectoryState &, const Plane &) const override
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
float localZ(const GlobalPoint &gp) const
Definition: Plane.h:49
std::string theParticleName
CLHEP::Hep3Vector globalVectorToHep3Vector(const GlobalVector &p)
bool configurePropagation(G4ErrorMode &mode, SurfaceType const &pDest, GlobalPoint const &cmsInitPos, GlobalVector const &cmsInitMom) const
PropagationDirection
TrackCharge charge() const
const MagneticField * theField
const CurvilinearTrajectoryError & curvilinearError() const
Definition: Plane.h:17
G4ErrorPropagatorManager * theG4eManager
CLHEP::HepRotation tkRotationFToHepRotation(const TkRotation< float > &tkr)
virtual Side side(const LocalPoint &p, Scalar toler) const
Definition: Cylinder.cc:9
Scalar radius() const
Radius of the cylinder.
Definition: Cylinder.h:67
AlgebraicSymMatrix55 g4ErrorTrajErrToAlgebraicSymMatrix55(const G4ErrorTrajErr &e, const int q)
G4ErrorPropagatorData * theG4eData
LocalPoint toLocal(const GlobalPoint &gp) const
FreeTrajectoryState const * freeState(bool withErrors=true) const
void debugReportTrackState(std::string const &currentContext, GlobalPoint const &cmsInitPos, CLHEP::Hep3Vector const &g4InitPos, GlobalVector const &cmsInitMom, CLHEP::Hep3Vector const &g4InitMom, const SurfaceType &pDest) const
GlobalPoint hepPoint3DToGlobalPoint(const HepGeom::Point3D< double > &r)
double f[11][100]
GlobalVector momentum() const
Vector3DBase unit() const
Definition: Vector3DBase.h:57
std::pair< TrajectoryStateOnSurface, double > propagateGeneric(const FreeTrajectoryState &ftsStart, const SurfaceType &pDest) const
GlobalPoint position() const
HepGeom::Point3D< double > globalPointToHepPoint3D(const GlobalPoint &r)
virtual ~Geant4ePropagator() override
ErrorTargetPair transformToG4SurfaceTarget(const SurfaceType &pDest, bool moveTargetToEndOfSurface) const
std::string getSurfaceType(SurfaceType const &surface) const
GlobalVector hep3VectorToGlobalVector(const CLHEP::Hep3Vector &p)
T eta() const
Definition: PV3DBase.h:76
bool configureAnyPropagation(G4ErrorMode &mode, SurfaceType const &pDest, GlobalPoint const &cmsInitPos, GlobalVector const &cmsInitMom) const
const AlgebraicSymMatrix55 & matrix() const
Local3DPoint LocalPoint
Definition: LocalPoint.h:11
const RotationType & rotation() const
const MagneticField & magneticField() const
G4ErrorTrajErr algebraicSymMatrix55ToG4ErrorTrajErr(const AlgebraicSymMatrix55 &e, const int q)
std::string generateParticleName(int charge) const
dbl *** dir
Definition: mlp_gen.cc:35
T degrees() const
Definition: Phi.h:54
const PositionType & position() const
CLHEP::Hep3Vector globalPointToHep3Vector(const GlobalPoint &r)
void ensureGeant4eIsInitilized(bool forceInit) const
std::pair< bool, std::shared_ptr< G4ErrorTarget > > ErrorTargetPair