CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/PhysicsTools/PatAlgos/plugins/PATElectronProducer.cc

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