CMS 3D CMS Logo

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