CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch13/src/RecoMuon/CosmicMuonProducer/src/CosmicMuonTrajectoryBuilder.cc

Go to the documentation of this file.
00001 #include "RecoMuon/CosmicMuonProducer/interface/CosmicMuonTrajectoryBuilder.h"
00013 #include "FWCore/Framework/interface/Frameworkfwd.h"
00014 #include "FWCore/Framework/interface/MakerMacros.h"
00015 
00016 /* Collaborating Class Header */
00017 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
00018 #include "Geometry/CommonDetUnit/interface/GeomDet.h"
00019 #include "TrackingTools/PatternTools/interface/Trajectory.h"
00020 #include "TrackingTools/GeomPropagators/interface/Propagator.h"
00021 #include "DataFormats/TrajectorySeed/interface/TrajectorySeed.h"
00022 #include "FWCore/Framework/interface/Event.h"
00023 #include "FWCore/Framework/interface/EventSetup.h"
00024 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00025 #include "FWCore/Utilities/interface/InputTag.h"
00026 #include "TrackingTools/DetLayers/interface/DetLayer.h"
00027 #include "RecoMuon/Navigation/interface/DirectMuonNavigation.h"
00028 #include "RecoMuon/MeasurementDet/interface/MuonDetLayerMeasurements.h"
00029 #include "RecoMuon/TrackingTools/interface/MuonBestMeasurementFinder.h"
00030 #include "RecoMuon/TrackingTools/interface/MuonTrajectoryUpdator.h"
00031 #include "RecoMuon/TrackingTools/interface/MuonServiceProxy.h"
00032 #include "RecoMuon/TrackingTools/interface/MuonPatternRecoDumper.h"
00033 #include "RecoMuon/TransientTrackingRecHit/interface/MuonTransientTrackingRecHit.h"
00034 #include "DataFormats/MuonDetId/interface/MuonSubdetId.h"
00035 #include "DataFormats/GeometrySurface/interface/PlaneBuilder.h"
00036 #include "DataFormats/GeometryCommonDetAlgo/interface/PerpendicularBoundPlaneBuilder.h"
00037 #include "RecoMuon/Records/interface/MuonRecoGeometryRecord.h"
00038 #include "DataFormats/CSCRecHit/interface/CSCRecHit2D.h"
00039 #include "DataFormats/DTRecHit/interface/DTRecHit1D.h"
00040 
00041 #include <algorithm>
00042 
00043 using namespace edm;
00044 using namespace std;
00045 
00046 CosmicMuonTrajectoryBuilder::CosmicMuonTrajectoryBuilder(const edm::ParameterSet& par, const MuonServiceProxy* service) : theService(service) { 
00047 
00048   thePropagatorName = par.getParameter<string>("Propagator");
00049 
00050   bool enableDTMeasurement = par.getParameter<bool>("EnableDTMeasurement");
00051   bool enableCSCMeasurement = par.getParameter<bool>("EnableCSCMeasurement");
00052   bool enableRPCMeasurement = par.getParameter<bool>("EnableRPCMeasurement");
00053 
00054 //  if(enableDTMeasurement)
00055   InputTag DTRecSegmentLabel = par.getParameter<InputTag>("DTRecSegmentLabel");
00056 
00057 //  if(enableCSCMeasurement)
00058   InputTag CSCRecSegmentLabel = par.getParameter<InputTag>("CSCRecSegmentLabel");
00059 
00060 //  if(enableRPCMeasurement)
00061   InputTag RPCRecSegmentLabel = par.getParameter<InputTag>("RPCRecSegmentLabel");
00062 
00063   theLayerMeasurements= new MuonDetLayerMeasurements(DTRecSegmentLabel,
00064                                                      CSCRecSegmentLabel,
00065                                                      RPCRecSegmentLabel,
00066                                                      enableDTMeasurement,
00067                                                      enableCSCMeasurement,
00068                                                      enableRPCMeasurement);
00069 
00070   ParameterSet muonUpdatorPSet = par.getParameter<ParameterSet>("MuonTrajectoryUpdatorParameters");
00071   
00072   theNavigation = 0; // new DirectMuonNavigation(theService->detLayerGeometry());
00073   theUpdator = new MuonTrajectoryUpdator(muonUpdatorPSet, insideOut);
00074 
00075   theBestMeasurementFinder = new MuonBestMeasurementFinder();
00076 
00077   ParameterSet muonBackwardUpdatorPSet = par.getParameter<ParameterSet>("BackwardMuonTrajectoryUpdatorParameters");
00078 
00079   theBKUpdator = new MuonTrajectoryUpdator(muonBackwardUpdatorPSet, outsideIn);
00080 
00081   theTraversingMuonFlag = par.getParameter<bool>("BuildTraversingMuon");
00082 
00083   theStrict1LegFlag = par.getParameter<bool>("Strict1Leg");
00084 
00085   ParameterSet smootherPSet = par.getParameter<ParameterSet>("MuonSmootherParameters");
00086 
00087   theNavigationPSet = par.getParameter<ParameterSet>("MuonNavigationParameters");
00088 
00089   theSmoother = new CosmicMuonSmoother(smootherPSet,theService);
00090 
00091   theNTraversing = 0;
00092   theNSuccess = 0;
00093   theCacheId_DG = 0;
00094   category_ = "Muon|RecoMuon|CosmicMuon|CosmicMuonTrajectoryBuilder";
00095 
00096 }
00097 
00098 
00099 CosmicMuonTrajectoryBuilder::~CosmicMuonTrajectoryBuilder() {
00100 
00101   LogTrace(category_)<< "CosmicMuonTrajectoryBuilder dtor called";
00102   if (theUpdator) delete theUpdator;
00103   if (theBKUpdator) delete theBKUpdator;
00104   if (theLayerMeasurements) delete theLayerMeasurements;
00105   if (theSmoother) delete theSmoother;
00106   if (theNavigation) delete theNavigation; 
00107   delete theBestMeasurementFinder;
00108 
00109   LogTrace(category_)<< "CosmicMuonTrajectoryBuilder Traversing: "<<theNSuccess<<"/"<<theNTraversing;
00110 
00111 }
00112 
00113 
00114 void CosmicMuonTrajectoryBuilder::setEvent(const edm::Event& event) {
00115 
00116   theLayerMeasurements->setEvent(event);
00117 
00118   // DetLayer Geometry
00119   unsigned long long newCacheId_DG = theService->eventSetup().get<MuonRecoGeometryRecord>().cacheIdentifier();
00120   if ( newCacheId_DG != theCacheId_DG ) {
00121     LogTrace(category_) << "Muon Reco Geometry changed!";
00122     theCacheId_DG = newCacheId_DG;
00123     if (theNavigation) delete theNavigation;
00124     theNavigation = new DirectMuonNavigation(theService->detLayerGeometry(), theNavigationPSet);
00125   }
00126 
00127 //  event.getByLabel("csc2DRecHits", cschits_);
00128 //  event.getByLabel("dt1DRecHits", dthits_);
00129 
00130 }
00131 
00132 
00133 MuonTrajectoryBuilder::TrajectoryContainer 
00134 CosmicMuonTrajectoryBuilder::trajectories(const TrajectorySeed& seed) {
00135 
00136   vector<Trajectory*> trajL = vector<Trajectory*>();
00137   TrajectoryStateTransform tsTransform;
00138   MuonPatternRecoDumper debug;
00139 
00140   PTrajectoryStateOnDet ptsd1(seed.startingState());
00141   DetId did(ptsd1.detId());
00142   const BoundPlane& bp = theService->trackingGeometry()->idToDet(did)->surface();
00143   TrajectoryStateOnSurface lastTsos = tsTransform.transientState(ptsd1,&bp,&*theService->magneticField());
00144   LogTrace(category_) << "Seed: mom "<<lastTsos.globalMomentum()
00145                           <<"pos: " <<lastTsos.globalPosition();
00146   LogTrace(category_)  << "Seed: mom eta "<<lastTsos.globalMomentum().eta()
00147                           <<"pos eta: " <<lastTsos.globalPosition().eta();
00148   
00149   bool beamhaloFlag =  ( (did.subdetId() == MuonSubdetId::CSC) && fabs(lastTsos.globalMomentum().eta()) > 4.0);
00150 
00151   vector<const DetLayer*> navLayers;
00152 
00153   if (did.subdetId() == MuonSubdetId::DT) {
00154     //DT
00155     navLayers = navigation()->compatibleLayers(*(lastTsos.freeState()), alongMomentum);
00156   } 
00157   else if (beamhaloFlag || (theTraversingMuonFlag && theStrict1LegFlag)) {
00158     //CSC
00159     navLayers = navigation()->compatibleEndcapLayers(*(lastTsos.freeState()), alongMomentum);
00160   } else {
00161     navLayers = navigation()->compatibleLayers(*(lastTsos.freeState()), alongMomentum);
00162   }
00163 
00164   LogTrace(category_) <<"found "<<navLayers.size()<<" compatible DetLayers for the Seed";
00165 
00166   if (navLayers.empty()) return trajL;
00167   
00168   vector<DetWithState> detsWithStates;
00169   LogTrace(category_) << "Compatible layers: ";
00170   for ( vector<const DetLayer*>::const_iterator layer = navLayers.begin();
00171         layer != navLayers.end(); layer++) {
00172     LogTrace(category_) << debug.dumpMuonId((*layer)->basicComponents().front()->geographicalId()) 
00173                         << debug.dumpLayer(*layer);
00174   }
00175 
00176   detsWithStates = navLayers.front()->compatibleDets(lastTsos, *propagator(), *(updator()->estimator()));
00177   LogTrace(category_) << "Number of compatible dets: " << detsWithStates.size() << endl;
00178 
00179   if ( !detsWithStates.empty() ) {
00180     // get the updated TSOS
00181     if ( detsWithStates.front().second.isValid() ) {
00182       LogTrace(category_) << "New starting TSOS is on det: " << endl;
00183       LogTrace(category_) << debug.dumpMuonId(detsWithStates.front().first->geographicalId())
00184                         << debug.dumpLayer(navLayers.front());
00185       lastTsos = detsWithStates.front().second;
00186       LogTrace(category_) << "Seed after extrapolation: mom " << lastTsos.globalMomentum()
00187                           << "pos: " << lastTsos.globalPosition();
00188     }
00189   }
00190   detsWithStates.clear();
00191   if ( !lastTsos.isValid() ) return trajL;
00192 
00193   TrajectoryStateOnSurface secondLast = lastTsos;
00194 
00195   lastTsos.rescaleError(10.0);
00196 
00197   Trajectory* theTraj = new Trajectory(seed,alongMomentum);
00198 
00199   navLayers.clear();
00200 
00201   if (fabs(lastTsos.globalMomentum().eta()) < 1.0) {
00202     //DT
00203     navLayers = navigation()->compatibleLayers(*(lastTsos.freeState()), alongMomentum);
00204   } else if (beamhaloFlag || (theTraversingMuonFlag && theStrict1LegFlag)) {
00205     //CSC
00206     navLayers = navigation()->compatibleEndcapLayers(*(lastTsos.freeState()), alongMomentum);
00207   } else {
00208     navLayers = navigation()->compatibleLayers(*(lastTsos.freeState()), alongMomentum);
00209   }
00210 
00211 
00212   int DTChamberUsedBack = 0;
00213   int CSCChamberUsedBack = 0;
00214   int RPCChamberUsedBack = 0;
00215   int TotalChamberUsedBack = 0;
00216   MuonTransientTrackingRecHit::MuonRecHitContainer allUnusedHits;
00217   vector<TrajectoryMeasurement> measL;
00218 
00219   LogTrace(category_) << "Begin forward fit " << navLayers.size();
00220 
00221   for ( vector<const DetLayer*>::const_iterator rnxtlayer = navLayers.begin(); rnxtlayer!= navLayers.end(); ++rnxtlayer) {
00222      LogTrace(category_) << "new layer ";
00223      measL.clear();
00224      LogTrace(category_) << debug.dumpMuonId((*rnxtlayer)->basicComponents().front()->geographicalId())
00225                          << debug.dumpLayer(*rnxtlayer);
00226      LogTrace(category_) << "from lastTsos " << lastTsos.globalMomentum()<< " at " <<lastTsos.globalPosition();
00227  
00228      measL = findBestMeasurements(*rnxtlayer, lastTsos, propagator(), (updator()->estimator()));
00229 
00230      if ( measL.empty() &&  (fabs(theService->magneticField()->inTesla(GlobalPoint(0,0,0)).z()) < 0.01) && (theService->propagator("StraightLinePropagator").isValid() ) )  {
00231        LogTrace(category_) << "try straight line propagator ";
00232        measL = findBestMeasurements(*rnxtlayer, lastTsos, &*theService->propagator("StraightLinePropagator"), (updator()->estimator()));
00233      }
00234      if ( measL.empty() ) continue;
00235 
00236      for (vector<TrajectoryMeasurement>::const_iterator theMeas = measL.begin(); theMeas != measL.end(); ++theMeas) {
00237        pair<bool,TrajectoryStateOnSurface> result = updator()->update((&*theMeas), *theTraj, propagator());
00238 
00239        if (result.first ) {
00240          LogTrace(category_) << "update ok ";
00241          incrementChamberCounters((*rnxtlayer), DTChamberUsedBack, CSCChamberUsedBack, RPCChamberUsedBack, TotalChamberUsedBack);
00242          secondLast = lastTsos;
00243          if ( (!theTraj->empty()) && result.second.isValid() ) {
00244            lastTsos = result.second;
00245            LogTrace(category_) << "get new lastTsos here " << lastTsos.globalMomentum() << " at " << lastTsos.globalPosition();
00246          }  else if ((theMeas)->predictedState().isValid()) lastTsos = (theMeas)->predictedState();
00247        }
00248      }
00249   } 
00250   measL.clear();
00251   while (!theTraj->empty()) {
00252     theTraj->pop();
00253   }
00254 
00255   if (!theTraj->isValid() || TotalChamberUsedBack < 2 || (DTChamberUsedBack+CSCChamberUsedBack) == 0 || !lastTsos.isValid()) {
00256     delete theTraj;
00257     return trajL;
00258   }
00259   delete theTraj;
00260 
00261 
00262   // if got good trajectory, then do backward refitting
00263   DTChamberUsedBack = 0;
00264   CSCChamberUsedBack = 0;
00265   RPCChamberUsedBack = 0;
00266   TotalChamberUsedBack = 0;
00267 
00268   Trajectory myTraj(seed, oppositeToMomentum);
00269 
00270   // set starting navigation direction for MuonTrajectoryUpdator
00271 
00272   GlobalPoint lastPos = lastTsos.globalPosition();
00273   GlobalPoint secondLastPos = secondLast.globalPosition();
00274   GlobalVector momDir = secondLastPos - lastPos;
00275 
00276   if ( lastPos.basicVector().dot(momDir.basicVector()) > 0 ) { 
00277 //      LogTrace("CosmicMuonTrajectoryBuilder")<<"Fit direction changed to insideOut";
00278       theBKUpdator->setFitDirection(insideOut);
00279     } else theBKUpdator->setFitDirection(outsideIn);
00280 
00281   if (fabs(lastTsos.globalMomentum().eta()) < 1.0) {
00282     //DT
00283     navLayers = navigation()->compatibleLayers(*(lastTsos.freeState()), oppositeToMomentum);
00284   } else if (beamhaloFlag || (theTraversingMuonFlag && theStrict1LegFlag)) {
00285     //CSC
00286     std::reverse(navLayers.begin(), navLayers.end());
00287   } else {
00288     navLayers = navigation()->compatibleLayers(*(lastTsos.freeState()), oppositeToMomentum);  
00289   } 
00290 
00291   LogTrace(category_) << "Begin backward refitting, with " << navLayers.size() << " layers" << endl;
00292 
00293   for (vector<const DetLayer*>::const_iterator rnxtlayer = navLayers.begin();
00294       rnxtlayer!= navLayers.end(); ++rnxtlayer) {
00295 
00296      measL.clear();
00297 
00298      measL = findBestMeasurements(*rnxtlayer, lastTsos, propagator(), (backwardUpdator()->estimator()));
00299 
00300      if ( measL.empty() ) {
00301          MuonTransientTrackingRecHit::MuonRecHitContainer tmpHits = theLayerMeasurements->recHits(*rnxtlayer);
00302          for (MuonRecHitContainer::const_iterator ihit = tmpHits.begin();
00303                                            ihit != tmpHits.end(); ++ihit ) {
00304          allUnusedHits.push_back(*ihit);
00305          } 
00306          continue;
00307       }
00308 
00309      for (vector<TrajectoryMeasurement>::const_iterator theMeas = measL.begin(); theMeas != measL.end(); ++theMeas) {
00310 
00311       // if the part change, we need to reconsider the fit direction
00312        if (rnxtlayer != navLayers.begin()) {
00313 
00314          vector<const DetLayer*>::const_iterator lastlayer = rnxtlayer;
00315          lastlayer--;
00316 
00317          if ( (*rnxtlayer)->location() != (*lastlayer)->location() ) {
00318 
00319            lastPos = lastTsos.globalPosition();
00320            GlobalPoint thisPos = (theMeas)->predictedState().globalPosition();
00321            GlobalVector momDir = thisPos - lastPos;
00322 //         LogTrace("CosmicMuonTrajectoryBuilder")<<"momDir "<<momDir;
00323  
00324            if ( momDir.mag() > 0.01 ) { //if lastTsos is on the surface, no need
00325              if ( thisPos.basicVector().dot(momDir.basicVector()) > 0 ) {
00326                theBKUpdator->setFitDirection(insideOut);
00327              } else theBKUpdator->setFitDirection(outsideIn);
00328            }
00329          }
00330          if ( ((*lastlayer)->location() == GeomDetEnumerators::endcap) && 
00331               ((*rnxtlayer)->location() == GeomDetEnumerators::endcap) && 
00332               (lastTsos.globalPosition().z() * (theMeas)->predictedState().globalPosition().z() < 0)  ) {
00333            theBKUpdator->setFitDirection(insideOut);
00334          }
00335      }
00336 
00337 //       if (theBKUpdator->fitDirection() == insideOut) 
00338 //          LogTrace("CosmicMuonTrajectoryBuilder")<<"Fit direction insideOut";
00339 //       else LogTrace("CosmicMuonTrajectoryBuilder")<<"Fit direction outsideIn";
00340          pair<bool,TrajectoryStateOnSurface> bkresult
00341               = backwardUpdator()->update((&*theMeas), myTraj, propagator());
00342 
00343          if (bkresult.first ) {
00344 
00345               incrementChamberCounters((*rnxtlayer), DTChamberUsedBack, CSCChamberUsedBack, RPCChamberUsedBack, TotalChamberUsedBack);
00346 
00347             if ( theTraversingMuonFlag ) {
00348 
00349               MuonRecHitContainer tmpUnusedHits = unusedHits(*rnxtlayer,*theMeas);
00350               allUnusedHits.insert(allUnusedHits.end(),tmpUnusedHits.begin(),tmpUnusedHits.end());
00351             }
00352             if ( (!myTraj.empty()) && bkresult.second.isValid() ) 
00353                lastTsos = bkresult.second;
00354             else if ((theMeas)->predictedState().isValid()) 
00355                lastTsos = (theMeas)->predictedState();
00356           }
00357        }
00358   }
00359 
00360   for ( vector<Trajectory*>::iterator t = trajL.begin(); t != trajL.end(); ++t ) delete *t;
00361 
00362   trajL.clear();
00363 
00364   if (( !myTraj.isValid() ) || ( myTraj.empty() ) || ( (selfDuplicate(myTraj)) )|| TotalChamberUsedBack < 2 || (DTChamberUsedBack+CSCChamberUsedBack) < 1) {
00365       return trajL;
00366   }
00367 
00368   if ( theTraversingMuonFlag && ( allUnusedHits.size() >= 2 )) { 
00369 //      LogTrace(category_)<<utilities()->print(allUnusedHits);
00370       LogTrace(category_)<<"Building trajectory in second hemisphere...";
00371       buildSecondHalf(myTraj);
00372       // check if traversing trajectory has hits in both hemispheres
00373 
00374       if ( theStrict1LegFlag && !utilities()->isTraversing(myTraj) ) {trajL.clear(); return trajL;}
00375   } else if (theStrict1LegFlag && theTraversingMuonFlag) {trajL.clear(); return trajL;} 
00376 
00377   LogTrace(category_) <<" traj ok ";
00378 
00379 //     getDirectionByTime(myTraj);
00380   if (beamhaloFlag) estimateDirection(myTraj);
00381   if ( myTraj.empty() ) return trajL;
00382 
00383   // try to smooth it 
00384   vector<Trajectory> smoothed = theSmoother->trajectories(myTraj); 
00385 
00386   if ( !smoothed.empty() && smoothed.front().foundHits()> 3 )  {  
00387     LogTrace(category_) <<" Smoothed successfully."; 
00388     myTraj = smoothed.front(); 
00389   } 
00390   else {  
00391     LogTrace(category_) <<" Smooth failed."; 
00392   } 
00393 
00394   LogTrace(category_) <<"first "<< myTraj.firstMeasurement().updatedState()
00395                       <<"\n last "<<myTraj.lastMeasurement().updatedState();
00396   if ( myTraj.direction() == alongMomentum ) LogTrace(category_)<<"alongMomentum";
00397   else if (myTraj.direction() == oppositeToMomentum ) LogTrace(category_)<<"oppositeMomentum";
00398   else LogTrace(category_)<<"anyDirection";
00399 
00400   if (!beamhaloFlag) {
00401       if ( myTraj.lastMeasurement().updatedState().globalMomentum().y() > 0 ) {
00402           LogTrace(category_)<<"flip trajectory ";
00403           flipTrajectory(myTraj);
00404       }
00405 
00406       if ( ( myTraj.direction() == alongMomentum && 
00407            (myTraj.firstMeasurement().updatedState().globalPosition().y() 
00408            < myTraj.lastMeasurement().updatedState().globalPosition().y()))
00409         || (myTraj.direction() == oppositeToMomentum && 
00410            (myTraj.firstMeasurement().updatedState().globalPosition().y() 
00411            > myTraj.lastMeasurement().updatedState().globalPosition().y())) ) {
00412            LogTrace(category_)<<"reverse propagation direction";
00413           reverseTrajectoryPropagationDirection(myTraj); 
00414       }
00415   }
00416 //  getDirectionByTime(myTraj);
00417   if ( !myTraj.isValid() ) return trajL;
00418 
00419   // check direction agree with position!
00420   PropagationDirection dir = myTraj.direction();
00421   GlobalVector dirFromPos = myTraj.measurements().back().recHit()->globalPosition() - myTraj.measurements().front().recHit()->globalPosition();
00422 
00423   if ( theStrict1LegFlag && !utilities()->isTraversing(myTraj) ) {trajL.clear(); return trajL;}
00424 
00425   LogTrace(category_)<< "last hit " <<myTraj.measurements().back().recHit()->globalPosition()<<endl;
00426   LogTrace(category_)<< "first hit " <<myTraj.measurements().front().recHit()->globalPosition()<<endl;
00427 
00428   LogTrace(category_)<< "last tsos " <<myTraj.measurements().back().updatedState().globalPosition()<<" mom "<<myTraj.measurements().back().updatedState().globalMomentum()<<endl;
00429   LogTrace(category_)<< "first tsos " <<myTraj.measurements().front().updatedState().globalPosition()<<" mom "<<myTraj.measurements().front().updatedState().globalMomentum()<<endl;
00430 
00431   PropagationDirection propDir =
00432       ( dirFromPos.basicVector().dot(myTraj.firstMeasurement().updatedState().globalMomentum().basicVector()) > 0) ? alongMomentum : oppositeToMomentum;
00433   LogTrace(category_)<<" dir "<<dir <<" propDir "<<propDir<<endl;
00434 
00435   LogTrace(category_)<<"chi2 "<<myTraj.chiSquared() <<endl;
00436 
00437   if (dir != propDir ) {
00438       LogTrace(category_)<< "reverse propagation direction ";
00439       reverseTrajectoryPropagationDirection(myTraj);
00440   }
00441   if ( myTraj.empty() ) return trajL;
00442 
00443   trajL.push_back(new Trajectory(myTraj));
00444   navLayers.clear();
00445   return trajL;
00446 }
00447 
00448 
00449 //
00450 //
00451 //
00452 MuonTransientTrackingRecHit::MuonRecHitContainer 
00453 CosmicMuonTrajectoryBuilder::unusedHits(const DetLayer* layer, const TrajectoryMeasurement& meas) const {
00454 
00455   MuonTransientTrackingRecHit::MuonRecHitContainer tmpHits = theLayerMeasurements->recHits(layer);
00456   MuonRecHitContainer result;
00457   for (MuonRecHitContainer::const_iterator ihit = tmpHits.begin();
00458        ihit != tmpHits.end(); ++ihit ) {
00459        if ((*ihit)->geographicalId() != meas.recHit()->geographicalId() ){ 
00460          result.push_back(*ihit);
00461          LogTrace(category_) << "Unused hit: " << (*ihit)->globalPosition() << endl;
00462     }
00463   }
00464 
00465   return result;
00466 
00467 }
00468 
00469 
00470 //
00471 // continue to build a trajectory starting from given trajectory state
00472 //
00473 void CosmicMuonTrajectoryBuilder::build(const TrajectoryStateOnSurface& ts, 
00474                                         const NavigationDirection& startingDir,
00475                                         Trajectory& traj) {
00476 
00477   if ( !ts.isValid() ) return;
00478 
00479   FreeTrajectoryState* fts = ts.freeState();
00480   if ( !fts ) return;
00481 
00482   vector<const DetLayer*> navLayers;
00483 
00484   if (fabs(fts->momentum().basicVector().eta()) < 1.0) {
00485     //DT
00486     if (fts->position().basicVector().dot(fts->momentum().basicVector())>0){
00487        navLayers = navigation()->compatibleLayers((*fts), alongMomentum);
00488       } else {
00489         navLayers = navigation()->compatibleLayers((*fts), oppositeToMomentum);
00490     }
00491 
00492   } else if (theTraversingMuonFlag && theStrict1LegFlag) {
00493     //CSC
00494       if (fts->position().basicVector().dot(fts->momentum().basicVector())>0){
00495            navLayers = navigation()->compatibleEndcapLayers((*fts), alongMomentum);
00496          } else {
00497             navLayers = navigation()->compatibleEndcapLayers((*fts), oppositeToMomentum);
00498           }
00499   } else {
00500 
00501     if (fts->position().basicVector().dot(fts->momentum().basicVector())>0){
00502        navLayers = navigation()->compatibleLayers((*fts), alongMomentum);
00503       } else {
00504         navLayers = navigation()->compatibleLayers((*fts), oppositeToMomentum);
00505    }
00506 
00507 }
00508 
00509   if (navLayers.empty()) return;
00510 
00511   theBKUpdator->setFitDirection(startingDir);
00512 
00513   int DTChamberUsedBack = 0;
00514   int CSCChamberUsedBack = 0;
00515   int RPCChamberUsedBack = 0;
00516   int TotalChamberUsedBack = 0;
00517 
00518   TrajectoryStateOnSurface lastTsos = 
00519       (traj.lastMeasurement().updatedState().globalPosition().y() <
00520       traj.firstMeasurement().updatedState().globalPosition().y()) ? 
00521       propagatorAlong()->propagate((*fts),navLayers.front()->surface()) : propagatorOpposite()->propagate((*fts),navLayers.front()->surface());
00522 
00523   if ( !lastTsos.isValid() ) { 
00524     LogTrace(category_)<<"propagation failed from fts to inner cylinder";
00525     return;
00526   }
00527   LogTrace(category_)<<"tsos  "<<lastTsos.globalPosition();
00528   lastTsos.rescaleError(10.);
00529   vector<TrajectoryMeasurement> measL;
00530   for (vector<const DetLayer*>::const_iterator rnxtlayer = navLayers.begin();
00531       rnxtlayer!= navLayers.end(); ++rnxtlayer) {
00532 
00533     measL.clear();
00534     measL = findBestMeasurements(*rnxtlayer, lastTsos, propagator(), (backwardUpdator()->estimator()));
00535 
00536     if ( measL.empty() ) continue;
00537 
00538     for (vector<TrajectoryMeasurement>::const_iterator theMeas = measL.begin(); theMeas != measL.end(); ++theMeas) {
00539 
00540       pair<bool,TrajectoryStateOnSurface> bkresult
00541              = backwardUpdator()->update((&*theMeas), traj, propagator());
00542       if (bkresult.first ) {
00543         LogTrace(category_)<<"update ok : "<<(theMeas)->recHit()->globalPosition() ;
00544 
00545         incrementChamberCounters((*rnxtlayer), DTChamberUsedBack, CSCChamberUsedBack, RPCChamberUsedBack, TotalChamberUsedBack);
00546 
00547         if ( (!traj.empty()) && bkresult.second.isValid() ) 
00548           lastTsos = bkresult.second;
00549         else if ((theMeas)->predictedState().isValid()) 
00550           lastTsos = (theMeas)->predictedState();
00551       }
00552     }
00553   }
00554   navLayers.clear();
00555   updator()->makeFirstTime();
00556   backwardUpdator()->makeFirstTime();
00557 
00558   measL.clear();
00559 
00560   return;
00561 
00562 }
00563 
00564 
00565 //
00566 // build trajectory in second hemisphere with pattern
00567 // recognition starting from an intermediate state
00568 //
00569 void CosmicMuonTrajectoryBuilder::buildSecondHalf(Trajectory& traj) {
00570 
00571   if ( (traj.firstMeasurement().recHit()->globalPosition().perp()
00572       < traj.lastMeasurement().recHit()->globalPosition().perp()) ) {
00573     LogTrace(category_)<<"inside-out: reverseTrajectory"; 
00574     reverseTrajectory(traj);
00575   }
00576   if (traj.empty()) return;
00577   TrajectoryStateOnSurface tsos = traj.lastMeasurement().updatedState();
00578   if ( !tsos.isValid() ) tsos = traj.lastMeasurement().predictedState();
00579  LogTrace(category_)<<"last tsos on traj: pos: "<< tsos.globalPosition()<<" mom: "<< tsos.globalMomentum();
00580   if ( !tsos.isValid() ) {
00581     LogTrace(category_)<<"last tsos on traj invalid";
00582     return;
00583   }
00584 
00585   build(intermediateState(tsos),insideOut,traj);
00586 
00587   return;
00588 
00589 }
00590 
00591 
00592 //
00593 //
00594 //
00595 TrajectoryStateOnSurface CosmicMuonTrajectoryBuilder::intermediateState(const TrajectoryStateOnSurface& tsos) const {
00596 
00597   PerpendicularBoundPlaneBuilder planeBuilder;
00598   GlobalPoint pos(0.0, 0.0, 0.0);
00599   BoundPlane* SteppingPlane = planeBuilder(pos,tsos.globalDirection());
00600 
00601   TrajectoryStateOnSurface predTsos = propagator()->propagate(tsos, *SteppingPlane);
00602   if ( predTsos.isValid() )
00603   LogTrace(category_)<<"intermediateState: a intermediate state: pos: "<<predTsos.globalPosition() << "mom: " << predTsos.globalMomentum();
00604 
00605   return predTsos;
00606 
00607 }
00608 
00609 
00610 //
00611 //
00612 //
00613 void CosmicMuonTrajectoryBuilder::selectHits(MuonTransientTrackingRecHit::MuonRecHitContainer& hits) const {
00614 
00615   if ( hits.size() < 2 ) return;
00616 
00617   MuonRecHitContainer tmp;
00618   vector<bool> keep(hits.size(),true);
00619   int i(0);
00620   int j(0);
00621 
00622   for (MuonRecHitContainer::const_iterator ihit = hits.begin();
00623        ihit != hits.end(); ++ihit ) {
00624     if ( !keep[i] ) { i++; continue; };
00625     j = i + 1;
00626     for (MuonRecHitContainer::const_iterator ihit2 = ihit + 1;
00627          ihit2 != hits.end(); ++ihit2 ) {
00628          if ( !keep[j] ) { j++; continue; }
00629          if ((*ihit)->geographicalId() == (*ihit2)->geographicalId() ) {
00630            if ( (*ihit)->dimension() > (*ihit2)->dimension() ) {
00631               keep[j] = false;
00632            } else if ( (*ihit)->dimension() < (*ihit2)->dimension() ) {
00633               keep[i] = false;
00634            } else  {
00635            if ( (*ihit)->transientHits().size()>(*ihit2)->transientHits().size() ) { 
00636               keep[j] = false;
00637            } else if ( (*ihit)->transientHits().size()<(*ihit2)->transientHits().size() ) {
00638               keep[i] = false;
00639            } 
00640             else if ( (*ihit)->degreesOfFreedom() != 0 && (*ihit2)->degreesOfFreedom() != 0)  {
00641             if (((*ihit)->chi2()/(*ihit)->degreesOfFreedom()) > ((*ihit2)->chi2()/(*ihit)->degreesOfFreedom())) keep[i] = false;
00642             else keep[j] = false;
00643            }
00644           }
00645          } // if same geomid 
00646       j++;
00647     }
00648     i++;
00649   }
00650 
00651   i = 0;
00652   for (MuonRecHitContainer::const_iterator ihit = hits.begin();
00653        ihit != hits.end(); ++ihit ) {
00654      if (keep[i] ) tmp.push_back(*ihit);
00655      i++;
00656   }
00657 
00658   hits.clear();
00659   hits.swap(tmp);
00660 
00661   return;
00662 
00663 }
00664 
00665 
00666 //
00667 //
00668 //
00669 bool CosmicMuonTrajectoryBuilder::selfDuplicate(const Trajectory& traj) const {
00670 
00671   TransientTrackingRecHit::ConstRecHitContainer hits = traj.recHits();
00672 
00673   if (traj.empty()) return true;
00674 
00675   bool result = false;
00676   for (ConstRecHitContainer::const_iterator ir = hits.begin(); ir != hits.end(); ir++ ) {
00677     if ( !(*ir)->isValid() )  continue;
00678     for (ConstRecHitContainer::const_iterator ir2 = ir+1; ir2 != hits.end(); ir2++ ) {
00679       if ( !(*ir2)->isValid() )  continue;
00680       if ( (*ir) == (*ir2) ) result = true;
00681     }
00682   }
00683 
00684   return result;
00685 
00686 }
00687 
00688 
00689 //
00690 // reverse a trajectory without refitting
00691 // this can only be used for cosmic muons that come from above
00692 //
00693 void CosmicMuonTrajectoryBuilder::reverseTrajectory(Trajectory& traj) const {
00694 
00695   PropagationDirection newDir = (traj.firstMeasurement().recHit()->globalPosition().y()
00696       < traj.lastMeasurement().recHit()->globalPosition().y())
00697   ? oppositeToMomentum : alongMomentum;
00698   Trajectory newTraj(traj.seed(), newDir);
00699   
00700  const std::vector<TrajectoryMeasurement>& meas = traj.measurements();
00701 
00702   for (std::vector<TrajectoryMeasurement>::const_reverse_iterator itm = meas.rbegin();
00703        itm != meas.rend(); ++itm ) {
00704     newTraj.push(*itm);
00705   }
00706   traj = newTraj;
00707 
00708 }
00709 
00710 
00711 //
00712 // reverse a trajectory momentum direction and then refit
00713 //
00714 void CosmicMuonTrajectoryBuilder::flipTrajectory(Trajectory& traj) const {
00715 
00716   TrajectoryStateOnSurface lastTSOS = traj.lastMeasurement().updatedState();
00717   if ( !lastTSOS.isValid() ) {
00718     LogTrace(category_) << "Error: last TrajectoryState invalid.";
00719   }  
00720   TransientTrackingRecHit::ConstRecHitContainer hits = traj.recHits();
00721   std::reverse(hits.begin(), hits.end());
00722 
00723   LogTrace(category_) << "last tsos before flipping "<<lastTSOS;
00724   utilities()->reverseDirection(lastTSOS,&*theService->magneticField());
00725   LogTrace(category_) << "last tsos after flipping "<<lastTSOS;
00726 
00727   vector<Trajectory> refittedback = theSmoother->fit(traj.seed(),hits,lastTSOS);
00728   if ( refittedback.empty() ) {
00729     LogTrace(category_) <<"flipTrajectory fail. "<<endl;
00730     return;
00731   }
00732   LogTrace(category_) <<"flipTrajectory: first "<< refittedback.front().firstMeasurement().updatedState()
00733                        <<"\nflipTrajectory: last "<<refittedback.front().lastMeasurement().updatedState();
00734 
00735   traj = refittedback.front();
00736 
00737   return;
00738 
00739 }
00740 
00741 
00742 //
00743 //
00744 //
00745 void CosmicMuonTrajectoryBuilder::reverseTrajectoryPropagationDirection(Trajectory& traj) const {
00746 
00747   if ( traj.direction() == anyDirection ) return;
00748   PropagationDirection newDir = (traj.direction() == alongMomentum)? oppositeToMomentum : alongMomentum;
00749   Trajectory newTraj(traj.seed(), newDir);
00750   const std::vector<TrajectoryMeasurement>& meas = traj.measurements();
00751 
00752   for (std::vector<TrajectoryMeasurement>::const_iterator itm = meas.begin(); itm != meas.end(); ++itm) {
00753     newTraj.push(*itm);
00754   }
00755 
00756   while (!traj.empty()) {
00757     traj.pop();
00758   }
00759 
00760   traj = newTraj;
00761 
00762 }
00763 
00764 
00765 //
00766 // guess the direction by normalized chi2
00767 //
00768 void CosmicMuonTrajectoryBuilder::estimateDirection(Trajectory& traj) const {
00769 
00770   TransientTrackingRecHit::ConstRecHitContainer hits = traj.recHits();
00771 
00772   TrajectoryStateOnSurface firstTSOS = traj.firstMeasurement().updatedState();
00773 
00774   TrajectoryStateOnSurface lastTSOS = traj.lastMeasurement().updatedState();
00775 
00776   if ( !firstTSOS.isValid() || !lastTSOS.isValid() ) return;
00777 
00778   LogTrace(category_) <<"Two ends of the traj "<<firstTSOS.globalPosition()
00779                       <<", "<<lastTSOS.globalPosition();
00780 
00781   LogTrace(category_) <<"Their mom: "<<firstTSOS.globalMomentum()
00782                       <<", "<<lastTSOS.globalMomentum();
00783 
00784   LogTrace(category_) <<"Their mom eta: "<<firstTSOS.globalMomentum().eta()
00785                       <<", "<<lastTSOS.globalMomentum().eta();
00786 
00787   // momentum eta can be used to estimate direction
00788   // the beam-halo muon seems enter with a larger |eta|
00789 
00790   if ( fabs(firstTSOS.globalMomentum().eta()) > fabs(lastTSOS.globalMomentum().eta()) ) {
00791 
00792     vector<Trajectory> refitted = theSmoother->trajectories(traj.seed(),hits,firstTSOS);
00793     if ( !refitted.empty() ) traj = refitted.front();
00794 
00795   } else {
00796     std::reverse(hits.begin(), hits.end());
00797     utilities()->reverseDirection(lastTSOS,&*theService->magneticField());
00798     vector<Trajectory> refittedback = theSmoother->trajectories(traj.seed(),hits,lastTSOS);
00799     if ( !refittedback.empty() ) traj = refittedback.front();
00800 
00801   }
00802 
00803   return;
00804 
00805 }
00806 
00807 
00808 //
00809 // get direction from timing information of rechits and segments
00810 //
00811 void CosmicMuonTrajectoryBuilder::getDirectionByTime(Trajectory& traj) const {
00812 
00813   TransientTrackingRecHit::ConstRecHitContainer hits = traj.recHits();
00814   LogTrace(category_) << "getDirectionByTime"<<endl;
00815   for (TransientTrackingRecHit::ConstRecHitContainer::const_iterator ir = hits.begin(); ir != hits.end(); ir++ ) {
00816     if ( !(*ir)->isValid() ) {
00817       LogTrace(category_) << "invalid RecHit"<<endl;
00818       continue;
00819     }
00820 
00821     const GlobalPoint& pos = (*ir)->globalPosition();
00822     LogTrace(category_)
00823     << "pos" << pos
00824     << "radius " << pos.perp()
00825     << "  dim " << (*ir)->dimension()
00826     << "  det " << (*ir)->det()->geographicalId().det()
00827     << "  sub det " << (*ir)->det()->subDetector()<<endl;
00828 
00829     if ((*ir)->det()->geographicalId().det() == 2 && (*ir)->det()->subDetector() == 6) { 
00830 //      const CSCRecHit2D* iCSC = dynamic_cast<const CSCRecHit2D*>(&**ir);
00831 //      if (iCSC) LogTrace(category_)<<"csc from cast tpeak "<<iCSC->tpeak(); 
00832       CSCRecHit2DCollection::range thisrange = cschits_->get(CSCDetId((*ir)->geographicalId()));
00833       for (CSCRecHit2DCollection::const_iterator rechit = thisrange.first; rechit!=thisrange.second;++rechit) {
00834          if ((*rechit).isValid()) LogTrace(category_)<<"csc from collection tpeak "<<(*rechit).tpeak();
00835       }
00836     }
00837     if ((*ir)->det()->geographicalId().det() == 2 && (*ir)->det()->subDetector() == 7) {
00838 //      const DTRecHit1D* iDT = dynamic_cast<const DTRecHit1D*>(&**ir);
00839 //      if (iDT) LogTrace(category_)<<"dt digitime "<<iDT->digiTime();
00840       DTRecHitCollection::range thisrange = dthits_->get(DTLayerId((*ir)->geographicalId()));
00841       for (DTRecHitCollection::const_iterator rechit = thisrange.first; rechit!=thisrange.second;++rechit) {
00842          if ((*rechit).isValid()) LogTrace(category_)<<"dt from collection digitime "<<(*rechit).digiTime();
00843       }
00844     }
00845   }
00846 
00847   return;
00848 
00849 }
00850 
00851 
00852 //
00853 //
00854 //
00855 std::vector<TrajectoryMeasurement>
00856 CosmicMuonTrajectoryBuilder::findBestMeasurements(const DetLayer* layer,
00857                                                   const TrajectoryStateOnSurface& tsos, 
00858                                                   const Propagator* propagator, 
00859                                                   const MeasurementEstimator* estimator) {
00860 
00861   std::vector<TrajectoryMeasurement> result;
00862   std::vector<TrajectoryMeasurement> measurements;
00863 
00864   if ( layer->hasGroups() ) {
00865     std::vector<TrajectoryMeasurementGroup> measurementGroups =
00866       theLayerMeasurements->groupedMeasurements(layer, tsos, *propagator, *estimator);
00867 
00868     for (std::vector<TrajectoryMeasurementGroup>::const_iterator tmGroupItr = measurementGroups.begin();
00869         tmGroupItr != measurementGroups.end(); ++tmGroupItr) {
00870     
00871       measurements = tmGroupItr->measurements();
00872       const TrajectoryMeasurement* bestMeasurement 
00873         = theBestMeasurementFinder->findBestMeasurement(measurements, propagator);
00874       
00875       if (bestMeasurement) result.push_back(*bestMeasurement);
00876     }
00877   } 
00878   else {
00879     measurements = theLayerMeasurements->measurements(layer, tsos, *propagator, *estimator);
00880     const TrajectoryMeasurement* bestMeasurement 
00881       = theBestMeasurementFinder->findBestMeasurement(measurements, propagator);
00882 
00883     if (bestMeasurement) result.push_back(*bestMeasurement);
00884   }
00885   measurements.clear();
00886 
00887   return result;
00888 
00889 }
00890 
00891 
00892 //
00893 //
00894 //
00895 void CosmicMuonTrajectoryBuilder::incrementChamberCounters(const DetLayer* layer,
00896                                                            int& dtChambers, 
00897                                                            int& cscChambers, 
00898                                                            int& rpcChambers, 
00899                                                            int& totalChambers) {
00900 
00901   if (layer->subDetector()==GeomDetEnumerators::DT) dtChambers++; 
00902   else if (layer->subDetector()==GeomDetEnumerators::CSC) cscChambers++; 
00903   else if (layer->subDetector()==GeomDetEnumerators::RPCBarrel || layer->subDetector()==GeomDetEnumerators::RPCEndcap) rpcChambers++; 
00904   totalChambers++;
00905 
00906 }
00907 
00908 
00909 //
00910 //
00911 //
00912 double CosmicMuonTrajectoryBuilder::t0(const DTRecSegment4D* dtseg) const {
00913 
00914    if ( (dtseg == 0) || (!dtseg->hasPhi()) ) return 0;
00915    // timing information
00916    double result = 0;
00917    if ( dtseg->phiSegment() == 0 ) return 0; 
00918    int phiHits = dtseg->phiSegment()->specificRecHits().size();
00919    LogTrace(category_) << "phiHits " << phiHits;
00920    if ( phiHits > 5 ) {
00921      if(dtseg->phiSegment()->ist0Valid()) result = dtseg->phiSegment()->t0();
00922      if (dtseg->phiSegment()->ist0Valid()){
00923        LogTrace(category_) << " Phi t0: " << dtseg->phiSegment()->t0() << " hits: " << phiHits;
00924      } else {
00925        LogTrace(category_) << " Phi t0 is invalid: " << dtseg->phiSegment()->t0() << " hits: " << phiHits;
00926      }
00927    }
00928 
00929    return result;
00930 
00931 }
00932 
00933 
00934 //
00935 //
00936 //
00937 PropagationDirection CosmicMuonTrajectoryBuilder::checkDirectionByT0(const DTRecSegment4D* dtseg1, 
00938                                                                      const DTRecSegment4D* dtseg2) const {
00939 
00940    LogTrace(category_) << "comparing dtseg: " << dtseg1 << " " << dtseg2 << endl;
00941    if (dtseg1 == dtseg2 || t0(dtseg1) == t0(dtseg2)) return anyDirection; 
00942 
00943    PropagationDirection result =
00944     ( t0(dtseg1) < t0(dtseg2) ) ? alongMomentum : oppositeToMomentum;
00945 
00946    return result;
00947 
00948 }