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