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