CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
TrajectoryManager.cc
Go to the documentation of this file.
1 //Framework Headers
3 
4 //CMSSW Headers
9 
10 // Tracker reco geometry headers
19 //#include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
20 
21 //FAMOS Headers
30 
32 
33 //#include "FastSimulation/Utilities/interface/Histos.h"
34 //#include "FastSimulation/Utilities/interface/FamosLooses.h"
35 // Numbering scheme
36 
37 //#define FAMOS_DEBUG
38 #ifdef FAMOS_DEBUG
41 #endif
42 
43 #include <list>
44 
46 
48  const edm::ParameterSet& matEff,
50  const edm::ParameterSet& decays,
51  const RandomEngine* engine) :
52  mySimEvent(aSimEvent),
53  _theGeometry(0),
54  _theFieldMap(0),
55  theMaterialEffects(0),
56  myDecayEngine(0),
57  theGeomTracker(0),
58  theGeomSearchTracker(0),
59  theLayerMap(56, static_cast<const DetLayer*>(0)), // reserve space for layers here
60  theNegLayerOffset(27),
61  // myHistos(0),
62  random(engine),
63  use_hardcoded(1)
64 
65 {
66  //std::cout << "TrajectoryManager.cc 1 use_hardcoded = " << use_hardcoded << std::endl;
67  use_hardcoded = matEff.getParameter<bool>("use_hardcoded_geometry");
68 
69  // Initialize Bthe stable particle decay engine
70  if ( decays.getParameter<bool>("ActivateDecays") && ( decays.getParameter<std::string>("Decayer") == "pythia6" || decays.getParameter<std::string>("Decayer") == "pythia8" ) ) {
71  decayer = decays.getParameter<std::string>("Decayer");
73  distCut = decays.getParameter<double>("DistCut");
74  } else if (! ( decays.getParameter<std::string>("Decayer") == "pythia6" || decays.getParameter<std::string>("Decayer") == "pythia8" ) )
75  std::cout << "No valid decayer has been selected! No decay performed..." << std::endl;
76  // Initialize the Material Effects updator, if needed
77  if ( matEff.getParameter<bool>("PairProduction") ||
78  matEff.getParameter<bool>("Bremsstrahlung") ||
79  matEff.getParameter<bool>("MuonBremsstrahlung") ||
80  matEff.getParameter<bool>("EnergyLoss") ||
81  matEff.getParameter<bool>("MultipleScattering") ||
82  matEff.getParameter<bool>("NuclearInteraction")
83  )
85 
86  // Save SimHits according to Optiom
87  // Only the hits from first half loop is saved
88  firstLoop = simHits.getUntrackedParameter<bool>("firstLoop",true);
89  // Only if pT>pTmin are the hits saved
90  pTmin = simHits.getUntrackedParameter<double>("pTmin",0.5);
91 
92  /*
93  // Get the Famos Histos pointer
94  myHistos = Histos::instance();
95 
96  // Initialize a few histograms
97 
98  myHistos->book("h302",1210,-121.,121.,1210,-121.,121.);
99  myHistos->book("h300",1210,-121.,121.,1210,-121.,121.);
100  myHistos->book("h301",1200,-300.,300.,1210,-121.,121.);
101  myHistos->book("h303",1200,-300.,300.,1210,-121.,121.);
102  */
103 }
104 
105 void
107  const TrackerInteractionGeometry* interactionGeometry,
108  const MagneticFieldMap* aFieldMap)
109 {
110 
111  // Initialize the reco tracker geometry
112  theGeomSearchTracker = geomSearchTracker;
113 
114  // Initialize the simplified tracker geometry
115  _theGeometry = interactionGeometry;
116 
118 
119  // Initialize the magnetic field
120  _theFieldMap = aFieldMap;
121 
122 }
123 
124 void
126 
127  theGeomTracker = geomTracker;
128 
129 }
130 
133  return _theGeometry;
134 }
135 
137 
138  if ( myDecayEngine ) delete myDecayEngine;
140 
141  //Write the histograms
142  /*
143  myHistos->put("histos.root");
144  if ( myHistos ) delete myHistos;
145  */
146 }
147 
148 void
150 {
151 
152  // Clear the hits of the previous event
153  // thePSimHits->clear();
154  thePSimHits.clear();
155 
156  // The new event
157  XYZTLorentzVector myBeamPipe = XYZTLorentzVector(0.,2.5, 9999999.,0.);
158 
159  std::list<TrackerLayer>::const_iterator cyliter;
160 
161  // bool debug = mySimEvent->id().event() == 8;
162 
163  // Loop over the particles (watch out: increasing upper limit!)
164  for( int fsimi=0; fsimi < (int) mySimEvent->nTracks(); ++fsimi) {
165  // If the particle has decayed inside the beampipe, or decays
166  // immediately, there is nothing to do
167  //if ( debug ) std::cout << mySimEvent->track(fsimi) << std::endl;
168  //if ( debug ) std::cout << "Not yet at end vertex ? " << mySimEvent->track(fsimi).notYetToEndVertex(myBeamPipe) << std::endl;
169  if( !mySimEvent->track(fsimi).notYetToEndVertex(myBeamPipe) ) continue;
170  mySimEvent->track(fsimi).setPropagate();
171 
172  // Get the geometry elements
173  cyliter = _theGeometry->cylinderBegin();
174  // Prepare the propagation
176  //The real work starts here
177  int success = 1;
178  int sign = +1;
179  int loop = 0;
180  int cyl = 0;
181 
182  // Find the initial cylinder to propagate to.
183  for ( ; cyliter != _theGeometry->cylinderEnd() ; ++cyliter ) {
184 
185  PP.setPropagationConditions(*cyliter);
186  if ( PP.inside() && !PP.onSurface() ) break;
187  ++cyl;
188 
189  }
190 
191  // The particle has a pseudo-rapidity (position or momentum direction)
192  // in excess of 3.0. Just simply go to the last tracker layer
193  // without bothering with all the details of the propagation and
194  // material effects.
195  // 08/02/06 - pv: increase protection from 0.99 (eta=2.9932) to 0.9998 (eta=4.9517)
196  // to simulate material effects at large eta
197  // if above 0.99: propagate to the last tracker cylinder where the material is concentrated!
198  double ppcos2T = PP.cos2Theta();
199  double ppcos2V = PP.cos2ThetaV();
200 
201  if(use_hardcoded){
202  if ( ( ppcos2T > 0.99 && ppcos2T < 0.9998 ) && ( cyl == 0 || ( ppcos2V > 0.99 && ppcos2V < 0.9998 ) ) ){
203  if ( cyliter != _theGeometry->cylinderEnd() ) {
204  cyliter = _theGeometry->cylinderEnd();
205  --cyliter;
206  }
207  // if above 0.9998: don't propagate at all (only to the calorimeters directly)
208  } else if ( ppcos2T > 0.9998 && ( cyl == 0 || ppcos2V > 0.9998 ) ) {
209  cyliter = _theGeometry->cylinderEnd();
210  }
211  }
212  else {
213  if ( ppcos2T > 0.9998 && ( cyl == 0 || ppcos2V > 0.9998 ) ) {
214  cyliter = _theGeometry->cylinderEnd();
215  }
216  }
217 
218  // Loop over the cylinders
219  while ( cyliter != _theGeometry->cylinderEnd() &&
220  loop<100 && // No more than 100 loops
221  mySimEvent->track(fsimi).notYetToEndVertex(PP.vertex())) { // The particle decayed
222 
223  // Skip layers with no material (kept just for historical reasons)
224  if ( cyliter->surface().mediumProperties().radLen() < 1E-10 ) {
225  ++cyliter; ++cyl;
226  continue;
227  }
228 
229  // Pathological cases:
230  // To prevent from interacting twice in a row with the same layer
231  // bool escapeBarrel = (PP.getSuccess() == -1 && success == 1);
232  bool escapeBarrel = PP.getSuccess() == -1;
233  bool escapeEndcap = (PP.getSuccess() == -2 && success == 1);
234  // To break the loop
235  bool fullPropagation =
236  (PP.getSuccess() <= 0 && success==0) || escapeEndcap;
237 
238  if ( escapeBarrel ) {
239  ++cyliter; ++cyl;
240  while (cyliter != _theGeometry->cylinderEnd() && cyliter->forward() ) {
241  sign=1; ++cyliter; ++cyl;
242  }
243 
244  if ( cyliter == _theGeometry->cylinderEnd() ) {
245  --cyliter; --cyl; fullPropagation=true;
246  }
247 
248  }
249 
250  // Define the propagation conditions
251  PP.setPropagationConditions(*cyliter,!fullPropagation);
252  if ( escapeEndcap ) PP.increaseRCyl(0.0005);
253 
254  // Remember last propagation outcome
255  success = PP.getSuccess();
256 
257  // Propagation was not successful :
258  // Change the sign of the cylinder increment and count the loops
259  if ( !PP.propagateToBoundSurface(*cyliter) ||
260  PP.getSuccess()<=0) {
261  sign = -sign;
262  ++loop;
263  }
264 
265  // The particle may have decayed on its way... in which the daughters
266  // have to be added to the event record
267  if ( PP.hasDecayed() || (!mySimEvent->track(fsimi).nDaughters() && PP.PDGcTau()<1E-3 ) ) {
268  updateWithDaughters(PP,fsimi);
269  break;
270  }
271 
272  // Exit by the endcaps or innermost cylinder :
273  // Positive cylinder increment
274  if ( PP.getSuccess()==2 || cyliter==_theGeometry->cylinderBegin() )
275  sign = +1;
276 
277  // Successful propagation to a cylinder, with some Material :
278  if( PP.getSuccess() > 0 && PP.onFiducial() ) {
279 
280  bool saveHit =
281  ( (loop==0 && sign>0) || !firstLoop ) && // Save only first half loop
282  PP.charge()!=0. && // Consider only charged particles
283  cyliter->sensitive() && // Consider only sensitive layers
284  PP.Perp2()>pTmin*pTmin; // Consider only pT > pTmin
285 
286  // Material effects are simulated there
287  if ( theMaterialEffects )
288  theMaterialEffects->interact(*mySimEvent,*cyliter,PP,fsimi);
289 
290  // There is a PP.setXYZT=(0,0,0,0) if bremss fails
291  saveHit &= PP.E()>1E-6;
292 
293  if ( saveHit ) {
294  // Consider only active layers
295  if ( cyliter->sensitive() ) {
296  // Add information to the FSimTrack (not yet available)
297  // myTrack.addSimHit(PP,layer);
298 
299  // Return one or two (for overlap regions) PSimHits in the full
300  // tracker geometry
301  if ( theGeomTracker )
302  createPSimHits(*cyliter, PP, thePSimHits[fsimi], fsimi,mySimEvent->track(fsimi).type(), tTopo);
303 
304  /*
305  myHistos->fill("h302",PP.X() ,PP.Y());
306  if ( sin(PP.vertex().Phi()) > 0. )
307  myHistos->fill("h303",PP.Z(),PP.R());
308  else
309  myHistos->fill("h303",PP.Z(),-PP.R());
310  */
311 
312  }
313  }
314 
315  // Fill Histos (~poor man event display)
316  /*
317  myHistos->fill("h300",PP.x(),PP.y());
318  if ( sin(PP.vertex().phi()) > 0. )
319  myHistos->fill("h301",PP.z(),sqrt(PP.vertex().Perp2()));
320  else
321  myHistos->fill("h301",PP.z(),-sqrt(PP.vertex().Perp2()));
322  */
323 
324  //The particle may have lost its energy in the material
325  if ( mySimEvent->track(fsimi).notYetToEndVertex(PP.vertex()) &&
326  !mySimEvent->filter().accept(PP) )
328 
329  }
330 
331  // Stop here if the particle has reached an end
332  if ( mySimEvent->track(fsimi).notYetToEndVertex(PP.vertex()) ) {
333 
334  // Otherwise increment the cylinder iterator
335  // do {
336  if (sign==1) {++cyliter;++cyl;}
337  else {--cyliter;--cyl;}
338 
339  // Check if the last surface has been reached
340  if( cyliter==_theGeometry->cylinderEnd()) {
341 
342  // Try to propagate to the ECAL in half a loop
343  // Note: Layer1 = ECAL Barrel entrance, or Preshower
344  // entrance, or ECAL Endcap entrance (in the corner)
345  PP.propagateToEcal();
346  // PP.propagateToPreshowerLayer1();
347 
348  // If it is not possible, try go back to the last cylinder
349  if(PP.getSuccess()==0) {
350  --cyliter; --cyl; sign = -sign;
351  PP.setPropagationConditions(*cyliter);
352  PP.propagateToBoundSurface(*cyliter);
353 
354  // If there is definitely no way, leave it here.
355  if(PP.getSuccess()<0) {++cyliter; ++cyl;}
356 
357  }
358 
359  // Check if the particle has decayed on the way to ECAL
360  if ( PP.hasDecayed() )
361  updateWithDaughters(PP,fsimi);
362 
363  }
364  }
365 
366  }
367 
368  // Propagate all particles without a end vertex to the Preshower,
369  // theECAL and the HCAL.
370  if ( mySimEvent->track(fsimi).notYetToEndVertex(PP.vertex()) )
371  propagateToCalorimeters(PP,fsimi);
372 
373  }
374 
375  // Save the information from Nuclear Interaction Generation
377 
378 }
379 
380 void
382 
383  FSimTrack& myTrack = mySimEvent->track(fsimi);
384 
385  // Set the position and momentum at the end of the tracker volume
386  myTrack.setTkPosition(PP.vertex().Vect());
387  myTrack.setTkMomentum(PP.momentum());
388 
389  // Propagate to Preshower Layer 1
390  PP.propagateToPreshowerLayer1(false);
391  if ( PP.hasDecayed() ) {
392  updateWithDaughters(PP,fsimi);
393  return;
394  }
395  if ( myTrack.notYetToEndVertex(PP.vertex()) && PP.getSuccess() > 0 )
396  myTrack.setLayer1(PP,PP.getSuccess());
397 
398  // Propagate to Preshower Layer 2
399  PP.propagateToPreshowerLayer2(false);
400  if ( PP.hasDecayed() ) {
401  updateWithDaughters(PP,fsimi);
402  return;
403  }
404  if ( myTrack.notYetToEndVertex(PP.vertex()) && PP.getSuccess() > 0 )
405  myTrack.setLayer2(PP,PP.getSuccess());
406 
407  // Propagate to Ecal Endcap
408  PP.propagateToEcalEntrance(false);
409  if ( PP.hasDecayed() ) {
410  updateWithDaughters(PP,fsimi);
411  return;
412  }
413  if ( myTrack.notYetToEndVertex(PP.vertex()) )
414  myTrack.setEcal(PP,PP.getSuccess());
415 
416  // Propagate to HCAL entrance
417  PP.propagateToHcalEntrance(false);
418  if ( PP.hasDecayed() ) {
419  updateWithDaughters(PP,fsimi);
420  return;
421  }
422  if ( myTrack.notYetToEndVertex(PP.vertex()) )
423  myTrack.setHcal(PP,PP.getSuccess());
424 
425  // Propagate to VFCAL entrance
426  PP.propagateToVFcalEntrance(false);
427  if ( PP.hasDecayed() ) {
428  updateWithDaughters(PP,fsimi);
429  return;
430  }
431  if ( myTrack.notYetToEndVertex(PP.vertex()) )
432  myTrack.setVFcal(PP,PP.getSuccess());
433 
434 }
435 
436 bool
438 
439  std::list<TrackerLayer>::const_iterator cyliter;
440  bool done = false;
441 
442  // Get the geometry elements
443  cyliter = _theGeometry->cylinderBegin();
444 
445  // Find the layer to propagate to.
446  for ( ; cyliter != _theGeometry->cylinderEnd() ; ++cyliter ) {
447 
448  if ( layer != cyliter->layerNumber() ) continue;
449 
450  PP.setPropagationConditions(*cyliter);
451 
452  done =
453  PP.propagateToBoundSurface(*cyliter) &&
454  PP.getSuccess() > 0 &&
455  PP.onFiducial();
456 
457  break;
458 
459  }
460 
461  return done;
462 
463 }
464 
465 void
467 
468  // The particle was already decayed in the GenEvent, but still the particle was
469  // allowed to propagate (for magnetic field bending, for material effects, etc...)
470  // Just modify the momentum of the daughters in that case
471  unsigned nDaugh = mySimEvent->track(fsimi).nDaughters();
472  if ( nDaugh ) {
473 
474  // Move the vertex
475  unsigned vertexId = mySimEvent->track(fsimi).endVertex().id();
476  mySimEvent->vertex(vertexId).setPosition(PP.vertex());
477 
478  // Before-propagation and after-propagation momentum and vertex position
479  XYZTLorentzVector momentumBefore = mySimEvent->track(fsimi).momentum();
480  XYZTLorentzVector momentumAfter = PP.momentum();
481  double magBefore = std::sqrt(momentumBefore.Vect().mag2());
482  double magAfter = std::sqrt(momentumAfter.Vect().mag2());
483  // Rotation to be applied
484  XYZVector axis = momentumBefore.Vect().Cross(momentumAfter.Vect());
485  double angle = std::acos(momentumBefore.Vect().Dot(momentumAfter.Vect())/(magAfter*magBefore));
486  Rotation r(axis,angle);
487  // Rescaling to be applied
488  double rescale = magAfter/magBefore;
489 
490  // Move, rescale and rotate daugthers, grand-daughters, etc.
491  moveAllDaughters(fsimi,r,rescale);
492 
493  // The particle is not decayed in the GenEvent, decay it with PYTHIA
494  } else {
495 
496  // Decays are not activated : do nothing
497  if ( !myDecayEngine ) return;
498 
499  // Invoke PYDECY (Pythia6) or Pythia8 to decay the particle and get the daughters
501 
502  // Update the FSimEvent with an end vertex and with the daughters
503  if ( daughters.size() ) {
504  double distMin = 1E99;
505  int theClosestChargedDaughterId = -1;
506  DaughterParticleIterator daughter = daughters.begin();
507 
508  int ivertex = mySimEvent->addSimVertex(daughter->vertex(),fsimi,
510 
511  if ( ivertex != -1 ) {
512  for ( ; daughter != daughters.end(); ++daughter) {
513  int theDaughterId = mySimEvent->addSimTrack(&(*daughter), ivertex);
514  // Find the closest charged daughter (if charged mother)
515  if ( PP.charge() * daughter->charge() > 1E-10 ) {
516  double dist = (daughter->Vect().Unit().Cross(PP.Vect().Unit())).R();
517  if ( dist < distCut && dist < distMin ) {
518  distMin = dist;
519  theClosestChargedDaughterId = theDaughterId;
520  }
521  }
522  }
523  }
524  // Attach mother and closest daughter sp as to cheat tracking ;-)
525  if ( theClosestChargedDaughterId >=0 )
526  mySimEvent->track(fsimi).setClosestDaughterId(theClosestChargedDaughterId);
527  }
528 
529  }
530 
531 }
532 
533 
534 void
535 TrajectoryManager::moveAllDaughters(int fsimi, const Rotation& r, double rescale) {
536 
537  //
538  for ( unsigned idaugh=0; idaugh < (unsigned)(mySimEvent->track(fsimi).nDaughters()); ++idaugh) {
539  // Initial momentum of the daughter
540  XYZTLorentzVector daughMomentum (mySimEvent->track(fsimi).daughter(idaugh).momentum());
541  // Rotate and rescale
542  XYZVector newMomentum (r * daughMomentum.Vect());
543  newMomentum *= rescale;
544  double newEnergy = std::sqrt(newMomentum.mag2() + daughMomentum.mag2());
545  // Set the new momentum
546  mySimEvent->track(fsimi).setMomentum(XYZTLorentzVector(newMomentum.X(),newMomentum.Y(),newMomentum.Z(),newEnergy));
547  // Watch out : recursive call to get all grand-daughters
548  int fsimDaug = mySimEvent->track(fsimi).daughter(idaugh).id();
549  moveAllDaughters(fsimDaug,r,rescale);
550  }
551 }
552 
553 void
555  const ParticlePropagator& PP,
556  std::map<double,PSimHit>& theHitMap,
557  int trackID, int partID, const TrackerTopology *tTopo) {
558 
559  // Propagate the particle coordinates to the closest tracker detector(s)
560  // in this layer and create the PSimHit(s)
561 
562  // const MagneticField& mf = MagneticFieldMap::instance()->magneticField();
563  // This solution is actually much faster !
565  AnalyticalPropagator alongProp(&mf, anyDirection);
567 
568 // std::cout << "PP.X() = " << PP.X() << std::endl;
569 // std::cout << "PP.Y() = " << PP.Y() << std::endl;
570 // std::cout << "PP.Z() = " << PP.Z() << std::endl;
571 
573  const DetLayer* tkLayer = detLayer(layer,PP.Z());
574 
575  TrajectoryStateOnSurface trajState = makeTrajectoryState( tkLayer, PP, &mf);
576  float thickness = theMaterialEffects ? theMaterialEffects->thickness() : 0.;
577  float eloss = theMaterialEffects ? theMaterialEffects->energyLoss() : 0.;
578 
579  // Find, in the corresponding layers, the detectors compatible
580  // with the current track
581  std::vector<DetWithState> compat
582  = tkLayer->compatibleDets( trajState, alongProp, est);
583 
584  // And create the corresponding PSimHits
585  std::map<double,PSimHit> theTrackHits;
586  for (std::vector<DetWithState>::const_iterator i=compat.begin(); i!=compat.end(); i++) {
587  // Correct Eloss for last 3 rings of TEC (thick sensors, 0.05 cm)
588  // Disgusting fudge factor !
589  makePSimHits( i->first, i->second, theHitMap, trackID, eloss, thickness, partID,tTopo);
590  }
591 
592 }
593 
596  const ParticlePropagator& pp,
597  const MagneticField* field) const
598 {
599  GlobalPoint pos( pp.X(), pp.Y(), pp.Z());
600  GlobalVector mom( pp.Px(), pp.Py(), pp.Pz());
603  (GlobalTrajectoryParameters( pos, mom, TrackCharge( pp.charge()), field), *plane);
604 }
605 
606 void
608  const TrajectoryStateOnSurface& ts,
609  std::map<double,PSimHit>& theHitMap,
610  int tkID, float el, float thick, int pID,
611  const TrackerTopology *tTopo)
612 {
613 
614  std::vector< const GeomDet*> comp = det->components();
615  if (!comp.empty()) {
616  for (std::vector< const GeomDet*>::const_iterator i = comp.begin();
617  i != comp.end(); i++) {
618  const GeomDetUnit* du = dynamic_cast<const GeomDetUnit*>(*i);
619  if (du != 0)
620  theHitMap.insert(theHitMap.end(),makeSinglePSimHit( *du, ts, tkID, el, thick, pID,tTopo));
621  }
622  }
623  else {
624  const GeomDetUnit* du = dynamic_cast<const GeomDetUnit*>(det);
625  if (du != 0)
626  theHitMap.insert(theHitMap.end(),makeSinglePSimHit( *du, ts, tkID, el, thick, pID,tTopo));
627  }
628 
629 }
630 
631 std::pair<double,PSimHit>
633  const TrajectoryStateOnSurface& ts,
634  int tkID, float el, float thick, int pID,
635  const TrackerTopology *tTopo) const
636 {
637 
638  const float onSurfaceTolarance = 0.01; // 10 microns
639 
640  LocalPoint lpos;
641  LocalVector lmom;
642  if ( fabs( det.toLocal(ts.globalPosition()).z()) < onSurfaceTolarance) {
643  lpos = ts.localPosition();
644  lmom = ts.localMomentum();
645  }
646  else {
647  HelixArbitraryPlaneCrossing crossing( ts.globalPosition().basicVector(),
649  ts.transverseCurvature(),
650  anyDirection);
651  std::pair<bool,double> path = crossing.pathLength(det.surface());
652  if (!path.first) {
653  // edm::LogWarning("FastTracking") << "TrajectoryManager ERROR: crossing with det failed, skipping PSimHit";
654  return std::pair<double,PSimHit>(0.,PSimHit());
655  }
656  lpos = det.toLocal( GlobalPoint( crossing.position(path.second)));
657  lmom = det.toLocal( GlobalVector( crossing.direction(path.second)));
658  lmom = lmom.unit() * ts.localMomentum().mag();
659  }
660 
661  // The module (half) thickness
662  const BoundPlane& theDetPlane = det.surface();
663  float halfThick = 0.5*theDetPlane.bounds().thickness();
664  // The Energy loss rescaled to the module thickness
665  float eloss = el;
666  if ( thick > 0. ) {
667  // Total thickness is in radiation lengths, 1 radlen = 9.36 cm
668  // Sensitive module thickness is about 30 microns larger than
669  // the module thickness itself
670  eloss *= (2.* halfThick - 0.003) / (9.36 * thick);
671  }
672  // The entry and exit points, and the time of flight
673  float pZ = lmom.z();
674  LocalPoint entry = lpos + (-halfThick/pZ) * lmom;
675  LocalPoint exit = lpos + halfThick/pZ * lmom;
676  float tof = ts.globalPosition().mag() / 30. ; // in nanoseconds, FIXME: very approximate
677 
678  // If a hadron suffered a nuclear interaction, just assign the hits of the closest
679  // daughter to the mother's track. The same applies to a charged particle decay into
680  // another charged particle.
681  int localTkID = tkID;
682  if ( mySimEvent->track(tkID).mother().closestDaughterId() == tkID )
683  localTkID = mySimEvent->track(tkID).mother().id();
684 
685  // FIXME: fix the track ID and the particle ID
686  PSimHit hit( entry, exit, lmom.mag(), tof, eloss, pID,
687  det.geographicalId().rawId(), localTkID,
688  lmom.theta(),
689  lmom.phi());
690 
691  // Check that the PSimHit is physically on the module!
692  unsigned subdet = DetId(hit.detUnitId()).subdetId();
693  double boundX = theDetPlane.bounds().width()/2.;
694  double boundY = theDetPlane.bounds().length()/2.;
695 
696  // Special treatment for TID and TEC trapeziodal modules
697  if ( subdet == 4 || subdet == 6 )
698  boundX *= 1. - hit.localPosition().y()/theDetPlane.position().perp();
699 
700 #ifdef FAMOS_DEBUG
701  unsigned detid = DetId(hit.detUnitId()).rawId();
702  unsigned stereo = 0;
703  unsigned theLayer = 0;
704  unsigned theRing = 0;
705  switch (subdet) {
706  case 1:
707  {
708 
709  theLayer = tTopo->pxbLayer(detid);
710  std::cout << "\tPixel Barrel Layer " << theLayer << std::endl;
711  stereo = 1;
712  break;
713  }
714  case 2:
715  {
716 
717  theLayer = tTopo->pxfDisk(detid);
718  std::cout << "\tPixel Forward Disk " << theLayer << std::endl;
719  stereo = 1;
720  break;
721  }
722  case 3:
723  {
724 
725  theLayer = tTopo->tibLayer(detid);
726  std::cout << "\tTIB Layer " << theLayer << std::endl;
727  stereo = module.stereo();
728  break;
729  }
730  case 4:
731  {
732 
733  theLayer = tTopo->tidWheel(detid);
734  theRing = tTopo->tidRing(detid);
735  unsigned int theSide = module.side();
736  if ( theSide == 1 )
737  std::cout << "\tTID Petal Back " << std::endl;
738  else
739  std::cout << "\tTID Petal Front" << std::endl;
740  std::cout << "\tTID Layer " << theLayer << std::endl;
741  std::cout << "\tTID Ring " << theRing << std::endl;
742  stereo = module.stereo();
743  break;
744  }
745  case 5:
746  {
747 
748  theLayer = tTopo->tobLayer(detid);
749  stereo = tTopo->tobStereo(detid);
750  std::cout << "\tTOB Layer " << theLayer << std::endl;
751  break;
752  }
753  case 6:
754  {
755 
756  theLayer = tTopo->tecWheel(detid);
757  theRing = tTopo->tecRing(detid);
758  unsigned int theSide = module.petal()[0];
759  if ( theSide == 1 )
760  std::cout << "\tTEC Petal Back " << std::endl;
761  else
762  std::cout << "\tTEC Petal Front" << std::endl;
763  std::cout << "\tTEC Layer " << theLayer << std::endl;
764  std::cout << "\tTEC Ring " << theRing << std::endl;
765  stereo = module.stereo();
766  break;
767  }
768  default:
769  {
770  stereo = 0;
771  break;
772  }
773  }
774 
775  std::cout << "Thickness = " << 2.*halfThick-0.003 << "; " << thick * 9.36 << std::endl
776  << "Length = " << det.surface().bounds().length() << std::endl
777  << "Width = " << det.surface().bounds().width() << std::endl;
778 
779  std::cout << "Hit position = "
780  << hit.localPosition().x() << " "
781  << hit.localPosition().y() << " "
782  << hit.localPosition().z() << std::endl;
783 #endif
784 
785  // Check if the hit is on the physical volume of the module
786  // (It happens that it is not, in the case of double sided modules,
787  // because the envelope of the gluedDet is larger than each of
788  // the mono and the stereo modules)
789 
790  double dist = 0.;
791  GlobalPoint IP (mySimEvent->track(localTkID).vertex().position().x(),
792  mySimEvent->track(localTkID).vertex().position().y(),
793  mySimEvent->track(localTkID).vertex().position().z());
794 
795  dist = ( fabs(hit.localPosition().x()) > boundX ||
796  fabs(hit.localPosition().y()) > boundY ) ?
797  // Will be used later as a flag to reject the PSimHit!
798  -( det.surface().toGlobal(hit.localPosition()) - IP ).mag2()
799  :
800  // These hits are kept!
801  ( det.surface().toGlobal(hit.localPosition()) - IP ).mag2();
802 
803  // Fill Histos (~poor man event display)
804  /*
805  GlobalPoint gpos( det.toGlobal(hit.localPosition()));
806 // std::cout << "gpos.x() = " << gpos.x() << std::endl;
807 // std::cout << "gpos.y() = " << gpos.y() << std::endl;
808 
809  myHistos->fill("h300",gpos.x(),gpos.y());
810  if ( sin(gpos.phi()) > 0. )
811  myHistos->fill("h301",gpos.z(),gpos.perp());
812  else
813  myHistos->fill("h301",gpos.z(),-gpos.perp());
814  */
815  return std::pair<double,PSimHit>(dist,hit);
816 
817 }
818 
819 void
821 {
822 
823 // These are the BoundSurface&, the BoundDisk* and the BoundCylinder* for that layer
824 // const BoundSurface& theSurface = layer.surface();
825 // BoundDisk* theDisk = layer.disk(); // non zero for endcaps
826 // BoundCylinder* theCylinder = layer.cylinder(); // non zero for barrel
827 // int theLayer = layer.layerNumber(); // 1->3 PixB, 4->5 PixD,
828 // // 6->9 TIB, 10->12 TID,
829 // // 13->18 TOB, 19->27 TEC
830 
833 
834  std::vector< BarrelDetLayer*> barrelLayers =
836  LogDebug("FastTracking") << "Barrel DetLayer dump: ";
837  for (std::vector< BarrelDetLayer*>::const_iterator bl=barrelLayers.begin();
838  bl != barrelLayers.end(); ++bl) {
839  LogDebug("FastTracking")<< "radius " << (**bl).specificSurface().radius();
840  }
841 
842  std::vector< ForwardDetLayer*> posForwardLayers =
844  LogDebug("FastTracking") << "Positive Forward DetLayer dump: ";
845  for (std::vector< ForwardDetLayer*>::const_iterator fl=posForwardLayers.begin();
846  fl != posForwardLayers.end(); ++fl) {
847  LogDebug("FastTracking") << "Z pos "
848  << (**fl).surface().position().z()
849  << " radii "
850  << (**fl).specificSurface().innerRadius()
851  << ", "
852  << (**fl).specificSurface().outerRadius();
853  }
854 
855  const float rTolerance = 1.5;
856  const float zTolerance = 3.;
857 
858  LogDebug("FastTracking")<< "Dump of TrackerInteractionGeometry cylinders:";
859  for( std::list<TrackerLayer>::const_iterator i=_theGeometry->cylinderBegin();
860  i!=_theGeometry->cylinderEnd(); ++i) {
861  const BoundCylinder* cyl = i->cylinder();
862  const BoundDisk* disk = i->disk();
863 
864  LogDebug("FastTracking") << "Famos Layer no " << i->layerNumber()
865  << " is sensitive? " << i->sensitive()
866  << " pos " << i->surface().position();
867  if (!i->sensitive()) continue;
868 
869  if (cyl != 0) {
870  LogDebug("FastTracking") << " cylinder radius " << cyl->radius();
871  bool found = false;
872  for (std::vector< BarrelDetLayer*>::const_iterator
873  bl=barrelLayers.begin(); bl != barrelLayers.end(); ++bl) {
874 
875  if (fabs( cyl->radius() - (**bl).specificSurface().radius()) < rTolerance) {
876  theLayerMap[i->layerNumber()] = *bl;
877  found = true;
878  LogDebug("FastTracking")<< "Corresponding DetLayer found with radius "
879  << (**bl).specificSurface().radius();
880  break;
881  }
882  }
883  if (!found) {
884  edm::LogWarning("FastTracking") << " Trajectory manager FAILED to find a corresponding DetLayer!";
885  }
886  }
887  else {
888  LogDebug("FastTracking") << " disk radii " << disk->innerRadius()
889  << ", " << disk->outerRadius();
890  bool found = false;
891  for (std::vector< ForwardDetLayer*>::const_iterator fl=posForwardLayers.begin();
892  fl != posForwardLayers.end(); ++fl) {
893 
894  if (fabs( disk->position().z() - (**fl).surface().position().z()) < zTolerance) {
895  theLayerMap[i->layerNumber()] = *fl;
896  found = true;
897  LogDebug("FastTracking") << "Corresponding DetLayer found with Z pos "
898  << (**fl).surface().position().z()
899  << " and radii "
900  << (**fl).specificSurface().innerRadius()
901  << ", "
902  << (**fl).specificSurface().outerRadius();
903  break;
904  }
905  }
906  if (!found) {
907  edm::LogWarning("FastTracking") << "FAILED to find a corresponding DetLayer!";
908  }
909  }
910  }
911 
912  // Put the negative layers in the same map but with an offset
913  std::vector< ForwardDetLayer*> negForwardLayers = theGeomSearchTracker->negForwardLayers();
914  for (std::vector< ForwardDetLayer*>::const_iterator nl=negForwardLayers.begin();
915  nl != negForwardLayers.end(); ++nl) {
916  for (int i=0; i<=theNegLayerOffset; i++) {
917  if (theLayerMap[i] == 0) continue;
918  if ( fabs( (**nl).surface().position().z() +theLayerMap[i]-> surface().position().z()) < zTolerance) {
920  break;
921  }
922  }
923  }
924 
925 }
926 
927 const DetLayer*
928 TrajectoryManager::detLayer( const TrackerLayer& layer, float zpos) const
929 {
930  if (zpos > 0 || !layer.forward() ) return theLayerMap[layer.layerNumber()];
931  else return theLayerMap[layer.layerNumber()+theNegLayerOffset];
932 }
933 
934 void
936 {
937 
938  std::map<unsigned,std::map<double,PSimHit> >::const_iterator itrack = thePSimHits.begin();
939  std::map<unsigned,std::map<double,PSimHit> >::const_iterator itrackEnd = thePSimHits.end();
940  for ( ; itrack != itrackEnd; ++itrack ) {
941  std::map<double,PSimHit>::const_iterator it = (itrack->second).begin();
942  std::map<double,PSimHit>::const_iterator itEnd = (itrack->second).end();
943  for( ; it!= itEnd; ++it) {
944  /*
945  DetId theDetUnitId((it->second).detUnitId());
946  const GeomDet* theDet = theGeomTracker->idToDet(theDetUnitId);
947  std::cout << "Track/z/r after : "
948  << (it->second).trackId() << " "
949  << theDet->surface().toGlobal((it->second).localPosition()).z() << " "
950  << theDet->surface().toGlobal((it->second).localPosition()).perp() << std::endl;
951  */
952  // Keep only those hits that are on the physical volume of a module
953  // (The other hits have been assigned a negative <double> value.
954  if ( it->first > 0. ) c.push_back(it->second);
955  }
956  }
957 
958 }
#define LogDebug(id)
bool hasDecayed() const
Has the particle decayed while propagated ?
int id() const
the index in FBaseSimEvent
Definition: FSimVertex.h:44
void initializeLayerMap()
Initialize correspondence map between Famos interaction geometry and tracker reco geometry...
GlobalPoint toGlobal(const Point2DBase< Scalar, LocalTag > lp) const
Definition: Surface.h:114
T getParameter(std::string const &) const
int addSimVertex(const XYZTLorentzVector &decayVertex, int im=-1, FSimVertexType::VertexType type=FSimVertexType::ANY)
Add a new vertex to the Event and to the various lists.
T getUntrackedParameter(std::string const &, T const &) const
virtual const BoundSurface & surface() const =0
The surface of the GeometricSearchDet.
int i
Definition: DBlmapReader.cc:9
const DetLayer * detLayer(const TrackerLayer &layer, float zpos) const
Returns the DetLayer pointer corresponding to the FAMOS layer.
void initializeTrackerGeometry(const TrackerGeometry *geomTracker)
Initialize the full Tracker Geometry.
PythiaDecays * myDecayEngine
std::pair< double, PSimHit > makeSinglePSimHit(const GeomDetUnit &det, const TrajectoryStateOnSurface &ts, int tkID, float el, float thick, int pID, const TrackerTopology *tTopo) const
and there
virtual float length() const =0
int addSimTrack(const RawParticle *p, int iv, int ig=-1, const HepMC::GenVertex *ev=0)
Add a new track to the Event and to the various lists.
bool propagateToPreshowerLayer1(bool first=true)
void makePSimHits(const GeomDet *det, const TrajectoryStateOnSurface &ts, std::map< double, PSimHit > &theHitMap, int tkID, float el, float thick, int pID, const TrackerTopology *tTopo)
and there
unsigned int tibLayer(const DetId &id) const
unsigned int tidRing(const DetId &id) const
const FSimVertex & endVertex() const
end vertex
tuple pp
Definition: createTree.py:15
void createPSimHits(const TrackerLayer &layer, const ParticlePropagator &P_before, std::map< double, PSimHit > &theHitMap, int trackID, int partID, const TrackerTopology *tTopo)
Create a vector of PSimHits.
const MagneticFieldMap * _theFieldMap
unsigned int layerNumber() const
Returns the layer number.
Definition: TrackerLayer.h:82
bool forward() const
Is the layer forward ?
Definition: TrackerLayer.h:70
void setPosition(const math::XYZTLorentzVector &newPosition)
Reset the position (to be used with care)
Definition: FSimVertex.h:52
const TrackerGeometry * theGeomTracker
void initializeRecoGeometry(const GeometricSearchTracker *geomSearchTracker, const TrackerInteractionGeometry *interactionGeometry, const MagneticFieldMap *aFieldMap)
Initialize the Reconstruction Geometry.
unsigned int pxfDisk(const DetId &id) const
const XYZTLorentzVector & momentum() const
Temporary (until move of SimTrack to Mathcore) - No! Actually very useful.
Definition: FSimTrack.h:190
TrajectoryStateOnSurface makeTrajectoryState(const DetLayer *layer, const ParticlePropagator &pp, const MagneticField *field) const
Teddy, you must put comments there.
unsigned int tecRing(const DetId &id) const
ring id
uint32_t tobStereo(const DetId &id) const
void moveAllDaughters(int fsimi, const Rotation &r, double rescale)
Move, rescale and rotate all daughters after propagation, material effects and decay of the mother...
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
const FSimTrack & daughter(int i) const
Ith daughter.
const GeometricSearchTracker * theGeomSearchTracker
void setEcal(const RawParticle &pp, int success)
Set the ecal variables.
Definition: FSimTrack.cc:69
std::list< TrackerLayer >::const_iterator cylinderEnd() const
Returns the last pointer in the cylinder list.
int getSuccess() const
Has propagation been performed and was barrel or endcap reached ?
void setPropagate()
The particle has been propgated through the tracker.
Definition: FSimTrack.cc:49
GlobalPoint globalPosition() const
LocalPoint toLocal(const GlobalPoint &gp) const
Conversion to the R.F. of the GeomDet.
Definition: GeomDet.h:62
bool propagateToBoundSurface(const TrackerLayer &)
int nDaughters() const
Number of daughters.
const Bounds & bounds() const
Definition: Surface.h:128
DaughterParticleList::const_iterator DaughterParticleIterator
Definition: PythiaDecays.h:22
unsigned int tidWheel(const DetId &id) const
void setClosestDaughterId(int id)
Set the index of the closest charged daughter.
Definition: FSimTrack.h:184
void setLayer2(const RawParticle &pp, int success)
Set the preshower layer2 variables.
Definition: FSimTrack.cc:62
TRandom random
Definition: MVATrainer.cc:138
ROOT::Math::AxisAngle Rotation
const Plane & surface() const
The nominal surface of the GeomDet.
Definition: GeomDet.h:35
float float float z
bool notYetToEndVertex(const XYZTLorentzVector &pos) const
Compare the end vertex position with another position.
Definition: FSimTrack.cc:33
virtual std::vector< DetWithState > compatibleDets(const TrajectoryStateOnSurface &startingState, const Propagator &prop, const MeasurementEstimator &est) const
FSimVertex & vertex(int id) const
Return vertex with given Id.
uint32_t rawId() const
get the raw id
Definition: DetId.h:45
LocalVector localMomentum() const
std::vector< BarrelDetLayer * > const & barrelLayers() const
int TrackCharge
Definition: TrackCharge.h:4
void reconstruct(const TrackerTopology *tTopo)
Does the real job.
bool propagateToVFcalEntrance(bool first=true)
void setLayer1(const RawParticle &pp, int success)
Set the preshower layer1 variables.
Definition: FSimTrack.cc:55
const XYZTLorentzVector & momentum() const
the momentum fourvector
Definition: RawParticle.h:285
~TrajectoryManager()
Default Destructor.
T mag() const
Definition: PV3DBase.h:67
math::XYZVector XYZVector
const RandomEngine * random
const TrackerInteractionGeometry * _theGeometry
const math::XYZTLorentzVector & position() const
Temporary (until CMSSW moves to Mathcore) - No ! Actually very useful.
Definition: FSimVertex.h:49
MaterialEffects * theMaterialEffects
const DaughterParticleList & particleDaughtersPy8(ParticlePropagator &particle)
Definition: PythiaDecays.cc:51
T sqrt(T t)
Definition: SSEVec.h:48
void updateWithDaughters(ParticlePropagator &PP, int fsimi)
Decay the particle and update the SimEvent with daughters.
const DaughterParticleList & particleDaughtersPy6(ParticlePropagator &particle)
std::pair< std::string, MonitorElement * > entry
Definition: ME_MAP.h:8
T z() const
Definition: PV3DBase.h:64
double Y() const
y of vertex
Definition: RawParticle.h:274
tuple IP
Definition: listHistos.py:76
int closestDaughterId() const
Get the index of the closest charged daughter.
Definition: FSimTrack.h:187
double Z() const
z of vertex
Definition: RawParticle.h:275
void setPropagationConditions(const TrackerLayer &, bool firstLoop=true)
DetId geographicalId() const
The label of this GeomDet.
Definition: GeomDet.h:72
void save()
Save nuclear interaction information.
const FSimVertex & vertex() const
Origin vertex.
#define end
Definition: vmac.h:38
std::vector< ForwardDetLayer * > const & negForwardLayers() const
std::pair< const GeomDet *, TrajectoryStateOnSurface > DetWithState
double charge() const
get the MEASURED charge
Definition: RawParticle.h:281
TrajectoryManager()
Default Constructor.
virtual std::vector< const GeomDet * > components() const =0
Returns direct components, if any.
void propagateToCalorimeters(ParticlePropagator &PP, int fsimi)
Propagate the particle through the calorimeters.
bool propagateToEcalEntrance(bool first=true)
unsigned int nTracks() const
Number of tracks.
Definition: FSimEvent.cc:48
std::map< unsigned, std::map< double, PSimHit > > thePSimHits
unsigned int pxbLayer(const DetId &id) const
bool accept(const RawParticle &p) const
const XYZTLorentzVector & vertex() const
the vertex fourvector
Definition: RawParticle.h:284
double energyLoss() const
Return the energy loss by ionization in the current layer.
Vector3DBase unit() const
Definition: Vector3DBase.h:57
Definition: DetId.h:20
virtual ReferenceCountingPointer< TangentPlane > tangentPlane(const GlobalPoint &) const =0
std::vector< ForwardDetLayer * > const & posForwardLayers() const
double thickness() const
Return the thickness of the current layer.
void loadSimHits(edm::PSimHitContainer &c) const
std::list< TrackerLayer >::const_iterator cylinderBegin() const
Returns the first pointer in the cylinder list.
tuple simHits
Definition: trackerHits.py:16
string const
Definition: compareJSON.py:14
void setTkPosition(const math::XYZVectorD &pos)
Definition: SimTrack.h:40
const TrackerInteractionGeometry * theGeometry()
Returns the pointer to geometry.
double X() const
x of vertex
Definition: RawParticle.h:273
double getMagneticField() const
Get the magnetic field.
int type() const
particle type (HEP PDT convension)
Definition: CoreSimTrack.h:40
std::vector< const DetLayer * > theLayerMap
bool propagateToHcalEntrance(bool first=true)
#define begin
Definition: vmac.h:31
GlobalVector globalMomentum() const
const KineParticleFilter & filter() const
int id() const
the index in FBaseSimEvent and other vectors
Definition: FSimTrack.h:86
void interact(FSimEvent &simEvent, const TrackerLayer &layer, ParticlePropagator &PP, unsigned i)
void setTkMomentum(const math::XYZTLorentzVectorD &mom)
Definition: SimTrack.h:42
void setVFcal(const RawParticle &pp, int success)
Set the hcal variables.
Definition: FSimTrack.cc:83
std::pair< const GeomDet *, TrajectoryStateOnSurface > DetWithState
bool propagateToLayer(ParticlePropagator &PP, unsigned layer)
tuple cout
Definition: gather_cfg.py:121
std::vector< PSimHit > PSimHitContainer
void setHcal(const RawParticle &pp, int success)
Set the hcal variables.
Definition: FSimTrack.cc:76
bool onFiducial() const
Is the vertex on some material ?
void setMomentum(const math::XYZTLorentzVector &newMomentum)
Reset the momentum (to be used with care)
Definition: FSimTrack.h:193
virtual float width() const =0
const BasicVectorType & basicVector() const
Definition: PV3DBase.h:56
unsigned int tecWheel(const DetId &id) const
Definition: vlib.h:209
bool propagateToPreshowerLayer2(bool first=true)
const FSimTrack & mother() const
mother
unsigned int tobLayer(const DetId &id) const
Global3DVector GlobalVector
Definition: GlobalVector.h:10
math::XYZTLorentzVector XYZTLorentzVector
Definition: RawParticle.h:15
std::vector< RawParticle > DaughterParticleList
Definition: PythiaDecays.h:19
FSimTrack & track(int id) const
Return track with given Id.
T angle(T x1, T y1, T z1, T x2, T y2, T z2)
Definition: angle.h:11