CMS 3D CMS Logo

MuonSimHitProducer.cc
Go to the documentation of this file.
1 //
2 // Package: MuonSimHitProducer
3 // Class: MuonSimHitProducer
4 //
14 //
15 // Original Author: Martijn Mulders/Matthew Jones
16 // Created: Wed Jul 30 11:37:24 CET 2007
17 // Working: Fri Nov 9 09:39:33 CST 2007
18 //
19 // $Id: MuonSimHitProducer.cc,v 1.36 2011/10/07 08:25:42 aperrott Exp $
20 //
21 //
22 
23 // CMSSW headers
25 
26 // Fast Simulation headers
34 
35 // SimTrack
39 
40 // STL headers
41 #include <vector>
42 #include <iostream>
43 
44 // RecoMuon headers
49 
50 // Tracking Tools
53 
54 // Data Formats
58 
60 // Geometry, Magnetic Field
66 
68 
69 // #include "TrackingTools/TrackAssociator/interface/TrackDetectorAssociator.h"
70 
71 //for debug only
72 //#define FAMOS_DEBUG
73 
74 //
75 // constructors and destructor
76 //
78  : theEstimator(iConfig.getParameter<double>("Chi2EstimatorCut")), propagatorWithoutMaterial(nullptr) {
79  // Read relevant parameters
81  iConfig.getParameter<edm::ParameterSet>("TRACKS"),
82  iConfig.getParameter<edm::ParameterSet>("MaterialEffectsForMuons"));
83 
84  //
85  // register your products ... need to declare at least one possible product...
86  //
87  produces<edm::PSimHitContainer>("MuonCSCHits");
88  produces<edm::PSimHitContainer>("MuonDTHits");
89  produces<edm::PSimHitContainer>("MuonRPCHits");
90 
91  edm::ParameterSet serviceParameters = iConfig.getParameter<edm::ParameterSet>("ServiceParameters");
92  theService = new MuonServiceProxy(serviceParameters);
93 
94  // consumes
95  simMuonToken = consumes<std::vector<SimTrack> >(simMuonLabel);
96  simVertexToken = consumes<std::vector<SimVertex> >(simVertexLabel);
97 }
98 
99 // ---- method called once each job just before starting event loop ----
101  //services
103  edm::ESHandle<DTGeometry> dtGeometry;
104  edm::ESHandle<CSCGeometry> cscGeometry;
105  edm::ESHandle<RPCGeometry> rpcGeometry;
107 
108  es.get<IdealMagneticFieldRecord>().get(magField);
109  es.get<MuonGeometryRecord>().get("MisAligned", dtGeometry);
110  es.get<MuonGeometryRecord>().get("MisAligned", cscGeometry);
111  es.get<MuonGeometryRecord>().get(rpcGeometry);
112 
113  magfield = &(*magField);
114  dtGeom = &(*dtGeometry);
115  cscGeom = &(*cscGeometry);
116  rpcGeom = &(*rpcGeometry);
117 
118  theService->update(es);
119 
120  // A few propagators
121  propagatorWithMaterial = &(*(theService->propagator("SteppingHelixPropagatorAny")));
123  SteppingHelixPropagator* SHpropagator = dynamic_cast<SteppingHelixPropagator*>(propagatorWithoutMaterial); // Beuark!
124  SHpropagator->setMaterialMode(true); // switches OFF material effects;
125 }
126 
128  // do anything here that needs to be done at destruction time
129  // (e.g. close files, deallocate resources etc.)
130 
131  if (theMaterialEffects)
132  delete theMaterialEffects;
135 }
136 
137 //
138 // member functions
139 //
140 
141 // ------------ method called to produce the data ------------
142 
144  // using namespace edm;
145  // using namespace std;
147  iSetup.getData(pdg);
148 
149  RandomEngineAndDistribution random(iEvent.streamID());
150 
151  MuonPatternRecoDumper dumper;
152 
155  std::vector<PSimHit> theCSCHits;
156  std::vector<PSimHit> theDTHits;
157  std::vector<PSimHit> theRPCHits;
158 
160  iEvent.getByToken(simMuonToken, simMuons);
161  iEvent.getByToken(simVertexToken, simVertices);
162 
163  for (unsigned int itrk = 0; itrk < simMuons->size(); itrk++) {
164  const SimTrack& mySimTrack = (*simMuons)[itrk];
165  math::XYZTLorentzVector mySimP4(
166  mySimTrack.momentum().x(), mySimTrack.momentum().y(), mySimTrack.momentum().z(), mySimTrack.momentum().t());
167 
168  // Decaying hadrons are now in the list, and so are their muon daughter
169  // Ignore the hadrons here.
170  int pid = mySimTrack.type();
171  if (abs(pid) != 13 && abs(pid) != 1000024)
172  continue;
173  double t0 = 0;
174  GlobalPoint initialPosition;
175  int ivert = mySimTrack.vertIndex();
176  if (ivert >= 0) {
177  t0 = (*simVertices)[ivert].position().t();
178  GlobalPoint xyzzy((*simVertices)[ivert].position().x(),
179  (*simVertices)[ivert].position().y(),
180  (*simVertices)[ivert].position().z());
181  initialPosition = xyzzy;
182  }
183  //
184  // Presumably t0 has dimensions of cm if not mm?
185  // Convert to ns for internal calculations.
186  // I wonder where we should get c from?
187  //
188  double tof = t0 / 29.98;
189 
190 #ifdef FAMOS_DEBUG
191  std::cout << " ===> MuonSimHitProducer::reconstruct() found SIMTRACK - pid = " << pid;
192  std::cout << " : pT = " << mySimP4.Pt() << ", eta = " << mySimP4.Eta() << ", phi = " << mySimP4.Phi() << std::endl;
193 #endif
194 
195  //
196  // Produce muons sim hits starting from undecayed simulated muons
197  //
198 
199  GlobalPoint startingPosition(mySimTrack.trackerSurfacePosition().x(),
200  mySimTrack.trackerSurfacePosition().y(),
201  mySimTrack.trackerSurfacePosition().z());
202  GlobalVector startingMomentum(mySimTrack.trackerSurfaceMomentum().x(),
203  mySimTrack.trackerSurfaceMomentum().y(),
204  mySimTrack.trackerSurfaceMomentum().z());
205  //
206  // Crap... there's no time-of-flight to the trackerSurfacePosition()...
207  // So, this will be wrong when the curvature can't be neglected, but that
208  // will be rather seldom... May as well ignore the mass too.
209  //
210  GlobalVector dtracker = startingPosition - initialPosition;
211  tof += dtracker.mag() / 29.98;
212 
213 #ifdef FAMOS_DEBUG
214  std::cout << " the Muon START position " << startingPosition << std::endl;
215  std::cout << " the Muon START momentum " << startingMomentum << std::endl;
216 #endif
217 
218  //
219  // Some magic to define a TrajectoryStateOnSurface
220  //
221  PlaneBuilder pb;
222  GlobalVector zAxis = startingMomentum.unit();
223  GlobalVector yAxis(zAxis.y(), -zAxis.x(), 0);
224  GlobalVector xAxis = yAxis.cross(zAxis);
226  PlaneBuilder::ReturnType startingPlane = pb.plane(startingPosition, rot);
227  GlobalTrajectoryParameters gtp(startingPosition, startingMomentum, (int)mySimTrack.charge(), magfield);
228  TrajectoryStateOnSurface startingState(gtp, *startingPlane);
229 
230  std::vector<const DetLayer*> navLayers;
231  if (fabs(startingState.globalMomentum().eta()) > 4.5) {
232  navLayers = navigation.compatibleEndcapLayers(*(startingState.freeState()), alongMomentum);
233  } else {
234  navLayers = navigation.compatibleLayers(*(startingState.freeState()), alongMomentum);
235  }
236  /*
237  edm::ESHandle<Propagator> propagator =
238  theService->propagator("SteppingHelixPropagatorAny");
239  */
240 
241  if (navLayers.empty())
242  continue;
243 
244 #ifdef FAMOS_DEBUG
245  std::cout << "Found " << navLayers.size() << " compatible DetLayers..." << std::endl;
246 #endif
247 
248  TrajectoryStateOnSurface propagatedState = startingState;
249  for (unsigned int ilayer = 0; ilayer < navLayers.size(); ilayer++) {
250 #ifdef FAMOS_DEBUG
251  std::cout << "Propagating to layer " << ilayer << " " << dumper.dumpLayer(navLayers[ilayer]) << std::endl;
252 #endif
253 
254  std::vector<DetWithState> comps =
255  navLayers[ilayer]->compatibleDets(propagatedState, *propagatorWithMaterial, theEstimator);
256  if (comps.empty())
257  continue;
258 
259 #ifdef FAMOS_DEBUG
260  std::cout << "Propagating " << propagatedState << std::endl;
261 #endif
262 
263  // Starting momentum
264  double pi = propagatedState.globalMomentum().mag();
265 
266  // Propagate with material effects (dE/dx average only)
267  SteppingHelixStateInfo shsStart(*(propagatedState.freeTrajectoryState()));
268  SteppingHelixStateInfo shsDest;
270  ->propagate(shsStart, navLayers[ilayer]->surface(), shsDest);
271  std::pair<TrajectoryStateOnSurface, double> next(shsDest.getStateOnSurface(navLayers[ilayer]->surface()),
272  shsDest.path());
273  // No need to continue if there is no valid propagation available.
274  // This happens rarely (~0.1% of ttbar events)
275  if (!next.first.isValid())
276  continue;
277  // This is the estimate of the number of radiation lengths traversed,
278  // together with the total path length
279  double radPath = shsDest.radPath();
280  double pathLength = next.second;
281 
282  // Now propagate without dE/dx (average)
283  // [To add the dE/dx fluctuations to the actual dE/dx]
284  std::pair<TrajectoryStateOnSurface, double> nextNoMaterial =
285  propagatorWithoutMaterial->propagateWithPath(propagatedState, navLayers[ilayer]->surface());
286 
287  // Update the propagated state
288  propagatedState = next.first;
289  double pf = propagatedState.globalMomentum().mag();
290 
291  // Insert dE/dx fluctuations and multiple scattering
292  // Skip this step if nextNoMaterial.first is not valid
293  // This happens rarely (~0.02% of ttbar events)
294  if (theMaterialEffects && nextNoMaterial.first.isValid())
295  applyMaterialEffects(propagatedState, nextNoMaterial.first, radPath, &random, *pdg);
296  // Check that the 'shaken' propagatedState is still valid, otherwise continue
297  if (!propagatedState.isValid())
298  continue;
299  // (No evidence that this ever happens)
300  //
301  // Consider this... 1 GeV muon has a velocity that is only 0.5% slower than c...
302  // We probably can safely ignore the mass for anything that makes it out to the
303  // muon chambers.
304  //
305  double pavg = 0.5 * (pi + pf);
306  double m = mySimP4.M();
307  double rbeta = sqrt(1 + m * m / (pavg * pavg)) / 29.98;
308  double dtof = pathLength * rbeta;
309 
310 #ifdef FAMOS_DEBUG
311  std::cout << "Propagated to next surface... path length = " << pathLength << " cm, dTOF = " << dtof << " ns"
312  << std::endl;
313 #endif
314 
315  tof += dtof;
316 
317  for (unsigned int icomp = 0; icomp < comps.size(); icomp++) {
318  const GeomDet* gd = comps[icomp].first;
319  if (gd->subDetector() == GeomDetEnumerators::DT) {
321  const DTChamber* chamber = dtGeom->chamber(id);
322  std::vector<const DTSuperLayer*> superlayer = chamber->superLayers();
323  for (unsigned int isl = 0; isl < superlayer.size(); isl++) {
324  std::vector<const DTLayer*> layer = superlayer[isl]->layers();
325  for (unsigned int ilayer = 0; ilayer < layer.size(); ilayer++) {
326  DTLayerId lid = layer[ilayer]->id();
327 #ifdef FAMOS_DEBUG
328  std::cout << " Extrapolated to DT (" << lid.wheel() << "," << lid.station() << "," << lid.sector()
329  << "," << lid.superlayer() << "," << lid.layer() << ")" << std::endl;
330 #endif
331 
332  const GeomDetUnit* det = dtGeom->idToDetUnit(lid);
333 
334  HelixArbitraryPlaneCrossing crossing(propagatedState.globalPosition().basicVector(),
335  propagatedState.globalMomentum().basicVector(),
336  propagatedState.transverseCurvature(),
337  anyDirection);
338  std::pair<bool, double> path = crossing.pathLength(det->surface());
339  if (!path.first)
340  continue;
341  LocalPoint lpos = det->toLocal(GlobalPoint(crossing.position(path.second)));
342  if (!det->surface().bounds().inside(lpos))
343  continue;
344  const DTTopology& dtTopo = layer[ilayer]->specificTopology();
345  int wire = dtTopo.channel(lpos);
346  if (wire - dtTopo.firstChannel() < 0 || wire - dtTopo.lastChannel() > 0)
347  continue;
348  // no drift cell here (on the chamber edge or just outside)
349  // this hit would otherwise be discarded downstream in the digitizer
350 
351  DTWireId wid(lid, wire);
352  double thickness = det->surface().bounds().thickness();
353  LocalVector lmom = det->toLocal(GlobalVector(crossing.direction(path.second)));
354  lmom = lmom.unit() * propagatedState.localMomentum().mag();
355 
356  // Factor that takes into account the (rec)hits lost because of delta's, etc.:
357  // (Not fully satisfactory patch, but it seems to work...)
358  double pmu = lmom.mag();
359  double theDTHitIneff = pmu > 0 ? exp(kDT * log(pmu) + fDT) : 0.;
360  if (random.flatShoot() < theDTHitIneff)
361  continue;
362 
363  double eloss = 0;
364  double pz = fabs(lmom.z());
365  LocalPoint entry = lpos - 0.5 * thickness * lmom / pz;
366  LocalPoint exit = lpos + 0.5 * thickness * lmom / pz;
367  double dtof = path.second * rbeta;
368  int trkid = mySimTrack.trackId();
369  unsigned int id = wid.rawId();
370  short unsigned int processType = 2;
371  PSimHit hit(
372  entry, exit, lmom.mag(), tof + dtof, eloss, pid, id, trkid, lmom.theta(), lmom.phi(), processType);
373  theDTHits.push_back(hit);
374  }
375  }
376  } else if (gd->subDetector() == GeomDetEnumerators::CSC) {
377  CSCDetId id(gd->geographicalId());
378  const CSCChamber* chamber = cscGeom->chamber(id);
379  std::vector<const CSCLayer*> layers = chamber->layers();
380  for (unsigned int ilayer = 0; ilayer < layers.size(); ilayer++) {
381  CSCDetId lid = layers[ilayer]->id();
382 
383 #ifdef FAMOS_DEBUG
384  std::cout << " Extrapolated to CSC (" << lid.endcap() << "," << lid.ring() << "," << lid.station() << ","
385  << lid.layer() << ")" << std::endl;
386 #endif
387 
388  const GeomDetUnit* det = cscGeom->idToDetUnit(lid);
389  HelixArbitraryPlaneCrossing crossing(propagatedState.globalPosition().basicVector(),
390  propagatedState.globalMomentum().basicVector(),
391  propagatedState.transverseCurvature(),
392  anyDirection);
393  std::pair<bool, double> path = crossing.pathLength(det->surface());
394  if (!path.first)
395  continue;
396  LocalPoint lpos = det->toLocal(GlobalPoint(crossing.position(path.second)));
397  // For CSCs the Bounds are for chamber frames not gas regions
398  // if ( ! det->surface().bounds().inside(lpos) ) continue;
399  // New function knows where the 'active' volume is:
400  const CSCLayerGeometry* laygeom = layers[ilayer]->geometry();
401  if (!laygeom->inside(lpos))
402  continue;
403  //double thickness = laygeom->thickness(); gives number which is about 20 times too big
404  double thickness = det->surface().bounds().thickness(); // this one works much better...
405  LocalVector lmom = det->toLocal(GlobalVector(crossing.direction(path.second)));
406  lmom = lmom.unit() * propagatedState.localMomentum().mag();
407 
408  // Factor that takes into account the (rec)hits lost because of delta's, etc.:
409  // (Not fully satisfactory patch, but it seems to work...)
410  double pmu = lmom.mag();
411  double theCSCHitIneff = pmu > 0 ? exp(kCSC * log(pmu) + fCSC) : 0.;
412  // Take into account the different geometry in ME11:
413  if (id.station() == 1 && id.ring() == 1)
414  theCSCHitIneff = theCSCHitIneff * 0.442;
415  if (random.flatShoot() < theCSCHitIneff)
416  continue;
417 
418  double eloss = 0;
419  double pz = fabs(lmom.z());
420  LocalPoint entry = lpos - 0.5 * thickness * lmom / pz;
421  LocalPoint exit = lpos + 0.5 * thickness * lmom / pz;
422  double dtof = path.second * rbeta;
423  int trkid = mySimTrack.trackId();
424  unsigned int id = lid.rawId();
425  short unsigned int processType = 2;
426  PSimHit hit(
427  entry, exit, lmom.mag(), tof + dtof, eloss, pid, id, trkid, lmom.theta(), lmom.phi(), processType);
428  theCSCHits.push_back(hit);
429  }
430  } else if (gd->subDetector() == GeomDetEnumerators::RPCBarrel ||
432  RPCDetId id(gd->geographicalId());
433  const RPCChamber* chamber = rpcGeom->chamber(id);
434  std::vector<const RPCRoll*> roll = chamber->rolls();
435  for (unsigned int iroll = 0; iroll < roll.size(); iroll++) {
436  RPCDetId rid = roll[iroll]->id();
437 
438 #ifdef FAMOS_DEBUG
439  std::cout << " Extrapolated to RPC (" << rid.ring() << "," << rid.station() << "," << rid.sector() << ","
440  << rid.subsector() << "," << rid.layer() << "," << rid.roll() << ")" << std::endl;
441 #endif
442 
443  const GeomDetUnit* det = rpcGeom->idToDetUnit(rid);
444  HelixArbitraryPlaneCrossing crossing(propagatedState.globalPosition().basicVector(),
445  propagatedState.globalMomentum().basicVector(),
446  propagatedState.transverseCurvature(),
447  anyDirection);
448  std::pair<bool, double> path = crossing.pathLength(det->surface());
449  if (!path.first)
450  continue;
451  LocalPoint lpos = det->toLocal(GlobalPoint(crossing.position(path.second)));
452  if (!det->surface().bounds().inside(lpos))
453  continue;
454  double thickness = det->surface().bounds().thickness();
455  LocalVector lmom = det->toLocal(GlobalVector(crossing.direction(path.second)));
456  lmom = lmom.unit() * propagatedState.localMomentum().mag();
457  double eloss = 0;
458  double pz = fabs(lmom.z());
459  LocalPoint entry = lpos - 0.5 * thickness * lmom / pz;
460  LocalPoint exit = lpos + 0.5 * thickness * lmom / pz;
461  double dtof = path.second * rbeta;
462  int trkid = mySimTrack.trackId();
463  unsigned int id = rid.rawId();
464  short unsigned int processType = 2;
465  PSimHit hit(
466  entry, exit, lmom.mag(), tof + dtof, eloss, pid, id, trkid, lmom.theta(), lmom.phi(), processType);
467  theRPCHits.push_back(hit);
468  }
469  } else {
470  std::cout << "Extrapolated to unknown subdetector '" << gd->subDetector() << "'..." << std::endl;
471  }
472  }
473  }
474  }
475 
476  std::unique_ptr<edm::PSimHitContainer> pcsc(new edm::PSimHitContainer);
477  int n = 0;
478  for (std::vector<PSimHit>::const_iterator i = theCSCHits.begin(); i != theCSCHits.end(); i++) {
479  pcsc->push_back(*i);
480  n += 1;
481  }
482  iEvent.put(std::move(pcsc), "MuonCSCHits");
483 
484  std::unique_ptr<edm::PSimHitContainer> pdt(new edm::PSimHitContainer);
485  n = 0;
486  for (std::vector<PSimHit>::const_iterator i = theDTHits.begin(); i != theDTHits.end(); i++) {
487  pdt->push_back(*i);
488  n += 1;
489  }
490  iEvent.put(std::move(pdt), "MuonDTHits");
491 
492  std::unique_ptr<edm::PSimHitContainer> prpc(new edm::PSimHitContainer);
493  n = 0;
494  for (std::vector<PSimHit>::const_iterator i = theRPCHits.begin(); i != theRPCHits.end(); i++) {
495  prpc->push_back(*i);
496  n += 1;
497  }
498  iEvent.put(std::move(prpc), "MuonRPCHits");
499 }
500 
502  const edm::ParameterSet& fastTracks,
503  const edm::ParameterSet& matEff) {
504  // Muons
505  std::string _simModuleLabel = fastMuons.getParameter<std::string>("simModuleLabel");
506  std::string _simModuleProcess = fastMuons.getParameter<std::string>("simModuleProcess");
507  simMuonLabel = edm::InputTag(_simModuleLabel, _simModuleProcess);
508  simVertexLabel = edm::InputTag(_simModuleLabel);
509 
510  std::vector<double> simHitIneffDT = fastMuons.getParameter<std::vector<double> >("simHitDTIneffParameters");
511  std::vector<double> simHitIneffCSC = fastMuons.getParameter<std::vector<double> >("simHitCSCIneffParameters");
512  kDT = simHitIneffDT[0];
513  fDT = simHitIneffDT[1];
514  kCSC = simHitIneffCSC[0];
515  fCSC = simHitIneffCSC[1];
516 
517  // Tracks
518  fullPattern_ = fastTracks.getUntrackedParameter<bool>("FullPatternRecognition");
519 
520  // The following should be on LogInfo
521  // std::cout << " MUON SIM HITS: FastSimulation parameters " << std::endl;
522  // std::cout << " ============================================== " << std::endl;
523  // if ( fullPattern_ )
524  // std::cout << " The FULL pattern recognition option is turned ON" << std::endl;
525  // else
526  // std::cout << " The FAST tracking option is turned ON" << std::endl;
527 
528  // Material Effects
529  theMaterialEffects = nullptr;
530  if (matEff.getParameter<bool>("PairProduction") || matEff.getParameter<bool>("Bremsstrahlung") ||
531  matEff.getParameter<bool>("MuonBremsstrahlung") || matEff.getParameter<bool>("EnergyLoss") ||
532  matEff.getParameter<bool>("MultipleScattering"))
533  theMaterialEffects = new MaterialEffects(matEff);
534 }
535 
538  double radPath,
539  RandomEngineAndDistribution const* random,
541  // The energy loss simulator
543 
544  // The multiple scattering simulator
546 
547  // The Muon Bremsstrahlung simulator
549 
550  // Initialize the Particle position, momentum and energy
551  const Surface& nextSurface = tsos.surface();
552  GlobalPoint gPos = energyLoss ? tsos.globalPosition() : tsosWithdEdx.globalPosition();
553  GlobalVector gMom = energyLoss ? tsos.globalMomentum() : tsosWithdEdx.globalMomentum();
554  double mu = 0.1056583692;
555  double en = std::sqrt(gMom.mag2() + mu * mu);
556 
557  // And now create the Particle
558  XYZTLorentzVector position(gPos.x(), gPos.y(), gPos.z(), 0.);
559  XYZTLorentzVector momentum(gMom.x(), gMom.y(), gMom.z(), en);
560  float charge = (float)(tsos.charge());
561  ParticlePropagator theMuon(rawparticle::makeMuon(charge < 1., momentum, position), nullptr, nullptr, &table);
562 
563  // Recompute the energy loss to get the fluctuations
564  if (energyLoss) {
565  // Difference between with and without dE/dx (average only)
566  // (for corrections once fluctuations are applied)
567  GlobalPoint gPosWithdEdx = tsosWithdEdx.globalPosition();
568  GlobalVector gMomWithdEdx = tsosWithdEdx.globalMomentum();
569  double enWithdEdx = std::sqrt(gMomWithdEdx.mag2() + mu * mu);
570  XYZTLorentzVector deltaPos(
571  gPosWithdEdx.x() - gPos.x(), gPosWithdEdx.y() - gPos.y(), gPosWithdEdx.z() - gPos.z(), 0.);
572  XYZTLorentzVector deltaMom(
573  gMomWithdEdx.x() - gMom.x(), gMomWithdEdx.y() - gMom.y(), gMomWithdEdx.z() - gMom.z(), enWithdEdx - en);
574 
575  // Energy loss in iron (+ fluctuations)
576  energyLoss->updateState(theMuon, radPath, random);
577 
578  // Correcting factors to account for slight differences in material descriptions
579  // (Material description is more accurate in the stepping helix propagator)
580  radPath *= -deltaMom.E() / energyLoss->mostLikelyLoss();
581  double fac = energyLoss->deltaMom().E() / energyLoss->mostLikelyLoss();
582 
583  // Particle momentum & position after energy loss + fluctuation
584  XYZTLorentzVector theNewMomentum = theMuon.particle().momentum() + energyLoss->deltaMom() + fac * deltaMom;
585  XYZTLorentzVector theNewPosition = theMuon.particle().vertex() + fac * deltaPos;
586  fac = (theNewMomentum.E() * theNewMomentum.E() - mu * mu) / theNewMomentum.Vect().Mag2();
587  fac = fac > 0. ? std::sqrt(fac) : 1E-9;
588  theMuon.particle().setMomentum(
589  theNewMomentum.Px() * fac, theNewMomentum.Py() * fac, theNewMomentum.Pz() * fac, theNewMomentum.E());
590  theMuon.particle().setVertex(theNewPosition);
591  }
592 
593  // Does the actual mutliple scattering
594  if (multipleScattering) {
595  // Pass the vector normal to the "next" surface
596  GlobalVector normal = nextSurface.tangentPlane(tsos.globalPosition())->normalVector();
597  multipleScattering->setNormalVector(normal);
598  // Compute the amount of multiple scattering after a given path length
599  multipleScattering->updateState(theMuon, radPath, random);
600  }
601 
602  // Muon Bremsstrahlung
603  if (bremsstrahlung) {
604  // Compute the amount of Muon Bremsstrahlung after given path length
605  bremsstrahlung->updateState(theMuon, radPath, random);
606  }
607 
608  // Fill the propagated state
609  GlobalPoint propagatedPosition(theMuon.particle().X(), theMuon.particle().Y(), theMuon.particle().Z());
610  GlobalVector propagatedMomentum(theMuon.particle().Px(), theMuon.particle().Py(), theMuon.particle().Pz());
611  GlobalTrajectoryParameters propagatedGtp(propagatedPosition, propagatedMomentum, (int)charge, magfield);
612  tsosWithdEdx = TrajectoryStateOnSurface(propagatedGtp, nextSurface);
613 }
614 
615 //define this as a plug-in
void update(const edm::EventSetup &setup)
update the services each event
MuonSimHitProducer(const edm::ParameterSet &)
double mostLikelyLoss() const
Return most probable energy loss.
edm::ESHandle< MuonDetLayerGeometry > detLayerGeometry() const
get the detLayer geometry
void setMomentum(const XYZTLorentzVector &vtx)
set the momentum
Definition: RawParticle.h:328
const math::XYZVectorD & trackerSurfacePosition() const
Definition: SimTrack.h:37
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
const MagneticField * magfield
T mag2() const
Definition: PV3DBase.h:63
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:131
virtual Propagator * clone() const =0
virtual ConstReferenceCountingPointer< TangentPlane > tangentPlane(const GlobalPoint &) const =0
const GeomDet * idToDetUnit(DetId) const override
Return the pointer to the GeomDetUnit corresponding to a given DetId.
Definition: RPCGeometry.cc:30
int channel(const LocalPoint &p) const override
Definition: DTTopology.cc:54
const DTGeometry * dtGeom
const DTChamber * chamber(const DTChamberId &id) const
Return a DTChamber given its id.
Definition: DTGeometry.cc:90
HepPDT::ParticleDataTable ParticleDataTable
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:525
void setNormalVector(const GlobalVector &normal)
Sets the vector normal to the surface traversed.
MaterialEffects * theMaterialEffects
#define nullptr
Geom::Phi< T > phi() const
Definition: PV3DBase.h:66
MultipleScatteringSimulator * multipleScatteringSimulator() const
Return the Multiple Scattering engine.
ReturnType plane(const PositionType &pos, const RotationType &rot) const
Definition: PlaneBuilder.h:21
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:57
T y() const
Definition: PV3DBase.h:60
GlobalPoint globalPosition() const
LocalPoint toLocal(const GlobalPoint &gp) const
Conversion to the R.F. of the GeomDet.
Definition: GeomDet.h:58
const Bounds & bounds() const
Definition: Surface.h:89
void updateState(ParticlePropagator &myTrack, double radlen, RandomEngineAndDistribution const *)
Compute the material effect (calls the sub class)
edm::EDGetTokenT< std::vector< SimVertex > > simVertexToken
RawParticle makeMuon(bool isParticle, const math::XYZTLorentzVector &p, const math::XYZTLorentzVector &xStart)
Definition: makeMuon.cc:20
int layer() const
Return the layer number.
Definition: DTLayerId.h:42
RawParticle const & particle() const
The particle being propagated.
float charge() const
charge
Definition: CoreSimTrack.cc:17
int layer() const
Definition: CSCDetId.h:56
const Plane & surface() const
The nominal surface of the GeomDet.
Definition: GeomDet.h:37
void applyMaterialEffects(TrajectoryStateOnSurface &tsosWithdEdx, TrajectoryStateOnSurface &tsos, double radPath, RandomEngineAndDistribution const *, HepPDT::ParticleDataTable const &)
Simulate material effects in iron (dE/dx, multiple scattering)
int firstChannel() const
Returns the wire number of the first wire.
Definition: DTTopology.h:79
const Double_t pi
Geom::Theta< T > theta() const
Definition: PV3DBase.h:72
const RPCGeometry * rpcGeom
LocalVector localMomentum() const
int endcap() const
Definition: CSCDetId.h:85
bool getData(T &iHolder) const
Definition: EventSetup.h:113
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
int lastChannel() const
Returns the wire number of the last wire.
Definition: DTTopology.h:81
const RPCChamber * chamber(RPCDetId id) const
Definition: RPCGeometry.cc:46
MuonBremsstrahlungSimulator * muonBremsstrahlungSimulator() const
Return the Muon Bremsstrahlung engine.
virtual bool inside(const Local3DPoint &) const =0
Determine if the point is inside the bounds.
int iEvent
Definition: GenABIO.cc:224
const SurfaceType & surface() const
const XYZTLorentzVector & momentum() const
the momentum fourvector
Definition: RawParticle.h:321
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
T mag() const
Definition: PV3DBase.h:64
int roll() const
Definition: RPCDetId.h:92
const GeomDet * idToDetUnit(DetId) const override
Return the pointer to the GeomDetUnit corresponding to a given DetId.
Definition: DTGeometry.cc:75
FreeTrajectoryState const * freeTrajectoryState(bool withErrors=true) const
const std::vector< const DTSuperLayer * > & superLayers() const
Return the superlayers in the chamber.
Definition: DTChamber.cc:51
int ring() const
Definition: RPCDetId.h:59
const Propagator * propagatorWithMaterial
TrajectoryStateOnSurface getStateOnSurface(const Surface &surf, bool returnTangentPlane=false) const
T sqrt(T t)
Definition: SSEVec.h:19
Propagator * propagatorWithoutMaterial
T z() const
Definition: PV3DBase.h:61
double Y() const
y of vertex
Definition: RawParticle.h:287
const XYZTLorentzVector & deltaMom() const
Returns the actual energy lost.
double Py() const
y of the momentum
Definition: RawParticle.h:300
double Z() const
z of vertex
Definition: RawParticle.h:288
virtual std::pair< TrajectoryStateOnSurface, double > propagateWithPath(const FreeTrajectoryState &, const Surface &) const final
Definition: Propagator.cc:10
const std::vector< const RPCRoll * > & rolls() const
Return the Rolls.
Definition: RPCChamber.cc:40
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
const CSCGeometry * cscGeom
DetId geographicalId() const
The label of this GeomDet.
Definition: GeomDet.h:64
void beginRun(edm::Run const &run, const edm::EventSetup &es) override
void produce(edm::Event &, const edm::EventSetup &) override
double Pz() const
z of the momentum
Definition: RawParticle.h:303
bool inside(const Local3DPoint &, const LocalError &, float scale=1.f) const override
int vertIndex() const
index of the vertex in the Event container (-1 if no vertex)
Definition: SimTrack.h:30
const XYZTLorentzVector & vertex() const
the vertex fourvector
Definition: RawParticle.h:320
int superlayer() const
Return the superlayer number (deprecated method name)
int ring() const
Definition: CSCDetId.h:68
Vector3DBase unit() const
Definition: Vector3DBase.h:54
int layer() const
Definition: RPCDetId.h:85
unsigned int trackId() const
Definition: CoreSimTrack.h:31
virtual float thickness() const =0
const math::XYZTLorentzVectorD & trackerSurfaceMomentum() const
Definition: SimTrack.h:39
const CSCChamber * chamber(CSCDetId id) const
Return the chamber corresponding to given DetId.
Definition: CSCGeometry.cc:100
edm::EDGetTokenT< std::vector< SimTrack > > simMuonToken
int sector() const
Sector id: the group of chambers at same phi (and increasing r)
Definition: RPCDetId.h:81
double X() const
x of vertex
Definition: RawParticle.h:286
MuonServiceProxy * theService
const GeomDet * idToDetUnit(DetId) const override
Return the pointer to the GeomDetUnit corresponding to a given DetId.
Definition: CSCGeometry.cc:89
int subsector() const
SubSector id : some sectors are divided along the phi direction in subsectors (from 1 to 4 in Barrel...
Definition: RPCDetId.h:88
int type() const
particle type (HEP PDT convension)
Definition: CoreSimTrack.h:22
void readParameters(const edm::ParameterSet &, const edm::ParameterSet &, const edm::ParameterSet &)
GlobalVector globalMomentum() const
int sector() const
Definition: DTChamberId.h:49
const math::XYZTLorentzVectorD & momentum() const
Definition: CoreSimTrack.h:19
static int position[264][3]
Definition: ReadPGInfo.cc:289
T get() const
Definition: EventSetup.h:73
TkRotation< float > RotationType
double Px() const
x of the momentum
Definition: RawParticle.h:297
edm::InputTag simMuonLabel
StreamID streamID() const
Definition: Event.h:96
int station() const
Definition: CSCDetId.h:79
std::vector< PSimHit > PSimHitContainer
int station() const
Return the station number.
Definition: DTChamberId.h:42
EnergyLossSimulator * energyLossSimulator() const
Return the Energy Loss engine.
virtual SubDetector subDetector() const
Which subdetector.
Definition: GeomDet.cc:38
int wheel() const
Return the wheel number.
Definition: DTChamberId.h:39
T x() const
Definition: PV3DBase.h:59
const BasicVectorType & basicVector() const
Definition: PV3DBase.h:53
void setMaterialMode(bool noMaterial)
Switch for material effects mode: no material effects if true.
void setVertex(const XYZTLorentzVector &vtx)
set the vertex
Definition: RawParticle.h:325
def move(src, dest)
Definition: eostools.py:511
edm::ESHandle< Propagator > propagator(std::string propagatorName) const
get the propagator
Definition: Run.h:45
Global3DVector GlobalVector
Definition: GlobalVector.h:10
math::XYZTLorentzVector XYZTLorentzVector
Definition: RawParticle.h:25
edm::InputTag simVertexLabel
Chi2MeasurementEstimator theEstimator
def exit(msg="")
int station() const
Definition: RPCDetId.h:78