CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/RecoMuon/GlobalTrackingTools/src/GlobalMuonRefitter.cc

Go to the documentation of this file.
00001 
00015 #include "RecoMuon/GlobalTrackingTools/interface/GlobalMuonRefitter.h"
00016 
00017 //---------------
00018 // C++ Headers --
00019 //---------------
00020 
00021 #include <iostream>
00022 #include <iomanip>
00023 #include <algorithm>
00024 
00025 //-------------------------------
00026 // Collaborating Class Headers --
00027 //-------------------------------
00028 
00029 #include "FWCore/Framework/interface/Event.h"
00030 
00031 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00032 #include "CommonTools/Statistics/interface/ChiSquaredProbability.h"
00033 #include "TrackingTools/TrackFitters/interface/RecHitLessByDet.h"
00034 #include "TrackingTools/PatternTools/interface/TrajectoryMeasurement.h"
00035 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
00036 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
00037 #include "TrackingTools/Records/interface/TrackingComponentsRecord.h"
00038 #include "TrackingTools/TrackFitters/interface/TrajectoryFitter.h"
00039 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
00040 
00041 
00042 #include "DataFormats/DetId/interface/DetId.h"
00043 #include "DataFormats/MuonDetId/interface/DTChamberId.h"
00044 #include "DataFormats/MuonDetId/interface/CSCDetId.h"
00045 #include "DataFormats/MuonDetId/interface/RPCDetId.h"
00046 #include "Geometry/DTGeometry/interface/DTGeometry.h"
00047 #include "Geometry/DTGeometry/interface/DTLayer.h"
00048 #include <Geometry/CSCGeometry/interface/CSCLayer.h>
00049 #include <DataFormats/CSCRecHit/interface/CSCRecHit2D.h>
00050 #include "DataFormats/SiPixelDetId/interface/PXBDetId.h"
00051 #include "DataFormats/SiPixelDetId/interface/PXFDetId.h"
00052 #include "DataFormats/SiStripDetId/interface/TECDetId.h"
00053 #include "DataFormats/SiStripDetId/interface/TIBDetId.h"
00054 #include "DataFormats/SiStripDetId/interface/TIDDetId.h"
00055 #include "DataFormats/SiStripDetId/interface/TOBDetId.h"
00056 
00057 #include "DataFormats/TrackReco/interface/Track.h"
00058 #include "DataFormats/TrackReco/interface/TrackExtraFwd.h"
00059 
00060 #include "RecoMuon/MeasurementDet/interface/MuonDetLayerMeasurements.h"
00061 #include "RecoMuon/TransientTrackingRecHit/interface/MuonTransientTrackingRecHitBuilder.h"
00062 #include "TrackingTools/Records/interface/TransientRecHitRecord.h"
00063 #include "RecoMuon/TransientTrackingRecHit/interface/MuonTransientTrackingRecHit.h"
00064 #include "RecoMuon/TrackingTools/interface/MuonCandidate.h"
00065 #include "RecoMuon/TrackingTools/interface/MuonServiceProxy.h"
00066 #include "RecoMuon/GlobalTrackingTools/interface/DynamicTruncation.h"
00067 
00068 using namespace std;
00069 using namespace edm;
00070 
00071 //----------------
00072 // Constructors --
00073 //----------------
00074 
00075 GlobalMuonRefitter::GlobalMuonRefitter(const edm::ParameterSet& par,
00076                                        const MuonServiceProxy* service) : 
00077   theCosmicFlag(par.getParameter<bool>("PropDirForCosmics")),
00078   theDTRecHitLabel(par.getParameter<InputTag>("DTRecSegmentLabel")),
00079   theCSCRecHitLabel(par.getParameter<InputTag>("CSCRecSegmentLabel")),
00080   theService(service) {
00081 
00082   theCategory = par.getUntrackedParameter<string>("Category", "Muon|RecoMuon|GlobalMuon|GlobalMuonRefitter");
00083 
00084   theHitThreshold = par.getParameter<int>("HitThreshold");
00085   theDTChi2Cut  = par.getParameter<double>("Chi2CutDT");
00086   theCSCChi2Cut = par.getParameter<double>("Chi2CutCSC");
00087   theRPCChi2Cut = par.getParameter<double>("Chi2CutRPC");
00088 
00089   // Refit direction
00090   string refitDirectionName = par.getParameter<string>("RefitDirection");
00091 
00092   if (refitDirectionName == "insideOut" ) theRefitDirection = insideOut;
00093   else if (refitDirectionName == "outsideIn" ) theRefitDirection = outsideIn;
00094   else 
00095     throw cms::Exception("TrackTransformer constructor") 
00096       <<"Wrong refit direction chosen in TrackTransformer ParameterSet"
00097       << "\n"
00098       << "Possible choices are:"
00099       << "\n"
00100       << "RefitDirection = insideOut or RefitDirection = outsideIn";
00101   
00102   theFitterName = par.getParameter<string>("Fitter");  
00103   thePropagatorName = par.getParameter<string>("Propagator");
00104 
00105   theSkipStation        = par.getParameter<int>("SkipStation");
00106   theTrackerSkipSystem  = par.getParameter<int>("TrackerSkipSystem");
00107   theTrackerSkipSection = par.getParameter<int>("TrackerSkipSection");//layer, wheel, or disk depending on the system
00108 
00109   theTrackerRecHitBuilderName = par.getParameter<string>("TrackerRecHitBuilder");
00110   theMuonRecHitBuilderName = par.getParameter<string>("MuonRecHitBuilder");
00111 
00112   theRPCInTheFit = par.getParameter<bool>("RefitRPCHits");
00113 
00114   theDYTthrs = par.getParameter< std::vector<int> >("DYTthrs");
00115 
00116   if (par.existsAs<double>("RescaleErrorFactor")) {
00117     theRescaleErrorFactor = par.getParameter<double>("RescaleErrorFactor");
00118     edm::LogWarning("GlobalMuonRefitter") << "using error rescale factor " << theRescaleErrorFactor;
00119   }
00120   else
00121     theRescaleErrorFactor = 1000.;
00122   
00123 
00124   theCacheId_TRH = 0;
00125 
00126 }
00127 
00128 //--------------
00129 // Destructor --
00130 //--------------
00131 
00132 GlobalMuonRefitter::~GlobalMuonRefitter() {
00133 }
00134 
00135 
00136 //
00137 // set Event
00138 //
00139 void GlobalMuonRefitter::setEvent(const edm::Event& event) {
00140 
00141   theEvent = &event;
00142   event.getByLabel(theDTRecHitLabel, theDTRecHits);
00143   event.getByLabel(theCSCRecHitLabel, theCSCRecHits);
00144 }
00145 
00146 
00147 void GlobalMuonRefitter::setServices(const EventSetup& setup) {
00148 
00149   theService->eventSetup().get<TrajectoryFitter::Record>().get(theFitterName,theFitter);
00150 
00151   // Transient Rechit Builders
00152   unsigned long long newCacheId_TRH = setup.get<TransientRecHitRecord>().cacheIdentifier();
00153   if ( newCacheId_TRH != theCacheId_TRH ) {
00154     LogDebug(theCategory) << "TransientRecHitRecord changed!";
00155     setup.get<TransientRecHitRecord>().get(theTrackerRecHitBuilderName,theTrackerRecHitBuilder);
00156     setup.get<TransientRecHitRecord>().get(theMuonRecHitBuilderName,theMuonRecHitBuilder);
00157   }
00158 }
00159 
00160 
00161 //
00162 // build a combined tracker-muon trajectory
00163 //
00164 vector<Trajectory> GlobalMuonRefitter::refit(const reco::Track& globalTrack, 
00165                                              const int theMuonHitsOption) const {
00166   LogTrace(theCategory) << " *** GlobalMuonRefitter *** option " << theMuonHitsOption << endl;
00167     
00168   ConstRecHitContainer allRecHitsTemp; // all muon rechits temp
00169 
00170   reco::TransientTrack track(globalTrack,&*(theService->magneticField()),theService->trackingGeometry());
00171   
00172   for (trackingRecHit_iterator hit = track.recHitsBegin(); hit != track.recHitsEnd(); ++hit)
00173     if ((*hit)->isValid()) {
00174       if ((*hit)->geographicalId().det() == DetId::Tracker)
00175         allRecHitsTemp.push_back(theTrackerRecHitBuilder->build(&**hit));
00176       else if ((*hit)->geographicalId().det() == DetId::Muon) {
00177         if ((*hit)->geographicalId().subdetId() == 3 && !theRPCInTheFit) {
00178           LogTrace(theCategory) << "RPC Rec Hit discarged"; 
00179           continue;
00180         }
00181         allRecHitsTemp.push_back(theMuonRecHitBuilder->build(&**hit));
00182       }
00183     }  
00184   vector<Trajectory> refitted = refit(globalTrack,track,allRecHitsTemp,theMuonHitsOption);
00185   return refitted;
00186 }
00187 
00188 //
00189 // build a combined tracker-muon trajectory
00190 //
00191 vector<Trajectory> GlobalMuonRefitter::refit(const reco::Track& globalTrack,
00192                                              const reco::TransientTrack track,
00193                                              TransientTrackingRecHit::ConstRecHitContainer allRecHitsTemp,
00194                                              const int theMuonHitsOption) const {
00195 
00196   // MuonHitsOption: 0 - tracker only
00197   //                 1 - include all muon hits
00198   //                 2 - include only first muon hit(s)
00199   //                 3 - include only selected muon hits
00200   //                 4 - redo pattern recognition with dynamic truncation
00201 
00202   vector<int> stationHits(4,0);
00203   map<DetId, int> hitMap;
00204 
00205   ConstRecHitContainer allRecHits; // all muon rechits
00206   ConstRecHitContainer fmsRecHits; // only first muon rechits
00207   ConstRecHitContainer selectedRecHits; // selected muon rechits
00208   ConstRecHitContainer DYTRecHits; // rec hits from dynamic truncation algorithm
00209 
00210   LogTrace(theCategory) << " *** GlobalMuonRefitter *** option " << theMuonHitsOption << endl;
00211   LogTrace(theCategory) << " Track momentum before refit: " << globalTrack.pt() << endl;
00212   LogTrace(theCategory) << " Hits size before : " << allRecHitsTemp.size() << endl;
00213 
00214   allRecHits = getRidOfSelectStationHits(allRecHitsTemp);  
00215   //    printHits(allRecHits);
00216   LogTrace(theCategory) << " Hits size: " << allRecHits.size() << endl;
00217 
00218   vector <Trajectory> outputTraj;
00219 
00220   if ((theMuonHitsOption == 1) || (theMuonHitsOption == 3) || (theMuonHitsOption == 4) ) {
00221     // refit the full track with all muon hits
00222     vector <Trajectory> globalTraj = transform(globalTrack, track, allRecHits);
00223 
00224     if (!globalTraj.size()) {
00225       LogTrace(theCategory) << "No trajectory from the TrackTransformer!" << endl;
00226       return vector<Trajectory>();
00227     }
00228 
00229     LogTrace(theCategory) << " Initial trajectory state: " 
00230                           << globalTraj.front().lastMeasurement().updatedState().freeState()->parameters() << endl;
00231   
00232     if (theMuonHitsOption == 1 )
00233       outputTraj.push_back(globalTraj.front());
00234     
00235     if (theMuonHitsOption == 3 ) {
00236       checkMuonHits(globalTrack, allRecHits, hitMap);
00237       selectedRecHits = selectMuonHits(globalTraj.front(),hitMap);
00238       LogTrace(theCategory) << " Selected hits size: " << selectedRecHits.size() << endl;  
00239       outputTraj = transform(globalTrack, track, selectedRecHits);
00240     }     
00241 
00242     if (theMuonHitsOption == 4 ) {
00243       // here we use the single thr per subdetector (better performance can be obtained using thr as function of eta)
00244         
00245       DynamicTruncation dytRefit(*theEvent,*theService);
00246       dytRefit.setThr(theDYTthrs.at(0),theDYTthrs.at(1));                                
00247       DYTRecHits = dytRefit.filter(globalTraj.front());
00248       //vector<double> est = dytRefit.getEstimators();
00249       if ((DYTRecHits.size() > 1) && (DYTRecHits.front()->globalPosition().mag() > DYTRecHits.back()->globalPosition().mag()))
00250         stable_sort(DYTRecHits.begin(),DYTRecHits.end(),RecHitLessByDet(alongMomentum));
00251       outputTraj = transform(globalTrack, track, DYTRecHits);
00252     }
00253 
00254   } else if (theMuonHitsOption == 2 )  {
00255       getFirstHits(globalTrack, allRecHits, fmsRecHits);
00256       outputTraj = transform(globalTrack, track, fmsRecHits);
00257     } 
00258 
00259 
00260   if (outputTraj.size()) {
00261     LogTrace(theCategory) << "Refitted pt: " << outputTraj.front().firstMeasurement().updatedState().globalParameters().momentum().perp() << endl;
00262     return outputTraj;
00263   } else {
00264     LogTrace(theCategory) << "No refitted Tracks... " << endl;
00265     return vector<Trajectory>();
00266   }
00267   
00268 }
00269 
00270 
00271 //
00272 //
00273 //
00274 void GlobalMuonRefitter::checkMuonHits(const reco::Track& muon, 
00275                                        ConstRecHitContainer& all,
00276                                        map<DetId, int> &hitMap) const {
00277 
00278   LogTrace(theCategory) << " GlobalMuonRefitter::checkMuonHits " << endl;
00279 
00280   float coneSize = 20.0;
00281 
00282   // loop through all muon hits and calculate the maximum # of hits in each chamber
00283   for (ConstRecHitContainer::const_iterator imrh = all.begin(); imrh != all.end(); imrh++ ) {
00284         
00285     if ( (*imrh != 0 ) && !(*imrh)->isValid() ) continue;
00286   
00287     int detRecHits = 0;
00288     MuonRecHitContainer dRecHits;
00289       
00290     DetId id = (*imrh)->geographicalId();
00291     DetId chamberId;
00292 
00293     // Skip tracker hits
00294     if (id.det()!=DetId::Muon) continue;
00295 
00296     if ( id.subdetId() == MuonSubdetId::DT ) {
00297       DTChamberId did(id.rawId());
00298       chamberId=did;
00299       
00300       if ((*imrh)->recHits().size()>1) {
00301         std::vector <const TrackingRecHit*> hits2d = (*imrh)->recHits();
00302         for (std::vector <const TrackingRecHit*>::const_iterator hit2d = hits2d.begin(); hit2d!= hits2d.end(); hit2d++) {
00303           if ((*imrh)->recHits().size()>1) {
00304             std::vector <const TrackingRecHit*> hits1d = (*hit2d)->recHits();
00305             for (std::vector <const TrackingRecHit*>::const_iterator hit1d = hits1d.begin(); hit1d!= hits1d.end(); hit1d++) {
00306               DetId id1 = (*hit1d)->geographicalId();
00307               DTLayerId lid(id1.rawId());
00308               // Get the 1d DT RechHits from this layer
00309               DTRecHitCollection::range dRecHits = theDTRecHits->get(lid);
00310               int layerHits=0;
00311               for (DTRecHitCollection::const_iterator ir = dRecHits.first; ir != dRecHits.second; ir++ ) {
00312                 double rhitDistance = fabs(ir->localPosition().x()-(**hit1d).localPosition().x()); 
00313                 if ( rhitDistance < coneSize ) layerHits++;
00314                 LogTrace(theCategory) << "       " << (ir)->localPosition() << "  " << (**hit1d).localPosition()
00315                      << " Distance: " << rhitDistance << " recHits: " << layerHits << "  SL: " << lid.superLayer() << endl;
00316               }
00317               if (layerHits>detRecHits) detRecHits=layerHits;
00318             }
00319           }
00320         }
00321       
00322       } else {
00323         DTLayerId lid(id.rawId());
00324     
00325         // Get the 1d DT RechHits from this layer
00326         DTRecHitCollection::range dRecHits = theDTRecHits->get(lid);
00327 
00328         for (DTRecHitCollection::const_iterator ir = dRecHits.first; ir != dRecHits.second; ir++ ) {
00329           double rhitDistance = fabs(ir->localPosition().x()-(**imrh).localPosition().x());
00330           if ( rhitDistance < coneSize ) detRecHits++;
00331           LogTrace(theCategory) << "       " << (ir)->localPosition() << "  " << (**imrh).localPosition()
00332                << " Distance: " << rhitDistance << " recHits: " << detRecHits << endl;
00333         }
00334       }
00335     }// end of if DT
00336     else if ( id.subdetId() == MuonSubdetId::CSC ) {
00337       CSCDetId did(id.rawId());
00338       chamberId=did.chamberId();
00339 
00340       if ((*imrh)->recHits().size()>1) {
00341         std::vector <const TrackingRecHit*> hits2d = (*imrh)->recHits();
00342         for (std::vector <const TrackingRecHit*>::const_iterator hit2d = hits2d.begin(); hit2d!= hits2d.end(); hit2d++) {
00343           DetId id1 = (*hit2d)->geographicalId();
00344           CSCDetId lid(id1.rawId());
00345           
00346           // Get the CSC Rechits from this layer
00347           CSCRecHit2DCollection::range dRecHits = theCSCRecHits->get(lid);      
00348           int layerHits=0;
00349 
00350           for (CSCRecHit2DCollection::const_iterator ir = dRecHits.first; ir != dRecHits.second; ir++ ) {
00351             double rhitDistance = (ir->localPosition()-(**hit2d).localPosition()).mag();
00352             if ( rhitDistance < coneSize ) layerHits++;
00353             LogTrace(theCategory) << ir->localPosition() << "  " << (**hit2d).localPosition()
00354                    << " Distance: " << rhitDistance << " recHits: " << layerHits << endl;
00355           }
00356           if (layerHits>detRecHits) detRecHits=layerHits;
00357         }
00358       } else {
00359         // Get the CSC Rechits from this layer
00360         CSCRecHit2DCollection::range dRecHits = theCSCRecHits->get(did);      
00361 
00362         for (CSCRecHit2DCollection::const_iterator ir = dRecHits.first; ir != dRecHits.second; ir++ ) {
00363           double rhitDistance = (ir->localPosition()-(**imrh).localPosition()).mag();
00364           if ( rhitDistance < coneSize ) detRecHits++;
00365           LogTrace(theCategory) << ir->localPosition() << "  " << (**imrh).localPosition()
00366                  << " Distance: " << rhitDistance << " recHits: " << detRecHits << endl;
00367         }
00368       }
00369     }
00370     else {
00371       if ( id.subdetId() != MuonSubdetId::RPC ) LogError(theCategory)<<" Wrong Hit Type ";
00372       continue;      
00373     }
00374       
00375     map<DetId,int>::iterator imap=hitMap.find(chamberId);
00376     if (imap!=hitMap.end()) {
00377       if (detRecHits>imap->second) imap->second=detRecHits;
00378     } else hitMap[chamberId]=detRecHits;
00379 
00380   } // end of loop over muon rechits
00381 
00382   for (map<DetId,int>::iterator imap=hitMap.begin(); imap!=hitMap.end(); imap++ ) 
00383     LogTrace(theCategory) << " Station " << imap->first.rawId() << ": " << imap->second <<endl; 
00384 
00385   LogTrace(theCategory) << "CheckMuonHits: "<<all.size();
00386 
00387   // check order of muon measurements
00388   if ( (all.size() > 1) &&
00389        ( all.front()->globalPosition().mag() >
00390          all.back()->globalPosition().mag() ) ) {
00391     LogTrace(theCategory)<< "reverse order: ";
00392     stable_sort(all.begin(),all.end(),RecHitLessByDet(alongMomentum));
00393   }
00394 }
00395 
00396 
00397 //
00398 // Get the hits from the first muon station (containing hits)
00399 //
00400 void GlobalMuonRefitter::getFirstHits(const reco::Track& muon, 
00401                                        ConstRecHitContainer& all,
00402                                        ConstRecHitContainer& first) const {
00403 
00404   LogTrace(theCategory) << " GlobalMuonRefitter::getFirstHits\nall rechits length:" << all.size() << endl;
00405   first.clear();
00406 
00407   int station_to_keep = 999;
00408   vector<int> stations;
00409   for (ConstRecHitContainer::const_iterator ihit = all.begin(); ihit != all.end(); ++ihit) {
00410   
00411     int station = 0;
00412     bool use_it = true;
00413     DetId id = (*ihit)->geographicalId();
00414     unsigned raw_id = id.rawId();
00415     if (!(*ihit)->isValid()) station = -1;
00416       else {
00417         if (id.det() == DetId::Muon) {
00418           switch (id.subdetId()) {
00419           case MuonSubdetId::DT:  station = DTChamberId(raw_id).station(); break;
00420           case MuonSubdetId::CSC: station = CSCDetId(raw_id).station(); break;
00421           case MuonSubdetId::RPC: station = RPCDetId(raw_id).station(); use_it = false; break;
00422           }
00423         }
00424       }
00425 
00426     if (use_it && station > 0 && station < station_to_keep) station_to_keep = station;
00427     stations.push_back(station);
00428 
00429     LogTrace(theCategory) << "rawId: " << raw_id << " station = " << station << " station_to_keep is now " << station_to_keep;
00430   }
00431 
00432   if (station_to_keep <= 0 || station_to_keep > 4 || stations.size() != all.size())
00433     LogInfo(theCategory) << "failed to getFirstHits (all muon hits are outliers/bad ?)! station_to_keep = " 
00434                             << station_to_keep << " stations.size " << stations.size() << " all.size " << all.size();
00435 
00436   for (unsigned i = 0; i < stations.size(); ++i)
00437     if (stations[i] >= 0 && stations[i] <= station_to_keep) first.push_back(all[i]);
00438 
00439   return;
00440 }
00441 
00442 
00443 //
00444 // select muon hits compatible with trajectory; 
00445 // check hits in chambers with showers
00446 //
00447 GlobalMuonRefitter::ConstRecHitContainer 
00448 GlobalMuonRefitter::selectMuonHits(const Trajectory& traj, 
00449                                    const map<DetId, int> &hitMap) const {
00450 
00451   ConstRecHitContainer muonRecHits;
00452   const double globalChi2Cut = 200.0;
00453 
00454   vector<TrajectoryMeasurement> muonMeasurements = traj.measurements(); 
00455 
00456   // loop through all muon hits and skip hits with bad chi2 in chambers with high occupancy      
00457   for (std::vector<TrajectoryMeasurement>::const_iterator im = muonMeasurements.begin(); im != muonMeasurements.end(); im++ ) {
00458 
00459     if ( !(*im).recHit()->isValid() ) continue;
00460     if ( (*im).recHit()->det()->geographicalId().det() != DetId::Muon ) {
00461       //      if ( ( chi2ndf < globalChi2Cut ) )
00462       muonRecHits.push_back((*im).recHit());
00463       continue;
00464     }  
00465     ConstMuonRecHitPointer immrh = dynamic_cast<const MuonTransientTrackingRecHit*>((*im).recHit().get());
00466 
00467     DetId id = immrh->geographicalId();
00468     DetId chamberId;
00469     int threshold = 0;
00470     double chi2Cut = 0.0;
00471 
00472     // get station of hit if it is in DT
00473     if ( (*immrh).isDT() ) {
00474       DTChamberId did(id.rawId());
00475       chamberId = did;
00476       threshold = theHitThreshold;
00477       chi2Cut = theDTChi2Cut;
00478     }
00479     // get station of hit if it is in CSC
00480     else if ( (*immrh).isCSC() ) {
00481       CSCDetId did(id.rawId());
00482       chamberId = did.chamberId();
00483       threshold = theHitThreshold;
00484       chi2Cut = theCSCChi2Cut;
00485     }
00486     // get station of hit if it is in RPC
00487     else if ( (*immrh).isRPC() ) {
00488       RPCDetId rpcid(id.rawId());
00489       chamberId = rpcid;
00490       threshold = theHitThreshold;
00491       chi2Cut = theRPCChi2Cut;
00492     } else
00493       continue;
00494 
00495     double chi2ndf = (*im).estimate()/(*im).recHit()->dimension();  
00496 
00497     bool keep = true;
00498     map<DetId,int>::const_iterator imap=hitMap.find(chamberId);
00499     if ( imap!=hitMap.end() ) 
00500       if (imap->second>threshold) keep = false;
00501     
00502     if ( (keep || (chi2ndf<chi2Cut)) && (chi2ndf<globalChi2Cut) ) {
00503       muonRecHits.push_back((*im).recHit());
00504     } else {
00505       LogTrace(theCategory)
00506         << "Skip hit: " << id.rawId() << " chi2=" 
00507         << chi2ndf << " ( threshold: " << chi2Cut << ") Det: " 
00508         << imap->second << endl;
00509     }
00510   }
00511   
00512   // check order of rechits
00513   reverse(muonRecHits.begin(),muonRecHits.end());
00514   return muonRecHits;
00515 }
00516 
00517 
00518 //
00519 // print RecHits
00520 //
00521 void GlobalMuonRefitter::printHits(const ConstRecHitContainer& hits) const {
00522 
00523   LogTrace(theCategory) << "Used RecHits: " << hits.size();
00524   for (ConstRecHitContainer::const_iterator ir = hits.begin(); ir != hits.end(); ir++ ) {
00525     if ( !(*ir)->isValid() ) {
00526       LogTrace(theCategory) << "invalid RecHit";
00527       continue; 
00528     }
00529     
00530     const GlobalPoint& pos = (*ir)->globalPosition();
00531     
00532     LogTrace(theCategory) 
00533       << "r = " << sqrt(pos.x() * pos.x() + pos.y() * pos.y())
00534       << "  z = " << pos.z()
00535       << "  dimension = " << (*ir)->dimension()
00536       << "  det = " << (*ir)->det()->geographicalId().det()
00537       << "  subdet = " << (*ir)->det()->subDetector()
00538       << "  raw id = " << (*ir)->det()->geographicalId().rawId();
00539   }
00540 
00541 }
00542 
00543 
00544 //
00545 // add Trajectory* to TrackCand if not already present
00546 //
00547 GlobalMuonRefitter::RefitDirection
00548 GlobalMuonRefitter::checkRecHitsOrdering(const TransientTrackingRecHit::ConstRecHitContainer& recHits) const {
00549 
00550   if (!recHits.empty()){
00551     ConstRecHitContainer::const_iterator frontHit = recHits.begin();
00552     ConstRecHitContainer::const_iterator backHit  = recHits.end() - 1;
00553     while( !(*frontHit)->isValid() && frontHit != backHit) {frontHit++;}
00554     while( !(*backHit)->isValid() && backHit != frontHit)  {backHit--;}
00555 
00556     double rFirst = (*frontHit)->globalPosition().mag();
00557     double rLast  = (*backHit) ->globalPosition().mag();
00558 
00559     if(rFirst < rLast) return insideOut;
00560     else if(rFirst > rLast) return outsideIn;
00561     else {
00562       LogError(theCategory) << "Impossible determine the rechits order" <<endl;
00563       return undetermined;
00564     }
00565   } else {
00566     LogError(theCategory) << "Impossible determine the rechits order" <<endl;
00567     return undetermined;
00568   }
00569 }
00570 
00571 
00572 //
00573 // Convert Tracks into Trajectories with a given set of hits
00574 //
00575 vector<Trajectory> GlobalMuonRefitter::transform(const reco::Track& newTrack,
00576                                                  const reco::TransientTrack track,
00577                                                  TransientTrackingRecHit::ConstRecHitContainer recHitsForReFit) const {
00578 
00579   LogTrace(theCategory) << "GlobalMuonRefitter::transform: " << recHitsForReFit.size() << " hits:";
00580   printHits(recHitsForReFit);
00581 
00582   if(recHitsForReFit.size() < 2) return vector<Trajectory>();
00583 
00584   // Check the order of the rechits
00585   RefitDirection recHitsOrder = checkRecHitsOrdering(recHitsForReFit);
00586 
00587   LogTrace(theCategory) << "checkRecHitsOrdering() returned " << recHitsOrder
00588                         << ", theRefitDirection is " << theRefitDirection
00589                         << " (insideOut == " << insideOut << ", outsideIn == " << outsideIn << ")";
00590 
00591   // Reverse the order in the case of inconsistency between the fit direction and the rechit order
00592   if(theRefitDirection != recHitsOrder) reverse(recHitsForReFit.begin(),recHitsForReFit.end());
00593 
00594   // Even though we checked the rechits' ordering above, we may have
00595   // already flipped them elsewhere (getFirstHits() is such a
00596   // culprit). Use the global positions of the states and the desired
00597   // refit direction to find the starting TSOS.
00598   TrajectoryStateOnSurface firstTSOS, lastTSOS;
00599   unsigned int innerId; //UNUSED: outerId;
00600   bool order_swapped = track.outermostMeasurementState().globalPosition().mag() < track.innermostMeasurementState().globalPosition().mag();
00601   bool inner_is_first;
00602   LogTrace(theCategory) << "order swapped? " << order_swapped;
00603 
00604   // Fill the starting state, depending on the ordering above.
00605   if ((theRefitDirection == insideOut && !order_swapped) || (theRefitDirection == outsideIn && order_swapped)) {
00606     innerId   = newTrack.innerDetId();
00607     //UNUSED:    outerId   = newTrack.outerDetId();
00608     firstTSOS = track.innermostMeasurementState();
00609     lastTSOS  = track.outermostMeasurementState();
00610     inner_is_first = true;
00611   }
00612   else {
00613     innerId   = newTrack.outerDetId();
00614     //UNUSED:    outerId   = newTrack.innerDetId();
00615     firstTSOS = track.outermostMeasurementState();
00616     lastTSOS  = track.innermostMeasurementState();
00617     inner_is_first = false;
00618   } 
00619 
00620   LogTrace(theCategory) << "firstTSOS: inner_is_first? " << inner_is_first
00621                         << " globalPosition is " << firstTSOS.globalPosition()
00622                         << " innerId is " << innerId;
00623 
00624   if(!firstTSOS.isValid()){
00625     LogWarning(theCategory) << "Error wrong initial state!" << endl;
00626     return vector<Trajectory>();
00627   }
00628 
00629   firstTSOS.rescaleError(theRescaleErrorFactor);
00630 
00631   // This is the only way to get a TrajectorySeed with settable propagation direction
00632   PTrajectoryStateOnDet garbage1;
00633   edm::OwnVector<TrackingRecHit> garbage2;
00634   PropagationDirection propDir = 
00635     (firstTSOS.globalPosition().basicVector().dot(firstTSOS.globalMomentum().basicVector())>0) ? alongMomentum : oppositeToMomentum;
00636 
00637   // These lines cause the code to ignore completely what was set
00638   // above, and force propDir for tracks from collisions!
00639 //  if(propDir == alongMomentum && theRefitDirection == outsideIn)  propDir=oppositeToMomentum;
00640 //  if(propDir == oppositeToMomentum && theRefitDirection == insideOut) propDir=alongMomentum;
00641 
00642   const TrajectoryStateOnSurface& tsosForDir = inner_is_first ? lastTSOS : firstTSOS;
00643   propDir = (tsosForDir.globalPosition().basicVector().dot(tsosForDir.globalMomentum().basicVector())>0) ? alongMomentum : oppositeToMomentum;
00644   LogTrace(theCategory) << "propDir based on firstTSOS x dot p is " << propDir
00645                         << " (alongMomentum == " << alongMomentum << ", oppositeToMomentum == " << oppositeToMomentum << ")";
00646 
00647   // Additional propagation diretcion determination logic for cosmic muons
00648   if (theCosmicFlag) {
00649     PropagationDirection propDir_first = (firstTSOS.globalPosition().basicVector().dot(firstTSOS.globalMomentum().basicVector()) > 0) ? alongMomentum : oppositeToMomentum;
00650     PropagationDirection propDir_last  = (lastTSOS .globalPosition().basicVector().dot(lastTSOS .globalMomentum().basicVector()) > 0) ? alongMomentum : oppositeToMomentum;
00651     LogTrace(theCategory) << "propDir_first " << propDir_first << ", propdir_last " << propDir_last
00652                           << " : they " << (propDir_first == propDir_last ? "agree" : "disagree");
00653 
00654     int y_count = 0;
00655     for (TransientTrackingRecHit::ConstRecHitContainer::const_iterator it = recHitsForReFit.begin(); it != recHitsForReFit.end(); ++it) {
00656       if ((*it)->globalPosition().y() > 0) ++y_count;
00657       else --y_count;
00658     }
00659     
00660     PropagationDirection propDir_ycount = alongMomentum;
00661     if (y_count > 0) {
00662       if      (theRefitDirection == insideOut) propDir_ycount = oppositeToMomentum;
00663       else if (theRefitDirection == outsideIn) propDir_ycount = alongMomentum;
00664     }
00665     else {
00666       if      (theRefitDirection == insideOut) propDir_ycount = alongMomentum;
00667       else if (theRefitDirection == outsideIn) propDir_ycount = oppositeToMomentum;
00668     }
00669     
00670     LogTrace(theCategory) << "y_count = " << y_count
00671                           << "; based on geometrically-outermost TSOS, propDir is " << propDir << ": "
00672                           << (propDir == propDir_ycount ? "agrees" : "disagrees")
00673                           << " with ycount determination";
00674     
00675     if (propDir_first != propDir_last) {
00676       LogTrace(theCategory) << "since first/last disagreed, using y_count propDir";
00677       propDir = propDir_ycount;
00678     }
00679   }
00680 
00681   TrajectorySeed seed(garbage1,garbage2,propDir);
00682 
00683   if(recHitsForReFit.front()->geographicalId() != DetId(innerId)){
00684     LogDebug(theCategory)<<"Propagation occured"<<endl;
00685     LogTrace(theCategory) << "propagating firstTSOS at " << firstTSOS.globalPosition()
00686                           << " to first rechit with surface pos " << recHitsForReFit.front()->det()->surface().toGlobal(LocalPoint(0,0,0));
00687     firstTSOS = theService->propagator(thePropagatorName)->propagate(firstTSOS, recHitsForReFit.front()->det()->surface());
00688     if(!firstTSOS.isValid()){
00689       LogDebug(theCategory)<<"Propagation error!"<<endl;
00690       return vector<Trajectory>();
00691     }
00692   }
00693 
00694 /*  
00695   cout << " GlobalMuonRefitter : theFitter " << propDir << endl;
00696   cout << "                      First TSOS: " 
00697        << firstTSOS.globalPosition() << "  p="
00698        << firstTSOS.globalMomentum() << " = "
00699        << firstTSOS.globalMomentum().mag() << endl;
00700        
00701   cout << "                      Starting seed: "
00702        << " nHits= " << seed.nHits()
00703        << " tsos: "
00704        << seed.startingState().parameters().position() << "  p="
00705        << seed.startingState().parameters().momentum() << endl;
00706        
00707   cout << "                      RecHits: "
00708        << recHitsForReFit.size() << endl;
00709 */
00710        
00711   vector<Trajectory> trajectories = theFitter->fit(seed,recHitsForReFit,firstTSOS);
00712   
00713   if(trajectories.empty()){
00714     LogDebug(theCategory) << "No Track refitted!" << endl;
00715     return vector<Trajectory>();
00716   }
00717   
00718   return trajectories;
00719 }
00720 
00721 
00722 //
00723 // Remove Selected Station Rec Hits
00724 //
00725 GlobalMuonRefitter::ConstRecHitContainer GlobalMuonRefitter::getRidOfSelectStationHits(ConstRecHitContainer hits) const
00726 {
00727   ConstRecHitContainer results;
00728   ConstRecHitContainer::const_iterator it = hits.begin();
00729   for (; it!=hits.end(); it++) {
00730 
00731     DetId id = (*it)->geographicalId();
00732 
00733     //Check that this is a Muon hit that we're toying with -- else pass on this because the hacker is a moron / not careful
00734 
00735     if (id.det() == DetId::Tracker && theTrackerSkipSystem > 0) {
00736       int layer = -999;
00737       int disk  = -999;
00738       int wheel = -999;
00739       if ( id.subdetId() == theTrackerSkipSystem){
00740         //                              continue;  //caveat that just removes the whole system from refitting
00741 
00742         if (theTrackerSkipSystem == PXB) {
00743           PXBDetId did(id.rawId());
00744           layer = did.layer();
00745         }
00746         if (theTrackerSkipSystem == TIB) {
00747           TIBDetId did(id.rawId());
00748           layer = did.layer();
00749         }
00750 
00751         if (theTrackerSkipSystem == TOB) {
00752           TOBDetId did(id.rawId());
00753           layer = did.layer();
00754         }
00755         if (theTrackerSkipSystem == PXF) {
00756           PXFDetId did(id.rawId());
00757           disk = did.disk();
00758         }
00759         if (theTrackerSkipSystem == TID) {
00760           TIDDetId did(id.rawId());
00761           wheel = did.wheel();
00762         }
00763         if (theTrackerSkipSystem == TEC) {
00764           TECDetId did(id.rawId());
00765           wheel = did.wheel();
00766         }
00767         if (theTrackerSkipSection >= 0 && layer == theTrackerSkipSection) continue;
00768         if (theTrackerSkipSection >= 0 && disk == theTrackerSkipSection) continue;
00769         if (theTrackerSkipSection >= 0 && wheel == theTrackerSkipSection) continue;
00770       }
00771     }
00772 
00773     if (id.det() == DetId::Muon && theSkipStation) {
00774       int station = -999;
00775       //UNUSED:      int wheel = -999;
00776       if ( id.subdetId() == MuonSubdetId::DT ) {
00777         DTChamberId did(id.rawId());
00778         station = did.station();
00779         //UNUSED:       wheel = did.wheel();
00780       } else if ( id.subdetId() == MuonSubdetId::CSC ) {
00781         CSCDetId did(id.rawId());
00782         station = did.station();
00783       } else if ( id.subdetId() == MuonSubdetId::RPC ) {
00784         RPCDetId rpcid(id.rawId());
00785         station = rpcid.station();
00786       }
00787       if(station == theSkipStation) continue;
00788     }
00789     results.push_back(*it);
00790   }
00791   return results;
00792 }
00793