CMS 3D CMS Logo

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