Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:27:01

0001 /**
0002   \class    MuonsFromRefitTracks "RecoMuon/MuonIdentification/plugins/MuonsFromRefitTracks.cc"
0003   \brief    Replaces the kinematic information in the input muons with those of the chosen refit tracks.
0004 
0005   \author   Jordan Tucker
0006 */
0007 
0008 #include "FWCore/Framework/interface/Frameworkfwd.h"
0009 #include "FWCore/Framework/interface/stream/EDProducer.h"
0010 #include "FWCore/Framework/interface/Event.h"
0011 #include "FWCore/Framework/interface/MakerMacros.h"
0012 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0013 
0014 #include "DataFormats/MuonReco/interface/Muon.h"
0015 #include "DataFormats/MuonReco/interface/MuonFwd.h"
0016 #include "DataFormats/MuonReco/interface/MuonCocktails.h"
0017 #include "DataFormats/TrackReco/interface/Track.h"
0018 #include "DataFormats/TrackReco/interface/TrackFwd.h"
0019 #include "DataFormats/TrackReco/interface/TrackToTrackMap.h"
0020 
0021 reco::Muon::MuonTrackTypePair tevOptimizedTMR(const reco::Muon& muon,
0022                                               const reco::TrackToTrackMap& fmsMap,
0023                                               const double cut) {
0024   const reco::TrackRef& combinedTrack = muon.globalTrack();
0025   const reco::TrackRef& trackerTrack = muon.innerTrack();
0026 
0027   reco::TrackToTrackMap::const_iterator fmsTrack = fmsMap.find(combinedTrack);
0028 
0029   double probTK = 0;
0030   double probFMS = 0;
0031 
0032   if (trackerTrack.isAvailable() && trackerTrack->numberOfValidHits())
0033     probTK = muon::trackProbability(trackerTrack);
0034   if (fmsTrack != fmsMap.end() && fmsTrack->val->numberOfValidHits())
0035     probFMS = muon::trackProbability(fmsTrack->val);
0036 
0037   bool TKok = probTK > 0;
0038   bool FMSok = probFMS > 0;
0039 
0040   if (TKok && FMSok) {
0041     if (probFMS - probTK > cut)
0042       return make_pair(trackerTrack, reco::Muon::InnerTrack);
0043     else
0044       return make_pair(fmsTrack->val, reco::Muon::TPFMS);
0045   } else if (FMSok)
0046     return make_pair(fmsTrack->val, reco::Muon::TPFMS);
0047   else if (TKok)
0048     return make_pair(trackerTrack, reco::Muon::InnerTrack);
0049 
0050   return make_pair(combinedTrack, reco::Muon::CombinedTrack);
0051 }
0052 
0053 reco::Muon::MuonTrackTypePair sigmaSwitch(const reco::Muon& muon, const double nSigma, const double ptThreshold) {
0054   const reco::TrackRef& combinedTrack = muon.globalTrack();
0055   const reco::TrackRef& trackerTrack = muon.innerTrack();
0056 
0057   if (combinedTrack->pt() < ptThreshold || trackerTrack->pt() < ptThreshold)
0058     return make_pair(trackerTrack, reco::Muon::InnerTrack);
0059 
0060   double delta = fabs(trackerTrack->qoverp() - combinedTrack->qoverp());
0061   double threshold = nSigma * trackerTrack->qoverpError();
0062 
0063   return delta > threshold ? make_pair(trackerTrack, reco::Muon::InnerTrack)
0064                            : make_pair(combinedTrack, reco::Muon::CombinedTrack);
0065 }
0066 
0067 class MuonsFromRefitTracksProducer : public edm::stream::EDProducer<> {
0068 public:
0069   explicit MuonsFromRefitTracksProducer(const edm::ParameterSet&);
0070   ~MuonsFromRefitTracksProducer() override {}
0071 
0072 private:
0073   void produce(edm::Event&, const edm::EventSetup&) override;
0074 
0075   // Store the track-to-track map(s) used when using TeV refit tracks.
0076   bool storeMatchMaps(const edm::Event& event);
0077 
0078   // Take the muon passed in, clone it (so that we save all the muon
0079   // id information such as isolation, calo energy, etc.) and replace
0080   // its combined muon track with the passed in track.
0081   reco::Muon* cloneAndSwitchTrack(const reco::Muon& muon, const reco::Muon::MuonTrackTypePair& newTrack) const;
0082 
0083   // The input muons -- i.e. the merged collection of reco::Muons.
0084   edm::InputTag src;
0085 
0086   // Allow building the muon from just the tracker track. This
0087   // functionality should go away after understanding the difference
0088   // between the output of option 1 of GlobalMuonProducer and just
0089   // looking at the tracker tracks of these muons.
0090   bool fromTrackerTrack;
0091 
0092   // Allow building the muon from just the global track. This option
0093   // is introduced since starting from CMSSW 3_1_0, the MuonIdProducer
0094   // makes the p4() of the reco::Muon object be what we call the sigma
0095   // switch above.
0096   bool fromGlobalTrack;
0097 
0098   // If tevMuonTracks below is not "none", use the TeV refit track as
0099   // the combined track of the muon.
0100   bool fromTeVRefit;
0101 
0102   // Optionally switch out the combined muon track for one of the TeV
0103   // muon refit tracks, specified by the input tag here
0104   // (e.g. "tevMuons:firstHit").
0105   std::string tevMuonTracks;
0106 
0107   // Whether to make a cocktail muon instead of using just the one
0108   // type in tevMuonTracks, where "cocktail" means use the result of
0109   // Piotr's tevOptimized().
0110   bool fromCocktail;
0111 
0112   // Whether to use the TMR version of the cocktail function, defined
0113   // above. If true, overrides fromCocktail.
0114   bool fromTMR;
0115 
0116   // The cut value for TMR, read from the config file.
0117   double TMRcut;
0118 
0119   // Whether to use Adam Everett's sigma-switch method, choosing
0120   // between the global track and the tracker track.
0121   bool fromSigmaSwitch;
0122 
0123   // The number of sigma to switch on in the above method.
0124   double nSigmaSwitch;
0125 
0126   // The pT threshold to switch at in the above method.
0127   double ptThreshold;
0128 
0129   // If we're not making cocktail muons, trackMap is the map that maps
0130   // global tracks to the desired TeV refit (e.g. from globalMuons to
0131   // tevMuons:picky).
0132   edm::Handle<reco::TrackToTrackMap> trackMap;
0133 
0134   // All the track maps used in making cocktail muons.
0135   edm::Handle<reco::TrackToTrackMap> trackMapDefault;
0136   edm::Handle<reco::TrackToTrackMap> trackMapFirstHit;
0137   edm::Handle<reco::TrackToTrackMap> trackMapPicky;
0138 
0139   // All the tokens
0140   edm::EDGetTokenT<edm::View<reco::Muon> > srcToken_;
0141   edm::EDGetTokenT<reco::TrackToTrackMap> trackMapToken_;
0142   edm::EDGetTokenT<reco::TrackToTrackMap> trackMapDefaultToken_;
0143   edm::EDGetTokenT<reco::TrackToTrackMap> trackMapFirstHitToken_;
0144   edm::EDGetTokenT<reco::TrackToTrackMap> trackMapPickyToken_;
0145 };
0146 
0147 MuonsFromRefitTracksProducer::MuonsFromRefitTracksProducer(const edm::ParameterSet& cfg)
0148     : src(cfg.getParameter<edm::InputTag>("src")),
0149       fromTrackerTrack(cfg.getParameter<bool>("fromTrackerTrack")),
0150       fromGlobalTrack(cfg.getParameter<bool>("fromGlobalTrack")),
0151       tevMuonTracks(cfg.getParameter<std::string>("tevMuonTracks")),
0152       fromCocktail(cfg.getParameter<bool>("fromCocktail")),
0153       fromTMR(cfg.getParameter<bool>("fromTMR")),
0154       TMRcut(cfg.getParameter<double>("TMRcut")),
0155       fromSigmaSwitch(cfg.getParameter<bool>("fromSigmaSwitch")),
0156       nSigmaSwitch(cfg.getParameter<double>("nSigmaSwitch")),
0157       ptThreshold(cfg.getParameter<double>("ptThreshold")) {
0158   fromTeVRefit = tevMuonTracks != "none";
0159 
0160   srcToken_ = consumes<edm::View<reco::Muon> >(src);
0161   trackMapToken_ = consumes<reco::TrackToTrackMap>(edm::InputTag(tevMuonTracks, "default"));
0162   trackMapDefaultToken_ = consumes<reco::TrackToTrackMap>(edm::InputTag(tevMuonTracks));
0163   trackMapFirstHitToken_ = consumes<reco::TrackToTrackMap>(edm::InputTag(tevMuonTracks, "firstHit"));
0164   trackMapPickyToken_ = consumes<reco::TrackToTrackMap>(edm::InputTag(tevMuonTracks, "picky"));
0165 
0166   produces<reco::MuonCollection>();
0167 }
0168 
0169 bool MuonsFromRefitTracksProducer::storeMatchMaps(const edm::Event& event) {
0170   if (fromCocktail || fromTMR) {
0171     event.getByToken(trackMapDefaultToken_, trackMapDefault);
0172     event.getByToken(trackMapFirstHitToken_, trackMapFirstHit);
0173     event.getByToken(trackMapPickyToken_, trackMapPicky);
0174     return !trackMapDefault.failedToGet() && !trackMapFirstHit.failedToGet() && !trackMapPicky.failedToGet();
0175   } else {
0176     event.getByToken(trackMapToken_, trackMap);
0177     return !trackMap.failedToGet();
0178   }
0179 }
0180 
0181 reco::Muon* MuonsFromRefitTracksProducer::cloneAndSwitchTrack(const reco::Muon& muon,
0182                                                               const reco::Muon::MuonTrackTypePair& newTrack) const {
0183   // Muon mass to make a four-vector out of the new track.
0184   static const double muMass = 0.10566;
0185 
0186   reco::TrackRef tkTrack = muon.innerTrack();
0187   reco::TrackRef muTrack = muon.outerTrack();
0188 
0189   // Make up a real Muon from the tracker track.
0190   reco::Particle::Point vtx(newTrack.first->vx(), newTrack.first->vy(), newTrack.first->vz());
0191   reco::Particle::LorentzVector p4;
0192   double p = newTrack.first->p();
0193   p4.SetXYZT(newTrack.first->px(), newTrack.first->py(), newTrack.first->pz(), sqrt(p * p + muMass * muMass));
0194 
0195   reco::Muon* mu = muon.clone();
0196   mu->setCharge(newTrack.first->charge());
0197   mu->setP4(p4);
0198   mu->setVertex(vtx);
0199   mu->setGlobalTrack(newTrack.first);
0200   mu->setInnerTrack(tkTrack);
0201   mu->setOuterTrack(muTrack);
0202   mu->setBestTrack(newTrack.second);
0203   return mu;
0204 }
0205 
0206 void MuonsFromRefitTracksProducer::produce(edm::Event& event, const edm::EventSetup& eSetup) {
0207   // Get the global muons from the event.
0208   edm::Handle<edm::View<reco::Muon> > muons;
0209   event.getByToken(srcToken_, muons);
0210 
0211   // If we can't get the global muon collection, or below the
0212   // track-to-track maps needed, still produce an empty collection of
0213   // muons so consumers don't throw an exception.
0214   bool ok = !muons.failedToGet();
0215 
0216   // If we're instructed to use the TeV refit tracks in some way, we
0217   // need the track-to-track maps. If we're making a cocktail muon,
0218   // get all three track maps (the cocktail ingredients); else just
0219   // get the map which takes the above global tracks to the desired
0220   // TeV-muon refitted tracks (firstHit or picky).
0221   if (ok && fromTeVRefit)
0222     ok = storeMatchMaps(event);
0223 
0224   // Make the output collection.
0225   auto cands = std::make_unique<reco::MuonCollection>();
0226 
0227   if (ok) {
0228     edm::View<reco::Muon>::const_iterator muon;
0229     for (muon = muons->begin(); muon != muons->end(); muon++) {
0230       // Filter out the so-called trackerMuons and stand-alone muons
0231       // (and caloMuons, if they were ever to get into the input muons
0232       // collection).
0233       if (!muon->isGlobalMuon())
0234         continue;
0235 
0236       if (fromTeVRefit || fromSigmaSwitch) {
0237         // Start out with a null TrackRef.
0238         reco::Muon::MuonTrackTypePair tevTk;
0239 
0240         // If making a cocktail muon, use tevOptimized() to get the track
0241         // desired. Otherwise, get the refit track from the desired track
0242         // map.
0243         if (fromTMR)
0244           tevTk = tevOptimizedTMR(*muon, *trackMapFirstHit, TMRcut);
0245         else if (fromCocktail)
0246           tevTk = muon::tevOptimized(*muon);
0247         else if (fromSigmaSwitch)
0248           tevTk = sigmaSwitch(*muon, nSigmaSwitch, ptThreshold);
0249         else {
0250           reco::TrackToTrackMap::const_iterator tevTkRef = trackMap->find(muon->combinedMuon());
0251           if (tevTkRef != trackMap->end())
0252             tevTk = make_pair(tevTkRef->val, reco::Muon::CombinedTrack);
0253         }
0254 
0255         // If the TrackRef is valid, make a new Muon that has the same
0256         // tracker and stand-alone tracks, but has the refit track as
0257         // its global track.
0258         if (tevTk.first.isNonnull())
0259           cands->push_back(*cloneAndSwitchTrack(*muon, tevTk));
0260       } else if (fromTrackerTrack)
0261         cands->push_back(*cloneAndSwitchTrack(*muon, make_pair(muon->innerTrack(), reco::Muon::InnerTrack)));
0262       else if (fromGlobalTrack)
0263         cands->push_back(*cloneAndSwitchTrack(*muon, make_pair(muon->globalTrack(), reco::Muon::CombinedTrack)));
0264       else {
0265         cands->push_back(*muon->clone());
0266 
0267         // Just cloning does not work in the case of the source being
0268         // a pat::Muon with embedded track references -- these do not
0269         // get copied. Explicitly set them.
0270         reco::Muon& last = cands->at(cands->size() - 1);
0271         if (muon->globalTrack().isTransient())
0272           last.setGlobalTrack(muon->globalTrack());
0273         if (muon->innerTrack().isTransient())
0274           last.setInnerTrack(muon->innerTrack());
0275         if (muon->outerTrack().isTransient())
0276           last.setOuterTrack(muon->outerTrack());
0277       }
0278     }
0279   } else
0280     edm::LogWarning("MuonsFromRefitTracksProducer") << "either " << src << " or the track map(s) " << tevMuonTracks
0281                                                     << " not present in the event; producing empty collection";
0282 
0283   event.put(std::move(cands));
0284 }
0285 
0286 DEFINE_FWK_MODULE(MuonsFromRefitTracksProducer);