CMS 3D CMS Logo

TrajectoryManager.cc

Go to the documentation of this file.
00001 //Framework Headers
00002 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00003 
00004 //CMSSW Headers
00005 #include "DataFormats/GeometrySurface/interface/BoundDisk.h"
00006 #include "DataFormats/GeometrySurface/interface/BoundCylinder.h"
00007 #include "DataFormats/GeometrySurface/interface/Surface.h"
00008 #include "DataFormats/GeometrySurface/interface/TangentPlane.h"
00009 
00010 // Tracker reco geometry headers 
00011 #include "TrackingTools/DetLayers/interface/DetLayer.h"
00012 #include "TrackingTools/DetLayers/interface/BarrelDetLayer.h"
00013 #include "TrackingTools/DetLayers/interface/ForwardDetLayer.h"
00014 #include "TrackingTools/GeomPropagators/interface/AnalyticalPropagator.h"
00015 #include "FastSimulation/TrajectoryManager/interface/InsideBoundsMeasurementEstimator.h"
00016 #include "Geometry/CommonDetUnit/interface/GeomDetUnit.h"
00017 #include "TrackingTools/GeomPropagators/interface/HelixArbitraryPlaneCrossing.h"
00018 #include "RecoTracker/TkDetLayers/interface/GeometricSearchTracker.h"
00019 //#include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
00020 
00021 //FAMOS Headers
00022 #include "FastSimulation/TrajectoryManager/interface/TrajectoryManager.h"
00023 #include "FastSimulation/TrajectoryManager/interface/LocalMagneticField.h"
00024 #include "FastSimulation/ParticlePropagator/interface/ParticlePropagator.h"
00025 #include "FastSimulation/TrackerSetup/interface/TrackerInteractionGeometry.h"
00026 #include "FastSimulation/ParticleDecay/interface/Pythia6Decays.h"
00027 #include "FastSimulation/Event/interface/FSimEvent.h"
00028 #include "FastSimulation/Event/interface/FSimVertex.h"
00029 #include "FastSimulation/Event/interface/KineParticleFilter.h"
00030 
00031 #include "FastSimulation/Utilities/interface/RandomEngine.h"
00032 //#include "FastSimulation/Utilities/interface/Histos.h"
00033 //#include "FastSimulation/Utilities/interface/FamosLooses.h"
00034 // Numbering scheme
00035 
00036 //#define FAMOS_DEBUG
00037 #ifdef FAMOS_DEBUG
00038 #include "DataFormats/SiStripDetId/interface/TIBDetId.h"
00039 #include "DataFormats/SiStripDetId/interface/TIDDetId.h"
00040 #include "DataFormats/SiStripDetId/interface/TOBDetId.h"
00041 #include "DataFormats/SiStripDetId/interface/TECDetId.h"
00042 #include "DataFormats/SiPixelDetId/interface/PXBDetId.h"
00043 #include "DataFormats/SiPixelDetId/interface/PXFDetId.h"
00044 #endif
00045 
00046 #include <list>
00047 
00048 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00049 
00050 TrajectoryManager::TrajectoryManager(FSimEvent* aSimEvent, 
00051                                      const edm::ParameterSet& matEff,
00052                                      const edm::ParameterSet& simHits,
00053                                      const edm::ParameterSet& decays,
00054                                      const RandomEngine* engine) : 
00055   mySimEvent(aSimEvent), 
00056   _theGeometry(0),
00057   _theFieldMap(0),
00058   theMaterialEffects(0), 
00059   myDecayEngine(0), 
00060   theGeomTracker(0),
00061   theGeomSearchTracker(0),
00062   theLayerMap(56, static_cast<const DetLayer*>(0)), // reserve space for layers here
00063   theNegLayerOffset(27),
00064   //  myHistos(0),
00065   random(engine)
00066 
00067 {
00068   
00069   // Initialize Bthe stable particle decay engine 
00070   if ( decays.getParameter<bool>("ActivateDecays") ) { 
00071     int seed = (int) ( 900000000. * random->flatShoot() );
00072     double comE = decays.getParameter<double>("comEnergy");
00073     myDecayEngine = new Pythia6Decays(seed,comE);
00074     distCut = decays.getParameter<double>("DistCut");
00075   }
00076 
00077   // Initialize the Material Effects updator, if needed
00078   if ( matEff.getParameter<bool>("PairProduction") || 
00079        matEff.getParameter<bool>("Bremsstrahlung") ||
00080        matEff.getParameter<bool>("EnergyLoss") || 
00081        matEff.getParameter<bool>("MultipleScattering") )
00082        theMaterialEffects = new MaterialEffects(matEff,random);
00083 
00084   // Save SimHits according to Optiom
00085   // Only the hits from first half loop is saved
00086   firstLoop = simHits.getUntrackedParameter<bool>("firstLoop",true);
00087   // Only if pT>pTmin are the hits saved
00088   pTmin = simHits.getUntrackedParameter<double>("pTmin",0.5);
00089 
00090   // Get the Famos Histos pointer
00091   //  myHistos = Histos::instance();
00092 
00093   // Initialize a few histograms
00094   /* 
00095   myHistos->book("h300",1210,-121.,121.,1210,-121.,121.);
00096   myHistos->book("h301",1200,-300.,300.,1210,-121.,121.);
00097   */
00098 
00099   
00100 }
00101 
00102 void 
00103 TrajectoryManager::initializeRecoGeometry(const GeometricSearchTracker* geomSearchTracker,
00104                                           const TrackerInteractionGeometry* interactionGeometry,
00105                                           const MagneticFieldMap* aFieldMap)
00106 {
00107   
00108   // Initialize the reco tracker geometry
00109   theGeomSearchTracker = geomSearchTracker;
00110   
00111   // Initialize the simplified tracker geometry
00112   _theGeometry = interactionGeometry;
00113 
00114   initializeLayerMap();
00115 
00116   // Initialize the magnetic field
00117   _theFieldMap = aFieldMap;
00118 
00119 }
00120 
00121 void 
00122 TrajectoryManager::initializeTrackerGeometry(const TrackerGeometry* geomTracker) { 
00123   
00124   theGeomTracker = geomTracker;
00125 
00126 }
00127 
00128 const TrackerInteractionGeometry*
00129 TrajectoryManager::theGeometry() {
00130   return _theGeometry;
00131 }
00132 
00133 TrajectoryManager::~TrajectoryManager() {
00134 
00135   if ( myDecayEngine ) delete myDecayEngine;
00136   if ( theMaterialEffects ) delete theMaterialEffects;
00137 
00138   //Write the histograms
00139   //myHistos->put("histos.root");
00140   //  if ( myHistos ) delete myHistos;
00141 
00142 }
00143 
00144 void
00145 TrajectoryManager::reconstruct()
00146 {
00147 
00148   // Get pythia random state for decay (after saving current pythia state)
00149   if ( myDecayEngine ) myDecayEngine->getRandom();
00150   
00151   // Clear the hits of the previous event
00152   //  thePSimHits->clear();
00153   thePSimHits.clear();
00154 
00155   // The new event
00156   XYZTLorentzVector myBeamPipe = XYZTLorentzVector(0.,25., 9999999.,0.);
00157 
00158   std::list<TrackerLayer>::const_iterator cyliter;
00159 
00160   //  bool debug = mySimEvent->id().event() == 3;
00161 
00162   // Loop over the particles (watch out: increasing upper limit!)
00163   for( int fsimi=0; fsimi < (int) mySimEvent->nTracks(); ++fsimi) {
00164 
00165     // If the particle has decayed inside the beampipe, or decays 
00166     // immediately, there is nothing to do
00167     if( !mySimEvent->track(fsimi).notYetToEndVertex(myBeamPipe) ) continue;
00168     mySimEvent->track(fsimi).setPropagate();
00169 
00170     // Get the geometry elements 
00171     cyliter = _theGeometry->cylinderBegin();
00172     // Prepare the propagation  
00173     ParticlePropagator PP(mySimEvent->track(fsimi),_theFieldMap,random);
00174     //The real work starts here
00175     int success = 1;
00176     int sign = +1;
00177     int loop = 0;
00178     int cyl = 0;
00179 
00180     // Find the initial cylinder to propagate to.      
00181     for ( ; cyliter != _theGeometry->cylinderEnd() ; ++cyliter ) {
00182       
00183       PP.setPropagationConditions(*cyliter);
00184       if ( PP.inside() && !PP.onSurface() ) break;
00185       ++cyl;
00186 
00187     }
00188 
00189     // The particle has a pseudo-rapidity (position or momentum direction) 
00190     // in excess of 3.0. Just simply go to the last tracker layer
00191     // without bothering with all the details of the propagation and 
00192     // material effects.
00193     // 08/02/06 - pv: increase protection from 0.99 (eta=2.9932) to 0.9998 (eta=4.9517)
00194     //                to simulate material effects at large eta 
00195     // if above 0.99: propagate to the last tracker cylinder where the material is concentrated!
00196     double ppcos2T =  PP.cos2Theta();
00197     double ppcos2V =  PP.cos2ThetaV();
00198     if ( ( ppcos2T > 0.99 && ppcos2T < 0.9998 ) && ( cyl == 0 || ( ppcos2V > 0.99 && ppcos2V < 0.9998 ) ) ){ 
00199       if ( cyliter != _theGeometry->cylinderEnd() ) { 
00200         cyliter = _theGeometry->cylinderEnd(); 
00201         --cyliter;
00202       }
00203     // if above 0.9998: don't propagate at all (only to the calorimeters directly)
00204     } else if ( ppcos2T > 0.9998 && ( cyl == 0 || ppcos2V > 0.9998 ) ) { 
00205       cyliter = _theGeometry->cylinderEnd();
00206     }
00207         
00208     // Loop over the cylinders
00209     while ( cyliter != _theGeometry->cylinderEnd() &&
00210             loop<100 &&                            // No more than 100 loops
00211             mySimEvent->track(fsimi).notYetToEndVertex(PP.vertex())) { // The particle decayed
00212       
00213       // Pathological cases:
00214       // To prevent from interacting twice in a row with the same layer
00215       //      bool escapeBarrel    = (PP.getSuccess() == -1 && success == 1);
00216       bool escapeBarrel    = PP.getSuccess() == -1;
00217       bool escapeEndcap    = (PP.getSuccess() == -2 && success == 1);
00218       // To break the loop
00219       bool fullPropagation = 
00220         (PP.getSuccess() <= 0 && success==0) || escapeEndcap;
00221 
00222       if ( escapeBarrel ) {
00223         ++cyliter; ++cyl;
00224         while (cyliter != _theGeometry->cylinderEnd() && cyliter->forward() ) {
00225           sign=1; ++cyliter; ++cyl;
00226         }
00227 
00228         if ( cyliter == _theGeometry->cylinderEnd()  ) {
00229           --cyliter; --cyl; fullPropagation=true; 
00230         }
00231 
00232       }
00233 
00234       // Define the propagation conditions
00235       PP.setPropagationConditions(*cyliter,!fullPropagation);
00236       if ( escapeEndcap ) PP.increaseRCyl(0.0005);
00237 
00238       // Remember last propagation outcome
00239       success = PP.getSuccess();
00240 
00241       // Propagation was not successful :
00242       // Change the sign of the cylinder increment and count the loops
00243       if ( !PP.propagateToBoundSurface(*cyliter) || 
00244            PP.getSuccess()<=0) {
00245         sign = -sign;
00246         ++loop;
00247       }
00248 
00249       // The particle may have decayed on its way... in which the daughters
00250       // have to be added to the event record
00251       if ( PP.hasDecayed() || PP.PDGcTau()<1E-3 ) updateWithDaughters(PP,fsimi);
00252       if ( PP.hasDecayed() || PP.PDGcTau()<1E-3 ) break;
00253 
00254       // Exit by the endcaps or innermost cylinder :
00255       // Positive cylinder increment
00256       if ( PP.getSuccess()==2 || cyliter==_theGeometry->cylinderBegin() ) 
00257         sign = +1; 
00258           
00259       // Successful propagation to a cylinder, with some Material :
00260       if( PP.getSuccess() > 0 && PP.onFiducial() ) {
00261 
00262         bool saveHit = 
00263           ( (loop==0 && sign>0) || !firstLoop ) &&   // Save only first half loop
00264           PP.charge()!=0. &&                         // Consider only charged particles
00265           cyliter->sensitive() &&                    // Consider only sensitive layers
00266           PP.Perp2()>pTmin*pTmin;                    // Consider only pT > pTmin
00267 
00268         // Material effects are simulated there
00269         if ( theMaterialEffects ) 
00270           theMaterialEffects->interact(*mySimEvent,*cyliter,PP,fsimi); 
00271         
00272         if ( saveHit ) { 
00273 
00274           // Consider only active layers
00275           if ( cyliter->sensitive() ) {
00276             // Add information to the FSimTrack (not yet available)
00277             //      myTrack.addSimHit(PP,layer);
00278 
00279             // Return one or two (for overlap regions) PSimHits in the full 
00280             // tracker geometry
00281             if ( theGeomTracker ) 
00282               createPSimHits(*cyliter, PP, thePSimHits[fsimi], fsimi,mySimEvent->track(fsimi).type());
00283 
00284           }
00285         }
00286 
00287         // Fill Histos (~poor man event display)
00288         /* 
00289         myHistos->fill("h300",PP.x(),PP.y());
00290         if ( sin(PP.vertex().phi()) > 0. ) 
00291           myHistos->fill("h301",PP.z(),PP.vertex().perp());
00292         else
00293           myHistos->fill("h301",PP.z(),-PP.vertex().perp());
00294         */
00295 
00296         //The particle may have lost its energy in the material
00297         if ( mySimEvent->track(fsimi).notYetToEndVertex(PP.vertex()) && 
00298              !mySimEvent->filter().accept(PP)  ) 
00299           mySimEvent->addSimVertex(PP.vertex(),fsimi);
00300           
00301       }
00302 
00303       // Stop here if the particle has reached an end
00304       if ( mySimEvent->track(fsimi).notYetToEndVertex(PP.vertex()) ) {
00305 
00306         // Otherwise increment the cylinder iterator
00307         //      do { 
00308         if (sign==1) {++cyliter;++cyl;}
00309         else         {--cyliter;--cyl;}
00310 
00311         // Check if the last surface has been reached 
00312         if( cyliter==_theGeometry->cylinderEnd()) {
00313 
00314           // Try to propagate to the ECAL in half a loop
00315           // Note: Layer1 = ECAL Barrel entrance, or Preshower
00316           // entrance, or ECAL Endcap entrance (in the corner)
00317           PP.propagateToEcal();
00318           // PP.propagateToPreshowerLayer1();
00319 
00320           // If it is not possible, try go back to the last cylinder
00321           if(PP.getSuccess()==0) {
00322             --cyliter; --cyl; sign = -sign;
00323             PP.setPropagationConditions(*cyliter);
00324             PP.propagateToBoundSurface(*cyliter);
00325 
00326             // If there is definitely no way, leave it here.
00327             if(PP.getSuccess()<0) {++cyliter; ++cyl;}
00328 
00329           }
00330 
00331           // Check if the particle has decayed on the way to ECAL
00332           if ( PP.hasDecayed() )
00333             updateWithDaughters(PP,fsimi);
00334 
00335         }
00336       }
00337 
00338     }
00339 
00340     // Propagate all particles without a end vertex to the Preshower, 
00341     // theECAL and the HCAL.
00342     if ( mySimEvent->track(fsimi).notYetToEndVertex(PP.vertex()) )
00343       propagateToCalorimeters(PP,fsimi);
00344 
00345   }
00346 
00347   // Save the information from Nuclear Interaction Generation
00348   if ( theMaterialEffects ) theMaterialEffects->save();
00349 
00350   // Save pythia random state for decay (and put pythia state for event generation back on the stack)
00351   if ( myDecayEngine ) myDecayEngine->saveRandom();
00352   
00353 }
00354 
00355 void 
00356 TrajectoryManager::propagateToCalorimeters(ParticlePropagator& PP, int fsimi) {
00357 
00358   FSimTrack& myTrack = mySimEvent->track(fsimi);
00359 
00360   // Set the position and momentum at the end of the tracker volume
00361   myTrack.setTkPosition(PP.vertex().Vect());
00362   myTrack.setTkMomentum(PP.momentum());
00363 
00364   // Propagate to Preshower Layer 1 
00365   PP.propagateToPreshowerLayer1(false);
00366   if ( PP.hasDecayed() ) {
00367     updateWithDaughters(PP,fsimi);
00368     return;
00369   }
00370   if ( myTrack.notYetToEndVertex(PP.vertex()) && PP.getSuccess() > 0 )
00371     myTrack.setLayer1(PP,PP.getSuccess());
00372   
00373   // Propagate to Preshower Layer 2 
00374   PP.propagateToPreshowerLayer2(false);
00375   if ( PP.hasDecayed() ) { 
00376     updateWithDaughters(PP,fsimi);
00377     return;
00378   }
00379   if ( myTrack.notYetToEndVertex(PP.vertex()) && PP.getSuccess() > 0 )
00380     myTrack.setLayer2(PP,PP.getSuccess());
00381 
00382   // Propagate to Ecal Endcap
00383   PP.propagateToEcalEntrance(false);
00384   if ( PP.hasDecayed() ) { 
00385     updateWithDaughters(PP,fsimi);
00386     return;
00387   }
00388   if ( myTrack.notYetToEndVertex(PP.vertex()) )
00389     myTrack.setEcal(PP,PP.getSuccess());
00390 
00391   // Propagate to HCAL entrance
00392   PP.propagateToHcalEntrance(false);
00393   if ( PP.hasDecayed() ) { 
00394     updateWithDaughters(PP,fsimi);
00395     return;
00396   }
00397   if ( myTrack.notYetToEndVertex(PP.vertex()) )
00398     myTrack.setHcal(PP,PP.getSuccess());
00399 
00400   // Propagate to VFCAL entrance
00401   PP.propagateToVFcalEntrance(false);
00402   if ( PP.hasDecayed() ) { 
00403     updateWithDaughters(PP,fsimi);
00404     return;
00405   }
00406   if ( myTrack.notYetToEndVertex(PP.vertex()) )
00407     myTrack.setVFcal(PP,PP.getSuccess());
00408     
00409 }
00410 
00411 bool
00412 TrajectoryManager::propagateToLayer(ParticlePropagator& PP, unsigned layer) {
00413 
00414   std::list<TrackerLayer>::const_iterator cyliter;
00415   bool done = false;
00416 
00417   // Get the geometry elements 
00418   cyliter = _theGeometry->cylinderBegin();
00419 
00420   // Find the layer to propagate to.      
00421   for ( ; cyliter != _theGeometry->cylinderEnd() ; ++cyliter ) {
00422 
00423     if ( layer != cyliter->layerNumber() ) continue;
00424       
00425     PP.setPropagationConditions(*cyliter);
00426 
00427     done =  
00428       PP.propagateToBoundSurface(*cyliter) &&
00429       PP.getSuccess() > 0 && 
00430       PP.onFiducial();
00431 
00432     break;
00433     
00434   }
00435 
00436   return done;
00437 
00438 }
00439 
00440 void
00441 TrajectoryManager::updateWithDaughters(ParticlePropagator& PP, int fsimi) {
00442 
00443   // Decays are not activated : do nothing
00444   if ( !myDecayEngine ) return;
00445 
00446   // Invoke PYDECY to decay the particle and get the daughters
00447   const DaughterParticleList& daughters = myDecayEngine->particleDaughters(PP);
00448   
00449   // Update the FSimEvent with an end vertex and with the daughters
00450   if ( daughters.size() ) { 
00451     double distMin = 1E99;
00452     int theClosestChargedDaughterId = -1;
00453     DaughterParticleIterator daughter = daughters.begin();
00454     
00455     int ivertex = mySimEvent->addSimVertex(daughter->vertex(),fsimi);
00456 
00457     if ( ivertex != -1 ) {
00458       for ( ; daughter != daughters.end(); ++daughter) {
00459         int theDaughterId = mySimEvent->addSimTrack(&(*daughter), ivertex);
00460         // Find the closest charged daughter (if charged mother)
00461         if ( PP.charge() * daughter->charge() > 1E-10 ) {
00462           double dist = (daughter->Vect().Unit().Cross(PP.Vect().Unit())).R();
00463           if ( dist < distCut && dist < distMin ) { 
00464             distMin = dist;
00465             theClosestChargedDaughterId = theDaughterId;
00466           }
00467         }
00468       }
00469     }
00470     // Attach mother and closest daughter sp as to cheat tracking ;-)
00471     if ( theClosestChargedDaughterId >=0 ) 
00472       mySimEvent->track(fsimi).setClosestDaughterId(theClosestChargedDaughterId);
00473   }
00474 }
00475 
00476 
00477 void
00478 TrajectoryManager::createPSimHits(const TrackerLayer& layer,
00479                                   const ParticlePropagator& PP,
00480                                   std::map<double,PSimHit>& theHitMap,
00481                                   int trackID, int partID) {
00482 
00483   // Propagate the particle coordinates to the closest tracker detector(s) 
00484   // in this layer and create the PSimHit(s)
00485 
00486   //  const MagneticField& mf = MagneticFieldMap::instance()->magneticField();
00487   // This solution is actually much faster !
00488   LocalMagneticField mf(PP.getMagneticField());
00489   AnalyticalPropagator alongProp(&mf, anyDirection);
00490   InsideBoundsMeasurementEstimator est;
00491 
00492   typedef GeometricSearchDet::DetWithState   DetWithState;
00493   const DetLayer* tkLayer = detLayer(layer,PP.Z());
00494 
00495   TrajectoryStateOnSurface trajState = makeTrajectoryState( tkLayer, PP, &mf);
00496   float thickness = theMaterialEffects ? theMaterialEffects->thickness() : 0.;
00497   float eloss = theMaterialEffects ? theMaterialEffects->energyLoss() : 0.;
00498 
00499   // Find, in the corresponding layers, the detectors compatible 
00500   // with the current track 
00501   std::vector<DetWithState> compat 
00502     = tkLayer->compatibleDets( trajState, alongProp, est);
00503 
00504   // And create the corresponding PSimHits
00505   std::map<double,PSimHit> theTrackHits;
00506   for (std::vector<DetWithState>::const_iterator i=compat.begin(); i!=compat.end(); i++) {
00507     // Correct Eloss for last 3 rings of TEC (thick sensors, 0.05 cm)
00508     // Disgusting fudge factor ! 
00509       makePSimHits( i->first, i->second, theHitMap, trackID, eloss, thickness, partID);
00510   }
00511 }
00512 
00513 TrajectoryStateOnSurface 
00514 TrajectoryManager::makeTrajectoryState( const DetLayer* layer, 
00515                                         const ParticlePropagator& pp,
00516                                         const MagneticField* field) const
00517 {
00518   GlobalPoint  pos( pp.X(), pp.Y(), pp.Z());
00519   GlobalVector mom( pp.Px(), pp.Py(), pp.Pz());
00520   ReferenceCountingPointer<TangentPlane> plane = layer->surface().tangentPlane(pos);
00521   return TrajectoryStateOnSurface
00522     (GlobalTrajectoryParameters( pos, mom, TrackCharge( pp.charge()), field), *plane);
00523 }
00524 
00525 void 
00526 TrajectoryManager::makePSimHits( const GeomDet* det, 
00527                                  const TrajectoryStateOnSurface& ts,
00528                                  std::map<double,PSimHit>& theHitMap,
00529                                  int tkID, float el, float thick, int pID ) 
00530 {
00531 
00532   std::vector< const GeomDet*> comp = det->components();
00533   if (!comp.empty()) {
00534     for (std::vector< const GeomDet*>::const_iterator i = comp.begin();
00535          i != comp.end(); i++) {
00536       const GeomDetUnit* du = dynamic_cast<const GeomDetUnit*>(*i);
00537       if (du != 0)
00538         theHitMap.insert(theHitMap.end(),makeSinglePSimHit( *du, ts, tkID, el, thick, pID));
00539     }
00540   }
00541   else {
00542     const GeomDetUnit* du = dynamic_cast<const GeomDetUnit*>(det);
00543     if (du != 0)
00544       theHitMap.insert(theHitMap.end(),makeSinglePSimHit( *du, ts, tkID, el, thick, pID));
00545   }
00546 
00547 
00548 }
00549 
00550 std::pair<double,PSimHit> 
00551 TrajectoryManager::makeSinglePSimHit( const GeomDetUnit& det,
00552                                       const TrajectoryStateOnSurface& ts, 
00553                                       int tkID, float el, float thick, int pID) const
00554 {
00555 
00556   const float onSurfaceTolarance = 0.01; // 10 microns
00557 
00558   LocalPoint lpos;
00559   LocalVector lmom;
00560   if ( fabs( det.toLocal(ts.globalPosition()).z()) < onSurfaceTolarance) {
00561     lpos = ts.localPosition();
00562     lmom = ts.localMomentum();
00563   }
00564   else {
00565     HelixArbitraryPlaneCrossing crossing( ts.globalPosition().basicVector(),
00566                                           ts.globalMomentum().basicVector(),
00567                                           ts.transverseCurvature(),
00568                                           anyDirection);
00569     std::pair<bool,double> path = crossing.pathLength(det.surface());
00570     if (!path.first) {
00571       // edm::LogError("FastTracker") << "TrajectoryManager ERROR: crossing with det failed, skipping PSimHit";
00572       return  std::pair<double,PSimHit>(0.,PSimHit());
00573     }
00574     lpos = det.toLocal( GlobalPoint( crossing.position(path.second)));
00575     lmom = det.toLocal( GlobalVector( crossing.direction(path.second)));
00576     lmom = lmom.unit() * ts.localMomentum().mag();
00577   }
00578 
00579   // The module (half) thickness 
00580   const BoundPlane& theDetPlane = det.surface();
00581   float halfThick = 0.5*theDetPlane.bounds().thickness();
00582   // The Energy loss rescaled to the module thickness
00583   float eloss = el;
00584   if ( thick > 0. ) {
00585     // Total thickness is in radiation lengths, 1 radlen = 9.36 cm
00586     // Sensitive module thickness is about 30 microns larger than 
00587     // the module thickness itself
00588     eloss *= (2.* halfThick - 0.003) / (9.36 * thick);
00589   }
00590   // The entry and exit points, and the time of flight
00591   float pZ = lmom.z();
00592   LocalPoint entry = lpos + (-halfThick/pZ) * lmom;
00593   LocalPoint exit = lpos + halfThick/pZ * lmom;
00594   float tof = ts.globalPosition().mag() / 30. ; // in nanoseconds, FIXME: very approximate
00595 
00596   // If a hadron suffered a nuclear interaction, just assign the hits of the closest 
00597   // daughter to the mother's track. The same applies to a charged particle decay into
00598   // another charged particle.
00599   int localTkID = tkID;
00600   if ( mySimEvent->track(tkID).mother().closestDaughterId() == tkID )
00601     localTkID = mySimEvent->track(tkID).mother().id();
00602 
00603   // FIXME: fix the track ID and the particle ID
00604   PSimHit hit( entry, exit, lmom.mag(), tof, eloss, pID,
00605                   det.geographicalId().rawId(), localTkID,
00606                   lmom.theta(),
00607                   lmom.phi());
00608 
00609   // Check that the PSimHit is physically on the module!
00610   unsigned subdet = DetId(hit.detUnitId()).subdetId(); 
00611   double boundX = theDetPlane.bounds().width()/2.;
00612   double boundY = theDetPlane.bounds().length()/2.;
00613 
00614   // Special treatment for TID and TEC trapeziodal modules
00615   if ( subdet == 4 || subdet == 6 ) 
00616     boundX *=  1. - hit.localPosition().y()/theDetPlane.position().perp();
00617 
00618 #ifdef FAMOS_DEBUG
00619   unsigned detid  = DetId(hit.detUnitId()).rawId();
00620   unsigned stereo = 0;
00621   unsigned theLayer = 0;
00622   unsigned theRing = 0;
00623   switch (subdet) { 
00624   case 1: 
00625     {
00626       PXBDetId module(detid);
00627       theLayer = module.layer();
00628       std::cout << "\tPixel Barrel Layer " << theLayer << std::endl;
00629       stereo = 1;
00630       break;
00631     }
00632   case 2: 
00633     {
00634       PXFDetId module(detid);
00635       theLayer = module.disk();
00636       std::cout << "\tPixel Forward Disk " << theLayer << std::endl;
00637       stereo = 1;
00638       break;
00639     }
00640   case 3:
00641     {
00642       TIBDetId module(detid);
00643       theLayer  = module.layer();
00644       std::cout << "\tTIB Layer " << theLayer << std::endl;
00645       stereo = module.stereo();
00646       break;
00647     }
00648   case 4:
00649     {
00650       TIDDetId module(detid);
00651       theLayer = module.wheel();
00652       theRing  = module.ring();
00653       unsigned int theSide = module.side();
00654       if ( theSide == 1 ) 
00655         std::cout << "\tTID Petal Back " << std::endl; 
00656       else
00657         std::cout << "\tTID Petal Front" << std::endl; 
00658       std::cout << "\tTID Layer " << theLayer << std::endl;
00659       std::cout << "\tTID Ring " << theRing << std::endl;
00660       stereo = module.stereo();
00661       break;
00662     }
00663   case 5:
00664     {
00665       TOBDetId module(detid);
00666       theLayer  = module.layer();
00667       stereo = module.stereo();
00668       std::cout << "\tTOB Layer " << theLayer << std::endl;
00669       break;
00670     }
00671   case 6:
00672     {
00673       TECDetId module(detid);
00674       theLayer = module.wheel();
00675       theRing  = module.ring();
00676       unsigned int theSide = module.petal()[0];
00677       if ( theSide == 1 ) 
00678         std::cout << "\tTEC Petal Back " << std::endl; 
00679       else
00680         std::cout << "\tTEC Petal Front" << std::endl; 
00681       std::cout << "\tTEC Layer " << theLayer << std::endl;
00682       std::cout << "\tTEC Ring " << theRing << std::endl;
00683       stereo = module.stereo();
00684       break;
00685     }
00686   default:
00687     {
00688       stereo = 0;
00689       break;
00690     }
00691   }
00692   
00693   std::cout << "Thickness = " << 2.*halfThick-0.003 << "; " << thick * 9.36 << std::endl
00694             << "Length    = " << det.surface().bounds().length() << std::endl
00695             << "Width     = " << det.surface().bounds().width() << std::endl;
00696     
00697   std::cout << "Hit position = " 
00698             << hit.localPosition().x() << " " 
00699             << hit.localPosition().y() << " " 
00700             << hit.localPosition().z() << std::endl;
00701 #endif
00702 
00703   // Check if the hit is on the physical volume of the module
00704   // (It happens that it is not, in the case of double sided modules,
00705   //  because the envelope of the gluedDet is larger than each of 
00706   //  the mono and the stereo modules)
00707 
00708   double dist = 0.;
00709   GlobalPoint IP (mySimEvent->track(localTkID).vertex().position().x(),
00710                   mySimEvent->track(localTkID).vertex().position().y(),
00711                   mySimEvent->track(localTkID).vertex().position().z());
00712 
00713   dist = ( fabs(hit.localPosition().x()) > boundX  || 
00714            fabs(hit.localPosition().y()) > boundY ) ?  
00715     // Will be used later as a flag to reject the PSimHit!
00716     -( det.surface().toGlobal(hit.localPosition()) - IP ).mag2() 
00717     : 
00718     // These hits are kept!
00719      ( det.surface().toGlobal(hit.localPosition()) - IP ).mag2();
00720 
00721   // Fill Histos (~poor man event display)
00722   /* 
00723      GlobalPoint gpos( det.toGlobal(hit.localPosition()));
00724      myHistos->fill("h300",gpos.x(),gpos.y());
00725      if ( sin(gpos.phi()) > 0. ) 
00726      myHistos->fill("h301",gpos.z(),gpos.perp());
00727      else
00728      myHistos->fill("h301",gpos.z(),-gpos.perp());
00729   */
00730   
00731   return std::pair<double,PSimHit>(dist,hit);
00732 
00733 }
00734 
00735 void 
00736 TrajectoryManager::initializeLayerMap()
00737 {
00738 
00739 // These are the BoundSurface&, the BoundDisk* and the BoundCylinder* for that layer
00740 //   const BoundSurface& theSurface = layer.surface();
00741 //   BoundDisk* theDisk = layer.disk();  // non zero for endcaps
00742 //   BoundCylinder* theCylinder = layer.cylinder(); // non zero for barrel
00743 //   int theLayer = layer.layerNumber(); // 1->3 PixB, 4->5 PixD, 
00744 //                                       // 6->9 TIB, 10->12 TID, 
00745 //                                       // 13->18 TOB, 19->27 TEC
00746 
00749 
00750   std::vector< BarrelDetLayer*>   barrelLayers = 
00751     theGeomSearchTracker->barrelLayers();
00752   LogDebug("FastTracker") << "Barrel DetLayer dump: ";
00753   for (std::vector< BarrelDetLayer*>::const_iterator bl=barrelLayers.begin();
00754        bl != barrelLayers.end(); ++bl) {
00755     LogDebug("FastTracker")<< "radius " << (**bl).specificSurface().radius(); 
00756   }
00757 
00758   std::vector< ForwardDetLayer*>  posForwardLayers = 
00759     theGeomSearchTracker->posForwardLayers();
00760   LogDebug("FastTracker") << "Positive Forward DetLayer dump: ";
00761   for (std::vector< ForwardDetLayer*>::const_iterator fl=posForwardLayers.begin();
00762        fl != posForwardLayers.end(); ++fl) {
00763     LogDebug("FastTracker") << "Z pos "
00764                             << (**fl).surface().position().z()
00765                             << " radii " 
00766                             << (**fl).specificSurface().innerRadius() 
00767                             << ", " 
00768                             << (**fl).specificSurface().outerRadius(); 
00769   }
00770 
00771   const float rTolerance = 1.5;
00772   const float zTolerance = 3.;
00773 
00774   LogDebug("FastTracker")<< "Dump of TrackerInteractionGeometry cylinders:";
00775   for( std::list<TrackerLayer>::const_iterator i=_theGeometry->cylinderBegin();
00776        i!=_theGeometry->cylinderEnd(); ++i) {
00777     const BoundCylinder* cyl = i->cylinder();
00778     const BoundDisk* disk = i->disk();
00779 
00780     LogDebug("FastTracker") << "Famos Layer no " << i->layerNumber()
00781                             << " is sensitive? " << i->sensitive()
00782                             << " pos " << i->surface().position();
00783     if (!i->sensitive()) continue;
00784 
00785     if (cyl != 0) {
00786       LogDebug("FastTracker") << " cylinder radius " << cyl->radius();
00787       bool found = false;
00788       for (std::vector< BarrelDetLayer*>::const_iterator 
00789              bl=barrelLayers.begin(); bl != barrelLayers.end(); ++bl) {
00790         if (fabs( cyl->radius() - (**bl).specificSurface().radius()) < rTolerance) {
00791           theLayerMap[i->layerNumber()] = *bl;
00792           found = true;
00793           LogDebug("FastTracker")<< "Corresponding DetLayer found with radius "
00794                                  << (**bl).specificSurface().radius();
00795           break;
00796         }
00797       }
00798       if (!found) {
00799         edm::LogError("FastTracker") << "FAILED to find a corresponding DetLayer!";
00800       }
00801     }
00802     else {
00803       LogDebug("FastTracker") << " disk radii " << disk->innerRadius() 
00804                  << ", " << disk->outerRadius();
00805       bool found = false;
00806       for (std::vector< ForwardDetLayer*>::const_iterator fl=posForwardLayers.begin();
00807            fl != posForwardLayers.end(); ++fl) {
00808         if (fabs( disk->position().z() - (**fl).surface().position().z()) < zTolerance) {
00809           theLayerMap[i->layerNumber()] = *fl;
00810           found = true;
00811           LogDebug("FastTracker") << "Corresponding DetLayer found with Z pos "
00812                                   << (**fl).surface().position().z()
00813                                   << " and radii " 
00814                                   << (**fl).specificSurface().innerRadius() 
00815                                   << ", " 
00816                                   << (**fl).specificSurface().outerRadius(); 
00817           break;
00818         }
00819       }
00820       if (!found) {
00821         edm::LogError("FastTracker") << "FAILED to find a corresponding DetLayer!";
00822       }
00823     }
00824   }
00825 
00826   // Put the negative layers in the same map but with an offset
00827   std::vector< ForwardDetLayer*>  negForwardLayers = theGeomSearchTracker->negForwardLayers();
00828   for (std::vector< ForwardDetLayer*>::const_iterator nl=negForwardLayers.begin();
00829        nl != negForwardLayers.end(); ++nl) {
00830     for (int i=0; i<=theNegLayerOffset; i++) {
00831       if (theLayerMap[i] == 0) continue;
00832       if ( fabs( (**nl).surface().position().z() +theLayerMap[i]-> surface().position().z()) < zTolerance) {
00833         theLayerMap[i+theNegLayerOffset] = *nl;
00834         break;
00835       }
00836     }
00837   }  
00838 
00839 }
00840 
00841 const DetLayer*  
00842 TrajectoryManager::detLayer( const TrackerLayer& layer, float zpos) const
00843 {
00844   if (zpos > 0 || !layer.forward() ) return theLayerMap[layer.layerNumber()];
00845   else return theLayerMap[layer.layerNumber()+theNegLayerOffset];
00846 }
00847 
00848 void 
00849 TrajectoryManager::loadSimHits(edm::PSimHitContainer & c) const
00850 {
00851 
00852   std::map<unsigned,std::map<double,PSimHit> >::const_iterator itrack = thePSimHits.begin();
00853   std::map<unsigned,std::map<double,PSimHit> >::const_iterator itrackEnd = thePSimHits.end();
00854   for ( ; itrack != itrackEnd; ++itrack ) {
00855     std::map<double,PSimHit>::const_iterator it = (itrack->second).begin();
00856     std::map<double,PSimHit>::const_iterator itEnd = (itrack->second).end();
00857     for( ; it!= itEnd; ++it) { 
00858       /*
00859       DetId theDetUnitId((it->second).detUnitId());
00860       const GeomDet* theDet = theGeomTracker->idToDet(theDetUnitId);
00861       std::cout << "Track/z/r after : "
00862                 << (it->second).trackId() << " " 
00863                 << theDet->surface().toGlobal((it->second).localPosition()).z() << " " 
00864                 << theDet->surface().toGlobal((it->second).localPosition()).perp() << std::endl;
00865       */
00866       // Keep only those hits that are on the physical volume of a module
00867       // (The other hits have been assigned a negative <double> value. 
00868       if ( it->first > 0. ) c.push_back(it->second); 
00869     }
00870   }
00871 
00872 }

Generated on Tue Jun 9 17:35:17 2009 for CMSSW by  doxygen 1.5.4