CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/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::Muon::MuonTrackTypePair 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 make_pair(trackerTrack,reco::Muon::InnerTrack);
00043     else
00044       return make_pair(fmsTrack->val,reco::Muon::TPFMS);
00045   }
00046   else if (FMSok)
00047     return make_pair(fmsTrack->val,reco::Muon::TPFMS);
00048   else if (TKok)
00049     return make_pair(trackerTrack,reco::Muon::InnerTrack);
00050 
00051   return make_pair(combinedTrack,reco::Muon::CombinedTrack);
00052 }
00053 
00054  reco::Muon::MuonTrackTypePair 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 make_pair(trackerTrack,reco::Muon::InnerTrack);
00060 
00061   double delta = fabs(trackerTrack->qoverp() - combinedTrack->qoverp());
00062   double threshold = nSigma * trackerTrack->qoverpError();
00063 
00064   return delta > threshold ? make_pair(trackerTrack,reco::Muon::InnerTrack) : make_pair(combinedTrack,reco::Muon::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::Muon::MuonTrackTypePair& 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::Muon::MuonTrackTypePair& 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.first->vx(), newTrack.first->vy(), newTrack.first->vz());
00183   reco::Particle::LorentzVector p4;
00184   double p = newTrack.first->p();
00185   p4.SetXYZT(newTrack.first->px(), newTrack.first->py(), newTrack.first->pz(),
00186              sqrt(p*p + muMass*muMass));
00187 
00188   reco::Muon* mu = muon.clone();
00189   mu->setCharge(newTrack.first->charge());
00190   mu->setP4(p4);
00191   mu->setVertex(vtx);
00192   mu->setGlobalTrack(newTrack.first);
00193   mu->setInnerTrack(tkTrack);
00194   mu->setOuterTrack(muTrack);
00195   mu->setBestTrack(newTrack.second);
00196   return mu;
00197 }
00198 
00199 void MuonsFromRefitTracksProducer::produce(edm::Event& event, const edm::EventSetup& eSetup) {
00200   // Get the global muons from the event.
00201   edm::Handle<edm::View<reco::Muon> > muons;
00202   event.getByLabel(src, muons);
00203 
00204   // If we can't get the global muon collection, or below the
00205   // track-to-track maps needed, still produce an empty collection of
00206   // muons so consumers don't throw an exception.
00207   bool ok = !muons.failedToGet();
00208 
00209   // If we're instructed to use the TeV refit tracks in some way, we
00210   // need the track-to-track maps. If we're making a cocktail muon,
00211   // get all three track maps (the cocktail ingredients); else just
00212   // get the map which takes the above global tracks to the desired
00213   // TeV-muon refitted tracks (firstHit or picky).
00214   if (ok && fromTeVRefit)
00215     ok = storeMatchMaps(event);
00216 
00217   // Make the output collection.
00218   std::auto_ptr<reco::MuonCollection> cands(new reco::MuonCollection);
00219 
00220   if (ok) {
00221     edm::View<reco::Muon>::const_iterator muon;
00222     for (muon = muons->begin(); muon != muons->end(); muon++) {
00223       // Filter out the so-called trackerMuons and stand-alone muons
00224       // (and caloMuons, if they were ever to get into the input muons
00225       // collection).
00226       if (!muon->isGlobalMuon()) continue;
00227 
00228       if (fromTeVRefit || fromSigmaSwitch) {
00229         // Start out with a null TrackRef.
00230         reco::Muon::MuonTrackTypePair tevTk;
00231       
00232         // If making a cocktail muon, use tevOptimized() to get the track
00233         // desired. Otherwise, get the refit track from the desired track
00234         // map.
00235         if (fromTMR)
00236           tevTk = tevOptimizedTMR(*muon, *trackMapFirstHit, TMRcut);
00237         else if (fromCocktail)
00238           tevTk = muon::tevOptimized(*muon, *trackMapDefault, *trackMapFirstHit,
00239                                      *trackMapPicky);
00240         else if (fromSigmaSwitch)
00241           tevTk = sigmaSwitch(*muon, nSigmaSwitch, ptThreshold);
00242         else {
00243         reco::TrackToTrackMap::const_iterator tevTkRef =
00244             trackMap->find(muon->combinedMuon());
00245           if (tevTkRef != trackMap->end())
00246             tevTk = make_pair(tevTkRef->val,reco::Muon::CombinedTrack);
00247         }
00248         
00249         // If the TrackRef is valid, make a new Muon that has the same
00250         // tracker and stand-alone tracks, but has the refit track as
00251         // its global track.
00252         if (tevTk.first.isNonnull())
00253           cands->push_back(*cloneAndSwitchTrack(*muon, tevTk));
00254       }
00255       else if (fromTrackerTrack)
00256         cands->push_back(*cloneAndSwitchTrack(*muon, make_pair(muon->innerTrack(),reco::Muon::InnerTrack)));
00257       else if (fromGlobalTrack)
00258         cands->push_back(*cloneAndSwitchTrack(*muon, make_pair(muon->globalTrack(),reco::Muon::CombinedTrack)));
00259       else {
00260         cands->push_back(*muon->clone());
00261 
00262         // Just cloning does not work in the case of the source being
00263         // a pat::Muon with embedded track references -- these do not
00264         // get copied. Explicitly set them.
00265     reco::Muon& last = cands->at(cands->size()-1);
00266         if (muon->globalTrack().isTransient())
00267           last.setGlobalTrack(muon->globalTrack());
00268         if (muon->innerTrack().isTransient())
00269           last.setInnerTrack(muon->innerTrack());
00270         if (muon->outerTrack().isTransient())
00271           last.setOuterTrack(muon->outerTrack());
00272       }
00273     }
00274   }
00275   else
00276     edm::LogWarning("MuonsFromRefitTracksProducer")
00277       << "either " << src << " or the track map(s) " << tevMuonTracks
00278       << " not present in the event; producing empty collection";
00279   
00280   event.put(cands);
00281 }
00282 
00283 DEFINE_FWK_MODULE(MuonsFromRefitTracksProducer);