00001
00002
00003
00004
00005
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <memory>
00022
00023
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
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
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
00117
00118 delete tcmetAlgo_;
00119 }
00120
00121
00122
00123
00124
00125
00126 void MuonTCMETValueMapProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
00127
00128
00129 iEvent.getByLabel(muonInputTag_ , muon_h );
00130 iEvent.getByLabel(beamSpotInputTag_, beamSpot_h);
00131
00132
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
00144 edm::ESHandle<MagneticField> theMagField;
00145 iSetup.get<IdealMagneticFieldRecord>().get(theMagField);
00146 bField = theMagField.product();
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
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
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
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
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
00230 void MuonTCMETValueMapProducer::endJob() {
00231 }
00232
00233
00234 bool MuonTCMETValueMapProducer::isGoodMuon( const reco::Muon* muon ) {
00235 double d0 = -999;
00236 double nhits = 0;
00237 double chi2 = 999;
00238
00239
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
00264 if( !siTrack.isNonnull() ) return false;
00265 if( siTrack->ptError() / siTrack->pt() > muon_dptrel_ ) return false;
00266
00267 else return true;
00268 }
00269
00270
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
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
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
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
00323 d0 = -1 * siTrack->dxy( pvtx );
00324
00325 }else{
00326
00327
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
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
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
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
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
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