CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch12/src/FastSimulation/Muons/plugins/FastL1MuonProducer.cc

Go to the documentation of this file.
00001 //
00002 // Package:    FastL1MuonProducer
00003 // Class:      FastL1MuonProducer
00004 // 
00012 //
00013 // Original Author:  Andrea Perrotta
00014 // Modifications: Patrick Janot.
00015 //         Created:  Mon Oct 30 14:37:24 CET 2006
00016 //
00017 //
00018 
00019 // CMSSW headers 
00020 #include "FWCore/ServiceRegistry/interface/Service.h"
00021 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00022 #include "FWCore/Framework/interface/Event.h"
00023 #include "FWCore/Framework/interface/ESHandle.h"
00024 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00025 
00026 // Regional eta scales...
00027 #include "CondFormats/L1TObjects/interface/L1MuTriggerScales.h"
00028 #include "CondFormats/DataRecord/interface/L1MuTriggerScalesRcd.h"
00029 #include "CondFormats/L1TObjects/interface/L1MuTriggerPtScale.h"
00030 #include "CondFormats/DataRecord/interface/L1MuTriggerPtScaleRcd.h"
00031 
00032 // Fast Simulation headers
00033 #include "FastSimulation/Utilities/interface/RandomEngine.h"
00034 #include "FastSimulation/Muons/plugins/FastL1MuonProducer.h"
00035 
00036 // SimTrack
00037 #include "SimDataFormats/Track/interface/SimTrack.h"
00038 #include "SimDataFormats/TrackingHit/interface/PSimHitContainer.h"
00039 #include "SimDataFormats/TrackingHit/interface/PSimHit.h"
00040 
00041 // L1
00042 #include "FastSimDataFormats/L1GlobalMuonTrigger/interface/SimpleL1MuGMTCand.h"
00043 #include "FastSimulation/Muons/interface/FML1EfficiencyHandler.h"
00044 #include "FastSimulation/Muons/interface/FML1PtSmearer.h"
00045 
00046 // STL headers 
00047 #include <iostream>
00048 
00049 // Data Formats
00050 #include "DataFormats/L1GlobalMuonTrigger/interface/L1MuGMTReadoutCollection.h"
00051 #include "DataFormats/L1Trigger/interface/L1MuonParticle.h"
00052 #include "DataFormats/GeometryVector/interface/LocalPoint.h"
00053 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
00054 
00055 // Geometry
00056 #include "Geometry/Records/interface/MuonGeometryRecord.h"
00057 
00058 #include <map>
00059 
00060 // constants, enums and typedefs
00061 
00062 //
00063 // static data member definitions
00064 //
00065 
00066 double FastL1MuonProducer::muonMassGeV_ = 0.105658369 ; // PDG06
00067 
00068 //
00069 // constructors and destructor
00070 //
00071 FastL1MuonProducer::FastL1MuonProducer(const edm::ParameterSet& iConfig):
00072   myL1EfficiencyHandler(0),
00073   myL1PtSmearer(0)
00074 {
00075 
00076   readParameters(iConfig.getParameter<edm::ParameterSet>("MUONS"));
00077 
00078   //register your products
00079   produces<L1MuonCollection> ();
00080   produces<L1ExtraCollection> ();
00081   produces<L1MuGMTReadoutCollection>();
00082 
00083   // Initialize the random number generator service
00084   edm::Service<edm::RandomNumberGenerator> rng;
00085   if ( ! rng.isAvailable() ) {
00086     throw cms::Exception("Configuration") <<
00087       "ParamMuonProducer requires the RandomGeneratorService \n"
00088       "which is not present in the configuration file. \n"
00089       "You must add the service in the configuration file\n"
00090       "or remove the module that requires it.";
00091   }
00092 
00093   random = new RandomEngine(&(*rng));
00094 
00095 }
00096 
00097 
00098 FastL1MuonProducer::~FastL1MuonProducer()
00099 {
00100  
00101   // do anything here that needs to be done at destruction time
00102   // (e.g. close files, deallocate resources etc.)
00103   
00104   if ( random ) { 
00105     delete random;
00106   }
00107 }
00108 
00109 
00110 //
00111 // member functions
00112 //
00113 
00114 // ------------ method called to produce the data  ------------
00115 
00116 void 
00117 FastL1MuonProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) 
00118 {
00119   using namespace edm;
00120 
00121   Handle<std::vector<SimTrack> > simMuons;
00122   iEvent.getByLabel(theSimModule,simMuons);
00123   unsigned nmuons = simMuons->size();
00124   //  Handle<std::vector<SimVertex> > simVertices;
00125   //  iEvent.getByLabel(theSimModuleLabel_,simVertices);
00126 
00127   Handle<PSimHitContainer> muonDTHits;
00128   iEvent.getByLabel(theDTHits,muonDTHits);
00129   Handle<PSimHitContainer> muonCSCHits;
00130   iEvent.getByLabel(theCSCHits,muonCSCHits);
00131   Handle<PSimHitContainer> muonRPCHits;
00132   iEvent.getByLabel(theRPCHits,muonRPCHits);
00133 
00134 
00135 //
00136 // Loop over generated muons and reconstruct L1, L3 and Global muons
00137 //
00138   
00139   int nMu = 0;
00140   mySimpleL1MuonCands.clear();
00141   mySimpleL1MuonExtraCands.clear();
00142 
00143   std::multimap<float,SimpleL1MuGMTCand*>  mySimpleL1MuonCandsTemp;
00144 
00145   for( unsigned fsimi=0; fsimi < nmuons; ++fsimi) {
00146     // The sim track can be a muon or a decaying hadron
00147     const SimTrack& mySimTrack = (*simMuons)[fsimi];
00148     // Keep only the muons at L1 (either primary or secondary)
00149     int pid = mySimTrack.type();        
00150     if ( fabs(pid) != 13 ) continue;
00151 
00152     // Check whether there are hits in DT/CSC/RPC,
00153     // and keep for the L1 mu the position of first such hit:
00154     bool hasPSimHits = false;
00155     GlobalPoint glbPosition;
00156     PSimHitContainer::const_iterator simDTHit=muonDTHits->begin();
00157     PSimHitContainer::const_iterator endDTHit=muonDTHits->end();
00158     for ( ; simDTHit!=endDTHit; ++simDTHit) {
00159       if ( simDTHit->trackId() == mySimTrack.trackId() ) {
00160         glbPosition = dtGeometry->idToDet(simDTHit->detUnitId())->surface().toGlobal(simDTHit->localPosition());
00161         hasPSimHits = true;
00162         break;
00163       }
00164     }
00165 
00166     if (! hasPSimHits) {
00167       PSimHitContainer::const_iterator simCSCHit=muonCSCHits->begin();
00168       PSimHitContainer::const_iterator endCSCHit=muonCSCHits->end();
00169       for ( ; simCSCHit!=endCSCHit; ++simCSCHit) {
00170         if ( simCSCHit->trackId() == mySimTrack.trackId() ) {
00171           glbPosition = cscGeometry->idToDet(simCSCHit->detUnitId())->surface().toGlobal(simCSCHit->localPosition());
00172           hasPSimHits = true;
00173           break;
00174         }
00175       }
00176     }
00177 
00178     if (! hasPSimHits) {
00179       PSimHitContainer::const_iterator simRPCHit=muonRPCHits->begin();
00180       PSimHitContainer::const_iterator endRPCHit=muonRPCHits->end();
00181       for ( ; simRPCHit!=endRPCHit; ++simRPCHit) {
00182         if ( simRPCHit->trackId() == mySimTrack.trackId() ) {
00183           glbPosition = rpcGeometry->idToDet(simRPCHit->detUnitId())->surface().toGlobal(simRPCHit->localPosition());
00184           hasPSimHits = true;
00185           break;
00186         }
00187       }
00188     }
00189 
00190     // *** Reconstruct parameterized muons starting from undecayed simulated muons
00191     if (hasPSimHits) {
00192 
00193       nMu++;
00194 
00195       //
00196       // Now L1 parametrization
00197       //
00198       double pT = mySimTrack.momentum().pt();
00199       double eta = glbPosition.eta();
00200       // Avoid L1MuScales complains if |eta|>2.4:
00201       if (eta > 2.4) eta = 2.4-1e-6; else if (eta < -2.4) eta = -2.4+1e-6;
00202       double phi = glbPosition.phi();
00203       if ( phi < 0. ) phi = 2* M_PI + phi;
00204 
00205       unsigned etaIndex = theMuScales->getGMTEtaScale()->getPacked(eta);
00206       unsigned phiIndex = theMuScales->getPhiScale()->getPacked(phi);
00207       unsigned pTIndex = theMuPtScale->getPtScale()->getPacked(pT);
00208       float etaValue = theMuScales->getGMTEtaScale()->getLowEdge(etaIndex);
00209       float phiValue = theMuScales->getPhiScale()->getLowEdge(phiIndex);
00210       float pTValue = theMuPtScale->getPtScale()->getLowEdge(pTIndex) + 1e-6;
00211       float etaValue2 = theMuScales->getGMTEtaScale()->getLowEdge(etaIndex+1);
00212       float phiValue2 = theMuScales->getPhiScale()->getLowEdge(phiIndex+1);
00213       float pTValue2 = theMuPtScale->getPtScale()->getLowEdge(pTIndex+1) + 1e-6;
00214      
00215       // Choose the closest index. (Not sure it is what is to be done)
00216       if ( fabs(etaValue2 - eta) < fabs(etaValue-eta) ) { 
00217         etaValue = etaValue2;
00218         ++etaIndex;
00219       }
00220       if ( fabs(phiValue2-phi) < fabs(phiValue-phi) ) { 
00221         phiValue = phiValue2;
00222         ++phiIndex;
00223       }
00224       if ( fabs(pTValue2-pT) < fabs(pTValue-pT) ) { 
00225         pTValue = pTValue2;
00226         ++pTIndex;
00227       }
00228 
00229       SimpleL1MuGMTCand * thisL1MuonCand = 
00230         new SimpleL1MuGMTCand(&mySimTrack,
00231                               etaIndex, phiIndex, pTIndex,
00232                               etaValue,phiValue,pTValue);
00233       bool hasL1 = myL1EfficiencyHandler->kill(thisL1MuonCand);
00234       if (hasL1) {
00235         bool status2 = myL1PtSmearer->smear(thisL1MuonCand);
00236         if (!status2) { std::cout << "Pt smearing of L1 muon went wrong!!" << std::endl; }
00237         if (status2) {
00238           mySimpleL1MuonCandsTemp.insert(
00239                std::pair<float,SimpleL1MuGMTCand*>(thisL1MuonCand->ptValue(),thisL1MuonCand));
00240         }
00241         else {
00242           delete thisL1MuonCand;
00243         }
00244       }
00245 
00246     }
00247 
00248   }
00249   
00250   // kill low ranked L1 muons, and fill L1extra muons -->
00251   std::multimap<float,SimpleL1MuGMTCand*>::const_reverse_iterator L1mu = mySimpleL1MuonCandsTemp.rbegin();
00252   std::multimap<float,SimpleL1MuGMTCand*>::const_reverse_iterator lastL1mu = mySimpleL1MuonCandsTemp.rend();
00253   unsigned rank=0;
00254   unsigned rankb=0;
00255   unsigned rankf=0;
00256   for ( ; L1mu!=lastL1mu; ++L1mu ) {
00257     SimpleL1MuGMTCand* theMuon = L1mu->second;
00258     theMuon->setRPCBit(0);
00259     ++rank;
00260     bool addMu = false;
00261     if  (theMuon->isFwd() ) { 
00262       if ( rankf < 4 ) addMu = true;
00263       theMuon->setRPCIndex(rankf);
00264       theMuon->setDTCSCIndex(rankf);
00265       rankf++;
00266     } else {  
00267       if ( rankb < 4 ) addMu = true;
00268       theMuon->setRPCIndex(rankb);
00269       theMuon->setDTCSCIndex(rankb);
00270       rankb++;
00271     } 
00272 
00273     if ( addMu ) {
00274       theMuon->setRank(rank);
00275       mySimpleL1MuonCands.push_back(theMuon);
00276       double pt = theMuon->ptValue() + 1.e-6 ;
00277       double eta = theMuon->etaValue();
00278       double phi = theMuon->phiValue();
00279       math::PtEtaPhiMLorentzVector PtEtaPhiMP4(pt,eta,phi,muonMassGeV_);
00280       math::XYZTLorentzVector myL1P4(PtEtaPhiMP4);
00281       // math::PtEtaPhiMLorentzVector myL1P4(pt,eta,phi,muonMassGeV_);
00282       mySimpleL1MuonExtraCands.push_back( l1extra::L1MuonParticle( theMuon->charge(), myL1P4, *theMuon ) );
00283     }
00284     else {
00285       theMuon->setRank(0);
00286     }
00287 
00288   }
00289 
00290 // end killing of low ranked L1 muons -->
00291 
00292 
00293   int nL1 =  mySimpleL1MuonCands.size();
00294   nMuonTot   += nMu;
00295   nL1MuonTot += nL1;
00296 
00297   std::auto_ptr<L1MuonCollection> l1Out(new L1MuonCollection);
00298   std::auto_ptr<L1ExtraCollection> l1ExtraOut(new L1ExtraCollection);
00299   std::auto_ptr<L1MuGMTReadoutCollection> l1ReadOut(new L1MuGMTReadoutCollection(1));
00300   
00301   loadL1Muons(*l1Out,*l1ExtraOut,*l1ReadOut);
00302   iEvent.put(l1Out);
00303   iEvent.put(l1ExtraOut);
00304   iEvent.put(l1ReadOut);
00305 
00306   L1mu = mySimpleL1MuonCandsTemp.rbegin();
00307   for ( ; L1mu!=lastL1mu; ++L1mu ) {
00308     delete L1mu->second;
00309   }
00310 }
00311 
00312 
00313 void FastL1MuonProducer::loadL1Muons(L1MuonCollection & c , 
00314                                      L1ExtraCollection & d,
00315                                      L1MuGMTReadoutCollection & e) const
00316 {
00317 
00318   FML1Muons::const_iterator l1mu;
00319   L1ExtraCollection::const_iterator l1ex;
00320   L1MuGMTReadoutRecord rc = L1MuGMTReadoutRecord(0);
00321 
00322   // Add L1 muons:
00323   // int nmuons = mySimpleL1MuonCands.size();
00324   for (l1mu=mySimpleL1MuonCands.begin();l1mu!=mySimpleL1MuonCands.end();++l1mu) {
00325     c.push_back(*(*l1mu));
00326   }
00327   
00328 // Add extra particles.
00329   int nr = 0; 
00330   int nrb = 0; 
00331   int nrf = 0;
00332   for (l1ex=mySimpleL1MuonExtraCands.begin();l1ex!=mySimpleL1MuonExtraCands.end();++l1ex) {
00333 
00334     d.push_back(*l1ex);
00335     
00336     L1MuGMTExtendedCand aMuon(l1ex->gmtMuonCand());
00337 
00338     rc.setGMTCand(nr,aMuon);
00339     // Find the regional eta index
00340     double etaPilePoil = mySimpleL1MuonCands[nr]->getMomentum().Eta();
00341 
00342     nr++;
00343     unsigned typeRPC=0;
00344     unsigned typeDTCSC=0;
00345     unsigned RPCIndex=0;
00346     unsigned DTCSCIndex=0;
00347     unsigned RPCRegionalEtaIndex=0;
00348     unsigned DTCSCRegionalEtaIndex=0;
00349     float etaRPCValue=-10.;
00350     float etaDTCSCValue=-10.;
00351     // Forward muons
00352     if ( aMuon.isFwd() ) { 
00353 
00354       rc.setGMTFwdCand(nrf,aMuon);
00355 
00356       // CSC
00357       typeDTCSC = 2;
00358       DTCSCIndex = 8+nrf;
00359       DTCSCRegionalEtaIndex = theMuScales->getRegionalEtaScale(2)->getPacked(etaPilePoil); 
00360       etaDTCSCValue = theMuScales->getRegionalEtaScale(2)->getLowEdge(DTCSCRegionalEtaIndex);
00361       float etaDTCSCValue2 = theMuScales->getRegionalEtaScale(2)->getLowEdge(DTCSCRegionalEtaIndex+1);
00362       if ( fabs(etaDTCSCValue2-etaPilePoil) < fabs(etaDTCSCValue-etaPilePoil) ) { 
00363         etaDTCSCValue = etaDTCSCValue2;
00364         ++DTCSCRegionalEtaIndex;
00365       }
00366       // RPC (limited to the RPC acceptance)
00367       if ( fabs(etaPilePoil) < 2.1 ) { 
00368         RPCIndex = 12+nrf;
00369         typeRPC = 3;
00370         RPCRegionalEtaIndex = theMuScales->getRegionalEtaScale(3)->getPacked(etaPilePoil); 
00371         etaRPCValue = theMuScales->getRegionalEtaScale(3)->getLowEdge(RPCRegionalEtaIndex);
00372         float etaRPCValue2 = theMuScales->getRegionalEtaScale(3)->getLowEdge(RPCRegionalEtaIndex+1);
00373         if ( fabs(etaRPCValue2-etaPilePoil) < fabs(etaRPCValue-etaPilePoil) ) { 
00374           etaRPCValue = etaRPCValue2;
00375           ++RPCRegionalEtaIndex;
00376         }
00377       }
00378       // Next muon
00379       nrf++;
00380 
00381     // Barrel muons
00382     } else { 
00383 
00384       rc.setGMTBrlCand(nrb,aMuon);
00385 
00386       // DT
00387       typeDTCSC = 0;
00388       DTCSCIndex = 0+nrb;
00389       DTCSCRegionalEtaIndex = theMuScales->getRegionalEtaScale(0)->getPacked(etaPilePoil); 
00390       etaDTCSCValue = theMuScales->getRegionalEtaScale(0)->getLowEdge(DTCSCRegionalEtaIndex);
00391       float etaDTCSCValue2 = theMuScales->getRegionalEtaScale(0)->getLowEdge(DTCSCRegionalEtaIndex+1);
00392       if ( fabs(etaDTCSCValue2-etaPilePoil) < fabs(etaDTCSCValue-etaPilePoil) ) { 
00393         etaDTCSCValue = etaDTCSCValue2;
00394         ++DTCSCRegionalEtaIndex;
00395       }
00396 
00397       // RPC
00398       typeRPC = 1;
00399       RPCIndex = 4+nrb;
00400       RPCRegionalEtaIndex = theMuScales->getRegionalEtaScale(1)->getPacked(etaPilePoil); 
00401       etaRPCValue = theMuScales->getRegionalEtaScale(1)->getLowEdge(RPCRegionalEtaIndex);
00402       float etaRPCValue2 = theMuScales->getRegionalEtaScale(1)->getLowEdge(RPCRegionalEtaIndex+1);
00403       if ( fabs(etaRPCValue2-etaPilePoil) < fabs(etaRPCValue-etaPilePoil) ) { 
00404         etaRPCValue = etaRPCValue2;
00405         ++RPCRegionalEtaIndex;
00406       }
00407 
00408       // Next muon
00409       nrb++;
00410 
00411     }
00412 
00413     // Add a muon regional candidate - first DT/CSC
00414     L1MuRegionalCand regionalMuonDTCSC = 
00415       L1MuRegionalCand(typeDTCSC,
00416                        aMuon.phiIndex(),
00417                        DTCSCRegionalEtaIndex,
00418                        aMuon.ptIndex(),
00419                        (1-aMuon.charge())/2,
00420                        aMuon.charge_valid(),
00421                        1,   // FineHalo
00422                        aMuon.quality(),
00423                        aMuon.bx());
00424     regionalMuonDTCSC.setPhiValue(aMuon.phiValue());
00425     regionalMuonDTCSC.setEtaValue(etaDTCSCValue);
00426     regionalMuonDTCSC.setPtValue(aMuon.ptValue());    
00427     
00428     rc.setInputCand(DTCSCIndex,regionalMuonDTCSC);
00429  
00430     // Then RPC (if in RPC acceptance)
00431     if ( fabs(etaPilePoil) < 2.1 ) { 
00432       L1MuRegionalCand regionalMuonRPC = 
00433         L1MuRegionalCand(typeRPC,
00434                          aMuon.phiIndex(),
00435                          RPCRegionalEtaIndex,
00436                          aMuon.ptIndex(),
00437                          (1-aMuon.charge())/2,
00438                          aMuon.charge_valid(),
00439                          0,   // FineHalo
00440                          aMuon.quality(),
00441                          aMuon.bx());
00442       regionalMuonRPC.setPhiValue(aMuon.phiValue());
00443       regionalMuonRPC.setEtaValue(etaRPCValue);
00444       regionalMuonRPC.setPtValue(aMuon.ptValue());
00445 
00446       rc.setInputCand(RPCIndex,regionalMuonRPC);
00447 
00448     }
00449 
00450   }
00451 
00452   // Update the event
00453   e.addRecord(rc);
00454 
00455 }
00456 
00457 // ------------ method called once each job just before starting event loop  ------------
00458 void 
00459 FastL1MuonProducer::beginJob()
00460 {
00461 
00462   // Initialize
00463   nMuonTot = 0;
00464 
00465   nL1MuonTot = 0;
00466   mySimpleL1MuonCands.clear();
00467   mySimpleL1MuonExtraCands.clear();
00468   myL1EfficiencyHandler = new FML1EfficiencyHandler(random);
00469   myL1PtSmearer = new FML1PtSmearer(random);
00470 
00471 
00472 }
00473 
00474 void 
00475 FastL1MuonProducer::beginRun(edm::Run & run, 
00476                              const edm::EventSetup & es) {
00477 
00478 // Get the DT Geometry
00479   es.get<MuonGeometryRecord>().get(dtGeometry);
00480 // Get the CSC Geometry
00481   es.get<MuonGeometryRecord>().get(cscGeometry);
00482 // Get the RPC Geometry
00483   es.get<MuonGeometryRecord>().get(rpcGeometry);
00484 
00485   // Read trigger scales
00486   edm::ESHandle< L1MuTriggerScales > muScales ;
00487   es.get< L1MuTriggerScalesRcd >().get( muScales ) ;
00488   theMuScales = &(*muScales);
00489 
00490   edm::ESHandle< L1MuTriggerPtScale > muPtScale ;
00491   es.get< L1MuTriggerPtScaleRcd >().get( muPtScale ) ;
00492   theMuPtScale = &(*muPtScale);
00493 
00494 }
00495 
00496 // ------------ method called once each job just after ending the event loop  ------------
00497 void 
00498 FastL1MuonProducer::endJob() {
00499 
00500   if (myL1EfficiencyHandler) delete myL1EfficiencyHandler;
00501   if ( myL1PtSmearer) delete myL1PtSmearer;
00502   std::cout << " ===> FastL1MuonProducer , final report." << std::endl;
00503   std::cout << " ===> Number of total -> L1 muons in the whole job : "
00504             <<   nMuonTot << " -> " << nL1MuonTot << std::endl;
00505 }
00506 
00507 
00508 void FastL1MuonProducer::readParameters(const edm::ParameterSet& fastMuons) {
00509   // Muons
00510   theSimModule = fastMuons.getParameter<edm::InputTag>("simModule");
00511   theDTHits = fastMuons.getParameter<edm::InputTag>("dtSimHits");
00512   theCSCHits = fastMuons.getParameter<edm::InputTag>("cscSimHits");
00513   theRPCHits = fastMuons.getParameter<edm::InputTag>("rpcSimHits");
00514 
00515 }
00516 
00517