CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/RecoMuon/MuonIdentification/plugins/MuonIdProducer.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:    MuonIdentification
00004 // Class:      MuonIdProducer
00005 // 
00006 //
00007 // Original Author:  Dmytro Kovalskyi
00008 // $Id: MuonIdProducer.cc,v 1.74 2013/02/25 21:29:14 chrjones Exp $
00009 //
00010 //
00011 
00012 
00013 // system include files
00014 #include <memory>
00015 
00016 // user include files
00017 #include "FWCore/Framework/interface/Frameworkfwd.h"
00018 #include "FWCore/Framework/interface/EDProducer.h"
00019 
00020 #include "FWCore/Framework/interface/Event.h"
00021 #include "FWCore/Framework/interface/EventSetup.h"
00022 
00023 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00024 
00025 #include "DataFormats/Common/interface/Handle.h"
00026 #include "DataFormats/TrackReco/interface/Track.h"
00027 #include "DataFormats/MuonReco/interface/Muon.h"
00028 #include "DataFormats/MuonReco/interface/CaloMuon.h"
00029 #include "DataFormats/MuonReco/interface/MuonCocktails.h"
00030 #include "DataFormats/MuonReco/interface/MuonTime.h"
00031 #include "DataFormats/MuonReco/interface/MuonTimeExtra.h"
00032 #include "DataFormats/MuonReco/interface/MuonTimeExtraMap.h"
00033 #include "DataFormats/RecoCandidate/interface/IsoDeposit.h"
00034 #include "DataFormats/RecoCandidate/interface/IsoDepositFwd.h"
00035 
00036 #include "TrackingTools/TrackAssociator/interface/TrackDetectorAssociator.h"
00037 #include "Utilities/Timing/interface/TimerStack.h"
00038 
00039 #include <boost/regex.hpp>
00040 #include "RecoMuon/MuonIdentification/plugins/MuonIdProducer.h"
00041 #include "RecoMuon/MuonIdentification/interface/MuonIdTruthInfo.h"
00042 #include "RecoMuon/MuonIdentification/interface/MuonArbitrationMethods.h"
00043 #include "RecoMuon/MuonIdentification/interface/MuonMesh.h"
00044 
00045 #include "PhysicsTools/IsolationAlgos/interface/IsoDepositExtractorFactory.h"
00046 #include "TrackingTools/Records/interface/TrackingComponentsRecord.h"
00047 
00048 #include <algorithm>
00049 
00050 #include "DataFormats/MuonDetId/interface/MuonSubdetId.h"
00051 #include "DataFormats/MuonDetId/interface/DTChamberId.h"
00052 #include "DataFormats/MuonDetId/interface/CSCDetId.h"
00053 #include "DataFormats/MuonDetId/interface/RPCDetId.h"
00054 
00055 // RPC-Muon stuffs
00056 #include "DataFormats/RPCRecHit/interface/RPCRecHit.h"
00057 #include "DataFormats/RPCRecHit/interface/RPCRecHitCollection.h"
00058 #include "DataFormats/MuonReco/interface/MuonRPCHitMatch.h"
00059 
00060 #include "DataFormats/Common/interface/ValueMap.h"
00061 
00062 #include "RecoMuon/MuonIdentification/interface/MuonKinkFinder.h"
00063 
00064 MuonIdProducer::MuonIdProducer(const edm::ParameterSet& iConfig):
00065 muIsoExtractorCalo_(0),muIsoExtractorTrack_(0),muIsoExtractorJet_(0)
00066 {
00067    produces<reco::MuonCollection>();
00068    produces<reco::CaloMuonCollection>();
00069    produces<reco::MuonTimeExtraMap>("combined");
00070    produces<reco::MuonTimeExtraMap>("dt");
00071    produces<reco::MuonTimeExtraMap>("csc");
00072    
00073    minPt_                   = iConfig.getParameter<double>("minPt");
00074    minP_                    = iConfig.getParameter<double>("minP");
00075    minPCaloMuon_            = iConfig.getParameter<double>("minPCaloMuon");
00076    minNumberOfMatches_      = iConfig.getParameter<int>("minNumberOfMatches");
00077    addExtraSoftMuons_       = iConfig.getParameter<bool>("addExtraSoftMuons");
00078    maxAbsEta_               = iConfig.getParameter<double>("maxAbsEta");
00079    maxAbsDx_                = iConfig.getParameter<double>("maxAbsDx");
00080    maxAbsPullX_             = iConfig.getParameter<double>("maxAbsPullX");
00081    maxAbsDy_                = iConfig.getParameter<double>("maxAbsDy");
00082    maxAbsPullY_             = iConfig.getParameter<double>("maxAbsPullY");
00083    fillCaloCompatibility_   = iConfig.getParameter<bool>("fillCaloCompatibility");
00084    fillEnergy_              = iConfig.getParameter<bool>("fillEnergy");
00085    fillMatching_            = iConfig.getParameter<bool>("fillMatching");
00086    fillIsolation_           = iConfig.getParameter<bool>("fillIsolation");
00087    writeIsoDeposits_        = iConfig.getParameter<bool>("writeIsoDeposits");
00088    fillGlobalTrackQuality_  = iConfig.getParameter<bool>("fillGlobalTrackQuality");
00089    fillGlobalTrackRefits_   = iConfig.getParameter<bool>("fillGlobalTrackRefits");
00090    //SK: (maybe temporary) run it only if the global is also run
00091    fillTrackerKink_         = false;
00092    if (fillGlobalTrackQuality_)  fillTrackerKink_ =  iConfig.getParameter<bool>("fillTrackerKink");
00093 
00094    ptThresholdToFillCandidateP4WithGlobalFit_    = iConfig.getParameter<double>("ptThresholdToFillCandidateP4WithGlobalFit");
00095    sigmaThresholdToFillCandidateP4WithGlobalFit_ = iConfig.getParameter<double>("sigmaThresholdToFillCandidateP4WithGlobalFit");
00096    caloCut_ = iConfig.getParameter<double>("minCaloCompatibility"); //CaloMuons
00097    arbClean_ = iConfig.getParameter<bool>("runArbitrationCleaner"); // muon mesh 
00098    
00099    // Load TrackDetectorAssociator parameters
00100    edm::ParameterSet parameters = iConfig.getParameter<edm::ParameterSet>("TrackAssociatorParameters");
00101    parameters_.loadParameters( parameters );
00102 
00103    // Load parameters for the TimingFiller
00104    edm::ParameterSet timingParameters = iConfig.getParameter<edm::ParameterSet>("TimingFillerParameters");
00105    theTimingFiller_ = new MuonTimingFiller(timingParameters);
00106    
00107    if (fillCaloCompatibility_){
00108       // Load MuonCaloCompatibility parameters
00109       parameters = iConfig.getParameter<edm::ParameterSet>("MuonCaloCompatibility");
00110       muonCaloCompatibility_.configure( parameters );
00111    }
00112 
00113    if (fillIsolation_){
00114       // Load MuIsoExtractor parameters
00115       edm::ParameterSet caloExtractorPSet = iConfig.getParameter<edm::ParameterSet>("CaloExtractorPSet");
00116       std::string caloExtractorName = caloExtractorPSet.getParameter<std::string>("ComponentName");
00117       muIsoExtractorCalo_ = IsoDepositExtractorFactory::get()->create( caloExtractorName, caloExtractorPSet);
00118 
00119       edm::ParameterSet trackExtractorPSet = iConfig.getParameter<edm::ParameterSet>("TrackExtractorPSet");
00120       std::string trackExtractorName = trackExtractorPSet.getParameter<std::string>("ComponentName");
00121       muIsoExtractorTrack_ = IsoDepositExtractorFactory::get()->create( trackExtractorName, trackExtractorPSet);
00122 
00123       edm::ParameterSet jetExtractorPSet = iConfig.getParameter<edm::ParameterSet>("JetExtractorPSet");
00124       std::string jetExtractorName = jetExtractorPSet.getParameter<std::string>("ComponentName");
00125       muIsoExtractorJet_ = IsoDepositExtractorFactory::get()->create( jetExtractorName, jetExtractorPSet);
00126    }
00127    if (fillIsolation_ && writeIsoDeposits_){
00128      trackDepositName_ = iConfig.getParameter<std::string>("trackDepositName");
00129      produces<reco::IsoDepositMap>(trackDepositName_);
00130      ecalDepositName_ = iConfig.getParameter<std::string>("ecalDepositName");
00131      produces<reco::IsoDepositMap>(ecalDepositName_);
00132      hcalDepositName_ = iConfig.getParameter<std::string>("hcalDepositName");
00133      produces<reco::IsoDepositMap>(hcalDepositName_);
00134      hoDepositName_ = iConfig.getParameter<std::string>("hoDepositName");
00135      produces<reco::IsoDepositMap>(hoDepositName_);
00136      jetDepositName_ = iConfig.getParameter<std::string>("jetDepositName");
00137      produces<reco::IsoDepositMap>(jetDepositName_);
00138    }
00139    
00140    inputCollectionLabels_ = iConfig.getParameter<std::vector<edm::InputTag> >("inputCollectionLabels");
00141    inputCollectionTypes_  = iConfig.getParameter<std::vector<std::string> >("inputCollectionTypes");
00142    if (inputCollectionLabels_.size() != inputCollectionTypes_.size()) 
00143      throw cms::Exception("ConfigurationError") << "Number of input collection labels is different from number of types. " <<
00144      "For each collection label there should be exactly one collection type specified.";
00145    if (inputCollectionLabels_.size()>7 ||inputCollectionLabels_.empty()) 
00146      throw cms::Exception("ConfigurationError") << "Number of input collections should be from 1 to 7.";
00147    
00148    debugWithTruthMatching_    = iConfig.getParameter<bool>("debugWithTruthMatching");
00149    if (debugWithTruthMatching_) edm::LogWarning("MuonIdentification") 
00150      << "========================================================================\n" 
00151      << "Debugging mode with truth matching is turned on!!! Make sure you understand what you are doing!\n"
00152      << "========================================================================\n";
00153    if (fillGlobalTrackQuality_){
00154      globalTrackQualityInputTag_ = iConfig.getParameter<edm::InputTag>("globalTrackQualityInputTag");
00155    }
00156 
00157    if (fillTrackerKink_) {
00158      trackerKinkFinder_.reset(new MuonKinkFinder(iConfig.getParameter<edm::ParameterSet>("TrackerKinkFinderParameters")));
00159    }
00160    
00161    //create mesh holder
00162    meshAlgo_ = new MuonMesh(iConfig.getParameter<edm::ParameterSet>("arbitrationCleanerOptions"));
00163 }
00164 
00165 
00166 MuonIdProducer::~MuonIdProducer()
00167 {
00168    if (muIsoExtractorCalo_) delete muIsoExtractorCalo_;
00169    if (muIsoExtractorTrack_) delete muIsoExtractorTrack_;
00170    if (muIsoExtractorJet_) delete muIsoExtractorJet_;
00171    if (theTimingFiller_) delete theTimingFiller_;
00172    if (meshAlgo_) delete meshAlgo_;
00173    // TimingReport::current()->dump(std::cout);
00174 }
00175 
00176 void MuonIdProducer::init(edm::Event& iEvent, const edm::EventSetup& iSetup)
00177 {
00178    // TimerStack timers;
00179    // timers.push("MuonIdProducer::produce::init");
00180    
00181    innerTrackCollectionHandle_.clear();
00182    outerTrackCollectionHandle_.clear();
00183    linkCollectionHandle_.clear();
00184    muonCollectionHandle_.clear();
00185    
00186    tpfmsCollectionHandle_.clear();
00187    pickyCollectionHandle_.clear();
00188    dytCollectionHandle_.clear();
00189    
00190 
00191    // timers.push("MuonIdProducer::produce::init::getPropagator");
00192    edm::ESHandle<Propagator> propagator;
00193    iSetup.get<TrackingComponentsRecord>().get("SteppingHelixPropagatorAny", propagator);
00194    trackAssociator_.setPropagator(propagator.product());
00195 
00196    if (fillTrackerKink_) trackerKinkFinder_->init(iSetup);
00197    
00198    // timers.pop_and_push("MuonIdProducer::produce::init::getInputCollections");
00199    for ( unsigned int i = 0; i < inputCollectionLabels_.size(); ++i ) {
00200       if ( inputCollectionTypes_[i] == "inner tracks" ) {
00201          iEvent.getByLabel(inputCollectionLabels_[i], innerTrackCollectionHandle_);
00202          if (! innerTrackCollectionHandle_.isValid()) 
00203            throw cms::Exception("FatalError") << "Failed to get input track collection with label: " << inputCollectionLabels_[i];
00204          LogTrace("MuonIdentification") << "Number of input inner tracks: " << innerTrackCollectionHandle_->size();
00205          continue;
00206       }
00207       if ( inputCollectionTypes_[i] == "outer tracks" ) {
00208          iEvent.getByLabel(inputCollectionLabels_[i], outerTrackCollectionHandle_);
00209          if (! outerTrackCollectionHandle_.isValid()) 
00210            throw cms::Exception("FatalError") << "Failed to get input track collection with label: " << inputCollectionLabels_[i];
00211          LogTrace("MuonIdentification") << "Number of input outer tracks: " << outerTrackCollectionHandle_->size();
00212          continue;
00213       }
00214       if ( inputCollectionTypes_[i] == "links" ) {
00215          iEvent.getByLabel(inputCollectionLabels_[i], linkCollectionHandle_);
00216          if (! linkCollectionHandle_.isValid()) 
00217            throw cms::Exception("FatalError") << "Failed to get input link collection with label: " << inputCollectionLabels_[i];
00218          LogTrace("MuonIdentification") << "Number of input links: " << linkCollectionHandle_->size();
00219          continue;
00220       }
00221       if ( inputCollectionTypes_[i] == "muons" ) {
00222          iEvent.getByLabel(inputCollectionLabels_[i], muonCollectionHandle_);
00223          if (! muonCollectionHandle_.isValid()) 
00224            throw cms::Exception("FatalError") << "Failed to get input muon collection with label: " << inputCollectionLabels_[i];
00225          LogTrace("MuonIdentification") << "Number of input muons: " << muonCollectionHandle_->size();
00226          continue;
00227       }
00228       if ( fillGlobalTrackRefits_  && inputCollectionTypes_[i] == "tev firstHit" ) {
00229          iEvent.getByLabel(inputCollectionLabels_[i], tpfmsCollectionHandle_);
00230          if (! tpfmsCollectionHandle_.isValid()) 
00231            throw cms::Exception("FatalError") << "Failed to get input muon collection with label: " << inputCollectionLabels_[i];
00232          LogTrace("MuonIdentification") << "Number of input muons: " << tpfmsCollectionHandle_->size();
00233          continue;
00234       }
00235 
00236       if ( fillGlobalTrackRefits_  && inputCollectionTypes_[i] == "tev picky" ) {
00237          iEvent.getByLabel(inputCollectionLabels_[i], pickyCollectionHandle_);
00238          if (! pickyCollectionHandle_.isValid()) 
00239            throw cms::Exception("FatalError") << "Failed to get input muon collection with label: " << inputCollectionLabels_[i];
00240          LogTrace("MuonIdentification") << "Number of input muons: " << pickyCollectionHandle_->size();
00241          continue;
00242       }
00243 
00244       if ( fillGlobalTrackRefits_  && inputCollectionTypes_[i] == "tev dyt" ) {
00245          iEvent.getByLabel(inputCollectionLabels_[i], dytCollectionHandle_);
00246          if (! dytCollectionHandle_.isValid()) 
00247            throw cms::Exception("FatalError") << "Failed to get input muon collection with label: " << inputCollectionLabels_[i];
00248          LogTrace("MuonIdentification") << "Number of input muons: " << dytCollectionHandle_->size();
00249          continue;
00250       }
00251       throw cms::Exception("FatalError") << "Unknown input collection type: " << inputCollectionTypes_[i];
00252    }
00253 }
00254 
00255 reco::Muon MuonIdProducer::makeMuon(edm::Event& iEvent, const edm::EventSetup& iSetup, 
00256                                      const reco::TrackRef& track, MuonIdProducer::TrackType type)
00257 {
00258    LogTrace("MuonIdentification") << "Creating a muon from a track " << track.get()->pt() << 
00259      " Pt (GeV), eta: " << track.get()->eta();
00260    reco::Muon aMuon( makeMuon( *(track.get()) ) );
00261 
00262    aMuon.setMuonTrack(type,track);
00263    aMuon.setBestTrack(type);
00264    aMuon.setTunePBestTrack(type);
00265 
00266    return aMuon;
00267 }
00268 
00269 reco::CaloMuon MuonIdProducer::makeCaloMuon( const reco::Muon& muon )
00270 {
00271    reco::CaloMuon aMuon;
00272    aMuon.setInnerTrack( muon.innerTrack() );
00273    
00274    if (muon.isEnergyValid()) aMuon.setCalEnergy( muon.calEnergy() );
00275    // get calo compatibility
00276    if (fillCaloCompatibility_) aMuon.setCaloCompatibility( muonCaloCompatibility_.evaluate(muon) );
00277    return aMuon;
00278 }
00279 
00280 
00281 reco::Muon MuonIdProducer::makeMuon( const reco::MuonTrackLinks& links )
00282 {
00283    LogTrace("MuonIdentification") << "Creating a muon from a link to tracks object";
00284 
00285    reco::Muon aMuon;
00286    reco::Muon::MuonTrackTypePair chosenTrack;
00287    reco::TrackRef tpfmsRef;
00288    reco::TrackRef pickyRef;
00289    bool useSigmaSwitch = false;
00290 
00291    if (tpfmsCollectionHandle_.isValid() && !tpfmsCollectionHandle_.failedToGet() && 
00292        pickyCollectionHandle_.isValid() && !pickyCollectionHandle_.failedToGet()) {
00293        
00294      tpfmsRef = muon::getTevRefitTrack(links.globalTrack(), *tpfmsCollectionHandle_);
00295      pickyRef = muon::getTevRefitTrack(links.globalTrack(), *pickyCollectionHandle_);
00296      
00297      if (tpfmsRef.isNull() && pickyRef.isNull()){
00298        edm::LogWarning("MakeMuonWithTEV")<<"Failed to get  TEV refits, fall back to sigma switch.";
00299        useSigmaSwitch = true;
00300      }
00301    } else {
00302      useSigmaSwitch = true;
00303    }
00304 
00305    if (useSigmaSwitch){
00306      chosenTrack = muon::sigmaSwitch( links.globalTrack(), links.trackerTrack(), 
00307                                       sigmaThresholdToFillCandidateP4WithGlobalFit_,
00308                                       ptThresholdToFillCandidateP4WithGlobalFit_);
00309    } else {
00310      chosenTrack = muon::tevOptimized( links.globalTrack(), links.trackerTrack(), 
00311                                        tpfmsRef, pickyRef,
00312                                        ptThresholdToFillCandidateP4WithGlobalFit_);
00313    }
00314    aMuon = makeMuon(*chosenTrack.first);
00315    aMuon.setInnerTrack( links.trackerTrack() );
00316    aMuon.setOuterTrack( links.standAloneTrack() );
00317    aMuon.setGlobalTrack( links.globalTrack() );
00318    aMuon.setBestTrack(chosenTrack.second);
00319    aMuon.setTunePBestTrack(chosenTrack.second);
00320 
00321    if(fillGlobalTrackRefits_){
00322      if (tpfmsCollectionHandle_.isValid() && !tpfmsCollectionHandle_.failedToGet()) {
00323        reco::TrackToTrackMap::const_iterator it = tpfmsCollectionHandle_->find(links.globalTrack());
00324        if (it != tpfmsCollectionHandle_->end()) aMuon.setMuonTrack(reco::Muon::TPFMS, (it->val));
00325      }
00326      if (pickyCollectionHandle_.isValid() && !pickyCollectionHandle_.failedToGet()) {
00327        reco::TrackToTrackMap::const_iterator it = pickyCollectionHandle_->find(links.globalTrack());
00328        if (it != pickyCollectionHandle_->end()) aMuon.setMuonTrack(reco::Muon::Picky, (it->val));
00329      }
00330      if (dytCollectionHandle_.isValid() && !dytCollectionHandle_.failedToGet()) {
00331        reco::TrackToTrackMap::const_iterator it = dytCollectionHandle_->find(links.globalTrack());
00332        if (it != dytCollectionHandle_->end()) aMuon.setMuonTrack(reco::Muon::DYT, (it->val));
00333      }
00334    }
00335    return aMuon;
00336 }
00337 
00338 
00339 bool MuonIdProducer::isGoodTrack( const reco::Track& track )
00340 {
00341    // Pt and absolute momentum requirement
00342    if (track.pt() < minPt_ || (track.p() < minP_ && track.p() < minPCaloMuon_)){ 
00343       LogTrace("MuonIdentification") << "Skipped low momentum track (Pt,P): " << track.pt() <<
00344         ", " << track.p() << " GeV";
00345       return false;
00346    }
00347         
00348    // Eta requirement
00349    if ( fabs(track.eta()) > maxAbsEta_ ){
00350       LogTrace("MuonIdentification") << "Skipped track with large pseudo rapidity (Eta: " << track.eta() << " )";
00351       return false;
00352    }
00353    return true;
00354 }
00355    
00356 unsigned int MuonIdProducer::chamberId( const DetId& id )
00357 {
00358    switch ( id.det() ) {
00359     case DetId::Muon:
00360       switch ( id.subdetId() ) {
00361        case MuonSubdetId::DT:
00362            { 
00363               DTChamberId detId(id.rawId());
00364               return detId.rawId();
00365            }
00366          break;
00367        case MuonSubdetId::CSC:
00368            {
00369               CSCDetId detId(id.rawId());
00370               return detId.chamberId().rawId();
00371            }
00372          break;
00373        default:
00374          return 0;
00375       }
00376     default:
00377       return 0;
00378    }
00379    return 0;
00380 }
00381 
00382 
00383 int MuonIdProducer::overlap(const reco::Muon& muon, const reco::Track& track)
00384 {
00385    int numberOfCommonDetIds = 0;
00386    if ( ! muon.isMatchesValid() || 
00387         track.extra().isNull() ||
00388         track.extra()->recHits().isNull() ) return numberOfCommonDetIds;
00389    const std::vector<reco::MuonChamberMatch>& matches( muon.matches() );
00390    for ( std::vector<reco::MuonChamberMatch>::const_iterator match = matches.begin();
00391          match != matches.end(); ++match ) 
00392      {
00393         if ( match->segmentMatches.empty() ) continue;
00394         bool foundCommonDetId = false;
00395         
00396         for ( TrackingRecHitRefVector::const_iterator hit = track.extra()->recHitsBegin();
00397               hit != track.extra()->recHitsEnd(); ++hit )
00398           {
00399              // LogTrace("MuonIdentification") << "hit DetId: " << std::hex << hit->get()->geographicalId().rawId() <<
00400              //  "\t hit chamber DetId: " << getChamberId(hit->get()->geographicalId()) <<
00401              //  "\t segment DetId: " << match->id.rawId() << std::dec;
00402              
00403              if ( chamberId(hit->get()->geographicalId()) == match->id.rawId() ) {
00404                 foundCommonDetId = true;
00405                 break;
00406              }
00407           }
00408         if ( foundCommonDetId ) {
00409            numberOfCommonDetIds++;
00410            break;
00411         }
00412      }
00413    return numberOfCommonDetIds;
00414 }
00415 
00416 void MuonIdProducer::beginRun(const edm::Run& iRun, const edm::EventSetup& iSetup)
00417 {
00418   edm::ESHandle<CSCGeometry> geomHandle;
00419   iSetup.get<MuonGeometryRecord>().get(geomHandle);
00420 
00421   meshAlgo_->setCSCGeometry(geomHandle.product());
00422   
00423 }
00424 
00425 bool validateGlobalMuonPair( const reco::MuonTrackLinks& goodMuon, 
00426                              const reco::MuonTrackLinks& badMuon )
00427 {
00428   if ( std::min(goodMuon.globalTrack()->hitPattern().numberOfValidMuonHits(),
00429                  badMuon.globalTrack()->hitPattern().numberOfValidMuonHits()) > 10 ){
00430     if ( goodMuon.globalTrack()->normalizedChi2() >
00431           badMuon.globalTrack()->normalizedChi2() )
00432       return false;
00433     else
00434       return true;
00435   } 
00436   if ( goodMuon.globalTrack()->hitPattern().numberOfValidMuonHits() <
00437        badMuon.globalTrack()->hitPattern().numberOfValidMuonHits() ) return false;
00438   return true;
00439 }
00440 
00441 void MuonIdProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup)
00442 {
00443    // TimerStack timers;
00444    // timers.push("MuonIdProducer::produce");
00445    
00446    std::auto_ptr<reco::MuonCollection> outputMuons(new reco::MuonCollection);
00447    std::auto_ptr<reco::CaloMuonCollection> caloMuons( new reco::CaloMuonCollection );
00448 
00449    init(iEvent, iSetup);
00450 
00451    std::auto_ptr<reco::MuonTimeExtraMap> muonTimeMap(new reco::MuonTimeExtraMap());
00452    reco::MuonTimeExtraMap::Filler filler(*muonTimeMap);
00453    std::auto_ptr<reco::MuonTimeExtraMap> muonTimeMapDT(new reco::MuonTimeExtraMap());
00454    reco::MuonTimeExtraMap::Filler fillerDT(*muonTimeMapDT);
00455    std::auto_ptr<reco::MuonTimeExtraMap> muonTimeMapCSC(new reco::MuonTimeExtraMap());
00456    reco::MuonTimeExtraMap::Filler fillerCSC(*muonTimeMapCSC);
00457 
00458    std::auto_ptr<reco::IsoDepositMap> trackDepMap(new reco::IsoDepositMap());
00459    reco::IsoDepositMap::Filler trackDepFiller(*trackDepMap);
00460    std::auto_ptr<reco::IsoDepositMap> ecalDepMap(new reco::IsoDepositMap());
00461    reco::IsoDepositMap::Filler ecalDepFiller(*ecalDepMap);
00462    std::auto_ptr<reco::IsoDepositMap> hcalDepMap(new reco::IsoDepositMap());
00463    reco::IsoDepositMap::Filler hcalDepFiller(*hcalDepMap);
00464    std::auto_ptr<reco::IsoDepositMap> hoDepMap(new reco::IsoDepositMap());
00465    reco::IsoDepositMap::Filler hoDepFiller(*hoDepMap);
00466    std::auto_ptr<reco::IsoDepositMap> jetDepMap(new reco::IsoDepositMap());
00467    reco::IsoDepositMap::Filler jetDepFiller(*jetDepMap);
00468 
00469    // loop over input collections
00470    
00471    // muons first - no cleaning, take as is.
00472    if ( muonCollectionHandle_.isValid() )
00473      for ( reco::MuonCollection::const_iterator muon = muonCollectionHandle_->begin();
00474            muon !=  muonCollectionHandle_->end(); ++muon )
00475        outputMuons->push_back(*muon);
00476    
00477    // links second ( assume global muon type )
00478    if ( linkCollectionHandle_.isValid() ){
00479      std::vector<bool> goodmuons(linkCollectionHandle_->size(),true);
00480      if ( goodmuons.size()>1 ){
00481        // check for shared tracker tracks
00482        for ( unsigned int i=0; i<linkCollectionHandle_->size()-1; ++i ){
00483          if (!checkLinks(&linkCollectionHandle_->at(i))) continue;
00484          for ( unsigned int j=i+1; j<linkCollectionHandle_->size(); ++j ){
00485            if (!checkLinks(&linkCollectionHandle_->at(j))) continue; 
00486            if ( linkCollectionHandle_->at(i).trackerTrack().isNonnull() &&
00487                 linkCollectionHandle_->at(i).trackerTrack() == 
00488                 linkCollectionHandle_->at(j).trackerTrack() )
00489              {
00490                // Tracker track is the essential part that dominates muon resolution
00491                // so taking either muon is fine. All that is important is to preserve
00492                // the muon identification information. If number of hits is small,
00493                // keep the one with large number of hits, otherwise take the smalest chi2/ndof
00494                if ( validateGlobalMuonPair(linkCollectionHandle_->at(i),linkCollectionHandle_->at(j)) )
00495                  goodmuons[j] = false;
00496                else
00497                  goodmuons[i] = false;
00498              }
00499          }
00500        }
00501        // check for shared stand-alone muons.
00502        for ( unsigned int i=0; i<linkCollectionHandle_->size()-1; ++i ){
00503          if ( !goodmuons[i] ) continue;
00504          if (!checkLinks(&linkCollectionHandle_->at(i))) continue;
00505          for ( unsigned int j=i+1; j<linkCollectionHandle_->size(); ++j ){
00506            if ( !goodmuons[j] ) continue;
00507            if (!checkLinks(&linkCollectionHandle_->at(j))) continue;
00508            if ( linkCollectionHandle_->at(i).standAloneTrack().isNonnull() &&
00509                 linkCollectionHandle_->at(i).standAloneTrack() == 
00510                 linkCollectionHandle_->at(j).standAloneTrack() )
00511              {
00512                if ( validateGlobalMuonPair(linkCollectionHandle_->at(i),linkCollectionHandle_->at(j)) )
00513                  goodmuons[j] = false;
00514                else
00515                  goodmuons[i] = false;
00516              }
00517          }
00518        }
00519      }
00520      for ( unsigned int i=0; i<linkCollectionHandle_->size(); ++i ){
00521        if ( !goodmuons[i] ) continue;
00522        const reco::MuonTrackLinks* links = &linkCollectionHandle_->at(i);
00523        if ( ! checkLinks(links))   continue;
00524        // check if this muon is already in the list
00525        bool newMuon = true;
00526        for ( reco::MuonCollection::const_iterator muon = outputMuons->begin();
00527              muon !=  outputMuons->end(); ++muon )
00528          if ( muon->track() == links->trackerTrack() &&
00529               muon->standAloneMuon() == links->standAloneTrack() &&
00530               muon->combinedMuon() == links->globalTrack() )
00531            newMuon = false;
00532        if ( newMuon ) {
00533          outputMuons->push_back( makeMuon( *links ) );
00534          outputMuons->back().setType(reco::Muon::GlobalMuon | reco::Muon::StandAloneMuon);
00535        }
00536      }
00537    }
00538 
00539    // tracker and calo muons are next
00540    if ( innerTrackCollectionHandle_.isValid() ) {
00541       LogTrace("MuonIdentification") << "Creating tracker muons";
00542       for ( unsigned int i = 0; i < innerTrackCollectionHandle_->size(); ++i )
00543         {
00544            const reco::Track& track = innerTrackCollectionHandle_->at(i);
00545            if ( ! isGoodTrack( track ) ) continue;
00546            bool splitTrack = false;
00547            if ( track.extra().isAvailable() && 
00548                 TrackDetectorAssociator::crossedIP( track ) ) splitTrack = true;
00549            std::vector<TrackDetectorAssociator::Direction> directions;
00550            if ( splitTrack ) {
00551               directions.push_back(TrackDetectorAssociator::InsideOut);
00552               directions.push_back(TrackDetectorAssociator::OutsideIn);
00553            } else {
00554               directions.push_back(TrackDetectorAssociator::Any);
00555            }
00556            for ( std::vector<TrackDetectorAssociator::Direction>::const_iterator direction = directions.begin();
00557                  direction != directions.end(); ++direction )
00558              {
00559                 // make muon
00560                 // timers.push("MuonIdProducer::produce::fillMuonId");
00561                reco::Muon trackerMuon( makeMuon(iEvent, iSetup, reco::TrackRef( innerTrackCollectionHandle_, i ), reco::Muon::InnerTrack ) );
00562                 trackerMuon.setType( reco::Muon::TrackerMuon | reco::Muon::RPCMuon );
00563                 fillMuonId(iEvent, iSetup, trackerMuon, *direction);
00564                 // timers.pop();
00565           
00566                 if ( debugWithTruthMatching_ ) {
00567                    // add MC hits to a list of matched segments. 
00568                    // Since it's debugging mode - code is slow
00569                    MuonIdTruthInfo::truthMatchMuon(iEvent, iSetup, trackerMuon);
00570                 }
00571           
00572                 // check if this muon is already in the list
00573                 // have to check where muon hits are really located
00574                 // to match properly
00575                 bool newMuon = true;
00576                 bool goodTrackerMuon = isGoodTrackerMuon( trackerMuon );
00577                 bool goodRPCMuon = isGoodRPCMuon( trackerMuon );
00578                 for ( reco::MuonCollection::iterator muon = outputMuons->begin();
00579                       muon !=  outputMuons->end(); ++muon )
00580                   {
00581                      if ( muon->innerTrack().get() == trackerMuon.innerTrack().get() &&
00582                           cos(phiOfMuonIneteractionRegion(*muon) - 
00583                               phiOfMuonIneteractionRegion(trackerMuon)) > 0 )
00584                        {
00585                           newMuon = false;
00586                           muon->setMatches( trackerMuon.matches() );
00587                           if (trackerMuon.isTimeValid()) muon->setTime( trackerMuon.time() );
00588                           if (trackerMuon.isEnergyValid()) muon->setCalEnergy( trackerMuon.calEnergy() );
00589                           if (goodTrackerMuon) muon->setType( muon->type() | reco::Muon::TrackerMuon );
00590                           if (goodRPCMuon) muon->setType( muon->type() | reco::Muon::RPCMuon );
00591                           LogTrace("MuonIdentification") << "Found a corresponding global muon. Set energy, matches and move on";
00592                           break;
00593                        }
00594                   }
00595                 if ( newMuon ) {
00596                    if ( goodTrackerMuon ){
00597                       outputMuons->push_back( trackerMuon );
00598                    } else {
00599                       LogTrace("MuonIdentification") << "track failed minimal number of muon matches requirement";
00600                       const reco::CaloMuon& caloMuon = makeCaloMuon(trackerMuon);
00601                       if ( ! caloMuon.isCaloCompatibilityValid() || caloMuon.caloCompatibility() < caloCut_ || caloMuon.p() < minPCaloMuon_) continue;
00602                       caloMuons->push_back( caloMuon );
00603                    }
00604                 }
00605              }
00606         }
00607    }
00608    
00609    // and at last the stand alone muons
00610    if ( outerTrackCollectionHandle_.isValid() ) {
00611       LogTrace("MuonIdentification") << "Looking for new muons among stand alone muon tracks";
00612       for ( unsigned int i = 0; i < outerTrackCollectionHandle_->size(); ++i )
00613         {
00614            // check if this muon is already in the list of global muons
00615            bool newMuon = true;
00616            for ( reco::MuonCollection::iterator muon = outputMuons->begin();
00617                  muon !=  outputMuons->end(); ++muon ) 
00618              {
00619                 if ( ! muon->standAloneMuon().isNull() ) {
00620                    // global muon
00621                    if ( muon->standAloneMuon().get() ==  &(outerTrackCollectionHandle_->at(i)) ) {
00622                       newMuon = false;
00623                       break;
00624                    }
00625                 } else {
00626                    // tracker muon - no direct links to the standalone muon
00627                    // since we have only a few real muons in an event, matching 
00628                    // the stand alone muon to the tracker muon by DetIds should 
00629                    // be good enough for association. At the end it's up to a 
00630                    // user to redefine the association and what it means. Here 
00631                    // we would like to avoid obvious double counting and we 
00632                    // tolerate a potential miss association
00633                    if ( overlap(*muon,outerTrackCollectionHandle_->at(i))>0 ) {
00634                       LogTrace("MuonIdentification") << "Found associated tracker muon. Set a reference and move on";
00635                       newMuon = false;
00636                       muon->setOuterTrack( reco::TrackRef( outerTrackCollectionHandle_, i ) );
00637                       muon->setType( muon->type() | reco::Muon::StandAloneMuon );
00638                       break;
00639                    }
00640                 }
00641              }
00642            if ( newMuon ) {
00643               LogTrace("MuonIdentification") << "No associated stand alone track is found. Making a muon";
00644               outputMuons->push_back( makeMuon(iEvent, iSetup, 
00645                                                reco::TrackRef( outerTrackCollectionHandle_, i ), reco::Muon::OuterTrack ) );
00646               outputMuons->back().setType( reco::Muon::StandAloneMuon );
00647            }
00648         }
00649    }
00650    
00651    LogTrace("MuonIdentification") << "Dress up muons if it's necessary";
00652 
00653    int nMuons=outputMuons->size();
00654 
00655    std::vector<reco::MuonTimeExtra> dtTimeColl(nMuons);
00656    std::vector<reco::MuonTimeExtra> cscTimeColl(nMuons);
00657    std::vector<reco::MuonTimeExtra> combinedTimeColl(nMuons);
00658    std::vector<reco::IsoDeposit> trackDepColl(nMuons);
00659    std::vector<reco::IsoDeposit> ecalDepColl(nMuons);
00660    std::vector<reco::IsoDeposit> hcalDepColl(nMuons);
00661    std::vector<reco::IsoDeposit> hoDepColl(nMuons);
00662    std::vector<reco::IsoDeposit> jetDepColl(nMuons);
00663 
00664    // Fill various information
00665    unsigned int i=0;
00666    for ( reco::MuonCollection::iterator muon = outputMuons->begin(); muon != outputMuons->end(); ++muon )
00667      {
00668         // Fill muonID
00669         // timers.push("MuonIdProducer::produce::fillMuonId");
00670         if ( ( fillMatching_ && ! muon->isMatchesValid() ) || 
00671              ( fillEnergy_ && !muon->isEnergyValid() ) )
00672           {
00673              // predict direction based on the muon interaction region location 
00674              // if it's available
00675              if ( muon->isStandAloneMuon() ) {
00676                 if ( cos(phiOfMuonIneteractionRegion(*muon) - muon->phi()) > 0 )
00677                   fillMuonId(iEvent, iSetup, *muon, TrackDetectorAssociator::InsideOut);
00678                 else
00679                   fillMuonId(iEvent, iSetup, *muon, TrackDetectorAssociator::OutsideIn);
00680              } else {
00681                 LogTrace("MuonIdentification") << "THIS SHOULD NEVER HAPPEN";
00682                 fillMuonId(iEvent, iSetup, *muon);
00683              }
00684           }
00685 
00686         if (fillGlobalTrackQuality_){
00687           // Fill global quality information
00688           fillGlbQuality(iEvent, iSetup, *muon);
00689         }
00690         LogDebug("MuonIdentification");
00691 
00692         if (fillTrackerKink_) {
00693             fillTrackerKink(*muon);
00694         }
00695 
00696         // timers.push("MuonIdProducer::produce::fillCaloCompatibility");
00697         if ( fillCaloCompatibility_ ) muon->setCaloCompatibility( muonCaloCompatibility_.evaluate(*muon) );
00698         // timers.pop();
00699         
00700         // timers.push("MuonIdProducer::produce::fillIsolation");
00701         if ( fillIsolation_ ) fillMuonIsolation(iEvent, iSetup, *muon,
00702                                                 trackDepColl[i], ecalDepColl[i], hcalDepColl[i], hoDepColl[i], jetDepColl[i]);
00703         // timers.pop();
00704 
00705         // fill timing information
00706         reco::MuonTime muonTime;
00707         reco::MuonTimeExtra dtTime;
00708         reco::MuonTimeExtra cscTime;
00709         reco::MuonTimeExtra combinedTime;
00710 
00711         theTimingFiller_->fillTiming(*muon, dtTime, cscTime, combinedTime, iEvent, iSetup);
00712 
00713         muonTime.nDof=combinedTime.nDof();
00714         muonTime.timeAtIpInOut=combinedTime.timeAtIpInOut();
00715         muonTime.timeAtIpInOutErr=combinedTime.timeAtIpInOutErr();
00716         muonTime.timeAtIpOutIn=combinedTime.timeAtIpOutIn();
00717         muonTime.timeAtIpOutInErr=combinedTime.timeAtIpOutInErr();
00718 
00719         muon->setTime(  muonTime);
00720         dtTimeColl[i] = dtTime;
00721         cscTimeColl[i] = cscTime;
00722         combinedTimeColl[i] = combinedTime;
00723         
00724         i++;
00725      
00726      }
00727         
00728    LogTrace("MuonIdentification") << "number of muons produced: " << outputMuons->size();
00729    // timers.push("MuonIdProducer::produce::fillArbitration");
00730    if ( fillMatching_ ) fillArbitrationInfo( outputMuons.get() );
00731    // timers.pop();
00732    edm::OrphanHandle<reco::MuonCollection> muonHandle = iEvent.put(outputMuons);
00733 
00734    filler.insert(muonHandle, combinedTimeColl.begin(), combinedTimeColl.end());
00735    filler.fill();
00736    fillerDT.insert(muonHandle, dtTimeColl.begin(), dtTimeColl.end());
00737    fillerDT.fill();
00738    fillerCSC.insert(muonHandle, cscTimeColl.begin(), cscTimeColl.end());
00739    fillerCSC.fill();
00740 
00741    iEvent.put(muonTimeMap,"combined");
00742    iEvent.put(muonTimeMapDT,"dt");
00743    iEvent.put(muonTimeMapCSC,"csc");
00744 
00745    if (writeIsoDeposits_ && fillIsolation_){
00746      trackDepFiller.insert(muonHandle, trackDepColl.begin(), trackDepColl.end());
00747      trackDepFiller.fill();
00748      iEvent.put(trackDepMap, trackDepositName_);
00749      ecalDepFiller.insert(muonHandle, ecalDepColl.begin(), ecalDepColl.end());
00750      ecalDepFiller.fill();
00751      iEvent.put(ecalDepMap,  ecalDepositName_);
00752      hcalDepFiller.insert(muonHandle, hcalDepColl.begin(), hcalDepColl.end());
00753      hcalDepFiller.fill();
00754      iEvent.put(hcalDepMap,  hcalDepositName_);
00755      hoDepFiller.insert(muonHandle, hoDepColl.begin(), hoDepColl.end());
00756      hoDepFiller.fill();
00757      iEvent.put(hoDepMap,    hoDepositName_);
00758      jetDepFiller.insert(muonHandle, jetDepColl.begin(), jetDepColl.end());
00759      jetDepFiller.fill();
00760      iEvent.put(jetDepMap,  jetDepositName_);
00761    }
00762 
00763    iEvent.put(caloMuons);
00764 }
00765 
00766 
00767 bool MuonIdProducer::isGoodTrackerMuon( const reco::Muon& muon )
00768 {
00769   if(muon.track()->pt() < minPt_ || muon.track()->p() < minP_) return false;
00770    if ( addExtraSoftMuons_ && 
00771         muon.pt()<5 && fabs(muon.eta())<1.5 && 
00772         muon.numberOfMatches( reco::Muon::NoArbitration ) >= 1 ) return true;
00773    return ( muon.numberOfMatches( reco::Muon::NoArbitration ) >= minNumberOfMatches_ );
00774 }
00775 
00776 bool MuonIdProducer::isGoodRPCMuon( const reco::Muon& muon )
00777 {
00778   if(muon.track()->pt() < minPt_ || muon.track()->p() < minP_) return false;
00779    if ( addExtraSoftMuons_ && 
00780         muon.pt()<5 && fabs(muon.eta())<1.5 && 
00781         muon.numberOfMatchedRPCLayers( reco::Muon::RPCHitAndTrackArbitration ) > 1 ) return true;
00782    return ( muon.numberOfMatchedRPCLayers( reco::Muon::RPCHitAndTrackArbitration ) > minNumberOfMatches_ );
00783 }
00784 
00785 void MuonIdProducer::fillMuonId(edm::Event& iEvent, const edm::EventSetup& iSetup,
00786                                 reco::Muon& aMuon, 
00787                                 TrackDetectorAssociator::Direction direction)
00788 {
00789    // perform track - detector association
00790    const reco::Track* track = 0;
00791    if ( ! aMuon.track().isNull() )
00792      track = aMuon.track().get();
00793    else 
00794      {
00795         if ( ! aMuon.standAloneMuon().isNull() )
00796           track = aMuon.standAloneMuon().get();
00797         else
00798           throw cms::Exception("FatalError") << "Failed to fill muon id information for a muon with undefined references to tracks"; 
00799      }
00800    
00801    TrackDetMatchInfo info = trackAssociator_.associate(iEvent, iSetup, *track, parameters_, direction);
00802    
00803    if ( fillEnergy_ ) {
00804       reco::MuonEnergy muonEnergy;
00805       muonEnergy.em      = info.crossedEnergy(TrackDetMatchInfo::EcalRecHits);
00806       muonEnergy.had     = info.crossedEnergy(TrackDetMatchInfo::HcalRecHits);
00807       muonEnergy.ho      = info.crossedEnergy(TrackDetMatchInfo::HORecHits);
00808       muonEnergy.tower   = info.crossedEnergy(TrackDetMatchInfo::TowerTotal);
00809       muonEnergy.emS9    = info.nXnEnergy(TrackDetMatchInfo::EcalRecHits,1); // 3x3 energy
00810       muonEnergy.emS25   = info.nXnEnergy(TrackDetMatchInfo::EcalRecHits,2); // 5x5 energy
00811       muonEnergy.hadS9   = info.nXnEnergy(TrackDetMatchInfo::HcalRecHits,1); // 3x3 energy
00812       muonEnergy.hoS9    = info.nXnEnergy(TrackDetMatchInfo::HORecHits,1);   // 3x3 energy
00813       muonEnergy.towerS9 = info.nXnEnergy(TrackDetMatchInfo::TowerTotal,1);  // 3x3 energy
00814       muonEnergy.ecal_position = info.trkGlobPosAtEcal;
00815       muonEnergy.hcal_position = info.trkGlobPosAtHcal;
00816       if (! info.crossedEcalIds.empty() ) muonEnergy.ecal_id = info.crossedEcalIds.front();
00817       if (! info.crossedHcalIds.empty() ) muonEnergy.hcal_id = info.crossedHcalIds.front();
00818       // find maximal energy depositions and their time
00819       DetId emMaxId      = info.findMaxDeposition(TrackDetMatchInfo::EcalRecHits,2); // max energy deposit in 5x5 shape
00820       for(std::vector<const EcalRecHit*>::const_iterator hit=info.ecalRecHits.begin(); 
00821           hit!=info.ecalRecHits.end(); ++hit) {
00822          if ((*hit)->id() != emMaxId) continue;
00823          muonEnergy.emMax   = (*hit)->energy();
00824          muonEnergy.ecal_time = (*hit)->time();
00825       }
00826       DetId hadMaxId     = info.findMaxDeposition(TrackDetMatchInfo::HcalRecHits,1); // max energy deposit in 3x3 shape
00827       for(std::vector<const HBHERecHit*>::const_iterator hit=info.hcalRecHits.begin(); 
00828           hit!=info.hcalRecHits.end(); ++hit) {
00829          if ((*hit)->id() != hadMaxId) continue;
00830          muonEnergy.hadMax   = (*hit)->energy();
00831          muonEnergy.hcal_time = (*hit)->time();
00832       }
00833       aMuon.setCalEnergy( muonEnergy );
00834    }
00835    if ( ! fillMatching_ && ! aMuon.isTrackerMuon() && ! aMuon.isRPCMuon() ) return;
00836    
00837   edm::Handle<RPCRecHitCollection> rpcRecHits;
00838   iEvent.getByLabel(edm::InputTag("rpcRecHits"), rpcRecHits);
00839 
00840    // fill muon match info
00841    std::vector<reco::MuonChamberMatch> muonChamberMatches;
00842    unsigned int nubmerOfMatchesAccordingToTrackAssociator = 0;
00843    for( std::vector<TAMuonChamberMatch>::const_iterator chamber=info.chambers.begin();
00844         chamber!=info.chambers.end(); chamber++ )
00845      {
00846        if  (chamber->id.subdetId() == 3 && rpcRecHits.isValid()  ) continue; // Skip RPC chambers, they are taken care of below)
00847         reco::MuonChamberMatch matchedChamber;
00848         
00849         LocalError localError = chamber->tState.localError().positionError();
00850         matchedChamber.x = chamber->tState.localPosition().x();
00851         matchedChamber.y = chamber->tState.localPosition().y();
00852         matchedChamber.xErr = sqrt( localError.xx() );
00853         matchedChamber.yErr = sqrt( localError.yy() );
00854                                                                                                                                                             
00855         matchedChamber.dXdZ = chamber->tState.localDirection().z()!=0?chamber->tState.localDirection().x()/chamber->tState.localDirection().z():9999;
00856         matchedChamber.dYdZ = chamber->tState.localDirection().z()!=0?chamber->tState.localDirection().y()/chamber->tState.localDirection().z():9999;
00857         // DANGEROUS - compiler cannot guaranty parameters ordering
00858         AlgebraicSymMatrix55 trajectoryCovMatrix = chamber->tState.localError().matrix();
00859         matchedChamber.dXdZErr = trajectoryCovMatrix(1,1)>0?sqrt(trajectoryCovMatrix(1,1)):0;
00860         matchedChamber.dYdZErr = trajectoryCovMatrix(2,2)>0?sqrt(trajectoryCovMatrix(2,2)):0;
00861         
00862         matchedChamber.edgeX = chamber->localDistanceX;
00863         matchedChamber.edgeY = chamber->localDistanceY;
00864         
00865         matchedChamber.id = chamber->id;
00866         if ( ! chamber->segments.empty() ) ++nubmerOfMatchesAccordingToTrackAssociator;
00867         
00868         // fill segments
00869         for( std::vector<TAMuonSegmentMatch>::const_iterator segment = chamber->segments.begin();
00870      segment != chamber->segments.end(); segment++ ) 
00871           {
00872              reco::MuonSegmentMatch matchedSegment;
00873              matchedSegment.x = segment->segmentLocalPosition.x();
00874              matchedSegment.y = segment->segmentLocalPosition.y();
00875              matchedSegment.dXdZ = segment->segmentLocalDirection.z()?segment->segmentLocalDirection.x()/segment->segmentLocalDirection.z():0;
00876              matchedSegment.dYdZ = segment->segmentLocalDirection.z()?segment->segmentLocalDirection.y()/segment->segmentLocalDirection.z():0;
00877              matchedSegment.xErr = segment->segmentLocalErrorXX>0?sqrt(segment->segmentLocalErrorXX):0;
00878              matchedSegment.yErr = segment->segmentLocalErrorYY>0?sqrt(segment->segmentLocalErrorYY):0;
00879              matchedSegment.dXdZErr = segment->segmentLocalErrorDxDz>0?sqrt(segment->segmentLocalErrorDxDz):0;
00880              matchedSegment.dYdZErr = segment->segmentLocalErrorDyDz>0?sqrt(segment->segmentLocalErrorDyDz):0;
00881              matchedSegment.t0 = segment->t0;
00882              matchedSegment.mask = 0;
00883              matchedSegment.dtSegmentRef  = segment->dtSegmentRef;
00884              matchedSegment.cscSegmentRef = segment->cscSegmentRef;
00885         matchedSegment.hasZed_ = segment->hasZed;
00886         matchedSegment.hasPhi_ = segment->hasPhi;
00887              // test segment
00888              bool matchedX = false;
00889              bool matchedY = false;
00890              LogTrace("MuonIdentification") << " matching local x, segment x: " << matchedSegment.x << 
00891                ", chamber x: " << matchedChamber.x << ", max: " << maxAbsDx_;
00892              LogTrace("MuonIdentification") << " matching local y, segment y: " << matchedSegment.y <<
00893                ", chamber y: " << matchedChamber.y << ", max: " << maxAbsDy_;
00894              if (matchedSegment.xErr>0 && matchedChamber.xErr>0 )
00895                LogTrace("MuonIdentification") << " xpull: " << 
00896                fabs(matchedSegment.x - matchedChamber.x)/sqrt(pow(matchedSegment.xErr,2) + pow(matchedChamber.xErr,2));
00897              if (matchedSegment.yErr>0 && matchedChamber.yErr>0 )
00898                LogTrace("MuonIdentification") << " ypull: " << 
00899                fabs(matchedSegment.y - matchedChamber.y)/sqrt(pow(matchedSegment.yErr,2) + pow(matchedChamber.yErr,2));
00900              
00901              if (fabs(matchedSegment.x - matchedChamber.x) < maxAbsDx_) matchedX = true;
00902              if (fabs(matchedSegment.y - matchedChamber.y) < maxAbsDy_) matchedY = true;
00903              if (matchedSegment.xErr>0 && matchedChamber.xErr>0 && 
00904                  fabs(matchedSegment.x - matchedChamber.x)/sqrt(pow(matchedSegment.xErr,2) + pow(matchedChamber.xErr,2)) < maxAbsPullX_) matchedX = true;
00905              if (matchedSegment.yErr>0 && matchedChamber.yErr>0 && 
00906                  fabs(matchedSegment.y - matchedChamber.y)/sqrt(pow(matchedSegment.yErr,2) + pow(matchedChamber.yErr,2)) < maxAbsPullY_) matchedY = true;
00907              if (matchedX && matchedY) matchedChamber.segmentMatches.push_back(matchedSegment);
00908           }
00909         muonChamberMatches.push_back(matchedChamber);
00910      }
00911 
00912   // Fill RPC info
00913   if ( rpcRecHits.isValid() )
00914   {
00915 
00916    for( std::vector<TAMuonChamberMatch>::const_iterator chamber=info.chambers.begin();
00917         chamber!=info.chambers.end(); chamber++ )
00918      {
00919 
00920       if ( chamber->id.subdetId() != 3 ) continue; // Consider RPC chambers only
00921 
00922       reco::MuonChamberMatch matchedChamber;
00923 
00924       LocalError localError = chamber->tState.localError().positionError();
00925       matchedChamber.x = chamber->tState.localPosition().x();
00926       matchedChamber.y = chamber->tState.localPosition().y();
00927       matchedChamber.xErr = sqrt( localError.xx() );
00928       matchedChamber.yErr = sqrt( localError.yy() );
00929       
00930       matchedChamber.dXdZ = chamber->tState.localDirection().z()!=0?chamber->tState.localDirection().x()/chamber->tState.localDirection().z():9999;
00931       matchedChamber.dYdZ = chamber->tState.localDirection().z()!=0?chamber->tState.localDirection().y()/chamber->tState.localDirection().z():9999;
00932       // DANGEROUS - compiler cannot guaranty parameters ordering
00933       AlgebraicSymMatrix55 trajectoryCovMatrix = chamber->tState.localError().matrix();
00934       matchedChamber.dXdZErr = trajectoryCovMatrix(1,1)>0?sqrt(trajectoryCovMatrix(1,1)):0;
00935       matchedChamber.dYdZErr = trajectoryCovMatrix(2,2)>0?sqrt(trajectoryCovMatrix(2,2)):0;
00936         
00937       matchedChamber.edgeX = chamber->localDistanceX;
00938       matchedChamber.edgeY = chamber->localDistanceY;
00939 
00940       matchedChamber.id = chamber->id;
00941 
00942       for ( RPCRecHitCollection::const_iterator rpcRecHit = rpcRecHits->begin();
00943             rpcRecHit != rpcRecHits->end(); ++rpcRecHit )
00944       {
00945         reco::MuonRPCHitMatch rpcHitMatch;
00946 
00947         if ( rpcRecHit->rawId() != chamber->id.rawId() ) continue;
00948 
00949         rpcHitMatch.x = rpcRecHit->localPosition().x();
00950         rpcHitMatch.mask = 0;
00951         rpcHitMatch.bx = rpcRecHit->BunchX();
00952 
00953         const double AbsDx = fabs(rpcRecHit->localPosition().x()-chamber->tState.localPosition().x());
00954         if( AbsDx <= 20 or AbsDx/sqrt(localError.xx()) <= 4 ) matchedChamber.rpcMatches.push_back(rpcHitMatch);
00955       }
00956 
00957       muonChamberMatches.push_back(matchedChamber);
00958     }
00959   }
00960 
00961    aMuon.setMatches(muonChamberMatches);
00962 
00963    LogTrace("MuonIdentification") << "number of muon chambers: " << aMuon.matches().size() << "\n" 
00964      << "number of chambers with segments according to the associator requirements: " << 
00965      nubmerOfMatchesAccordingToTrackAssociator;
00966    LogTrace("MuonIdentification") << "number of segment matches with the producer requirements: " << 
00967      aMuon.numberOfMatches( reco::Muon::NoArbitration );
00968    
00969    // fillTime( iEvent, iSetup, aMuon );
00970 }
00971 
00972 void MuonIdProducer::fillArbitrationInfo( reco::MuonCollection* pOutputMuons )
00973 {
00974    //
00975    // apply segment flags
00976    //
00977    std::vector<std::pair<reco::MuonChamberMatch*,reco::MuonSegmentMatch*> > chamberPairs;     // for chamber segment sorting
00978    std::vector<std::pair<reco::MuonChamberMatch*,reco::MuonSegmentMatch*> > stationPairs;     // for station segment sorting
00979    std::vector<std::pair<reco::MuonChamberMatch*,reco::MuonSegmentMatch*> > arbitrationPairs; // for muon segment arbitration
00980 
00981    // muonIndex1
00982    for( unsigned int muonIndex1 = 0; muonIndex1 < pOutputMuons->size(); ++muonIndex1 )
00983    {
00984       // chamberIter1
00985       for( std::vector<reco::MuonChamberMatch>::iterator chamberIter1 = pOutputMuons->at(muonIndex1).matches().begin();
00986             chamberIter1 != pOutputMuons->at(muonIndex1).matches().end(); ++chamberIter1 )
00987       {
00988          if(chamberIter1->segmentMatches.empty()) continue;
00989          chamberPairs.clear();
00990 
00991          // segmentIter1
00992          for( std::vector<reco::MuonSegmentMatch>::iterator segmentIter1 = chamberIter1->segmentMatches.begin();
00993                segmentIter1 != chamberIter1->segmentMatches.end(); ++segmentIter1 )
00994          {
00995             chamberPairs.push_back(std::make_pair(&(*chamberIter1), &(*segmentIter1)));
00996             if(!segmentIter1->isMask()) // has not yet been arbitrated
00997             {
00998                arbitrationPairs.clear();
00999                arbitrationPairs.push_back(std::make_pair(&(*chamberIter1), &(*segmentIter1)));
01000 
01001                
01002 
01003                // find identical segments with which to arbitrate
01004                // tracker muons only
01005                if (pOutputMuons->at(muonIndex1).isTrackerMuon()) {
01006                   // muonIndex2
01007                   for( unsigned int muonIndex2 = muonIndex1+1; muonIndex2 < pOutputMuons->size(); ++muonIndex2 )
01008                   {
01009                      // tracker muons only
01010                      if (! pOutputMuons->at(muonIndex2).isTrackerMuon()) continue;
01011                      // chamberIter2
01012                      for( std::vector<reco::MuonChamberMatch>::iterator chamberIter2 = pOutputMuons->at(muonIndex2).matches().begin();
01013                            chamberIter2 != pOutputMuons->at(muonIndex2).matches().end(); ++chamberIter2 )
01014                      {
01015                         // segmentIter2
01016                         for( std::vector<reco::MuonSegmentMatch>::iterator segmentIter2 = chamberIter2->segmentMatches.begin();
01017                               segmentIter2 != chamberIter2->segmentMatches.end(); ++segmentIter2 )
01018                         {
01019                            if(segmentIter2->isMask()) continue; // has already been arbitrated
01020                            if(fabs(segmentIter2->x       - segmentIter1->x      ) < 1E-3 &&
01021                                  fabs(segmentIter2->y       - segmentIter1->y      ) < 1E-3 &&
01022                                  fabs(segmentIter2->dXdZ    - segmentIter1->dXdZ   ) < 1E-3 &&
01023                                  fabs(segmentIter2->dYdZ    - segmentIter1->dYdZ   ) < 1E-3 &&
01024                                  fabs(segmentIter2->xErr    - segmentIter1->xErr   ) < 1E-3 &&
01025                                  fabs(segmentIter2->yErr    - segmentIter1->yErr   ) < 1E-3 &&
01026                                  fabs(segmentIter2->dXdZErr - segmentIter1->dXdZErr) < 1E-3 &&
01027                                  fabs(segmentIter2->dYdZErr - segmentIter1->dYdZErr) < 1E-3)
01028                               arbitrationPairs.push_back(std::make_pair(&(*chamberIter2), &(*segmentIter2)));
01029                         } // segmentIter2
01030                      } // chamberIter2
01031                   } // muonIndex2
01032                }
01033 
01034                // arbitration segment sort
01035                if(arbitrationPairs.empty()) continue; // this should never happen
01036                if(arbitrationPairs.size()==1) {
01037                   arbitrationPairs.front().second->setMask(reco::MuonSegmentMatch::BelongsToTrackByDRSlope);
01038                   arbitrationPairs.front().second->setMask(reco::MuonSegmentMatch::BelongsToTrackByDXSlope);
01039                   arbitrationPairs.front().second->setMask(reco::MuonSegmentMatch::BelongsToTrackByDR);
01040                   arbitrationPairs.front().second->setMask(reco::MuonSegmentMatch::BelongsToTrackByDX);
01041                   arbitrationPairs.front().second->setMask(reco::MuonSegmentMatch::Arbitrated);
01042                } else {
01043                   sort(arbitrationPairs.begin(), arbitrationPairs.end(), SortMuonSegmentMatches(reco::MuonSegmentMatch::BelongsToTrackByDRSlope));
01044                   arbitrationPairs.front().second->setMask(reco::MuonSegmentMatch::BelongsToTrackByDRSlope);
01045                   sort(arbitrationPairs.begin(), arbitrationPairs.end(), SortMuonSegmentMatches(reco::MuonSegmentMatch::BelongsToTrackByDXSlope));
01046                   arbitrationPairs.front().second->setMask(reco::MuonSegmentMatch::BelongsToTrackByDXSlope);
01047                   sort(arbitrationPairs.begin(), arbitrationPairs.end(), SortMuonSegmentMatches(reco::MuonSegmentMatch::BelongsToTrackByDR));
01048                   arbitrationPairs.front().second->setMask(reco::MuonSegmentMatch::BelongsToTrackByDR);
01049                   sort(arbitrationPairs.begin(), arbitrationPairs.end(), SortMuonSegmentMatches(reco::MuonSegmentMatch::BelongsToTrackByDX));
01050                   arbitrationPairs.front().second->setMask(reco::MuonSegmentMatch::BelongsToTrackByDX);
01051                   for( unsigned int it = 0; it < arbitrationPairs.size(); ++it )
01052                      arbitrationPairs.at(it).second->setMask(reco::MuonSegmentMatch::Arbitrated);
01053                }
01054             }
01055             
01056             // setup me1a cleaning for later
01057             if( chamberIter1->id.subdetId() == MuonSubdetId::CSC && arbClean_ ) {
01058               CSCDetId cscid(chamberIter1->id);
01059               if(cscid.ring() == 4)
01060                 for( std::vector<reco::MuonSegmentMatch>::iterator segmentIter2 = chamberIter1->segmentMatches.begin();
01061                      segmentIter2 != chamberIter1->segmentMatches.end(); ++segmentIter2 ) {
01062                   if( segmentIter1->cscSegmentRef.isNonnull() && segmentIter2->cscSegmentRef.isNonnull() ) 
01063                     if( meshAlgo_->isDuplicateOf(segmentIter1->cscSegmentRef,segmentIter2->cscSegmentRef) && 
01064                         (segmentIter2->mask & 0x1e0000) && 
01065                         (segmentIter1->mask & 0x1e0000) ) 
01066                       segmentIter2->setMask(reco::MuonSegmentMatch::BelongsToTrackByME1aClean);
01067                   //if the track has lost the segment already through normal arbitration no need to do it again.
01068                 }
01069             }// mark all ME1/a duplicates that this track owns
01070 
01071          } // segmentIter1
01072 
01073          // chamber segment sort
01074          if(chamberPairs.empty()) continue; // this should never happen
01075          if(chamberPairs.size()==1) {
01076             chamberPairs.front().second->setMask(reco::MuonSegmentMatch::BestInChamberByDRSlope);
01077             chamberPairs.front().second->setMask(reco::MuonSegmentMatch::BestInChamberByDXSlope);
01078             chamberPairs.front().second->setMask(reco::MuonSegmentMatch::BestInChamberByDR);
01079             chamberPairs.front().second->setMask(reco::MuonSegmentMatch::BestInChamberByDX);
01080          } else {
01081             sort(chamberPairs.begin(), chamberPairs.end(), SortMuonSegmentMatches(reco::MuonSegmentMatch::BestInChamberByDRSlope));
01082             chamberPairs.front().second->setMask(reco::MuonSegmentMatch::BestInChamberByDRSlope);
01083             sort(chamberPairs.begin(), chamberPairs.end(), SortMuonSegmentMatches(reco::MuonSegmentMatch::BestInChamberByDXSlope));
01084             chamberPairs.front().second->setMask(reco::MuonSegmentMatch::BestInChamberByDXSlope);
01085             sort(chamberPairs.begin(), chamberPairs.end(), SortMuonSegmentMatches(reco::MuonSegmentMatch::BestInChamberByDR));
01086             chamberPairs.front().second->setMask(reco::MuonSegmentMatch::BestInChamberByDR);
01087             sort(chamberPairs.begin(), chamberPairs.end(), SortMuonSegmentMatches(reco::MuonSegmentMatch::BestInChamberByDX));
01088             chamberPairs.front().second->setMask(reco::MuonSegmentMatch::BestInChamberByDX);
01089          }
01090       } // chamberIter1
01091 
01092       // station segment sort
01093       for( int stationIndex = 1; stationIndex < 5; ++stationIndex )
01094          for( int detectorIndex = 1; detectorIndex < 4; ++detectorIndex )
01095          {
01096             stationPairs.clear();
01097 
01098             // chamberIter
01099             for( std::vector<reco::MuonChamberMatch>::iterator chamberIter = pOutputMuons->at(muonIndex1).matches().begin();
01100                   chamberIter != pOutputMuons->at(muonIndex1).matches().end(); ++chamberIter )
01101             {
01102                if(!(chamberIter->station()==stationIndex && chamberIter->detector()==detectorIndex)) continue;
01103                if(chamberIter->segmentMatches.empty()) continue;
01104 
01105                for( std::vector<reco::MuonSegmentMatch>::iterator segmentIter = chamberIter->segmentMatches.begin();
01106                      segmentIter != chamberIter->segmentMatches.end(); ++segmentIter )
01107                   stationPairs.push_back(std::make_pair(&(*chamberIter), &(*segmentIter)));
01108             } // chamberIter
01109 
01110             if(stationPairs.empty()) continue; // this may very well happen
01111             if(stationPairs.size()==1) {
01112                stationPairs.front().second->setMask(reco::MuonSegmentMatch::BestInStationByDRSlope);
01113                stationPairs.front().second->setMask(reco::MuonSegmentMatch::BestInStationByDXSlope);
01114                stationPairs.front().second->setMask(reco::MuonSegmentMatch::BestInStationByDR);
01115                stationPairs.front().second->setMask(reco::MuonSegmentMatch::BestInStationByDX);
01116             } else {
01117                sort(stationPairs.begin(), stationPairs.end(), SortMuonSegmentMatches(reco::MuonSegmentMatch::BestInStationByDRSlope));
01118                stationPairs.front().second->setMask(reco::MuonSegmentMatch::BestInStationByDRSlope);
01119                sort(stationPairs.begin(), stationPairs.end(), SortMuonSegmentMatches(reco::MuonSegmentMatch::BestInStationByDXSlope));
01120                stationPairs.front().second->setMask(reco::MuonSegmentMatch::BestInStationByDXSlope);
01121                sort(stationPairs.begin(), stationPairs.end(), SortMuonSegmentMatches(reco::MuonSegmentMatch::BestInStationByDR));
01122                stationPairs.front().second->setMask(reco::MuonSegmentMatch::BestInStationByDR);
01123                sort(stationPairs.begin(), stationPairs.end(), SortMuonSegmentMatches(reco::MuonSegmentMatch::BestInStationByDX));
01124                stationPairs.front().second->setMask(reco::MuonSegmentMatch::BestInStationByDX);
01125             }
01126          }
01127 
01128    } // muonIndex1
01129 
01130    if(arbClean_) {
01131      // clear old mesh, create and prune new mesh!
01132      meshAlgo_->clearMesh();
01133      meshAlgo_->runMesh(pOutputMuons);
01134    }
01135 }
01136 
01137 void MuonIdProducer::fillMuonIsolation(edm::Event& iEvent, const edm::EventSetup& iSetup, reco::Muon& aMuon,
01138                                        reco::IsoDeposit& trackDep, reco::IsoDeposit& ecalDep, reco::IsoDeposit& hcalDep, reco::IsoDeposit& hoDep,
01139                                        reco::IsoDeposit& jetDep)
01140 {
01141    reco::MuonIsolation isoR03, isoR05;
01142    const reco::Track* track = 0;
01143    if ( ! aMuon.track().isNull() )
01144      track = aMuon.track().get();
01145    else 
01146      {
01147         if ( ! aMuon.standAloneMuon().isNull() )
01148           track = aMuon.standAloneMuon().get();
01149         else
01150           throw cms::Exception("FatalError") << "Failed to compute muon isolation information for a muon with undefined references to tracks"; 
01151      }
01152 
01153    // get deposits
01154    reco::IsoDeposit depTrk = muIsoExtractorTrack_->deposit(iEvent, iSetup, *track );
01155    std::vector<reco::IsoDeposit> caloDeps = muIsoExtractorCalo_->deposits(iEvent, iSetup, *track);
01156    reco::IsoDeposit depJet = muIsoExtractorJet_->deposit(iEvent, iSetup, *track );
01157 
01158    if(caloDeps.size()!=3) {
01159       LogTrace("MuonIdentification") << "Failed to fill vector of calorimeter isolation deposits!";
01160       return;
01161    }
01162 
01163    reco::IsoDeposit depEcal = caloDeps.at(0);
01164    reco::IsoDeposit depHcal = caloDeps.at(1);
01165    reco::IsoDeposit depHo   = caloDeps.at(2);
01166 
01167    trackDep = depTrk;
01168    ecalDep = depEcal;
01169    hcalDep = depHcal;
01170    hoDep = depHo;
01171    jetDep = depJet;
01172 
01173    isoR03.sumPt     = depTrk.depositWithin(0.3);
01174    isoR03.emEt      = depEcal.depositWithin(0.3);
01175    isoR03.hadEt     = depHcal.depositWithin(0.3);
01176    isoR03.hoEt      = depHo.depositWithin(0.3);
01177    isoR03.nTracks   = depTrk.depositAndCountWithin(0.3).second;
01178    isoR03.nJets     = depJet.depositAndCountWithin(0.3).second;
01179    isoR03.trackerVetoPt  = depTrk.candEnergy();
01180    isoR03.emVetoEt       = depEcal.candEnergy();
01181    isoR03.hadVetoEt      = depHcal.candEnergy();
01182    isoR03.hoVetoEt       = depHo.candEnergy();
01183 
01184    isoR05.sumPt     = depTrk.depositWithin(0.5);
01185    isoR05.emEt      = depEcal.depositWithin(0.5);
01186    isoR05.hadEt     = depHcal.depositWithin(0.5);
01187    isoR05.hoEt      = depHo.depositWithin(0.5);
01188    isoR05.nTracks   = depTrk.depositAndCountWithin(0.5).second;
01189    isoR05.nJets     = depJet.depositAndCountWithin(0.5).second;
01190    isoR05.trackerVetoPt  = depTrk.candEnergy();
01191    isoR05.emVetoEt       = depEcal.candEnergy();
01192    isoR05.hadVetoEt      = depHcal.candEnergy();
01193    isoR05.hoVetoEt       = depHo.candEnergy();
01194 
01195 
01196    aMuon.setIsolation(isoR03, isoR05);
01197 
01198 }
01199 
01200 reco::Muon MuonIdProducer::makeMuon( const reco::Track& track )
01201 {
01202    //FIXME: E = sqrt(p^2 + m^2), where m == 0.105658369(9)GeV 
01203    double energy = sqrt(track.p() * track.p() + 0.011163691);
01204    math::XYZTLorentzVector p4(track.px(),
01205                               track.py(),
01206                               track.pz(),
01207                               energy);
01208    return reco::Muon( track.charge(), p4, track.vertex() );
01209 }
01210 
01211 double MuonIdProducer::sectorPhi( const DetId& id )
01212 {
01213    double phi = 0;
01214    if( id.subdetId() ==  MuonSubdetId::DT ) {    // DT
01215       DTChamberId muonId(id.rawId());
01216       if ( muonId.sector() <= 12 )
01217         phi = (muonId.sector()-1)/6.*M_PI;
01218       if ( muonId.sector() == 13 ) phi = 3/6.*M_PI;
01219       if ( muonId.sector() == 14 ) phi = 9/6.*M_PI;
01220    }
01221    if( id.subdetId() == MuonSubdetId::CSC ) {    // CSC
01222       CSCDetId muonId(id.rawId());
01223       phi = M_PI/4+(muonId.triggerSector()-1)/3.*M_PI;
01224    }
01225    if ( phi > M_PI ) phi -= 2*M_PI; 
01226    return phi; 
01227 }
01228 
01229 double MuonIdProducer::phiOfMuonIneteractionRegion( const reco::Muon& muon ) const
01230 {
01231    if ( muon.isStandAloneMuon() ) return muon.standAloneMuon()->innerPosition().phi();
01232    // the rest is tracker muon only
01233    if ( muon.matches().empty() ){
01234       if ( muon.innerTrack().isAvailable() &&
01235            muon.innerTrack()->extra().isAvailable() )
01236         return muon.innerTrack()->outerPosition().phi();
01237       else
01238         return muon.phi(); // makes little sense, but what else can I use
01239    }
01240    return sectorPhi(muon.matches().at(0).id);
01241 }
01242 
01243 void MuonIdProducer::fillGlbQuality(edm::Event& iEvent, const edm::EventSetup& iSetup, reco::Muon& aMuon)
01244 {
01245   edm::Handle<edm::ValueMap<reco::MuonQuality> > glbQualH;
01246   iEvent.getByLabel(globalTrackQualityInputTag_, glbQualH);
01247 
01248   if(aMuon.isGlobalMuon() && glbQualH.isValid() && !glbQualH.failedToGet()) {
01249     aMuon.setCombinedQuality((*glbQualH)[aMuon.combinedMuon()]);
01250   }
01251 
01252   LogDebug("MuonIdentification") << "tkChiVal " << aMuon.combinedQuality().trkRelChi2;
01253 
01254 }
01255 
01256 void MuonIdProducer::fillTrackerKink( reco::Muon& aMuon ) {
01257     // skip muons with no tracks
01258     if (aMuon.innerTrack().isNull()) return;
01259     // get quality from muon if already there, otherwise make empty one
01260     reco::MuonQuality quality = (aMuon.isQualityValid() ? aMuon.combinedQuality() : reco::MuonQuality());
01261     // fill it
01262     bool filled = trackerKinkFinder_->fillTrkKink(quality, *aMuon.innerTrack());
01263     // if quality was there, or if we filled it, commit to the muon 
01264     if (filled || aMuon.isQualityValid()) aMuon.setCombinedQuality(quality);
01265 }
01266 
01267 bool MuonIdProducer::checkLinks(const reco::MuonTrackLinks* links) const {
01268   bool trackBAD = links->trackerTrack().isNull();
01269   bool staBAD = links->standAloneTrack().isNull();
01270   bool glbBAD = links->globalTrack().isNull();
01271   if (trackBAD || staBAD || glbBAD ) 
01272     {
01273       edm::LogWarning("muonIDbadLinks") << "Global muon links to constituent tracks are invalid: trkBad "
01274                                         <<trackBAD <<" standaloneBad "<<staBAD<<" globalBad "<<glbBAD
01275                                         <<". There should be no such object. Muon is skipped.";
01276       return false;
01277     }
01278   return true;
01279 }