CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/src/RecoMuon/MuonIdentification/plugins/MuonsFromRefitTracksProducer.cc

Go to the documentation of this file.
00001 
00009 #include "FWCore/Framework/interface/Frameworkfwd.h"
00010 #include "FWCore/Framework/interface/EDProducer.h"
00011 #include "FWCore/Framework/interface/Event.h"
00012 #include "FWCore/Framework/interface/MakerMacros.h"
00013 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00014 
00015 #include "DataFormats/MuonReco/interface/Muon.h"
00016 #include "DataFormats/MuonReco/interface/MuonFwd.h"
00017 #include "DataFormats/MuonReco/interface/MuonCocktails.h"
00018 #include "DataFormats/TrackReco/interface/Track.h"
00019 #include "DataFormats/TrackReco/interface/TrackFwd.h"
00020 #include "DataFormats/TrackReco/interface/TrackToTrackMap.h"
00021 
00022 reco::TrackRef tevOptimizedTMR(const reco::Muon& muon, const reco::TrackToTrackMap& fmsMap,
00023                          const double cut) {
00024   const reco::TrackRef& combinedTrack = muon.globalTrack();
00025   const reco::TrackRef& trackerTrack  = muon.innerTrack();
00026 
00027   reco::TrackToTrackMap::const_iterator fmsTrack = fmsMap.find(combinedTrack);
00028 
00029   double probTK  = 0;
00030   double probFMS = 0;
00031 
00032   if (trackerTrack.isAvailable() && trackerTrack->numberOfValidHits())
00033     probTK = muon::trackProbability(trackerTrack);
00034   if (fmsTrack != fmsMap.end() && fmsTrack->val->numberOfValidHits())
00035     probFMS = muon::trackProbability(fmsTrack->val);
00036 
00037   bool TKok  = probTK > 0;
00038   bool FMSok = probFMS > 0;
00039 
00040   if (TKok && FMSok) {
00041     if (probFMS - probTK > cut)
00042       return trackerTrack;
00043     else
00044       return fmsTrack->val;
00045   }
00046   else if (FMSok)
00047     return fmsTrack->val;
00048   else if (TKok)
00049     return trackerTrack;
00050 
00051   return combinedTrack;
00052 }
00053 
00054 reco::TrackRef sigmaSwitch(const reco::Muon& muon, const double nSigma, const double ptThreshold) {
00055   const reco::TrackRef& combinedTrack = muon.globalTrack();
00056   const reco::TrackRef& trackerTrack  = muon.innerTrack();
00057 
00058   if (combinedTrack->pt() < ptThreshold || trackerTrack->pt() < ptThreshold)
00059     return trackerTrack;
00060 
00061   double delta = fabs(trackerTrack->qoverp() - combinedTrack->qoverp());
00062   double threshold = nSigma * trackerTrack->qoverpError();
00063 
00064   return delta > threshold ? trackerTrack : combinedTrack;
00065 }
00066 
00067 class MuonsFromRefitTracksProducer : public edm::EDProducer {
00068 public:
00069   explicit MuonsFromRefitTracksProducer(const edm::ParameterSet&);
00070   ~MuonsFromRefitTracksProducer() {}
00071 
00072 private:
00073   virtual void beginJob() {}
00074   virtual void produce(edm::Event&, const edm::EventSetup&);
00075   virtual void endJob() {}
00076 
00077   // Store the track-to-track map(s) used when using TeV refit tracks.
00078   bool storeMatchMaps(const edm::Event& event);
00079 
00080   // Take the muon passed in, clone it (so that we save all the muon
00081   // id information such as isolation, calo energy, etc.) and replace
00082   // its combined muon track with the passed in track.
00083   reco::Muon* cloneAndSwitchTrack(const reco::Muon& muon,
00084                             const reco::TrackRef& newTrack) const;
00085 
00086   // The input muons -- i.e. the merged collection of reco::Muons.
00087   edm::InputTag src;
00088 
00089   // Allow building the muon from just the tracker track. This
00090   // functionality should go away after understanding the difference
00091   // between the output of option 1 of GlobalMuonProducer and just
00092   // looking at the tracker tracks of these muons.
00093   bool fromTrackerTrack;
00094 
00095   // Allow building the muon from just the global track. This option
00096   // is introduced since starting from CMSSW 3_1_0, the MuonIdProducer
00097   // makes the p4() of the reco::Muon object be what we call the sigma
00098   // switch above.
00099   bool fromGlobalTrack;
00100 
00101   // If tevMuonTracks below is not "none", use the TeV refit track as
00102   // the combined track of the muon.
00103   bool fromTeVRefit;
00104 
00105   // Optionally switch out the combined muon track for one of the TeV
00106   // muon refit tracks, specified by the input tag here
00107   // (e.g. "tevMuons:firstHit").
00108   std::string tevMuonTracks;
00109 
00110   // Whether to make a cocktail muon instead of using just the one
00111   // type in tevMuonTracks, where "cocktail" means use the result of
00112   // Piotr's tevOptimized().
00113   bool fromCocktail;
00114 
00115   // Whether to use the TMR version of the cocktail function, defined
00116   // above. If true, overrides fromCocktail.
00117   bool fromTMR;
00118 
00119   // The cut value for TMR, read from the config file.
00120   double TMRcut;
00121 
00122   // Whether to use Adam Everett's sigma-switch method, choosing
00123   // between the global track and the tracker track.
00124   bool fromSigmaSwitch;
00125   
00126   // The number of sigma to switch on in the above method.
00127   double nSigmaSwitch;
00128   
00129   // The pT threshold to switch at in the above method.
00130   double ptThreshold;
00131 
00132   // If we're not making cocktail muons, trackMap is the map that maps
00133   // global tracks to the desired TeV refit (e.g. from globalMuons to
00134   // tevMuons:picky).
00135   edm::Handle<reco::TrackToTrackMap> trackMap;
00136 
00137   // All the track maps used in making cocktail muons.
00138   edm::Handle<reco::TrackToTrackMap> trackMapDefault;
00139   edm::Handle<reco::TrackToTrackMap> trackMapFirstHit;
00140   edm::Handle<reco::TrackToTrackMap> trackMapPicky;
00141 };
00142 
00143 MuonsFromRefitTracksProducer::MuonsFromRefitTracksProducer(const edm::ParameterSet& cfg)
00144   : src(cfg.getParameter<edm::InputTag>("src")),
00145     fromTrackerTrack(cfg.getParameter<bool>("fromTrackerTrack")),
00146     fromGlobalTrack(cfg.getParameter<bool>("fromGlobalTrack")),
00147     tevMuonTracks(cfg.getParameter<std::string>("tevMuonTracks")),
00148     fromCocktail(cfg.getParameter<bool>("fromCocktail")),
00149     fromTMR(cfg.getParameter<bool>("fromTMR")),
00150     TMRcut(cfg.getParameter<double>("TMRcut")),
00151     fromSigmaSwitch(cfg.getParameter<bool>("fromSigmaSwitch")),
00152     nSigmaSwitch(cfg.getParameter<double>("nSigmaSwitch")),
00153     ptThreshold(cfg.getParameter<double>("ptThreshold"))
00154 {
00155   fromTeVRefit = tevMuonTracks != "none";
00156   produces<reco::MuonCollection>();
00157 }
00158 
00159 bool MuonsFromRefitTracksProducer::storeMatchMaps(const edm::Event& event) {
00160   if (fromCocktail || fromTMR) {
00161     event.getByLabel(tevMuonTracks, "default",  trackMapDefault);
00162     event.getByLabel(tevMuonTracks, "firstHit", trackMapFirstHit);
00163     event.getByLabel(tevMuonTracks, "picky",    trackMapPicky);
00164     return !trackMapDefault.failedToGet() && 
00165       !trackMapFirstHit.failedToGet() && !trackMapPicky.failedToGet();
00166   }
00167   else {
00168     event.getByLabel(edm::InputTag(tevMuonTracks), trackMap);
00169     return !trackMap.failedToGet();
00170   }
00171 }
00172 
00173 reco::Muon* MuonsFromRefitTracksProducer::cloneAndSwitchTrack(const reco::Muon& muon,
00174                                                         const reco::TrackRef& newTrack) const {
00175   // Muon mass to make a four-vector out of the new track.
00176   static const double muMass = 0.10566;
00177 
00178   reco::TrackRef tkTrack  = muon.innerTrack();
00179   reco::TrackRef muTrack  = muon.outerTrack();
00180           
00181   // Make up a real Muon from the tracker track.
00182   reco::Particle::Point vtx(newTrack->vx(), newTrack->vy(), newTrack->vz());
00183   reco::Particle::LorentzVector p4;
00184   double p = newTrack->p();
00185   p4.SetXYZT(newTrack->px(), newTrack->py(), newTrack->pz(),
00186              sqrt(p*p + muMass*muMass));
00187 
00188   reco::Muon* mu = muon.clone();
00189   mu->setCharge(newTrack->charge());
00190   mu->setP4(p4);
00191   mu->setVertex(vtx);
00192   mu->setGlobalTrack(newTrack);
00193   mu->setInnerTrack(tkTrack);
00194   mu->setOuterTrack(muTrack);
00195   return mu;
00196 }
00197 
00198 void MuonsFromRefitTracksProducer::produce(edm::Event& event, const edm::EventSetup& eSetup) {
00199   // Get the global muons from the event.
00200   edm::Handle<edm::View<reco::Muon> > muons;
00201   event.getByLabel(src, muons);
00202 
00203   // If we can't get the global muon collection, or below the
00204   // track-to-track maps needed, still produce an empty collection of
00205   // muons so consumers don't throw an exception.
00206   bool ok = !muons.failedToGet();
00207 
00208   // If we're instructed to use the TeV refit tracks in some way, we
00209   // need the track-to-track maps. If we're making a cocktail muon,
00210   // get all three track maps (the cocktail ingredients); else just
00211   // get the map which takes the above global tracks to the desired
00212   // TeV-muon refitted tracks (firstHit or picky).
00213   if (ok && fromTeVRefit)
00214     ok = storeMatchMaps(event);
00215 
00216   // Make the output collection.
00217   std::auto_ptr<reco::MuonCollection> cands(new reco::MuonCollection);
00218 
00219   if (ok) {
00220     edm::View<reco::Muon>::const_iterator muon;
00221     for (muon = muons->begin(); muon != muons->end(); muon++) {
00222       // Filter out the so-called trackerMuons and stand-alone muons
00223       // (and caloMuons, if they were ever to get into the input muons
00224       // collection).
00225       if (!muon->isGlobalMuon()) continue;
00226 
00227       if (fromTeVRefit || fromSigmaSwitch) {
00228         // Start out with a null TrackRef.
00229     reco::TrackRef tevTk;
00230       
00231         // If making a cocktail muon, use tevOptimized() to get the track
00232         // desired. Otherwise, get the refit track from the desired track
00233         // map.
00234         if (fromTMR)
00235           tevTk = tevOptimizedTMR(*muon, *trackMapFirstHit, TMRcut);
00236         else if (fromCocktail)
00237           tevTk = muon::tevOptimized(*muon, *trackMapDefault, *trackMapFirstHit,
00238                                      *trackMapPicky);
00239         else if (fromSigmaSwitch)
00240           tevTk = sigmaSwitch(*muon, nSigmaSwitch, ptThreshold);
00241         else {
00242         reco::TrackToTrackMap::const_iterator tevTkRef =
00243             trackMap->find(muon->combinedMuon());
00244           if (tevTkRef != trackMap->end())
00245             tevTk = tevTkRef->val;
00246         }
00247         
00248         // If the TrackRef is valid, make a new Muon that has the same
00249         // tracker and stand-alone tracks, but has the refit track as
00250         // its global track.
00251         if (tevTk.isNonnull())
00252           cands->push_back(*cloneAndSwitchTrack(*muon, tevTk));
00253       }
00254       else if (fromTrackerTrack)
00255         cands->push_back(*cloneAndSwitchTrack(*muon, muon->innerTrack()));
00256       else if (fromGlobalTrack)
00257         cands->push_back(*cloneAndSwitchTrack(*muon, muon->globalTrack()));
00258       else {
00259         cands->push_back(*muon->clone());
00260 
00261         // Just cloning does not work in the case of the source being
00262         // a pat::Muon with embedded track references -- these do not
00263         // get copied. Explicitly set them.
00264     reco::Muon& last = cands->at(cands->size()-1);
00265         if (muon->globalTrack().isTransient())
00266           last.setGlobalTrack(muon->globalTrack());
00267         if (muon->innerTrack().isTransient())
00268           last.setInnerTrack(muon->innerTrack());
00269         if (muon->outerTrack().isTransient())
00270           last.setOuterTrack(muon->outerTrack());
00271       }
00272     }
00273   }
00274   else
00275     edm::LogWarning("MuonsFromRefitTracksProducer")
00276       << "either " << src << " or the track map(s) " << tevMuonTracks
00277       << " not present in the event; producing empty collection";
00278   
00279   event.put(cands);
00280 }
00281 
00282 DEFINE_FWK_MODULE(MuonsFromRefitTracksProducer);