CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/PhysicsTools/PatAlgos/plugins/PATElectronProducer.cc

Go to the documentation of this file.
00001 //
00002 // $Id: PATElectronProducer.cc,v 1.51.2.2 2012/01/19 03:05:00 tjkim Exp $
00003 //
00004 
00005 #include "PhysicsTools/PatAlgos/plugins/PATElectronProducer.h"
00006 
00007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00008 #include "FWCore/ParameterSet/interface/FileInPath.h"
00009 
00010 #include "DataFormats/Common/interface/Association.h"
00011 #include "DataFormats/Common/interface/ValueMap.h"
00012 #include "DataFormats/HepMCCandidate/interface/GenParticleFwd.h"
00013 #include "DataFormats/HepMCCandidate/interface/GenParticle.h"
00014 
00015 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidateFwd.h"
00016 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
00017 
00018 #include "PhysicsTools/PatUtils/interface/TrackerIsolationPt.h"
00019 #include "PhysicsTools/PatUtils/interface/CaloIsolationEnergy.h"
00020 
00021 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
00022 #include "DataFormats/VertexReco/interface/Vertex.h"
00023 
00024 
00025 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
00026 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
00027 
00028 #include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
00029 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
00030 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
00031 #include "TrackingTools/IPTools/interface/IPTools.h"
00032 
00033 #include "DataFormats/GsfTrackReco/interface/GsfTrackFwd.h"
00034 #include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
00035 
00036 #include <vector>
00037 #include <memory>
00038 
00039 
00040 using namespace pat;
00041 using namespace std;
00042 
00043 
00044 PATElectronProducer::PATElectronProducer(const edm::ParameterSet & iConfig) :
00045   isolator_(iConfig.exists("userIsolation") ? iConfig.getParameter<edm::ParameterSet>("userIsolation") : edm::ParameterSet(), false) ,
00046   useUserData_(iConfig.exists("userData"))
00047 {
00048 
00049   // general configurables
00050   electronSrc_      = iConfig.getParameter<edm::InputTag>( "electronSource" );
00051   embedGsfElectronCore_    = iConfig.getParameter<bool>         ( "embedGsfElectronCore" );
00052   embedGsfTrack_    = iConfig.getParameter<bool>         ( "embedGsfTrack" );
00053   embedSuperCluster_= iConfig.getParameter<bool>         ( "embedSuperCluster" );
00054   embedTrack_       = iConfig.getParameter<bool>         ( "embedTrack" );
00055 
00056   // pflow specific
00057   pfElecSrc_           = iConfig.getParameter<edm::InputTag>( "pfElectronSource" );
00058   useParticleFlow_        = iConfig.getParameter<bool>( "useParticleFlow" );
00059   embedPFCandidate_   = iConfig.getParameter<bool>( "embedPFCandidate" );
00060 
00061 
00062   // MC matching configurables
00063   addGenMatch_      = iConfig.getParameter<bool>          ( "addGenMatch" );
00064   if (addGenMatch_) {
00065     embedGenMatch_ = iConfig.getParameter<bool>         ( "embedGenMatch" );
00066     if (iConfig.existsAs<edm::InputTag>("genParticleMatch")) {
00067       genMatchSrc_.push_back(iConfig.getParameter<edm::InputTag>( "genParticleMatch" ));
00068     } else {
00069       genMatchSrc_ = iConfig.getParameter<std::vector<edm::InputTag> >( "genParticleMatch" );
00070     }
00071   }
00072 
00073   // resolution configurables
00074   addResolutions_   = iConfig.getParameter<bool>         ( "addResolutions" );
00075   if (addResolutions_) {
00076     resolutionLoader_ = pat::helper::KinResolutionsLoader(iConfig.getParameter<edm::ParameterSet>("resolutions"));
00077   }
00078 
00079 
00080   // electron ID configurables
00081   addElecID_        = iConfig.getParameter<bool>         ( "addElectronID" );
00082   if (addElecID_) {
00083     // it might be a single electron ID
00084     if (iConfig.existsAs<edm::InputTag>("electronIDSource")) {
00085       elecIDSrcs_.push_back(NameTag("", iConfig.getParameter<edm::InputTag>("electronIDSource")));
00086     }
00087     // or there might be many of them
00088     if (iConfig.existsAs<edm::ParameterSet>("electronIDSources")) {
00089       // please don't configure me twice
00090       if (!elecIDSrcs_.empty()) throw cms::Exception("Configuration") <<
00091                                   "PATElectronProducer: you can't specify both 'electronIDSource' and 'electronIDSources'\n";
00092       // read the different electron ID names
00093       edm::ParameterSet idps = iConfig.getParameter<edm::ParameterSet>("electronIDSources");
00094       std::vector<std::string> names = idps.getParameterNamesForType<edm::InputTag>();
00095       for (std::vector<std::string>::const_iterator it = names.begin(), ed = names.end(); it != ed; ++it) {
00096         elecIDSrcs_.push_back(NameTag(*it, idps.getParameter<edm::InputTag>(*it)));
00097       }
00098     }
00099     // but in any case at least once
00100     if (elecIDSrcs_.empty()) throw cms::Exception("Configuration") <<
00101                                "PATElectronProducer: id addElectronID is true, you must specify either:\n" <<
00102                                "\tInputTag electronIDSource = <someTag>\n" << "or\n" <<
00103                                "\tPSet electronIDSources = { \n" <<
00104                                "\t\tInputTag <someName> = <someTag>   // as many as you want \n " <<
00105                                "\t}\n";
00106   }
00107 
00108   // construct resolution calculator
00109 
00110   //   // IsoDeposit configurables
00111   //   if (iConfig.exists("isoDeposits")) {
00112   //      edm::ParameterSet depconf = iConfig.getParameter<edm::ParameterSet>("isoDeposits");
00113   //      if (depconf.exists("tracker")) isoDepositLabels_.push_back(std::make_pair(TrackerIso, depconf.getParameter<edm::InputTag>("tracker")));
00114   //      if (depconf.exists("ecal"))    isoDepositLabels_.push_back(std::make_pair(ECalIso, depconf.getParameter<edm::InputTag>("ecal")));
00115   //      if (depconf.exists("hcal"))    isoDepositLabels_.push_back(std::make_pair(HCalIso, depconf.getParameter<edm::InputTag>("hcal")));
00116 
00117 
00118   //      if (depconf.exists("user")) {
00119   //         std::vector<edm::InputTag> userdeps = depconf.getParameter<std::vector<edm::InputTag> >("user");
00120   //         std::vector<edm::InputTag>::const_iterator it = userdeps.begin(), ed = userdeps.end();
00121   //         int key = UserBaseIso;
00122   //         for ( ; it != ed; ++it, ++key) {
00123   //             isoDepositLabels_.push_back(std::make_pair(IsolationKeys(key), *it));
00124   //         }
00125   //      }
00126   //   }
00127 
00128   // read isoDeposit labels, for direct embedding
00129   readIsolationLabels(iConfig, "isoDeposits", isoDepositLabels_);
00130 
00131   // read isolation value labels, for direct embedding
00132   readIsolationLabels(iConfig, "isolationValues", isolationValueLabels_);
00133 
00134   // Efficiency configurables
00135   addEfficiencies_ = iConfig.getParameter<bool>("addEfficiencies");
00136   if (addEfficiencies_) {
00137     efficiencyLoader_ = pat::helper::EfficiencyLoader(iConfig.getParameter<edm::ParameterSet>("efficiencies"));
00138   }
00139 
00140   // Check to see if the user wants to add user data
00141   if ( useUserData_ ) {
00142     userDataHelper_ = PATUserDataHelper<Electron>(iConfig.getParameter<edm::ParameterSet>("userData"));
00143   }
00144 
00145   // embed high level selection variables?
00146   embedHighLevelSelection_ = iConfig.getParameter<bool>("embedHighLevelSelection");
00147   if ( embedHighLevelSelection_ ) {
00148     beamLineSrc_ = iConfig.getParameter<edm::InputTag>("beamLineSrc");
00149     usePV_ = iConfig.getParameter<bool>("usePV");
00150     pvSrc_ = iConfig.getParameter<edm::InputTag>("pvSrc");
00151   }
00152 
00153 
00154   // produces vector of muons
00155   produces<std::vector<Electron> >();
00156 
00157 }
00158 
00159 
00160 PATElectronProducer::~PATElectronProducer() {
00161 }
00162 
00163 
00164 void PATElectronProducer::produce(edm::Event & iEvent, const edm::EventSetup & iSetup) {
00165 
00166   // Get the collection of electrons from the event
00167   edm::Handle<edm::View<reco::GsfElectron> > electrons;
00168   iEvent.getByLabel(electronSrc_, electrons);
00169 
00170   if (iEvent.isRealData()){
00171        addGenMatch_ = false;
00172        embedGenMatch_ = false;
00173    }
00174 
00175   // Get the ESHandle for the transient track builder, if needed for
00176   // high level selection embedding
00177   edm::ESHandle<TransientTrackBuilder> trackBuilder;
00178 
00179   if (isolator_.enabled()) isolator_.beginEvent(iEvent,iSetup);
00180 
00181   if (efficiencyLoader_.enabled()) efficiencyLoader_.newEvent(iEvent);
00182   if (resolutionLoader_.enabled()) resolutionLoader_.newEvent(iEvent, iSetup);
00183 
00184   IsoDepositMaps deposits(isoDepositLabels_.size());
00185   for (size_t j = 0, nd = deposits.size(); j < nd; ++j) {
00186     iEvent.getByLabel(isoDepositLabels_[j].second, deposits[j]);
00187   }
00188 
00189   IsolationValueMaps isolationValues(isolationValueLabels_.size());
00190   for (size_t j = 0; j<isolationValueLabels_.size(); ++j) {
00191     iEvent.getByLabel(isolationValueLabels_[j].second, isolationValues[j]);
00192   }
00193 
00194   // prepare the MC matching
00195   GenAssociations  genMatches(genMatchSrc_.size());
00196   if (addGenMatch_) {
00197     for (size_t j = 0, nd = genMatchSrc_.size(); j < nd; ++j) {
00198       iEvent.getByLabel(genMatchSrc_[j], genMatches[j]);
00199     }
00200   }
00201 
00202   // prepare ID extraction
00203   std::vector<edm::Handle<edm::ValueMap<float> > > idhandles;
00204   std::vector<pat::Electron::IdPair>               ids;
00205   if (addElecID_) {
00206     idhandles.resize(elecIDSrcs_.size());
00207     ids.resize(elecIDSrcs_.size());
00208     for (size_t i = 0; i < elecIDSrcs_.size(); ++i) {
00209       iEvent.getByLabel(elecIDSrcs_[i].second, idhandles[i]);
00210       ids[i].first = elecIDSrcs_[i].first;
00211     }
00212   }
00213 
00214 
00215   // prepare the high level selection:
00216   // needs beamline
00217   reco::TrackBase::Point beamPoint(0,0,0);
00218   reco::Vertex primaryVertex;
00219   reco::BeamSpot beamSpot;
00220   bool beamSpotIsValid = false;
00221   bool primaryVertexIsValid = false;
00222   if ( embedHighLevelSelection_ ) {
00223     // Get the beamspot
00224     edm::Handle<reco::BeamSpot> beamSpotHandle;
00225     iEvent.getByLabel(beamLineSrc_, beamSpotHandle);
00226 
00227     // Get the primary vertex
00228     edm::Handle< std::vector<reco::Vertex> > pvHandle;
00229     iEvent.getByLabel( pvSrc_, pvHandle );
00230 
00231     // This is needed by the IPTools methods from the tracking group
00232     iSetup.get<TransientTrackRecord>().get("TransientTrackBuilder", trackBuilder);
00233 
00234     if ( ! usePV_ ) {
00235       if ( beamSpotHandle.isValid() ){
00236         beamSpot = *beamSpotHandle;
00237         beamSpotIsValid = true;
00238       } else{
00239         edm::LogError("DataNotAvailable")
00240           << "No beam spot available from EventSetup, not adding high level selection \n";
00241       }
00242 
00243       double x0 = beamSpot.x0();
00244       double y0 = beamSpot.y0();
00245       double z0 = beamSpot.z0();
00246 
00247       beamPoint = reco::TrackBase::Point ( x0, y0, z0 );
00248     } else {
00249       if ( pvHandle.isValid() && !pvHandle->empty() ) {
00250         primaryVertex = pvHandle->at(0);
00251         primaryVertexIsValid = true;
00252       } else {
00253         edm::LogError("DataNotAvailable")
00254           << "No primary vertex available from EventSetup, not adding high level selection \n";
00255       }
00256     }
00257   }
00258 
00259   std::vector<Electron> * patElectrons = new std::vector<Electron>();
00260 
00261   if( useParticleFlow_ ) {
00262     edm::Handle< reco::PFCandidateCollection >  pfElectrons;
00263     iEvent.getByLabel(pfElecSrc_, pfElectrons);
00264     unsigned index=0;
00265 
00266     for( reco::PFCandidateConstIterator i = pfElectrons->begin();
00267          i != pfElectrons->end(); ++i, ++index) {
00268 
00269       reco::PFCandidateRef pfRef(pfElectrons, index);
00270       reco::PFCandidatePtr ptrToPFElectron(pfElectrons,index);
00271 //       reco::CandidateBaseRef pfBaseRef( pfRef );
00272 
00273       reco::GsfTrackRef PfTk= i->gsfTrackRef();
00274 
00275       bool Matched=false;
00276       bool MatchedToAmbiguousGsfTrack=false;
00277       for (edm::View<reco::GsfElectron>::const_iterator itElectron = electrons->begin(); itElectron != electrons->end(); ++itElectron) {
00278         unsigned int idx = itElectron - electrons->begin();
00279         if (Matched || MatchedToAmbiguousGsfTrack) continue;
00280 
00281         reco::GsfTrackRef EgTk= itElectron->gsfTrack();
00282 
00283         if (itElectron->gsfTrack()==i->gsfTrackRef()){
00284           Matched=true;
00285         }
00286         else {
00287           for( reco::GsfTrackRefVector::const_iterator it = itElectron->ambiguousGsfTracksBegin() ;
00288                it!=itElectron->ambiguousGsfTracksEnd(); it++ ){
00289             MatchedToAmbiguousGsfTrack |= (bool)(i->gsfTrackRef()==(*it));
00290           }
00291         }
00292 
00293         if (Matched || MatchedToAmbiguousGsfTrack){
00294 
00295           // ptr needed for finding the matched gen particle
00296           reco::CandidatePtr ptrToGsfElectron(electrons,idx);
00297 
00298           // ref to base needed for the construction of the pat object
00299           const edm::RefToBase<reco::GsfElectron>& elecsRef = electrons->refAt(idx);
00300           Electron anElectron(elecsRef);
00301           anElectron.setPFCandidateRef( pfRef  );
00302 
00303           if( embedPFCandidate_ ) anElectron.embedPFCandidate();
00304 
00305           if ( useUserData_ ) {
00306             userDataHelper_.add( anElectron, iEvent, iSetup );
00307           }
00308 
00309 
00310           // embed high level selection
00311           if ( embedHighLevelSelection_ ) {
00312             // get the global track
00313             reco::GsfTrackRef track = PfTk;
00314 
00315             // Make sure the collection it points to is there
00316             if ( track.isNonnull() && track.isAvailable() ) {
00317 
00318               reco::TransientTrack tt = trackBuilder->build(track);
00319               embedHighLevel( anElectron, 
00320                               track,
00321                               tt,
00322                               primaryVertex,
00323                               primaryVertexIsValid,
00324                               beamSpot,
00325                               beamSpotIsValid );
00326 
00327               if ( !usePV_ ) {
00328                 double corr_d0 = track->dxy( beamPoint );
00329                 anElectron.setDB( corr_d0, -1.0 );
00330               } else {
00331                 std::pair<bool,Measurement1D> result = IPTools::absoluteTransverseImpactParameter(tt, primaryVertex);
00332                 double d0_corr = result.second.value();
00333                 double d0_err = result.second.error();
00334                 anElectron.setDB( d0_corr, d0_err );
00335               }
00336             }
00337           }
00338 
00339           //Electron Id
00340 
00341           if (addElecID_) {
00342             //STANDARD EL ID
00343             for (size_t i = 0; i < elecIDSrcs_.size(); ++i) {
00344               ids[i].second = (*idhandles[i])[elecsRef];
00345             }
00346             //SPECIFIC PF ID
00347             ids.push_back(std::make_pair("pf_evspi",pfRef->mva_e_pi()));
00348             ids.push_back(std::make_pair("pf_evsmu",pfRef->mva_e_mu()));
00349             anElectron.setElectronIDs(ids);
00350           }
00351 
00352 //        fillElectron(anElectron,elecsRef,pfBaseRef,
00353 //                     genMatches, deposits, isolationValues);
00354 
00355           //COLIN small warning !
00356           // we are currently choosing to take the 4-momentum of the PFCandidate;
00357           // the momentum of the GsfElectron is saved though
00358           // we must therefore match the GsfElectron.
00359           // because of this, we should not change the source of the electron matcher
00360           // to the collection of PFElectrons in the python configuration
00361           // I don't know what to do with the efficiencyLoader, since I don't know
00362           // what this class is for.
00363           fillElectron2( anElectron,
00364                          ptrToPFElectron,
00365                          ptrToGsfElectron,
00366                          ptrToGsfElectron,
00367                          genMatches, deposits, isolationValues );
00368 
00369           //COLIN need to use fillElectron2 in the non-pflow case as well, and to test it.
00370 
00371           patElectrons->push_back(anElectron);
00372         }
00373       }
00374       //if( !Matched && !MatchedToAmbiguousGsfTrack) std::cout << "!!!!A pf electron could not be matched to a gsf!!!!"  << std::endl;
00375     }
00376   }
00377 
00378   else{
00379     for (edm::View<reco::GsfElectron>::const_iterator itElectron = electrons->begin(); itElectron != electrons->end(); ++itElectron) {
00380       // construct the Electron from the ref -> save ref to original object
00381       unsigned int idx = itElectron - electrons->begin();
00382       edm::RefToBase<reco::GsfElectron> elecsRef = electrons->refAt(idx);
00383       reco::CandidateBaseRef elecBaseRef(elecsRef);
00384       Electron anElectron(elecsRef);
00385 
00386       // add resolution info
00387 
00388       // Isolation
00389       if (isolator_.enabled()) {
00390         isolator_.fill(*electrons, idx, isolatorTmpStorage_);
00391         typedef pat::helper::MultiIsolator::IsolationValuePairs IsolationValuePairs;
00392         // better to loop backwards, so the vector is resized less times
00393         for (IsolationValuePairs::const_reverse_iterator it = isolatorTmpStorage_.rbegin(), ed = isolatorTmpStorage_.rend(); it != ed; ++it) {
00394           anElectron.setIsolation(it->first, it->second);
00395         }
00396       }
00397 
00398       for (size_t j = 0, nd = deposits.size(); j < nd; ++j) {
00399         anElectron.setIsoDeposit(isoDepositLabels_[j].first, (*deposits[j])[elecsRef]);
00400       }
00401 
00402       // add electron ID info
00403       if (addElecID_) {
00404         for (size_t i = 0; i < elecIDSrcs_.size(); ++i) {
00405           ids[i].second = (*idhandles[i])[elecsRef];
00406         }
00407         anElectron.setElectronIDs(ids);
00408       }
00409 
00410 
00411       if ( useUserData_ ) {
00412         userDataHelper_.add( anElectron, iEvent, iSetup );
00413       }
00414 
00415 
00416       // embed high level selection
00417       if ( embedHighLevelSelection_ ) {
00418         // get the global track
00419         reco::GsfTrackRef track = itElectron->gsfTrack();
00420 
00421         // Make sure the collection it points to is there
00422         if ( track.isNonnull() && track.isAvailable() ) {
00423 
00424           reco::TransientTrack tt = trackBuilder->build(track);
00425           embedHighLevel( anElectron, 
00426                           track,
00427                           tt,
00428                           primaryVertex,
00429                           primaryVertexIsValid,
00430                           beamSpot,
00431                           beamSpotIsValid );
00432 
00433 
00434           if ( !usePV_ ) {
00435             double corr_d0 = track->dxy( beamPoint );
00436             anElectron.setDB( corr_d0, -1.0 );
00437           } else {
00438             
00439             std::pair<bool,Measurement1D> result = IPTools::absoluteTransverseImpactParameter(tt, primaryVertex);
00440             double d0_corr = result.second.value();
00441             double d0_err = result.second.error();
00442             anElectron.setDB( d0_corr, d0_err );
00443           }
00444         }
00445       }
00446 
00447       // add sel to selected
00448       fillElectron( anElectron, elecsRef,elecBaseRef,
00449                     genMatches, deposits, isolationValues);
00450       patElectrons->push_back(anElectron);
00451     }
00452   }
00453 
00454   // sort electrons in pt
00455   std::sort(patElectrons->begin(), patElectrons->end(), pTComparator_);
00456 
00457   // add the electrons to the event output
00458   std::auto_ptr<std::vector<Electron> > ptr(patElectrons);
00459   iEvent.put(ptr);
00460 
00461   // clean up
00462   if (isolator_.enabled()) isolator_.endEvent();
00463 
00464 }
00465 
00466 void PATElectronProducer::fillElectron(Electron& anElectron,
00467                                        const edm::RefToBase<reco::GsfElectron>& elecRef,
00468                                        const reco::CandidateBaseRef& baseRef,
00469                                        const GenAssociations& genMatches,
00470                                        const IsoDepositMaps& deposits,
00471                                        const IsolationValueMaps& isolationValues
00472                                        ) const {
00473 
00474   //COLIN: might want to use the PFCandidate 4-mom. Which one is in use now?
00475   //   if (useParticleFlow_)
00476   //     aMuon.setP4( aMuon.pfCandidateRef()->p4() );
00477 
00478   //COLIN:
00479   //In the embedding case, the reference cannot be used to look into a value map.
00480   //therefore, one has to had the PFCandidateRef to this function, which becomes a bit
00481   //too much specific.
00482 
00483   // in fact, this function needs a baseref or ptr for genmatch
00484   // and a baseref or ptr for isodeposits and isolationvalues.
00485   // baseref is not needed
00486   // the ptrForIsolation and ptrForMatching should be defined upstream.
00487 
00488   // is the concrete elecRef needed for the efficiency loader? what is this loader?
00489   // how can we make it compatible with the particle flow electrons?
00490 
00491   if (embedGsfElectronCore_) anElectron.embedGsfElectronCore();
00492   if (embedGsfTrack_) anElectron.embedGsfTrack();
00493   if (embedSuperCluster_) anElectron.embedSuperCluster();
00494   if (embedTrack_) anElectron.embedTrack();
00495 
00496   // store the match to the generated final state muons
00497   if (addGenMatch_) {
00498     for(size_t i = 0, n = genMatches.size(); i < n; ++i) {
00499       if(useParticleFlow_) {
00500         reco::GenParticleRef genElectron = (*genMatches[i])[anElectron.pfCandidateRef()];
00501         anElectron.addGenParticleRef(genElectron);
00502       }
00503       else {
00504         reco::GenParticleRef genElectron = (*genMatches[i])[elecRef];
00505         anElectron.addGenParticleRef(genElectron);
00506       }
00507     }
00508     if (embedGenMatch_) anElectron.embedGenParticle();
00509   }
00510 
00511   if (efficiencyLoader_.enabled()) {
00512     efficiencyLoader_.setEfficiencies( anElectron, elecRef );
00513   }
00514 
00515   if (resolutionLoader_.enabled()) {
00516     resolutionLoader_.setResolutions(anElectron);
00517   }
00518 
00519   for (size_t j = 0, nd = deposits.size(); j < nd; ++j) {
00520     if(useParticleFlow_) {
00521 
00522       reco::PFCandidateRef pfcandref =  anElectron.pfCandidateRef();
00523       assert(!pfcandref.isNull());
00524       reco::CandidatePtr source = pfcandref->sourceCandidatePtr(0);
00525       anElectron.setIsoDeposit(isoDepositLabels_[j].first,
00526                           (*deposits[j])[source]);
00527     }
00528     else
00529       anElectron.setIsoDeposit(isoDepositLabels_[j].first,
00530                           (*deposits[j])[elecRef]);
00531   }
00532 
00533   for (size_t j = 0; j<isolationValues.size(); ++j) {
00534     if(useParticleFlow_) {
00535       reco::CandidatePtr source = anElectron.pfCandidateRef()->sourceCandidatePtr(0);
00536       anElectron.setIsolation(isolationValueLabels_[j].first,
00537                          (*isolationValues[j])[source]);
00538     }
00539     else
00540       anElectron.setIsolation(isolationValueLabels_[j].first,
00541                          (*isolationValues[j])[elecRef]);
00542   }
00543 
00544 
00545 
00546 }
00547 
00548 void PATElectronProducer::fillElectron2( Electron& anElectron,
00549                                          const reco::CandidatePtr& candPtrForIsolation,
00550                                          const reco::CandidatePtr& candPtrForGenMatch,
00551                                          const reco::CandidatePtr& candPtrForLoader,
00552                                          const GenAssociations& genMatches,
00553                                          const IsoDepositMaps& deposits,
00554                                          const IsolationValueMaps& isolationValues) const {
00555 
00556   //COLIN/Florian: use the PFCandidate 4-mom.
00557   anElectron.setEcalDrivenMomentum(anElectron.p4()) ;
00558   anElectron.setP4( anElectron.pfCandidateRef()->p4() );
00559 
00560 
00561   // is the concrete elecRef needed for the efficiency loader? what is this loader?
00562   // how can we make it compatible with the particle flow electrons?
00563 
00564   if (embedGsfElectronCore_) anElectron.embedGsfElectronCore();
00565   if (embedGsfTrack_) anElectron.embedGsfTrack();
00566   if (embedSuperCluster_) anElectron.embedSuperCluster();
00567   if (embedTrack_) anElectron.embedTrack();
00568 
00569   // store the match to the generated final state muons
00570 
00571   if (addGenMatch_) {
00572     for(size_t i = 0, n = genMatches.size(); i < n; ++i) {
00573       reco::GenParticleRef genElectron = (*genMatches[i])[candPtrForGenMatch];
00574       anElectron.addGenParticleRef(genElectron);
00575     }
00576     if (embedGenMatch_) anElectron.embedGenParticle();
00577   }
00578 
00579   //COLIN what's this? does it have to be GsfElectron specific?
00580   if (efficiencyLoader_.enabled()) {
00581     efficiencyLoader_.setEfficiencies( anElectron, candPtrForLoader );
00582   }
00583 
00584   if (resolutionLoader_.enabled()) {
00585     resolutionLoader_.setResolutions(anElectron);
00586   }
00587 
00588   for (size_t j = 0, nd = deposits.size(); j < nd; ++j) {
00589     if( isoDepositLabels_[j].first==pat::TrackIso ||
00590         isoDepositLabels_[j].first==pat::EcalIso ||
00591         isoDepositLabels_[j].first==pat::HcalIso ) {
00592 
00593       anElectron.setIsoDeposit(isoDepositLabels_[j].first,
00594                                (*deposits[j])[candPtrForGenMatch]);
00595     }
00596     else if (deposits[j]->contains(candPtrForIsolation.id())) {
00597       anElectron.setIsoDeposit(isoDepositLabels_[j].first,
00598                                (*deposits[j])[candPtrForIsolation]);
00599     }
00600     else {
00601       anElectron.setIsoDeposit(isoDepositLabels_[j].first,
00602                                (*deposits[j])[candPtrForIsolation->sourceCandidatePtr(0)]);
00603     }
00604   }
00605 
00606   for (size_t j = 0; j<isolationValues.size(); ++j) {
00607     if( isolationValueLabels_[j].first==pat::TrackIso ||
00608         isolationValueLabels_[j].first==pat::EcalIso ||
00609         isolationValueLabels_[j].first==pat::HcalIso ) {
00610       anElectron.setIsolation(isolationValueLabels_[j].first,
00611                               (*isolationValues[j])[candPtrForGenMatch]);
00612     }
00613     else if (isolationValues[j]->contains(candPtrForIsolation.id())) {
00614       anElectron.setIsolation(isolationValueLabels_[j].first,
00615                               (*isolationValues[j])[candPtrForIsolation]);
00616     }
00617     else {
00618       anElectron.setIsolation(isolationValueLabels_[j].first,
00619                               (*isolationValues[j])[candPtrForIsolation->sourceCandidatePtr(0)]);
00620     }    
00621   }
00622 }
00623 
00624 
00625 // ParameterSet description for module
00626 void PATElectronProducer::fillDescriptions(edm::ConfigurationDescriptions & descriptions)
00627 {
00628   edm::ParameterSetDescription iDesc;
00629   iDesc.setComment("PAT electron producer module");
00630 
00631   // input source
00632   iDesc.add<edm::InputTag>("electronSource", edm::InputTag("no default"))->setComment("input collection");
00633 
00634   // embedding
00635   iDesc.add<bool>("embedGsfElectronCore", true)->setComment("embed external gsf electron core");
00636   iDesc.add<bool>("embedGsfTrack", true)->setComment("embed external gsf track");
00637   iDesc.add<bool>("embedSuperCluster", true)->setComment("embed external super cluster");
00638   iDesc.add<bool>("embedTrack", false)->setComment("embed external track");
00639 
00640   // pf specific parameters
00641   iDesc.add<edm::InputTag>("pfElectronSource", edm::InputTag("pfElectrons"))->setComment("particle flow input collection");
00642   iDesc.add<bool>("useParticleFlow", false)->setComment("whether to use particle flow or not");
00643   iDesc.add<bool>("embedPFCandidate", false)->setComment("embed external particle flow object");
00644 
00645   // MC matching configurables
00646   iDesc.add<bool>("addGenMatch", true)->setComment("add MC matching");
00647   iDesc.add<bool>("embedGenMatch", false)->setComment("embed MC matched MC information");
00648   std::vector<edm::InputTag> emptySourceVector;
00649   iDesc.addNode( edm::ParameterDescription<edm::InputTag>("genParticleMatch", edm::InputTag(), true) xor
00650                  edm::ParameterDescription<std::vector<edm::InputTag> >("genParticleMatch", emptySourceVector, true)
00651                  )->setComment("input with MC match information");
00652 
00653   // electron ID configurables
00654   iDesc.add<bool>("addElectronID",true)->setComment("add electron ID variables");
00655   edm::ParameterSetDescription electronIDSourcesPSet;
00656   electronIDSourcesPSet.setAllowAnything();
00657   iDesc.addNode( edm::ParameterDescription<edm::InputTag>("electronIDSource", edm::InputTag(), true) xor
00658                  edm::ParameterDescription<edm::ParameterSetDescription>("electronIDSources", electronIDSourcesPSet, true)
00659                  )->setComment("input with electron ID variables");
00660 
00661 
00662   // IsoDeposit configurables
00663   edm::ParameterSetDescription isoDepositsPSet;
00664   isoDepositsPSet.addOptional<edm::InputTag>("tracker");
00665   isoDepositsPSet.addOptional<edm::InputTag>("ecal");
00666   isoDepositsPSet.addOptional<edm::InputTag>("hcal");
00667   isoDepositsPSet.addOptional<edm::InputTag>("pfAllParticles");
00668   isoDepositsPSet.addOptional<edm::InputTag>("pfChargedHadrons");
00669   isoDepositsPSet.addOptional<edm::InputTag>("pfChargedAll");
00670   isoDepositsPSet.addOptional<edm::InputTag>("pfPUChargedHadrons");
00671   isoDepositsPSet.addOptional<edm::InputTag>("pfNeutralHadrons");
00672   isoDepositsPSet.addOptional<edm::InputTag>("pfPhotons");
00673   isoDepositsPSet.addOptional<std::vector<edm::InputTag> >("user");
00674   iDesc.addOptional("isoDeposits", isoDepositsPSet);
00675 
00676   // isolation values configurables
00677   edm::ParameterSetDescription isolationValuesPSet;
00678   isolationValuesPSet.addOptional<edm::InputTag>("tracker");
00679   isolationValuesPSet.addOptional<edm::InputTag>("ecal");
00680   isolationValuesPSet.addOptional<edm::InputTag>("hcal");
00681   isolationValuesPSet.addOptional<edm::InputTag>("pfAllParticles");
00682   isolationValuesPSet.addOptional<edm::InputTag>("pfChargedHadrons");
00683   isolationValuesPSet.addOptional<edm::InputTag>("pfChargedAll");
00684   isolationValuesPSet.addOptional<edm::InputTag>("pfPUChargedHadrons");
00685   isolationValuesPSet.addOptional<edm::InputTag>("pfNeutralHadrons");
00686   isolationValuesPSet.addOptional<edm::InputTag>("pfPhotons");
00687   isolationValuesPSet.addOptional<std::vector<edm::InputTag> >("user");
00688   iDesc.addOptional("isolationValues", isolationValuesPSet);
00689 
00690   // Efficiency configurables
00691   edm::ParameterSetDescription efficienciesPSet;
00692   efficienciesPSet.setAllowAnything(); // TODO: the pat helper needs to implement a description.
00693   iDesc.add("efficiencies", efficienciesPSet);
00694   iDesc.add<bool>("addEfficiencies", false);
00695 
00696   // Check to see if the user wants to add user data
00697   edm::ParameterSetDescription userDataPSet;
00698   PATUserDataHelper<Electron>::fillDescription(userDataPSet);
00699   iDesc.addOptional("userData", userDataPSet);
00700 
00701   // electron shapes
00702   iDesc.add<bool>("addElectronShapes", true);
00703   iDesc.add<edm::InputTag>("reducedBarrelRecHitCollection", edm::InputTag("reducedEcalRecHitsEB"));
00704   iDesc.add<edm::InputTag>("reducedEndcapRecHitCollection", edm::InputTag("reducedEcalRecHitsEE"));
00705 
00706   edm::ParameterSetDescription isolationPSet;
00707   isolationPSet.setAllowAnything(); // TODO: the pat helper needs to implement a description.
00708   iDesc.add("userIsolation", isolationPSet);
00709 
00710   // Resolution configurables
00711   pat::helper::KinResolutionsLoader::fillDescription(iDesc);
00712 
00713   iDesc.add<bool>("embedHighLevelSelection", true)->setComment("embed high level selection");
00714   edm::ParameterSetDescription highLevelPSet;
00715   highLevelPSet.setAllowAnything();
00716   iDesc.addNode( edm::ParameterDescription<edm::InputTag>("beamLineSrc", edm::InputTag(), true)
00717                  )->setComment("input with high level selection");
00718   iDesc.addNode( edm::ParameterDescription<edm::InputTag>("pvSrc", edm::InputTag(), true)
00719                  )->setComment("input with high level selection");
00720   iDesc.addNode( edm::ParameterDescription<bool>("usePV", bool(), true)
00721                  )->setComment("input with high level selection, use primary vertex (true) or beam line (false)");
00722 
00723   descriptions.add("PATElectronProducer", iDesc);
00724 
00725 }
00726 
00727 
00728 
00729 void PATElectronProducer::readIsolationLabels( const edm::ParameterSet & iConfig,
00730                                                const char* psetName,
00731                                                IsolationLabels& labels) {
00732 
00733   labels.clear();
00734 
00735   if (iConfig.exists( psetName )) {
00736     edm::ParameterSet depconf
00737       = iConfig.getParameter<edm::ParameterSet>(psetName);
00738 
00739     if (depconf.exists("tracker")) labels.push_back(std::make_pair(pat::TrackIso, depconf.getParameter<edm::InputTag>("tracker")));
00740     if (depconf.exists("ecal"))    labels.push_back(std::make_pair(pat::EcalIso, depconf.getParameter<edm::InputTag>("ecal")));
00741     if (depconf.exists("hcal"))    labels.push_back(std::make_pair(pat::HcalIso, depconf.getParameter<edm::InputTag>("hcal")));
00742     if (depconf.exists("pfAllParticles"))  {
00743       labels.push_back(std::make_pair(pat::PfAllParticleIso, depconf.getParameter<edm::InputTag>("pfAllParticles")));
00744     }
00745     if (depconf.exists("pfChargedHadrons"))  {
00746       labels.push_back(std::make_pair(pat::PfChargedHadronIso, depconf.getParameter<edm::InputTag>("pfChargedHadrons")));
00747     }
00748     if (depconf.exists("pfChargedAll"))  {
00749       labels.push_back(std::make_pair(pat::PfChargedAllIso, depconf.getParameter<edm::InputTag>("pfChargedAll")));
00750     }
00751     if (depconf.exists("pfPUChargedHadrons"))  {
00752       labels.push_back(std::make_pair(pat::PfPUChargedHadronIso, depconf.getParameter<edm::InputTag>("pfPUChargedHadrons")));
00753     }
00754     if (depconf.exists("pfNeutralHadrons"))  {
00755       labels.push_back(std::make_pair(pat::PfNeutralHadronIso, depconf.getParameter<edm::InputTag>("pfNeutralHadrons")));
00756     }
00757     if (depconf.exists("pfPhotons")) {
00758       labels.push_back(std::make_pair(pat::PfGammaIso, depconf.getParameter<edm::InputTag>("pfPhotons")));
00759     }
00760     if (depconf.exists("user")) {
00761       std::vector<edm::InputTag> userdeps = depconf.getParameter<std::vector<edm::InputTag> >("user");
00762       std::vector<edm::InputTag>::const_iterator it = userdeps.begin(), ed = userdeps.end();
00763       int key = UserBaseIso;
00764       for ( ; it != ed; ++it, ++key) {
00765         labels.push_back(std::make_pair(IsolationKeys(key), *it));
00766       }
00767     }
00768   }
00769 
00770 
00771 }
00772 
00773 
00774 // embed various impact parameters with errors
00775 // embed high level selection
00776 void PATElectronProducer::embedHighLevel( pat::Electron & anElectron, 
00777                                           reco::GsfTrackRef track,
00778                                           reco::TransientTrack & tt,
00779                                           reco::Vertex & primaryVertex,
00780                                           bool primaryVertexIsValid,
00781                                           reco::BeamSpot & beamspot,
00782                                           bool beamspotIsValid
00783                                           )
00784 {
00785   // Correct to PV
00786 
00787   // PV2D
00788   std::pair<bool,Measurement1D> result =
00789     IPTools::signedTransverseImpactParameter(tt,
00790                                              GlobalVector(track->px(),
00791                                                           track->py(),
00792                                                           track->pz()),
00793                                              primaryVertex); 
00794   double d0_corr = result.second.value();
00795   double d0_err = primaryVertexIsValid ? result.second.error() : -1.0;
00796   anElectron.setDB( d0_corr, d0_err, pat::Electron::PV2D);
00797 
00798 
00799   // PV3D
00800   result =
00801     IPTools::signedImpactParameter3D(tt,
00802                                      GlobalVector(track->px(),
00803                                                   track->py(),
00804                                                   track->pz()),
00805                                      primaryVertex);
00806   d0_corr = result.second.value();
00807   d0_err = primaryVertexIsValid ? result.second.error() : -1.0;
00808   anElectron.setDB( d0_corr, d0_err, pat::Electron::PV3D);
00809   
00810 
00811   // Correct to beam spot
00812   // make a fake vertex out of beam spot
00813   reco::Vertex vBeamspot(beamspot.position(), beamspot.covariance3D());
00814   
00815   // BS2D
00816   result =
00817     IPTools::signedTransverseImpactParameter(tt,
00818                                              GlobalVector(track->px(),
00819                                                           track->py(),
00820                                                           track->pz()),
00821                                              vBeamspot);
00822   d0_corr = result.second.value();
00823   d0_err = beamspotIsValid ? result.second.error() : -1.0;
00824   anElectron.setDB( d0_corr, d0_err, pat::Electron::BS2D);
00825   
00826   // BS3D
00827   result =
00828     IPTools::signedImpactParameter3D(tt,
00829                                      GlobalVector(track->px(),
00830                                                   track->py(),
00831                                                   track->pz()),
00832                                      vBeamspot);
00833   d0_corr = result.second.value();
00834   d0_err = beamspotIsValid ? result.second.error() : -1.0;
00835   anElectron.setDB( d0_corr, d0_err, pat::Electron::BS3D);
00836 }
00837 
00838 #include "FWCore/Framework/interface/MakerMacros.h"
00839 
00840 DEFINE_FWK_MODULE(PATElectronProducer);