CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/Validation/RecoMuon/src/MuonTrackAnalyzer.cc

Go to the documentation of this file.
00001 
00009 #include "Validation/RecoMuon/src/MuonTrackAnalyzer.h"
00010 
00011 // Collaborating Class Header
00012 #include "FWCore/Framework/interface/Frameworkfwd.h"
00013 #include "FWCore/Framework/interface/Event.h"
00014 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00015 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00016 
00017 #include "Geometry/CommonDetUnit/interface/GeomDet.h"
00018 
00019 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
00020 #include "DataFormats/TrajectorySeed/interface/TrajectorySeedCollection.h"
00021 #include "DataFormats/TrackReco/interface/Track.h"
00022 #include "DataFormats/TrajectorySeed/interface/TrajectorySeedCollection.h"
00023 #include "TrackingTools/DetLayers/interface/DetLayer.h"
00024 #include "DataFormats/Math/interface/deltaR.h"
00025 
00026 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
00027 
00028 #include "CommonTools/Statistics/interface/ChiSquaredProbability.h"
00029 
00030 #include "RecoMuon/TrackingTools/interface/MuonPatternRecoDumper.h"
00031 #include "RecoMuon/TrackingTools/interface/MuonServiceProxy.h"
00032 #include "RecoMuon/TrackingTools/interface/MuonUpdatorAtVertex.h"
00033 
00034 #include "Validation/RecoMuon/src/Histograms.h"
00035 #include "Validation/RecoMuon/src/HTrack.h"
00036 
00037 #include "SimDataFormats/TrackingHit/interface/PSimHit.h"
00038 #include "SimDataFormats/TrackingHit/interface/PSimHitContainer.h"
00039 #include "SimDataFormats/Track/interface/SimTrackContainer.h"
00040 
00041 #include "TFile.h"
00042 #include "TH1F.h"
00043 #include "TH2F.h"
00044 
00045 using namespace std;
00046 using namespace edm;
00047 
00049 MuonTrackAnalyzer::MuonTrackAnalyzer(const ParameterSet& pset){
00050   
00051   // service parameters
00052   ParameterSet serviceParameters = pset.getParameter<ParameterSet>("ServiceParameters");
00053   // the services
00054   theService = new MuonServiceProxy(serviceParameters);
00055   
00056   theTracksLabel = pset.getParameter<InputTag>("Tracks");
00057   doTracksAnalysis = pset.getUntrackedParameter<bool>("DoTracksAnalysis",true);
00058 
00059   doSeedsAnalysis = pset.getUntrackedParameter<bool>("DoSeedsAnalysis",false);
00060   if(doSeedsAnalysis){
00061     theSeedsLabel = pset.getParameter<InputTag>("MuonSeed");
00062     ParameterSet updatorPar = pset.getParameter<ParameterSet>("MuonUpdatorAtVertexParameters");
00063     theSeedPropagatorName = updatorPar.getParameter<string>("Propagator");
00064 
00065     theUpdator = new MuonUpdatorAtVertex(updatorPar,theService);
00066   }
00067   
00068   theCSCSimHitLabel = pset.getParameter<InputTag>("CSCSimHit");
00069   theDTSimHitLabel = pset.getParameter<InputTag>("DTSimHit");
00070   theRPCSimHitLabel = pset.getParameter<InputTag>("RPCSimHit");
00071 
00072   theEtaRange = (EtaRange) pset.getParameter<int>("EtaRange");
00073   
00074   // number of sim tracks
00075   numberOfSimTracks=0;
00076   // number of reco tracks
00077   numberOfRecTracks=0;
00078 
00079   dbe_ = edm::Service<DQMStore>().operator->();
00080   out = pset.getUntrackedParameter<string>("rootFileName");
00081   dirName_ = pset.getUntrackedParameter<std::string>("dirName");
00082 
00083 }
00084 
00086 MuonTrackAnalyzer::~MuonTrackAnalyzer(){
00087   if (theService) delete theService;
00088 }
00089 
00090 void MuonTrackAnalyzer::beginJob(){
00091   dbe_->showDirStructure();
00092   
00093   dbe_->cd();
00094   InputTag algo = theTracksLabel;
00095   string dirName=dirName_;
00096   if (algo.process()!="")
00097     dirName+=algo.process()+"_";
00098   if(algo.label()!="")
00099     dirName+=algo.label()+"_";
00100   if(algo.instance()!="")
00101     dirName+=algo.instance()+"";      
00102   if (dirName.find("Tracks")<dirName.length()){
00103     dirName.replace(dirName.find("Tracks"),6,"");
00104   }
00105   std::replace(dirName.begin(), dirName.end(), ':', '_');
00106   dbe_->setCurrentFolder(dirName.c_str());
00107   
00108   //dbe_->goUp();
00109   std::string simName = dirName;
00110   simName+="/SimTracks";
00111   hSimTracks = new HTrackVariables(simName.c_str(),"SimTracks"); 
00112 
00113   dbe_->cd();
00114   dbe_->setCurrentFolder(dirName.c_str());
00115 
00116   // Create the root file
00117   //theFile = new TFile(theRootFileName.c_str(), "RECREATE");
00118 
00119   if(doSeedsAnalysis){
00120     dbe_->cd();
00121     dbe_->setCurrentFolder(dirName.c_str());
00122     hRecoSeedInner = new HTrack(dirName.c_str(),"RecoSeed","Inner");
00123     hRecoSeedPCA = new HTrack(dirName.c_str(),"RecoSeed","PCA");
00124   }
00125   
00126   if(doTracksAnalysis){
00127     dbe_->cd();
00128     dbe_->setCurrentFolder(dirName.c_str());    
00129     hRecoTracksPCA = new HTrack(dirName.c_str(),"RecoTracks","PCA"); 
00130     hRecoTracksInner = new HTrack(dirName.c_str(),"RecoTracks","Inner"); 
00131     hRecoTracksOuter = new HTrack(dirName.c_str(),"RecoTracks","Outer"); 
00132 
00133     dbe_->cd();
00134     dbe_->setCurrentFolder(dirName.c_str());
00135     
00136     // General Histos
00137 
00138 
00139     hChi2 = dbe_->book1D("chi2","#chi^2",200,0,200);
00140     hChi2VsEta = dbe_->book2D("chi2VsEta","#chi^2 VS #eta",120,-3.,3.,200,0,200);
00141     
00142     hChi2Norm = dbe_->book1D("chi2Norm","Normalized #chi^2",400,0,100);
00143     hChi2NormVsEta = dbe_->book2D("chi2NormVsEta","Normalized #chi^2 VS #eta",120,-3.,3.,400,0,100);
00144     
00145     hHitsPerTrack  = dbe_->book1D("HitsPerTrack","Number of hits per track",55,0,55);
00146     hHitsPerTrackVsEta  = dbe_->book2D("HitsPerTrackVsEta","Number of hits per track VS #eta",
00147                                    120,-3.,3.,55,0,55);
00148     
00149     hDof  = dbe_->book1D("dof","Number of Degree of Freedom",55,0,55);
00150     hDofVsEta  = dbe_->book2D("dofVsEta","Number of Degree of Freedom VS #eta",120,-3.,3.,55,0,55);
00151     
00152     hChi2Prob = dbe_->book1D("chi2Prob","#chi^2 probability",200,0,1);
00153     hChi2ProbVsEta = dbe_->book2D("chi2ProbVsEta","#chi^2 probability VS #eta",120,-3.,3.,200,0,1);
00154     
00155     hNumberOfTracks = dbe_->book1D("NumberOfTracks","Number of reconstructed tracks per event",200,0,200);
00156     hNumberOfTracksVsEta = dbe_->book2D("NumberOfTracksVsEta",
00157                                     "Number of reconstructed tracks per event VS #eta",
00158                                     120,-3.,3.,10,0,10);
00159     
00160     hChargeVsEta = dbe_->book2D("ChargeVsEta","Charge vs #eta gen",120,-3.,3.,4,-2.,2.);
00161     hChargeVsPt = dbe_->book2D("ChargeVsPt","Charge vs P_{T} gen",250,0,200,4,-2.,2.);
00162     hPtRecVsPtGen = dbe_->book2D("PtRecVsPtGen","P_{T} rec vs P_{T} gen",250,0,200,250,0,200);
00163 
00164     hDeltaPtVsEta = dbe_->book2D("DeltaPtVsEta","#Delta P_{t} vs #eta gen",120,-3.,3.,500,-250.,250.);
00165     hDeltaPt_In_Out_VsEta = dbe_->book2D("DeltaPt_In_Out_VsEta_","P^{in}_{t} - P^{out}_{t} vs #eta gen",120,-3.,3.,500,-250.,250.);
00166   }    
00167 
00168   //theFile->cd();
00169 }
00170 
00171 void MuonTrackAnalyzer::endJob(){
00172   LogInfo("MuonTrackAnalyzer")<< "Number of Sim tracks: " << numberOfSimTracks;
00173 
00174   LogInfo("MuonTrackAnalyzer") << "Number of Reco tracks: " << numberOfRecTracks;
00175 
00176   
00177   if(doTracksAnalysis){
00178     double eff = hRecoTracksPCA->computeEfficiency(hSimTracks);
00179     LogInfo("MuonTrackAnalyzer") <<" *Track Efficiency* = "<< eff <<"%";
00180   }
00181 
00182   if(doSeedsAnalysis){
00183     double eff = hRecoSeedInner->computeEfficiency(hSimTracks);
00184     LogInfo("MuonTrackAnalyzer")<<" *Seed Efficiency* = "<< eff <<"%";
00185   }
00186 
00187   if ( out.size() != 0 && dbe_ ) dbe_->save(out);
00188 }
00189 
00190 void MuonTrackAnalyzer::analyze(const Event & event, const EventSetup& eventSetup){
00191   
00192   LogDebug("MuonTrackAnalyzer") << "Run: " << event.id().run() << " Event: " << event.id().event();
00193 
00194   // Update the services
00195   theService->update(eventSetup);
00196 
00197   Handle<SimTrackContainer> simTracks;
00198   event.getByLabel("g4SimHits",simTracks);  
00199   fillPlots(event,simTracks);
00200 
00201   
00202   if(doTracksAnalysis)
00203     tracksAnalysis(event,eventSetup,simTracks);
00204   
00205   if(doSeedsAnalysis)
00206     seedsAnalysis(event,eventSetup,simTracks);
00207   
00208 
00209 }
00210 
00211 void MuonTrackAnalyzer::seedsAnalysis(const Event & event, const EventSetup& eventSetup,
00212                                       Handle<SimTrackContainer> simTracks){
00213 
00214   MuonPatternRecoDumper debug;
00215 
00216   // Get the RecTrack collection from the event
00217   Handle<TrajectorySeedCollection> seeds;
00218   event.getByLabel(theSeedsLabel, seeds);
00219   
00220   LogTrace("MuonTrackAnalyzer")<<"Number of reconstructed seeds: " << seeds->size()<<endl;
00221 
00222   for(TrajectorySeedCollection::const_iterator seed = seeds->begin(); 
00223       seed != seeds->end(); ++seed){
00224     TrajectoryStateOnSurface seedTSOS = getSeedTSOS(*seed);
00225     pair<SimTrack,double> sim = getSimTrack(seedTSOS,simTracks);
00226     fillPlots(seedTSOS, sim.first,
00227               hRecoSeedInner, debug);
00228     
00229     std::pair<bool,FreeTrajectoryState> propSeed =
00230       theUpdator->propagateToNominalLine(seedTSOS);
00231     if(propSeed.first)
00232       fillPlots(propSeed.second, sim.first,
00233                 hRecoSeedPCA, debug);
00234     else
00235       LogTrace("MuonTrackAnalyzer")<<"Error in seed propagation"<<endl;
00236    
00237   }
00238 }
00239 
00240 
00241 void MuonTrackAnalyzer::tracksAnalysis(const Event & event, const EventSetup& eventSetup,
00242                                       Handle<SimTrackContainer> simTracks){
00243   MuonPatternRecoDumper debug;
00244   
00245   
00246   // Get the RecTrack collection from the event
00247   Handle<reco::TrackCollection> tracks;
00248   event.getByLabel(theTracksLabel, tracks);
00249 
00250   LogTrace("MuonTrackAnalyzer")<<"Reconstructed tracks: " << tracks->size() << endl;
00251   hNumberOfTracks->Fill(tracks->size());
00252   
00253   if(tracks->size()) numberOfRecTracks++;
00254   
00255   // Loop over the Rec tracks
00256   for(reco::TrackCollection::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
00257     
00258     reco::TransientTrack track(*t,&*theService->magneticField(),theService->trackingGeometry()); 
00259 
00260     TrajectoryStateOnSurface outerTSOS = track.outermostMeasurementState();
00261     TrajectoryStateOnSurface innerTSOS = track.innermostMeasurementState();
00262     TrajectoryStateOnSurface pcaTSOS   = track.impactPointState();
00263 
00264     pair<SimTrack,double> sim = getSimTrack(pcaTSOS,simTracks);
00265     SimTrack simTrack = sim.first;
00266     hNumberOfTracksVsEta->Fill(simTrack.momentum().eta(), tracks->size());
00267     fillPlots(track,simTrack);
00268     
00269     LogTrace("MuonTrackAnalyzer") << "State at the outer surface: " << endl; 
00270     fillPlots(outerTSOS,simTrack,hRecoTracksOuter,debug);
00271 
00272     LogTrace("MuonTrackAnalyzer") << "State at the inner surface: " << endl; 
00273     fillPlots(innerTSOS,simTrack,hRecoTracksInner,debug);
00274 
00275     LogTrace("MuonTrackAnalyzer") << "State at PCA: " << endl; 
00276     fillPlots(pcaTSOS,simTrack,hRecoTracksPCA,debug);
00277     
00278     double deltaPt_in_out = innerTSOS.globalMomentum().perp()-outerTSOS.globalMomentum().perp();
00279     hDeltaPt_In_Out_VsEta->Fill(simTrack.momentum().eta(),deltaPt_in_out);
00280 
00281     double deltaPt_pca_sim = pcaTSOS.globalMomentum().perp()-sqrt(simTrack.momentum().Perp2());
00282     hDeltaPtVsEta->Fill(simTrack.momentum().eta(),deltaPt_pca_sim);
00283     
00284     hChargeVsEta->Fill(simTrack.momentum().eta(),pcaTSOS.charge());
00285     
00286     hChargeVsPt->Fill(sqrt(simTrack.momentum().perp2()),pcaTSOS.charge());
00287     
00288     hPtRecVsPtGen->Fill(sqrt(simTrack.momentum().perp2()),pcaTSOS.globalMomentum().perp());    
00289   }
00290   LogTrace("MuonTrackAnalyzer")<<"--------------------------------------------"<<endl;  
00291 }
00292 
00293 
00294 
00295 
00296 void  MuonTrackAnalyzer::fillPlots(const Event &event, edm::Handle<edm::SimTrackContainer> &simTracks){
00297   
00298   if(!checkMuonSimHitPresence(event,simTracks)) return;
00299   
00300   // Loop over the Sim tracks
00301   SimTrackContainer::const_iterator simTrack;
00302   LogTrace("MuonTrackAnalyzer")<<"Simulated tracks: "<<simTracks->size()<<endl;
00303   
00304   for (simTrack = simTracks->begin(); simTrack != simTracks->end(); ++simTrack)
00305     if (abs((*simTrack).type()) == 13) {
00306       
00307       if( !isInTheAcceptance( (*simTrack).momentum().eta()) ) continue; // FIXME!!
00308       
00309         numberOfSimTracks++;
00310         
00311         LogTrace("MuonTrackAnalyzer")<<"Simualted muon:"<<endl;
00312         LogTrace("MuonTrackAnalyzer")<<"Sim pT: "<<sqrt((*simTrack).momentum().perp2())<<endl;
00313         LogTrace("MuonTrackAnalyzer")<<"Sim Eta: "<<(*simTrack).momentum().eta()<<endl; // FIXME
00314         
00315         hSimTracks->Fill((*simTrack).momentum().mag(), 
00316                          sqrt((*simTrack).momentum().perp2()), 
00317                          (*simTrack).momentum().eta(), 
00318                          (*simTrack).momentum().phi(), 
00319                          -(*simTrack).type()/ abs((*simTrack).type()) ); // Double FIXME  
00320         LogTrace("MuonTrackAnalyzer") << "hSimTracks filled" << endl;
00321     }
00322   
00323   LogTrace("MuonTrackAnalyzer") << endl; 
00324 }
00325   
00326 
00327 void  MuonTrackAnalyzer::fillPlots(reco::TransientTrack &track, SimTrack &simTrack){
00328 
00329   LogTrace("MuonTrackAnalyzer")<<"Analizer: New track, chi2: "<<track.chi2()<<" dof: "<<track.ndof()<<endl;
00330   hChi2->Fill(track.chi2());
00331   hDof->Fill(track.ndof());
00332   hChi2Norm->Fill(track.normalizedChi2());
00333   hHitsPerTrack->Fill(track.recHitsSize());
00334   
00335   hChi2Prob->Fill( ChiSquaredProbability(track.chi2(),track.ndof()) );
00336 
00337   hChi2VsEta->Fill(simTrack.momentum().eta(),track.chi2());
00338   hChi2NormVsEta->Fill(simTrack.momentum().eta(),track.normalizedChi2());
00339   hChi2ProbVsEta->Fill(simTrack.momentum().eta(),ChiSquaredProbability(track.chi2(),track.ndof()));     
00340   hHitsPerTrackVsEta->Fill(simTrack.momentum().eta(),track.recHitsSize());
00341   hDofVsEta->Fill(simTrack.momentum().eta(),track.ndof()); 
00342 }
00343 
00344 
00345 void  MuonTrackAnalyzer::fillPlots(TrajectoryStateOnSurface &recoTSOS,SimTrack &simTrack,
00346                                    HTrack *histo, MuonPatternRecoDumper &debug){
00347   
00348   LogTrace("MuonTrackAnalyzer") << debug.dumpTSOS(recoTSOS)<<endl;
00349   histo->Fill(recoTSOS);
00350   
00351   GlobalVector tsosVect = recoTSOS.globalMomentum();
00352   math::XYZVectorD reco(tsosVect.x(), tsosVect.y(), tsosVect.z());
00353   double deltaRVal = deltaR<double>(reco.eta(),reco.phi(),
00354                                     simTrack.momentum().eta(),simTrack.momentum().phi());
00355   histo->FillDeltaR(deltaRVal);
00356 
00357   histo->computeResolutionAndPull(recoTSOS,simTrack);
00358 }
00359 
00360 
00361 void  MuonTrackAnalyzer::fillPlots(FreeTrajectoryState &recoFTS,SimTrack &simTrack,
00362                                    HTrack *histo, MuonPatternRecoDumper &debug){
00363   
00364   LogTrace("MuonTrackAnalyzer") << debug.dumpFTS(recoFTS)<<endl;
00365   histo->Fill(recoFTS);
00366   
00367   GlobalVector ftsVect = recoFTS.momentum();
00368   math::XYZVectorD reco(ftsVect.x(), ftsVect.y(), ftsVect.z());
00369   double deltaRVal = deltaR<double>(reco.eta(),reco.phi(),
00370                                     simTrack.momentum().eta(),simTrack.momentum().phi());
00371   histo->FillDeltaR(deltaRVal);
00372 
00373   histo->computeResolutionAndPull(recoFTS,simTrack);
00374 }
00375 
00376 pair<SimTrack,double> MuonTrackAnalyzer::getSimTrack(TrajectoryStateOnSurface &tsos,
00377                                                      Handle<SimTrackContainer> simTracks){
00378   
00379 //   // Loop over the Sim tracks
00380 //   SimTrackContainer::const_iterator simTrack;
00381   
00382 //   SimTrack result;
00383 //   int mu=0;
00384 //   for (simTrack = simTracks->begin(); simTrack != simTracks->end(); ++simTrack)
00385 //     if (abs((*simTrack).type()) == 13) { 
00386 //       result = *simTrack;
00387 //       ++mu;
00388 //     }
00389   
00390 //   if(mu != 1) LogTrace("MuonTrackAnalyzer") << "WARNING!! more than 1 simulated muon!!" <<endl;
00391 //   return result;
00392 
00393 
00394   // Loop over the Sim tracks
00395   SimTrackContainer::const_iterator simTrack;
00396   
00397   SimTrack result;
00398 
00399   double bestDeltaR = 10e5;
00400   for (simTrack = simTracks->begin(); simTrack != simTracks->end(); ++simTrack){
00401     if (abs((*simTrack).type()) != 13) continue;
00402     
00403     //    double newDeltaR = tsos.globalMomentum().basicVector().deltaR(simTrack->momentum().vect());
00404     GlobalVector tsosVect = tsos.globalMomentum();
00405     math::XYZVectorD vect(tsosVect.x(), tsosVect.y(), tsosVect.z());
00406     double newDeltaR = deltaR<double>(vect.eta(),vect.phi(),
00407                                       simTrack->momentum().eta(),simTrack->momentum().phi());
00408 
00409     if (  newDeltaR < bestDeltaR ) {
00410       LogTrace("MuonTrackAnalyzer") << "Matching Track with DeltaR = " << newDeltaR<<endl;
00411       bestDeltaR = newDeltaR;
00412       result  = *simTrack;
00413     }
00414   } 
00415   return pair<SimTrack,double>(result,bestDeltaR);
00416 }
00417 
00418 
00419 bool MuonTrackAnalyzer::isInTheAcceptance(double eta){
00420   switch(theEtaRange){
00421   case all:
00422     return ( abs(eta) <= 2.4 ) ? true : false;
00423   case barrel:
00424     return ( abs(eta) < 1.1 ) ? true : false;
00425   case endcap:
00426     return ( abs(eta) >= 1.1 && abs(eta) <= 2.4 ) ? true : false;  
00427   default:
00428     {LogTrace("MuonTrackAnalyzer")<<"No correct Eta range selected!! "<<endl; return false;}
00429   }
00430 }
00431 
00432 bool MuonTrackAnalyzer::checkMuonSimHitPresence(const Event & event,
00433                                                 edm::Handle<edm::SimTrackContainer> simTracks){
00434 
00435   // Get the SimHit collection from the event
00436   Handle<PSimHitContainer> dtSimHits;
00437   event.getByLabel(theDTSimHitLabel.instance(),theDTSimHitLabel.label(), dtSimHits);
00438   
00439   Handle<PSimHitContainer> cscSimHits;
00440   event.getByLabel(theCSCSimHitLabel.instance(),theCSCSimHitLabel.label(), cscSimHits);
00441   
00442   Handle<PSimHitContainer> rpcSimHits;
00443   event.getByLabel(theRPCSimHitLabel.instance(),theRPCSimHitLabel.label(), rpcSimHits);  
00444   
00445   map<unsigned int, vector<const PSimHit*> > mapOfMuonSimHits;
00446   
00447   for(PSimHitContainer::const_iterator simhit = dtSimHits->begin();
00448       simhit != dtSimHits->end(); ++simhit) {
00449     if (abs(simhit->particleType()) != 13) continue;
00450     mapOfMuonSimHits[simhit->trackId()].push_back(&*simhit);
00451   }
00452   
00453   for(PSimHitContainer::const_iterator simhit = cscSimHits->begin();
00454       simhit != cscSimHits->end(); ++simhit) {
00455     if (abs(simhit->particleType()) != 13) continue;
00456     mapOfMuonSimHits[simhit->trackId()].push_back(&*simhit);
00457   }
00458   
00459   for(PSimHitContainer::const_iterator simhit = rpcSimHits->begin();
00460       simhit != rpcSimHits->end(); ++simhit) {
00461     if (abs(simhit->particleType()) != 13) continue;
00462     mapOfMuonSimHits[simhit->trackId()].push_back(&*simhit);
00463   }
00464 
00465   bool presence = false;
00466 
00467   for (SimTrackContainer::const_iterator simTrack = simTracks->begin(); 
00468        simTrack != simTracks->end(); ++simTrack){
00469     
00470     if (abs(simTrack->type()) != 13) continue;
00471     
00472     map<unsigned int, vector<const PSimHit*> >::const_iterator mapIterator = 
00473       mapOfMuonSimHits.find(simTrack->trackId());
00474     
00475     if (mapIterator != mapOfMuonSimHits.end())
00476       presence = true;
00477   }
00478   
00479   return presence;
00480 }
00481 
00482 TrajectoryStateOnSurface MuonTrackAnalyzer::getSeedTSOS(const TrajectorySeed& seed){
00483 
00484   // Get the Trajectory State on Det (persistent version of a TSOS) from the seed
00485   PTrajectoryStateOnDet pTSOD = seed.startingState();
00486 
00487   // Transform it in a TrajectoryStateOnSurface
00488   
00489 
00490   DetId seedDetId(pTSOD.detId());
00491 
00492   const GeomDet* gdet = theService->trackingGeometry()->idToDet( seedDetId );
00493 
00494   TrajectoryStateOnSurface initialState = trajectoryStateTransform::transientState(pTSOD, &(gdet->surface()), &*theService->magneticField());
00495 
00496   // Get the layer on which the seed relies
00497   const DetLayer *initialLayer = theService->detLayerGeometry()->idToLayer( seedDetId );
00498 
00499   PropagationDirection detLayerOrder = oppositeToMomentum;
00500 
00501   // ask for compatible layers
00502   vector<const DetLayer*> detLayers;
00503   detLayers = initialLayer->compatibleLayers( *initialState.freeState(),detLayerOrder);
00504   
00505   TrajectoryStateOnSurface result = initialState;
00506   if(detLayers.size()){
00507     const DetLayer* finalLayer = detLayers.back();
00508     const TrajectoryStateOnSurface propagatedState = theService->propagator(theSeedPropagatorName)->propagate(initialState, finalLayer->surface());
00509     if(propagatedState.isValid())
00510       result = propagatedState;
00511   }
00512   
00513   return result;
00514 }