CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/RecoMET/METProducers/src/MuonTCMETValueMapProducer.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:    MuonTCMETValueMapProducer
00004 // Class:      MuonTCMETValueMapProducer
00005 // 
00013 //
00014 // Original Author:  Frank Golf
00015 //         Created:  Sun Mar 15 11:33:20 CDT 2009
00016 // $Id: MuonTCMETValueMapProducer.cc,v 1.10 2012/01/28 16:01:24 eulisse Exp $
00017 //
00018 //
00019 
00020 // system include files
00021 #include <memory>
00022 
00023 // user include files
00024 #include "RecoMET/METProducers/interface/MuonTCMETValueMapProducer.h"
00025 
00026 #include "RecoMET/METAlgorithms/interface/TCMETAlgo.h"
00027 
00028 #include "DataFormats/MuonReco/interface/Muon.h"
00029 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
00030 #include "DataFormats/TrackReco/interface/Track.h"
00031 #include "DataFormats/TrackReco/interface/TrackBase.h"
00032 #include "DataFormats/TrackReco/interface/TrackFwd.h"
00033 #include "DataFormats/Common/interface/ValueMap.h" 
00034 #include "DataFormats/MuonReco/interface/MuonMETCorrectionData.h"
00035 #include "DataFormats/GeometrySurface/interface/Plane.h"
00036 #include "DataFormats/GeometrySurface/interface/Cylinder.h"
00037 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
00038 #include "DataFormats/GeometryVector/interface/GlobalVector.h"
00039 #include "DataFormats/Math/interface/Point3D.h"
00040 
00041 #include "MagneticField/Engine/interface/MagneticField.h"
00042 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00043 
00044 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
00045 #include "TrackingTools/GeomPropagators/interface/AnalyticalPropagator.h"
00046 
00047 #include "Geometry/Records/interface/IdealGeometryRecord.h"
00048 #include "FWCore/Framework/interface/MakerMacros.h"
00049 
00050 #include "TH2D.h"
00051 #include "TVector3.h"
00052 #include "TMath.h"
00053 
00054 typedef math::XYZTLorentzVector LorentzVector;
00055 typedef math::XYZPoint Point;
00056 
00057 namespace cms {
00058   MuonTCMETValueMapProducer::MuonTCMETValueMapProducer(const edm::ParameterSet& iConfig) {
00059   
00060     produces<edm::ValueMap<reco::MuonMETCorrectionData> > ("muCorrData");
00061 
00062     // get input collections
00063     muonInputTag_     = iConfig.getParameter<edm::InputTag>("muonInputTag"    );
00064     beamSpotInputTag_ = iConfig.getParameter<edm::InputTag>("beamSpotInputTag");
00065     vertexInputTag_   = iConfig.getParameter<edm::InputTag>("vertexInputTag");
00066 
00067     rfType_     = iConfig.getParameter<int>("rf_type");
00068 
00069     nLayers_                = iConfig.getParameter<int>      ("nLayers");
00070     nLayersTight_           = iConfig.getParameter<int>      ("nLayersTight");
00071     vertexNdof_             = iConfig.getParameter<int>      ("vertexNdof");
00072     vertexZ_                = iConfig.getParameter<double>   ("vertexZ");
00073     vertexRho_              = iConfig.getParameter<double>   ("vertexRho");
00074     vertexMaxDZ_            = iConfig.getParameter<double>   ("vertexMaxDZ");
00075     maxpt_eta20_            = iConfig.getParameter<double>   ("maxpt_eta20");
00076     maxpt_eta25_            = iConfig.getParameter<double>   ("maxpt_eta25");
00077 
00078     // get configuration parameters
00079     maxTrackAlgo_    = iConfig.getParameter<int>("trackAlgo_max");
00080     maxd0cut_        = iConfig.getParameter<double>("d0_max"       );
00081     minpt_           = iConfig.getParameter<double>("pt_min"       );
00082     maxpt_           = iConfig.getParameter<double>("pt_max"       );
00083     maxeta_          = iConfig.getParameter<double>("eta_max"      );
00084     maxchi2_         = iConfig.getParameter<double>("chi2_max"     );
00085     minhits_         = iConfig.getParameter<double>("nhits_min"    );
00086     maxPtErr_        = iConfig.getParameter<double>("ptErr_max"    );
00087 
00088     trkQuality_      = iConfig.getParameter<std::vector<int> >("track_quality");
00089     trkAlgos_        = iConfig.getParameter<std::vector<int> >("track_algos"  );
00090     maxchi2_tight_   = iConfig.getParameter<double>("chi2_max_tight");
00091     minhits_tight_   = iConfig.getParameter<double>("nhits_min_tight");
00092     maxPtErr_tight_  = iConfig.getParameter<double>("ptErr_max_tight");
00093     usePvtxd0_       = iConfig.getParameter<bool>("usePvtxd0");
00094     d0cuta_          = iConfig.getParameter<double>("d0cuta");
00095     d0cutb_          = iConfig.getParameter<double>("d0cutb");
00096 
00097     muon_dptrel_  = iConfig.getParameter<double>("muon_dptrel");
00098     muond0_     = iConfig.getParameter<double>("d0_muon"    );
00099     muonpt_     = iConfig.getParameter<double>("pt_muon"    );
00100     muoneta_    = iConfig.getParameter<double>("eta_muon"   );
00101     muonchi2_   = iConfig.getParameter<double>("chi2_muon"  );
00102     muonhits_   = iConfig.getParameter<double>("nhits_muon" );
00103     muonGlobal_   = iConfig.getParameter<bool>("global_muon");
00104     muonTracker_  = iConfig.getParameter<bool>("tracker_muon");
00105     muonDeltaR_ = iConfig.getParameter<double>("deltaR_muon");
00106     useCaloMuons_ = iConfig.getParameter<bool>("useCaloMuons");
00107     muonMinValidStaHits_ = iConfig.getParameter<int>("muonMinValidStaHits");
00108 
00109     response_function = 0;
00110     tcmetAlgo_=new TCMETAlgo();
00111   }
00112 
00113   MuonTCMETValueMapProducer::~MuonTCMETValueMapProducer()
00114   {
00115  
00116     // do anything here that needs to be done at desctruction time
00117     // (e.g. close files, deallocate resources etc.)
00118     delete tcmetAlgo_;
00119   }
00120 
00121   //
00122   // member functions
00123   //
00124 
00125   // ------------ method called to produce the data  ------------
00126   void MuonTCMETValueMapProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
00127   
00128     //get input collections
00129     iEvent.getByLabel(muonInputTag_    , muon_h    );
00130     iEvent.getByLabel(beamSpotInputTag_, beamSpot_h);
00131 
00132     //get vertex collection
00133     hasValidVertex = false;
00134     if( usePvtxd0_ ){
00135       iEvent.getByLabel( vertexInputTag_  , VertexHandle  );
00136        
00137       if( VertexHandle.isValid() ) {
00138         vertexColl = VertexHandle.product();
00139         hasValidVertex = isValidVertex();
00140       } 
00141     }
00142 
00143     //get the Bfield
00144     edm::ESHandle<MagneticField> theMagField;
00145     iSetup.get<IdealMagneticFieldRecord>().get(theMagField);
00146     bField = theMagField.product();
00147 
00148     //make a ValueMap of ints => flags for 
00149     //met correction. The values and meanings of the flags are :
00150     // flag==0 --->    The muon is not used to correct the MET by default
00151     // flag==1 --->    The muon is used to correct the MET. The Global pt is used.
00152     // flag==2 --->    The muon is used to correct the MET. The tracker pt is used.
00153     // flag==3 --->    The muon is used to correct the MET. The standalone pt is used.
00154     // flag==4 --->    The muon is used to correct the MET as pion using the tcMET ZSP RF.
00155     // flag==5 --->    The muon is used to correct the MET.  The default fit is used; i.e. we get the pt from muon->pt().
00156     // In general, the flag should never be 3. You do not want to correct the MET using
00157     // the pt measurement from the standalone system (unless you really know what you're 
00158     // doing
00159 
00160     std::auto_ptr<edm::ValueMap<reco::MuonMETCorrectionData> > vm_muCorrData(new edm::ValueMap<reco::MuonMETCorrectionData>());
00161 
00162     std::vector<reco::MuonMETCorrectionData> v_muCorrData;
00163 
00164     unsigned int nMuons = muon_h->size();
00165 
00166     for (unsigned int iMu = 0; iMu < nMuons; iMu++) {
00167 
00168       const reco::Muon* mu = &(*muon_h)[iMu];
00169       double deltax = 0.0;
00170       double deltay = 0.0;
00171 
00172       reco::MuonMETCorrectionData muMETCorrData(reco::MuonMETCorrectionData::NotUsed, deltax, deltay);
00173     
00174       reco::TrackRef mu_track;
00175       if( mu->isGlobalMuon() || mu->isTrackerMuon() || mu->isCaloMuon() )
00176         mu_track = mu->innerTrack();
00177       else {
00178         v_muCorrData.push_back( muMETCorrData );
00179         continue;
00180       }
00181 
00182       // figure out depositions muons would make if they were treated as pions
00183       if( isGoodTrack( mu ) ) {
00184 
00185         if( mu_track->pt() < minpt_ ) 
00186           muMETCorrData = reco::MuonMETCorrectionData(reco::MuonMETCorrectionData::TreatedAsPion, deltax, deltay);
00187 
00188         else {
00189           int bin_index   = response_function->FindBin( mu_track->eta(), mu_track->pt() );
00190           double response = response_function->GetBinContent( bin_index );
00191 
00192           TVector3 outerTrkPosition = propagateTrack( mu );
00193 
00194           deltax = response * mu_track->p() * sin( outerTrkPosition.Theta() ) * cos( outerTrkPosition.Phi() );
00195           deltay = response * mu_track->p() * sin( outerTrkPosition.Theta() ) * sin( outerTrkPosition.Phi() );
00196 
00197           muMETCorrData = reco::MuonMETCorrectionData(reco::MuonMETCorrectionData::TreatedAsPion, deltax, deltay);
00198         }
00199       }
00200 
00201       // figure out muon flag
00202       if( isGoodMuon( mu ) )
00203         v_muCorrData.push_back( reco::MuonMETCorrectionData(reco::MuonMETCorrectionData::MuonCandidateValuesUsed, deltax, deltay) );
00204 
00205       else if( useCaloMuons_ && isGoodCaloMuon( mu, iMu ) )
00206         v_muCorrData.push_back( reco::MuonMETCorrectionData(reco::MuonMETCorrectionData::MuonCandidateValuesUsed, deltax, deltay) );
00207 
00208       else v_muCorrData.push_back( muMETCorrData );
00209     }
00210     
00211     edm::ValueMap<reco::MuonMETCorrectionData>::Filler dataFiller(*vm_muCorrData);
00212 
00213     dataFiller.insert( muon_h, v_muCorrData.begin(), v_muCorrData.end());
00214     dataFiller.fill();
00215     
00216     iEvent.put(vm_muCorrData, "muCorrData");    
00217   }
00218   
00219   // ------------ method called once each job just before starting event loop  ------------
00220   void MuonTCMETValueMapProducer::beginJob()
00221   {
00222 
00223     if( rfType_ == 1 )
00224                  response_function = tcmetAlgo_->getResponseFunction_fit();
00225     else if( rfType_ == 2 )
00226                  response_function = tcmetAlgo_->getResponseFunction_mode();
00227   }
00228 
00229   // ------------ method called once each job just after ending the event loop  ------------
00230   void MuonTCMETValueMapProducer::endJob() {
00231   }
00232 
00233   // ------------ check is muon is a good muon  ------------
00234   bool MuonTCMETValueMapProducer::isGoodMuon( const reco::Muon* muon ) {
00235     double d0    = -999;
00236     double nhits = 0;
00237     double chi2  = 999;  
00238 
00239     // get d0 corrected for beam spot
00240     bool haveBeamSpot = true;
00241     if( !beamSpot_h.isValid() ) haveBeamSpot = false;
00242 
00243     if( muonGlobal_  && !muon->isGlobalMuon()  ) return false;
00244     if( muonTracker_ && !muon->isTrackerMuon() ) return false;
00245 
00246     const reco::TrackRef siTrack     = muon->innerTrack();
00247     const reco::TrackRef globalTrack = muon->globalTrack();
00248 
00249     Point bspot = haveBeamSpot ? beamSpot_h->position() : Point(0,0,0);
00250     if( siTrack.isNonnull() ) nhits = siTrack->numberOfValidHits();
00251     if( globalTrack.isNonnull() ) {
00252       d0   = -1 * globalTrack->dxy( bspot );
00253       chi2 = globalTrack->normalizedChi2();
00254     }
00255 
00256     if( fabs( d0 ) > muond0_ )                          return false;
00257     if( muon->pt() < muonpt_ )                          return false;
00258     if( fabs( muon->eta() ) > muoneta_ )                return false;
00259     if( nhits < muonhits_ )                             return false;
00260     if( chi2 > muonchi2_ )                              return false;
00261     if( globalTrack->hitPattern().numberOfValidMuonHits() < muonMinValidStaHits_ ) return false;
00262 
00263     //reject muons with tracker dpt/pt > X
00264     if( !siTrack.isNonnull() )                                return false;
00265     if( siTrack->ptError() / siTrack->pt() > muon_dptrel_ )   return false;
00266 
00267     else return true;
00268   }
00269 
00270   // ------------ check if muon is a good calo muon  ------------
00271   bool MuonTCMETValueMapProducer::isGoodCaloMuon( const reco::Muon* muon, const unsigned int index ) {
00272 
00273     if( muon->pt() < 10 ) return false;
00274 
00275     if( !isGoodTrack( muon ) ) return false;
00276 
00277     const reco::TrackRef inputSiliconTrack = muon->innerTrack();
00278     if( !inputSiliconTrack.isNonnull() ) return false;
00279 
00280     //check if it is in the vicinity of a global or tracker muon
00281     unsigned int nMuons = muon_h->size();
00282     for (unsigned int iMu = 0; iMu < nMuons; iMu++) {
00283 
00284       if( iMu == index ) continue;
00285 
00286       const reco::Muon* mu = &(*muon_h)[iMu];
00287 
00288       const reco::TrackRef testSiliconTrack = mu->innerTrack();
00289       if( !testSiliconTrack.isNonnull() ) continue;
00290 
00291       double deltaEta = inputSiliconTrack.get()->eta() - testSiliconTrack.get()->eta();
00292       double deltaPhi = acos( cos( inputSiliconTrack.get()->phi() - testSiliconTrack.get()->phi() ) );
00293       double deltaR   = TMath::Sqrt( deltaEta * deltaEta + deltaPhi * deltaPhi );
00294 
00295       if( deltaR < muonDeltaR_ ) return false;
00296     }
00297 
00298     return true;
00299   }
00300 
00301   // ------------ check if track is good  ------------
00302   bool MuonTCMETValueMapProducer::isGoodTrack( const reco::Muon* muon ) {
00303     double d0    = -999;
00304 
00305     const reco::TrackRef siTrack = muon->innerTrack();
00306     if (!siTrack.isNonnull())
00307       return false;
00308 
00309     if( hasValidVertex ){
00310       //get d0 corrected for primary vertex
00311             
00312       const Point pvtx = Point(vertexColl->begin()->x(),
00313                                vertexColl->begin()->y(), 
00314                                vertexColl->begin()->z());
00315             
00316       d0 = -1 * siTrack->dxy( pvtx );
00317             
00318       double dz = siTrack->dz( pvtx );
00319             
00320       if( fabs( dz ) < vertexMaxDZ_ ){
00321               
00322         //get d0 corrected for pvtx
00323         d0 = -1 * siTrack->dxy( pvtx );
00324               
00325       }else{
00326               
00327         // get d0 corrected for beam spot
00328         bool haveBeamSpot = true;
00329         if( !beamSpot_h.isValid() ) haveBeamSpot = false;
00330               
00331         Point bspot = haveBeamSpot ? beamSpot_h->position() : Point(0,0,0);
00332         d0 = -1 * siTrack->dxy( bspot );
00333               
00334       }
00335     }else{
00336        
00337       // get d0 corrected for beam spot
00338       bool haveBeamSpot = true;
00339       if( !beamSpot_h.isValid() ) haveBeamSpot = false;
00340        
00341       Point bspot = haveBeamSpot ? beamSpot_h->position() : Point(0,0,0);
00342       d0 = -1 * siTrack->dxy( bspot );
00343     }
00344 
00345     if( siTrack->algo() < maxTrackAlgo_ ){
00346       //1st 4 tracking iterations (pT-dependent d0 cut)
00347        
00348       float d0cut = sqrt(std::pow(d0cuta_,2) + std::pow(d0cutb_/siTrack->pt(),2)); 
00349       if(d0cut > maxd0cut_) d0cut = maxd0cut_;
00350        
00351       if( fabs( d0 ) > d0cut )            return false;    
00352       if( nLayers( siTrack ) < nLayers_ ) return false;
00353     }
00354     else{
00355       //last 2 tracking iterations (tighten chi2, nhits, pt error cuts)
00356      
00357       if( siTrack->normalizedChi2() > maxchi2_tight_ )               return false;
00358       if( siTrack->numberOfValidHits() < minhits_tight_ )            return false;
00359       if( (siTrack->ptError() / siTrack->pt()) > maxPtErr_tight_ )   return false;
00360       if( nLayers( siTrack ) < nLayersTight_ )                       return false;
00361     }
00362 
00363     if( siTrack->numberOfValidHits() < minhits_ )                         return false;
00364     if( siTrack->normalizedChi2() > maxchi2_ )                            return false;
00365     if( fabs( siTrack->eta() ) > maxeta_ )                                return false;
00366     if( siTrack->pt() > maxpt_ )                                          return false;
00367     if( (siTrack->ptError() / siTrack->pt()) > maxPtErr_ )                return false;
00368     if( fabs( siTrack->eta() ) > 2.5 && siTrack->pt() > maxpt_eta25_ )    return false;
00369     if( fabs( siTrack->eta() ) > 2.0 && siTrack->pt() > maxpt_eta20_ )    return false;
00370 
00371     int cut = 0;          
00372     for( unsigned int i = 0; i < trkQuality_.size(); i++ ) {
00373 
00374       cut |= (1 << trkQuality_.at(i));
00375     }
00376 
00377     if( !( (siTrack->qualityMask() & cut) == cut ) ) return false;
00378           
00379     bool isGoodAlgo = false;    
00380     if( trkAlgos_.size() == 0 ) isGoodAlgo = true;
00381     for( unsigned int i = 0; i < trkAlgos_.size(); i++ ) {
00382 
00383       if( siTrack->algo() == trkAlgos_.at(i) ) isGoodAlgo = true;
00384     }
00385 
00386     if( !isGoodAlgo ) return false;
00387           
00388     return true;
00389   }
00390 
00391   // ------------ propagate track to calorimeter face  ------------
00392   TVector3 MuonTCMETValueMapProducer::propagateTrack( const reco::Muon* muon) {
00393 
00394     TVector3 outerTrkPosition;
00395 
00396     outerTrkPosition.SetPtEtaPhi( 999., -10., 2 * TMath::Pi() );
00397 
00398     const reco::TrackRef track = muon->innerTrack();
00399 
00400     if( !track.isNonnull() ) {
00401       return outerTrkPosition;
00402     }
00403 
00404     GlobalPoint  tpVertex ( track->vx(), track->vy(), track->vz() );
00405     GlobalVector tpMomentum ( track.get()->px(), track.get()->py(), track.get()->pz() );
00406     int tpCharge ( track->charge() );
00407 
00408     FreeTrajectoryState fts ( tpVertex, tpMomentum, tpCharge, bField);
00409 
00410     const double zdist = 314.;
00411 
00412     const double radius = 130.;
00413 
00414     const double corner = 1.479;
00415 
00416     Plane::PlanePointer lendcap = Plane::build( Plane::PositionType (0, 0, -zdist), Plane::RotationType () );
00417     Plane::PlanePointer rendcap = Plane::build( Plane::PositionType (0, 0, zdist),  Plane::RotationType () );
00418 
00419     Cylinder::CylinderPointer barrel = Cylinder::build( Cylinder::PositionType (0, 0, 0), Cylinder::RotationType (), radius);
00420 
00421     AnalyticalPropagator myAP (bField, alongMomentum, 2*M_PI);
00422 
00423     TrajectoryStateOnSurface tsos;
00424 
00425     if( track.get()->eta() < -corner ) {
00426       tsos = myAP.propagate( fts, *lendcap);
00427     }
00428     else if( fabs(track.get()->eta()) < corner ) {
00429       tsos = myAP.propagate( fts, *barrel);
00430     }
00431     else if( track.get()->eta() > corner ) {
00432       tsos = myAP.propagate( fts, *rendcap);
00433     }
00434 
00435     if( tsos.isValid() )
00436       outerTrkPosition.SetXYZ( tsos.globalPosition().x(), tsos.globalPosition().y(), tsos.globalPosition().z() );
00437 
00438     else 
00439       outerTrkPosition.SetPtEtaPhi( 999., -10., 2 * TMath::Pi() );
00440 
00441     return outerTrkPosition;
00442   }
00443 
00444   // ------------ single pion response function from fit  ------------
00445 
00446   int MuonTCMETValueMapProducer::nLayers(const reco::TrackRef track){
00447     const reco::HitPattern& p = track->hitPattern();
00448     return p.trackerLayersWithMeasurement();
00449   }
00450 
00451   //--------------------------------------------------------------------
00452 
00453   bool MuonTCMETValueMapProducer::isValidVertex(){
00454     
00455     if( vertexColl->begin()->isFake()                ) return false;
00456     if( vertexColl->begin()->ndof() < vertexNdof_    ) return false;
00457     if( fabs( vertexColl->begin()->z() ) > vertexZ_  ) return false;
00458     if( sqrt( std::pow( vertexColl->begin()->x() , 2 ) + std::pow( vertexColl->begin()->y() , 2 ) ) > vertexRho_ ) return false;
00459     
00460     return true;
00461     
00462   }
00463 }
00464