CMS 3D CMS Logo

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