CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_1/src/PhysicsTools/PatAlgos/plugins/PATElectronProducer.cc

Go to the documentation of this file.
00001 //
00002 // $Id: PATElectronProducer.cc,v 1.73 2012/12/06 16:54:49 eulisse Exp $
00003 //
00004 #include "PhysicsTools/PatAlgos/plugins/PATElectronProducer.h"
00005 
00006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00007 #include "FWCore/ParameterSet/interface/FileInPath.h"
00008 #include "FWCore/Utilities/interface/isFinite.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 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
00036 #include "RecoEcal/EgammaCoreTools/interface/EcalClusterLazyTools.h"
00037 #include "RecoEgamma/EgammaTools/interface/ConversionTools.h"
00038 #include "Geometry/CaloEventSetup/interface/CaloTopologyRecord.h"
00039 #include "Geometry/CaloTopology/interface/CaloTopology.h"
00040 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00041 
00042 #include <vector>
00043 #include <memory>
00044 
00045 
00046 using namespace pat;
00047 using namespace std;
00048 
00049 
00050 PATElectronProducer::PATElectronProducer(const edm::ParameterSet & iConfig) :
00051   isolator_(iConfig.exists("userIsolation") ? iConfig.getParameter<edm::ParameterSet>("userIsolation") : edm::ParameterSet(), false) ,
00052   useUserData_(iConfig.exists("userData"))
00053 {
00054   // general configurables
00055   electronSrc_ = iConfig.getParameter<edm::InputTag>( "electronSource" );
00056   embedGsfElectronCore_ = iConfig.getParameter<bool>( "embedGsfElectronCore" );
00057   embedGsfTrack_ = iConfig.getParameter<bool>( "embedGsfTrack" );
00058   embedSuperCluster_ = iConfig.getParameter<bool>         ( "embedSuperCluster"    );
00059   embedSeedCluster_ = iConfig.getParameter<bool>( "embedSeedCluster" );
00060   embedTrack_ = iConfig.getParameter<bool>( "embedTrack" );
00061   embedRecHits_ = iConfig.getParameter<bool>( "embedRecHits" );
00062   // pflow configurables
00063   pfElecSrc_ = iConfig.getParameter<edm::InputTag>( "pfElectronSource" );
00064   pfCandidateMap_ = iConfig.getParameter<edm::InputTag>( "pfCandidateMap" );
00065   useParticleFlow_ = iConfig.getParameter<bool>( "useParticleFlow" );
00066   embedPFCandidate_ = iConfig.getParameter<bool>( "embedPFCandidate" );
00067   // mva input variables
00068   reducedBarrelRecHitCollection_ = iConfig.getParameter<edm::InputTag>("reducedBarrelRecHitCollection");
00069   reducedEndcapRecHitCollection_ = iConfig.getParameter<edm::InputTag>("reducedEndcapRecHitCollection");
00070   // MC matching configurables (scheduled mode)
00071   addGenMatch_ = iConfig.getParameter<bool>( "addGenMatch" );
00072   if (addGenMatch_) {
00073     embedGenMatch_ = iConfig.getParameter<bool>( "embedGenMatch" );
00074     if (iConfig.existsAs<edm::InputTag>("genParticleMatch")) {
00075       genMatchSrc_.push_back(iConfig.getParameter<edm::InputTag>( "genParticleMatch" ));
00076     }
00077     else {
00078       genMatchSrc_ = iConfig.getParameter<std::vector<edm::InputTag> >( "genParticleMatch" );
00079     }
00080   }
00081   // resolution configurables
00082   addResolutions_ = iConfig.getParameter<bool>( "addResolutions" );
00083   if (addResolutions_) {
00084     resolutionLoader_ = pat::helper::KinResolutionsLoader(iConfig.getParameter<edm::ParameterSet>("resolutions"));
00085   }
00086   // electron ID configurables
00087   addElecID_ = iConfig.getParameter<bool>( "addElectronID" );
00088   if (addElecID_) {
00089     // it might be a single electron ID
00090     if (iConfig.existsAs<edm::InputTag>("electronIDSource")) {
00091       elecIDSrcs_.push_back(NameTag("", iConfig.getParameter<edm::InputTag>("electronIDSource")));
00092     }
00093     // or there might be many of them
00094     if (iConfig.existsAs<edm::ParameterSet>("electronIDSources")) {
00095       // please don't configure me twice
00096       if (!elecIDSrcs_.empty()){
00097         throw cms::Exception("Configuration") << "PATElectronProducer: you can't specify both 'electronIDSource' and 'electronIDSources'\n";
00098       }
00099       // read the different electron ID names
00100       edm::ParameterSet idps = iConfig.getParameter<edm::ParameterSet>("electronIDSources");
00101       std::vector<std::string> names = idps.getParameterNamesForType<edm::InputTag>();
00102       for (std::vector<std::string>::const_iterator it = names.begin(), ed = names.end(); it != ed; ++it) {
00103         elecIDSrcs_.push_back(NameTag(*it, idps.getParameter<edm::InputTag>(*it)));
00104       }
00105     }
00106     // but in any case at least once
00107     if (elecIDSrcs_.empty()){
00108       throw cms::Exception("Configuration") <<
00109         "PATElectronProducer: id addElectronID is true, you must specify either:\n" <<
00110         "\tInputTag electronIDSource = <someTag>\n" << "or\n" <<
00111         "\tPSet electronIDSources = { \n" <<
00112         "\t\tInputTag <someName> = <someTag>   // as many as you want \n " <<
00113         "\t}\n";
00114     }
00115   }
00116   // construct resolution calculator
00117 
00118   //   // IsoDeposit configurables
00119   //   if (iConfig.exists("isoDeposits")) {
00120   //      edm::ParameterSet depconf = iConfig.getParameter<edm::ParameterSet>("isoDeposits");
00121   //      if (depconf.exists("tracker")) isoDepositLabels_.push_back(std::make_pair(TrackerIso, depconf.getParameter<edm::InputTag>("tracker")));
00122   //      if (depconf.exists("ecal"))    isoDepositLabels_.push_back(std::make_pair(ECalIso, depconf.getParameter<edm::InputTag>("ecal")));
00123   //      if (depconf.exists("hcal"))    isoDepositLabels_.push_back(std::make_pair(HCalIso, depconf.getParameter<edm::InputTag>("hcal")));
00124 
00125 
00126   //      if (depconf.exists("user")) {
00127   //         std::vector<edm::InputTag> userdeps = depconf.getParameter<std::vector<edm::InputTag> >("user");
00128   //         std::vector<edm::InputTag>::const_iterator it = userdeps.begin(), ed = userdeps.end();
00129   //         int key = UserBaseIso;
00130   //         for ( ; it != ed; ++it, ++key) {
00131   //             isoDepositLabels_.push_back(std::make_pair(IsolationKeys(key), *it));
00132   //         }
00133   //      }
00134   //   }
00135 
00136   // read isoDeposit labels, for direct embedding
00137   readIsolationLabels(iConfig, "isoDeposits", isoDepositLabels_);
00138   // read isolation value labels, for direct embedding
00139   readIsolationLabels(iConfig, "isolationValues", isolationValueLabels_);
00140   // read isolation value labels for non PF identified electron, for direct embedding
00141   readIsolationLabels(iConfig, "isolationValuesNoPFId", isolationValueLabelsNoPFId_);
00142   // Efficiency configurables
00143   addEfficiencies_ = iConfig.getParameter<bool>("addEfficiencies");
00144   if (addEfficiencies_) {
00145     efficiencyLoader_ = pat::helper::EfficiencyLoader(iConfig.getParameter<edm::ParameterSet>("efficiencies"));
00146   }
00147   // Check to see if the user wants to add user data
00148   if ( useUserData_ ) {
00149     userDataHelper_ = PATUserDataHelper<Electron>(iConfig.getParameter<edm::ParameterSet>("userData"));
00150   }
00151   // embed high level selection variables?
00152   embedHighLevelSelection_ = iConfig.getParameter<bool>("embedHighLevelSelection");
00153   beamLineSrc_ = iConfig.getParameter<edm::InputTag>("beamLineSrc");
00154   if ( embedHighLevelSelection_ ) {
00155     usePV_ = iConfig.getParameter<bool>("usePV");
00156     pvSrc_ = iConfig.getParameter<edm::InputTag>("pvSrc");
00157   }
00158   // produces vector of muons
00159   produces<std::vector<Electron> >();
00160   }
00161 
00162 
00163   PATElectronProducer::~PATElectronProducer()
00164 {
00165 }
00166 
00167 
00168 void PATElectronProducer::produce(edm::Event & iEvent, const edm::EventSetup & iSetup)
00169 {
00170   // switch off embedding (in unschedules mode)
00171   if (iEvent.isRealData()){
00172     addGenMatch_ = false;
00173     embedGenMatch_ = false;
00174   }
00175 
00176   edm::ESHandle<CaloTopology> theCaloTopology;
00177   iSetup.get<CaloTopologyRecord>().get(theCaloTopology);
00178   ecalTopology_ = & (*theCaloTopology);
00179 
00180   // Get the collection of electrons from the event
00181   edm::Handle<edm::View<reco::GsfElectron> > electrons;
00182   iEvent.getByLabel(electronSrc_, electrons);
00183 
00184   // for additional mva variables
00185   edm::InputTag  reducedEBRecHitCollection(string("reducedEcalRecHitsEB"));
00186   edm::InputTag  reducedEERecHitCollection(string("reducedEcalRecHitsEE"));
00187   //EcalClusterLazyTools lazyTools(iEvent, iSetup, reducedEBRecHitCollection, reducedEERecHitCollection);
00188   EcalClusterLazyTools lazyTools(iEvent, iSetup, reducedBarrelRecHitCollection_, reducedEndcapRecHitCollection_);
00189 
00190   // for conversion veto selection
00191   edm::Handle<reco::ConversionCollection> hConversions;
00192   iEvent.getByLabel("allConversions", hConversions);
00193 
00194   // Get the ESHandle for the transient track builder, if needed for
00195   // high level selection embedding
00196   edm::ESHandle<TransientTrackBuilder> trackBuilder;
00197 
00198   if (isolator_.enabled()) isolator_.beginEvent(iEvent,iSetup);
00199 
00200   if (efficiencyLoader_.enabled()) efficiencyLoader_.newEvent(iEvent);
00201   if (resolutionLoader_.enabled()) resolutionLoader_.newEvent(iEvent, iSetup);
00202 
00203   IsoDepositMaps deposits(isoDepositLabels_.size());
00204   for (size_t j = 0, nd = deposits.size(); j < nd; ++j) {
00205     iEvent.getByLabel(isoDepositLabels_[j].second, deposits[j]);
00206   }
00207 
00208   IsolationValueMaps isolationValues(isolationValueLabels_.size());
00209   for (size_t j = 0; j<isolationValueLabels_.size(); ++j) {
00210     iEvent.getByLabel(isolationValueLabels_[j].second, isolationValues[j]);
00211   }
00212 
00213   IsolationValueMaps isolationValuesNoPFId(isolationValueLabelsNoPFId_.size());
00214   for (size_t j = 0; j<isolationValueLabelsNoPFId_.size(); ++j) {
00215     iEvent.getByLabel(isolationValueLabelsNoPFId_[j].second, isolationValuesNoPFId[j]);
00216   }
00217 
00218   // prepare the MC matching
00219   GenAssociations  genMatches(genMatchSrc_.size());
00220   if (addGenMatch_) {
00221     for (size_t j = 0, nd = genMatchSrc_.size(); j < nd; ++j) {
00222       iEvent.getByLabel(genMatchSrc_[j], genMatches[j]);
00223     }
00224   }
00225 
00226   // prepare ID extraction
00227   std::vector<edm::Handle<edm::ValueMap<float> > > idhandles;
00228   std::vector<pat::Electron::IdPair>               ids;
00229   if (addElecID_) {
00230     idhandles.resize(elecIDSrcs_.size());
00231     ids.resize(elecIDSrcs_.size());
00232     for (size_t i = 0; i < elecIDSrcs_.size(); ++i) {
00233       iEvent.getByLabel(elecIDSrcs_[i].second, idhandles[i]);
00234       ids[i].first = elecIDSrcs_[i].first;
00235     }
00236   }
00237 
00238 
00239   // prepare the high level selection:
00240   // needs beamline
00241   reco::TrackBase::Point beamPoint(0,0,0);
00242   reco::Vertex primaryVertex;
00243   reco::BeamSpot beamSpot;
00244   bool beamSpotIsValid = false;
00245   bool primaryVertexIsValid = false;
00246 
00247   // Get the beamspot
00248   edm::Handle<reco::BeamSpot> beamSpotHandle;
00249   iEvent.getByLabel(beamLineSrc_, beamSpotHandle);
00250 
00251   if ( embedHighLevelSelection_ ) {
00252     // Get the primary vertex
00253     edm::Handle< std::vector<reco::Vertex> > pvHandle;
00254     iEvent.getByLabel( pvSrc_, pvHandle );
00255 
00256     // This is needed by the IPTools methods from the tracking group
00257     iSetup.get<TransientTrackRecord>().get("TransientTrackBuilder", trackBuilder);
00258 
00259     if ( ! usePV_ ) {
00260 
00261       if ( beamSpotHandle.isValid() ){
00262         beamSpot = *beamSpotHandle;
00263         beamSpotIsValid = true;
00264       } else{
00265         edm::LogError("DataNotAvailable")
00266           << "No beam spot available from EventSetup, not adding high level selection \n";
00267       }
00268 
00269       double x0 = beamSpot.x0();
00270       double y0 = beamSpot.y0();
00271       double z0 = beamSpot.z0();
00272 
00273       beamPoint = reco::TrackBase::Point ( x0, y0, z0 );
00274     } else {
00275       if ( pvHandle.isValid() && !pvHandle->empty() ) {
00276         primaryVertex = pvHandle->at(0);
00277         primaryVertexIsValid = true;
00278       } else {
00279         edm::LogError("DataNotAvailable")
00280           << "No primary vertex available from EventSetup, not adding high level selection \n";
00281       }
00282     }
00283   }
00284 
00285   std::vector<Electron> * patElectrons = new std::vector<Electron>();
00286 
00287   if( useParticleFlow_ ) {
00288     edm::Handle< reco::PFCandidateCollection >  pfElectrons;
00289     iEvent.getByLabel(pfElecSrc_, pfElectrons);
00290     unsigned index=0;
00291 
00292     for( reco::PFCandidateConstIterator i = pfElectrons->begin();
00293          i != pfElectrons->end(); ++i, ++index) {
00294 
00295       reco::PFCandidateRef pfRef(pfElectrons, index);
00296       reco::PFCandidatePtr ptrToPFElectron(pfElectrons,index);
00297 //       reco::CandidateBaseRef pfBaseRef( pfRef );
00298 
00299       reco::GsfTrackRef PfTk= i->gsfTrackRef();
00300 
00301       bool Matched=false;
00302       bool MatchedToAmbiguousGsfTrack=false;
00303       for (edm::View<reco::GsfElectron>::const_iterator itElectron = electrons->begin(); itElectron != electrons->end(); ++itElectron) {
00304         unsigned int idx = itElectron - electrons->begin();
00305         if (Matched || MatchedToAmbiguousGsfTrack) continue;
00306 
00307         reco::GsfTrackRef EgTk= itElectron->gsfTrack();
00308 
00309         if (itElectron->gsfTrack()==i->gsfTrackRef()){
00310           Matched=true;
00311         }
00312         else {
00313           for( reco::GsfTrackRefVector::const_iterator it = itElectron->ambiguousGsfTracksBegin() ;
00314                it!=itElectron->ambiguousGsfTracksEnd(); it++ ){
00315             MatchedToAmbiguousGsfTrack |= (bool)(i->gsfTrackRef()==(*it));
00316           }
00317         }
00318 
00319         if (Matched || MatchedToAmbiguousGsfTrack){
00320 
00321           // ptr needed for finding the matched gen particle
00322           reco::CandidatePtr ptrToGsfElectron(electrons,idx);
00323 
00324           // ref to base needed for the construction of the pat object
00325           const edm::RefToBase<reco::GsfElectron>& elecsRef = electrons->refAt(idx);
00326           Electron anElectron(elecsRef);
00327           anElectron.setPFCandidateRef( pfRef  );
00328 
00329           //it should be always true when particleFlow electrons are used.
00330           anElectron.setIsPF( true );
00331 
00332           if( embedPFCandidate_ ) anElectron.embedPFCandidate();
00333 
00334           if ( useUserData_ ) {
00335             userDataHelper_.add( anElectron, iEvent, iSetup );
00336           }
00337 
00338           double ip3d = -999; // for mva variable
00339 
00340           // embed high level selection
00341           if ( embedHighLevelSelection_ ) {
00342             // get the global track
00343             reco::GsfTrackRef track = PfTk;
00344 
00345             // Make sure the collection it points to is there
00346             if ( track.isNonnull() && track.isAvailable() ) {
00347 
00348               reco::TransientTrack tt = trackBuilder->build(track);
00349               embedHighLevel( anElectron,
00350                               track,
00351                               tt,
00352                               primaryVertex,
00353                               primaryVertexIsValid,
00354                               beamSpot,
00355                               beamSpotIsValid );
00356 
00357               std::pair<bool,Measurement1D> ip3dpv = IPTools::absoluteImpactParameter3D(tt, primaryVertex);
00358               ip3d = ip3dpv.second.value(); // for mva variable
00359 
00360               if ( !usePV_ ) {
00361                 double corr_d0 = track->dxy( beamPoint );
00362                 anElectron.setDB( corr_d0, -1.0 );
00363               } else {
00364                  std::pair<bool,Measurement1D> result = IPTools::absoluteTransverseImpactParameter(tt, primaryVertex);
00365                 double d0_corr = result.second.value();
00366                 double d0_err = result.second.error();
00367                 anElectron.setDB( d0_corr, d0_err );
00368               }
00369             }
00370           }
00371 
00372           //Electron Id
00373 
00374           if (addElecID_) {
00375             //STANDARD EL ID
00376             for (size_t i = 0; i < elecIDSrcs_.size(); ++i) {
00377               ids[i].second = (*idhandles[i])[elecsRef];
00378             }
00379             //SPECIFIC PF ID
00380             ids.push_back(std::make_pair("pf_evspi",pfRef->mva_e_pi()));
00381             ids.push_back(std::make_pair("pf_evsmu",pfRef->mva_e_mu()));
00382             anElectron.setElectronIDs(ids);
00383           }
00384 
00385           // add missing mva variables
00386           double r9 = lazyTools.e3x3( *( itElectron->superCluster()->seed())) / itElectron->superCluster()->rawEnergy() ;
00387           double sigmaIphiIphi;
00388           double sigmaIetaIphi;
00389           std::vector<float> vCov = lazyTools.localCovariances(*( itElectron->superCluster()->seed()));
00390           if( !edm::isNotFinite(vCov[2])) sigmaIphiIphi = sqrt(vCov[2]);
00391           else sigmaIphiIphi = 0;
00392           sigmaIetaIphi = vCov[1];
00393           anElectron.setMvaVariables( r9, sigmaIphiIphi, sigmaIetaIphi, ip3d);
00394 
00395           // get list of EcalDetId within 5x5 around the seed 
00396           bool barrel = itElectron->isEB();
00397           DetId seed = lazyTools.getMaximum(*(itElectron->superCluster()->seed())).first;
00398           std::vector<DetId> selectedCells = (barrel) ? ecalTopology_->getSubdetectorTopology(DetId::Ecal,EcalBarrel)->getWindow(seed,5,5):
00399             ecalTopology_->getSubdetectorTopology(DetId::Ecal,EcalEndcap)->getWindow(seed,5,5);          
00400           // add the DetId of the SC
00401           std::vector< std::pair<DetId, float> >::const_iterator it=itElectron->superCluster()->hitsAndFractions().begin();
00402           std::vector< std::pair<DetId, float> >::const_iterator itend=itElectron->superCluster()->hitsAndFractions().end();
00403           for( ; it!=itend ; ++it) {
00404             DetId id=it->first;
00405             // check if already saved
00406             std::vector<DetId>::const_iterator itcheck = find(selectedCells.begin(),selectedCells.end(),id);
00407             if ( itcheck == selectedCells.end()) {
00408               selectedCells.push_back(id);
00409             }
00410           }
00411           // Retrieve the corresponding RecHits
00412 
00413           edm::Handle< EcalRecHitCollection > rechitsH ;
00414           if(barrel) 
00415             iEvent.getByLabel(reducedBarrelRecHitCollection_,rechitsH);
00416           else
00417             iEvent.getByLabel(reducedEndcapRecHitCollection_,rechitsH);
00418 
00419           EcalRecHitCollection selectedRecHits;
00420           const EcalRecHitCollection *recHits = rechitsH.product();
00421 
00422           unsigned nSelectedCells = selectedCells.size();
00423           for (unsigned icell = 0 ; icell < nSelectedCells ; ++icell) {
00424            EcalRecHitCollection::const_iterator  it = recHits->find( selectedCells[icell] );
00425             if ( it != recHits->end() ) {
00426               selectedRecHits.push_back(*it);
00427             }
00428           }
00429           selectedRecHits.sort();
00430           if (embedRecHits_) anElectron.embedRecHits(& selectedRecHits);
00431          
00432             // set conversion veto selection
00433           bool passconversionveto = false;
00434           if( hConversions.isValid()){
00435             // this is recommended method
00436             passconversionveto = !ConversionTools::hasMatchedConversion( *itElectron, hConversions, beamSpotHandle->position());
00437           }else{
00438             // use missing hits without vertex fit method
00439             passconversionveto = itElectron->gsfTrack()->trackerExpectedHitsInner().numberOfLostHits() < 1;
00440           }
00441 
00442           anElectron.setPassConversionVeto( passconversionveto );
00443 
00444 
00445 //        fillElectron(anElectron,elecsRef,pfBaseRef,
00446 //                     genMatches, deposits, isolationValues);
00447 
00448           //COLIN small warning !
00449           // we are currently choosing to take the 4-momentum of the PFCandidate;
00450           // the momentum of the GsfElectron is saved though
00451           // we must therefore match the GsfElectron.
00452           // because of this, we should not change the source of the electron matcher
00453           // to the collection of PFElectrons in the python configuration
00454           // I don't know what to do with the efficiencyLoader, since I don't know
00455           // what this class is for.
00456           fillElectron2( anElectron,
00457                          ptrToPFElectron,
00458                          ptrToGsfElectron,
00459                          ptrToGsfElectron,
00460                          genMatches, deposits, isolationValues );
00461 
00462           //COLIN need to use fillElectron2 in the non-pflow case as well, and to test it.
00463 
00464           patElectrons->push_back(anElectron);
00465         }
00466       }
00467       //if( !Matched && !MatchedToAmbiguousGsfTrack) std::cout << "!!!!A pf electron could not be matched to a gsf!!!!"  << std::endl;
00468     }
00469   }
00470 
00471   else{
00472     // Try to access PF electron collection
00473     edm::Handle<edm::ValueMap<reco::PFCandidatePtr> >ValMapH;
00474     bool valMapPresent = iEvent.getByLabel(pfCandidateMap_,ValMapH);
00475     // Try to access a PFCandidate collection, as supplied by the user
00476     edm::Handle< reco::PFCandidateCollection >  pfElectrons;
00477     bool pfCandsPresent = iEvent.getByLabel(pfElecSrc_, pfElectrons);
00478 
00479     for (edm::View<reco::GsfElectron>::const_iterator itElectron = electrons->begin(); itElectron != electrons->end(); ++itElectron) {
00480       // construct the Electron from the ref -> save ref to original object
00481       //FIXME: looks like a lot of instances could be turned into const refs
00482       unsigned int idx = itElectron - electrons->begin();
00483       edm::RefToBase<reco::GsfElectron> elecsRef = electrons->refAt(idx);
00484       reco::CandidateBaseRef elecBaseRef(elecsRef);
00485       Electron anElectron(elecsRef);
00486 
00487       // Is this GsfElectron also identified as an e- in the particle flow?
00488       bool pfId = false;
00489 
00490       if ( pfCandsPresent ) {
00491         // PF electron collection not available.
00492         const reco::GsfTrackRef& trkRef = itElectron->gsfTrack();
00493         int index = 0;
00494         for( reco::PFCandidateConstIterator ie = pfElectrons->begin();
00495              ie != pfElectrons->end(); ++ie, ++index) {
00496           if(ie->particleId()!=reco::PFCandidate::e) continue;
00497           const reco::GsfTrackRef& pfTrkRef= ie->gsfTrackRef();
00498           if( trkRef == pfTrkRef ) {
00499             pfId = true;
00500             reco::PFCandidateRef pfRef(pfElectrons, index);
00501             anElectron.setPFCandidateRef( pfRef );
00502             break;
00503           }
00504         }
00505       }
00506       else if( valMapPresent ) {
00507         // use value map if PF collection not available
00508         const edm::ValueMap<reco::PFCandidatePtr> & myValMap(*ValMapH);
00509         // Get the PFCandidate
00510         const reco::PFCandidatePtr& pfElePtr(myValMap[elecsRef]);
00511         pfId= pfElePtr.isNonnull();
00512       }
00513       // set PFId function
00514       anElectron.setIsPF( pfId );
00515 
00516       // add resolution info
00517 
00518       // Isolation
00519       if (isolator_.enabled()) {
00520         isolator_.fill(*electrons, idx, isolatorTmpStorage_);
00521         typedef pat::helper::MultiIsolator::IsolationValuePairs IsolationValuePairs;
00522         // better to loop backwards, so the vector is resized less times
00523         for (IsolationValuePairs::const_reverse_iterator it = isolatorTmpStorage_.rbegin(), ed = isolatorTmpStorage_.rend(); it != ed; ++it) {
00524           anElectron.setIsolation(it->first, it->second);
00525         }
00526       }
00527 
00528       for (size_t j = 0, nd = deposits.size(); j < nd; ++j) {
00529         anElectron.setIsoDeposit(isoDepositLabels_[j].first, (*deposits[j])[elecsRef]);
00530       }
00531 
00532       // add electron ID info
00533       if (addElecID_) {
00534         for (size_t i = 0; i < elecIDSrcs_.size(); ++i) {
00535           ids[i].second = (*idhandles[i])[elecsRef];
00536         }
00537         anElectron.setElectronIDs(ids);
00538       }
00539 
00540 
00541       if ( useUserData_ ) {
00542         userDataHelper_.add( anElectron, iEvent, iSetup );
00543       }
00544 
00545 
00546       double ip3d = -999; //for mva variable
00547 
00548       // embed high level selection
00549       if ( embedHighLevelSelection_ ) {
00550         // get the global track
00551         reco::GsfTrackRef track = itElectron->gsfTrack();
00552 
00553         // Make sure the collection it points to is there
00554         if ( track.isNonnull() && track.isAvailable() ) {
00555 
00556           reco::TransientTrack tt = trackBuilder->build(track);
00557           embedHighLevel( anElectron,
00558                           track,
00559                           tt,
00560                           primaryVertex,
00561                           primaryVertexIsValid,
00562                           beamSpot,
00563                           beamSpotIsValid );
00564 
00565           std::pair<bool,Measurement1D> ip3dpv = IPTools::absoluteImpactParameter3D(tt, primaryVertex);
00566           ip3d = ip3dpv.second.value(); // for mva variable
00567 
00568           if ( !usePV_ ) {
00569             double corr_d0 = track->dxy( beamPoint );
00570             anElectron.setDB( corr_d0, -1.0 );
00571           } else {
00572             std::pair<bool,Measurement1D> result = IPTools::absoluteTransverseImpactParameter(tt, primaryVertex);
00573             double d0_corr = result.second.value();
00574             double d0_err = result.second.error();
00575             anElectron.setDB( d0_corr, d0_err );
00576           }
00577         }
00578       }
00579 
00580       // add mva variables
00581       double r9 = lazyTools.e3x3( *( itElectron->superCluster()->seed())) / itElectron->superCluster()->rawEnergy() ;
00582       double sigmaIphiIphi;
00583       double sigmaIetaIphi;
00584       std::vector<float> vCov = lazyTools.localCovariances(*( itElectron->superCluster()->seed()));
00585       if( !edm::isNotFinite(vCov[2])) sigmaIphiIphi = sqrt(vCov[2]);
00586       else sigmaIphiIphi = 0;
00587       sigmaIetaIphi = vCov[1];
00588       anElectron.setMvaVariables( r9, sigmaIphiIphi, sigmaIetaIphi, ip3d);
00589 
00590       // get list of EcalDetId within 5x5 around the seed 
00591       bool barrel= itElectron->isEB();
00592       DetId seed=lazyTools.getMaximum(*(itElectron->superCluster()->seed())).first;
00593       std::vector<DetId> selectedCells = (barrel) ? ecalTopology_->getSubdetectorTopology(DetId::Ecal,EcalBarrel)->getWindow(seed,5,5):
00594         ecalTopology_->getSubdetectorTopology(DetId::Ecal,EcalEndcap)->getWindow(seed,5,5);
00595       // add the DetId of the SC
00596 
00597       std::vector< std::pair<DetId, float> >::const_iterator it=itElectron->superCluster()->hitsAndFractions().begin();
00598       std::vector< std::pair<DetId, float> >::const_iterator itend=itElectron->superCluster()->hitsAndFractions().end();
00599       for( ; it!=itend ; ++it) {
00600         DetId id=it->first;
00601         // check if already saved
00602         std::vector<DetId>::const_iterator itcheck = find(selectedCells.begin(),selectedCells.end(),id);
00603         if ( itcheck == selectedCells.end()) {
00604           selectedCells.push_back(id);
00605         }
00606       }
00607       // Retrieve the corresponding RecHits
00608 
00609       edm::Handle< EcalRecHitCollection > rechitsH ;
00610       if(barrel)
00611         iEvent.getByLabel(reducedBarrelRecHitCollection_,rechitsH);
00612       else
00613         iEvent.getByLabel(reducedEndcapRecHitCollection_,rechitsH);
00614 
00615       EcalRecHitCollection selectedRecHits;
00616       const EcalRecHitCollection *recHits = rechitsH.product();
00617 
00618       unsigned nSelectedCells = selectedCells.size();
00619       for (unsigned icell = 0 ; icell < nSelectedCells ; ++icell) {
00620         EcalRecHitCollection::const_iterator  it = recHits->find( selectedCells[icell] );
00621         if ( it != recHits->end() ) {
00622           selectedRecHits.push_back(*it);
00623         }
00624       }
00625       selectedRecHits.sort();
00626       if (embedRecHits_) anElectron.embedRecHits(& selectedRecHits);
00627 
00628       // set conversion veto selection
00629       bool passconversionveto = false;
00630       if( hConversions.isValid()){
00631         // this is recommended method
00632         passconversionveto = !ConversionTools::hasMatchedConversion( *itElectron, hConversions, beamSpotHandle->position());
00633       }else{
00634         // use missing hits without vertex fit method
00635         passconversionveto = itElectron->gsfTrack()->trackerExpectedHitsInner().numberOfLostHits() < 1;
00636       }
00637       anElectron.setPassConversionVeto( passconversionveto );
00638 
00639       // add sel to selected
00640       fillElectron( anElectron, elecsRef,elecBaseRef,
00641                     genMatches, deposits, pfId, isolationValues, isolationValuesNoPFId);
00642       patElectrons->push_back(anElectron);
00643     }
00644   }
00645 
00646   // sort electrons in pt
00647   std::sort(patElectrons->begin(), patElectrons->end(), pTComparator_);
00648 
00649   // add the electrons to the event output
00650   std::auto_ptr<std::vector<Electron> > ptr(patElectrons);
00651   iEvent.put(ptr);
00652 
00653   // clean up
00654   if (isolator_.enabled()) isolator_.endEvent();
00655 
00656 }
00657 
00658 void PATElectronProducer::fillElectron(Electron& anElectron,
00659                                        const edm::RefToBase<reco::GsfElectron>& elecRef,
00660                                        const reco::CandidateBaseRef& baseRef,
00661                                        const GenAssociations& genMatches,
00662                                        const IsoDepositMaps& deposits,
00663                                        const bool pfId,
00664                                        const IsolationValueMaps& isolationValues,
00665                                        const IsolationValueMaps& isolationValuesNoPFId
00666                                        ) const {
00667 
00668   //COLIN: might want to use the PFCandidate 4-mom. Which one is in use now?
00669   //   if (useParticleFlow_)
00670   //     aMuon.setP4( aMuon.pfCandidateRef()->p4() );
00671 
00672   //COLIN:
00673   //In the embedding case, the reference cannot be used to look into a value map.
00674   //therefore, one has to had the PFCandidateRef to this function, which becomes a bit
00675   //too much specific.
00676 
00677   // in fact, this function needs a baseref or ptr for genmatch
00678   // and a baseref or ptr for isodeposits and isolationvalues.
00679   // baseref is not needed
00680   // the ptrForIsolation and ptrForMatching should be defined upstream.
00681 
00682   // is the concrete elecRef needed for the efficiency loader? what is this loader?
00683   // how can we make it compatible with the particle flow electrons?
00684 
00685   if (embedGsfElectronCore_) anElectron.embedGsfElectronCore();
00686   if (embedGsfTrack_) anElectron.embedGsfTrack();
00687   if (embedSuperCluster_) anElectron.embedSuperCluster();
00688   if (embedSeedCluster_) anElectron.embedSeedCluster();
00689   if (embedTrack_) anElectron.embedTrack();
00690 
00691   // store the match to the generated final state muons
00692   if (addGenMatch_) {
00693     for(size_t i = 0, n = genMatches.size(); i < n; ++i) {
00694       if(useParticleFlow_) {
00695         reco::GenParticleRef genElectron = (*genMatches[i])[anElectron.pfCandidateRef()];
00696         anElectron.addGenParticleRef(genElectron);
00697       }
00698       else {
00699         reco::GenParticleRef genElectron = (*genMatches[i])[elecRef];
00700         anElectron.addGenParticleRef(genElectron);
00701       }
00702     }
00703     if (embedGenMatch_) anElectron.embedGenParticle();
00704   }
00705 
00706   if (efficiencyLoader_.enabled()) {
00707     efficiencyLoader_.setEfficiencies( anElectron, elecRef );
00708   }
00709 
00710   if (resolutionLoader_.enabled()) {
00711     resolutionLoader_.setResolutions(anElectron);
00712   }
00713 
00714   for (size_t j = 0, nd = deposits.size(); j < nd; ++j) {
00715     if(useParticleFlow_) {
00716 
00717       reco::PFCandidateRef pfcandref =  anElectron.pfCandidateRef();
00718       assert(!pfcandref.isNull());
00719       reco::CandidatePtr source = pfcandref->sourceCandidatePtr(0);
00720       anElectron.setIsoDeposit(isoDepositLabels_[j].first,
00721                           (*deposits[j])[source]);
00722     }
00723     else
00724       anElectron.setIsoDeposit(isoDepositLabels_[j].first,
00725                           (*deposits[j])[elecRef]);
00726   }
00727 
00728   for (size_t j = 0; j<isolationValues.size(); ++j) {
00729     if(useParticleFlow_) {
00730       reco::CandidatePtr source = anElectron.pfCandidateRef()->sourceCandidatePtr(0);
00731       anElectron.setIsolation(isolationValueLabels_[j].first,
00732                          (*isolationValues[j])[source]);
00733     }
00734     else
00735       if(pfId){
00736         anElectron.setIsolation(isolationValueLabels_[j].first,(*isolationValues[j])[elecRef]);
00737       }
00738   }
00739 
00740   //for electrons not identified as PF electrons
00741   for (size_t j = 0; j<isolationValuesNoPFId.size(); ++j) {
00742     if( !pfId) {
00743       anElectron.setIsolation(isolationValueLabelsNoPFId_[j].first,(*isolationValuesNoPFId[j])[elecRef]);
00744     }
00745   }
00746 
00747 }
00748 
00749 void PATElectronProducer::fillElectron2( Electron& anElectron,
00750                                          const reco::CandidatePtr& candPtrForIsolation,
00751                                          const reco::CandidatePtr& candPtrForGenMatch,
00752                                          const reco::CandidatePtr& candPtrForLoader,
00753                                          const GenAssociations& genMatches,
00754                                          const IsoDepositMaps& deposits,
00755                                          const IsolationValueMaps& isolationValues) const {
00756 
00757   //COLIN/Florian: use the PFCandidate 4-mom.
00758   anElectron.setEcalDrivenMomentum(anElectron.p4()) ;
00759   anElectron.setP4( anElectron.pfCandidateRef()->p4() );
00760 
00761 
00762   // is the concrete elecRef needed for the efficiency loader? what is this loader?
00763   // how can we make it compatible with the particle flow electrons?
00764 
00765   if (embedGsfElectronCore_) anElectron.embedGsfElectronCore();
00766   if (embedGsfTrack_) anElectron.embedGsfTrack();
00767   if (embedSuperCluster_) anElectron.embedSuperCluster();
00768   if (embedSeedCluster_) anElectron.embedSeedCluster();
00769   if (embedTrack_) anElectron.embedTrack();
00770 
00771   // store the match to the generated final state muons
00772 
00773   if (addGenMatch_) {
00774     for(size_t i = 0, n = genMatches.size(); i < n; ++i) {
00775       reco::GenParticleRef genElectron = (*genMatches[i])[candPtrForGenMatch];
00776       anElectron.addGenParticleRef(genElectron);
00777     }
00778     if (embedGenMatch_) anElectron.embedGenParticle();
00779   }
00780 
00781   //COLIN what's this? does it have to be GsfElectron specific?
00782   if (efficiencyLoader_.enabled()) {
00783     efficiencyLoader_.setEfficiencies( anElectron, candPtrForLoader );
00784   }
00785 
00786   if (resolutionLoader_.enabled()) {
00787     resolutionLoader_.setResolutions(anElectron);
00788   }
00789 
00790   for (size_t j = 0, nd = deposits.size(); j < nd; ++j) {
00791     if( isoDepositLabels_[j].first==pat::TrackIso ||
00792         isoDepositLabels_[j].first==pat::EcalIso ||
00793         isoDepositLabels_[j].first==pat::HcalIso ||
00794         deposits[j]->contains(candPtrForGenMatch.id())) {
00795       anElectron.setIsoDeposit(isoDepositLabels_[j].first,
00796                                (*deposits[j])[candPtrForGenMatch]);
00797     }
00798     else if (deposits[j]->contains(candPtrForIsolation.id())) {
00799       anElectron.setIsoDeposit(isoDepositLabels_[j].first,
00800                                (*deposits[j])[candPtrForIsolation]);
00801     }
00802     else {
00803       anElectron.setIsoDeposit(isoDepositLabels_[j].first,
00804                                (*deposits[j])[candPtrForIsolation->sourceCandidatePtr(0)]);
00805     }
00806   }
00807 
00808   for (size_t j = 0; j<isolationValues.size(); ++j) {
00809     if( isolationValueLabels_[j].first==pat::TrackIso ||
00810         isolationValueLabels_[j].first==pat::EcalIso ||
00811         isolationValueLabels_[j].first==pat::HcalIso ||
00812         isolationValues[j]->contains(candPtrForGenMatch.id())) {
00813       anElectron.setIsolation(isolationValueLabels_[j].first,
00814                               (*isolationValues[j])[candPtrForGenMatch]);
00815     }
00816     else if (isolationValues[j]->contains(candPtrForIsolation.id())) {
00817       anElectron.setIsolation(isolationValueLabels_[j].first,
00818                               (*isolationValues[j])[candPtrForIsolation]);
00819     }
00820     else {
00821       anElectron.setIsolation(isolationValueLabels_[j].first,
00822                               (*isolationValues[j])[candPtrForIsolation->sourceCandidatePtr(0)]);
00823     }
00824   }
00825 }
00826 
00827 
00828 // ParameterSet description for module
00829 void PATElectronProducer::fillDescriptions(edm::ConfigurationDescriptions & descriptions)
00830 {
00831   edm::ParameterSetDescription iDesc;
00832   iDesc.setComment("PAT electron producer module");
00833 
00834   // input source
00835   iDesc.add<edm::InputTag>("pfCandidateMap", edm::InputTag("no default"))->setComment("input collection");
00836   iDesc.add<edm::InputTag>("electronSource", edm::InputTag("no default"))->setComment("input collection");
00837 
00838   // embedding
00839   iDesc.add<bool>("embedGsfElectronCore", true)->setComment("embed external gsf electron core");
00840   iDesc.add<bool>("embedGsfTrack", true)->setComment("embed external gsf track");
00841   iDesc.add<bool>("embedSuperCluster", true)->setComment("embed external super cluster");
00842   iDesc.add<bool>("embedSeedCluster", true)->setComment("embed external seed cluster");
00843   iDesc.add<bool>("embedTrack", false)->setComment("embed external track");
00844   iDesc.add<bool>("embedRecHits", true)->setComment("embed external RecHits");
00845 
00846   // pf specific parameters
00847   iDesc.add<edm::InputTag>("pfElectronSource", edm::InputTag("pfElectrons"))->setComment("particle flow input collection");
00848   iDesc.add<bool>("useParticleFlow", false)->setComment("whether to use particle flow or not");
00849   iDesc.add<bool>("embedPFCandidate", false)->setComment("embed external particle flow object");
00850 
00851   // MC matching configurables
00852   iDesc.add<bool>("addGenMatch", true)->setComment("add MC matching");
00853   iDesc.add<bool>("embedGenMatch", false)->setComment("embed MC matched MC information");
00854   std::vector<edm::InputTag> emptySourceVector;
00855   iDesc.addNode( edm::ParameterDescription<edm::InputTag>("genParticleMatch", edm::InputTag(), true) xor
00856                  edm::ParameterDescription<std::vector<edm::InputTag> >("genParticleMatch", emptySourceVector, true)
00857                  )->setComment("input with MC match information");
00858 
00859   // electron ID configurables
00860   iDesc.add<bool>("addElectronID",true)->setComment("add electron ID variables");
00861   edm::ParameterSetDescription electronIDSourcesPSet;
00862   electronIDSourcesPSet.setAllowAnything();
00863   iDesc.addNode( edm::ParameterDescription<edm::InputTag>("electronIDSource", edm::InputTag(), true) xor
00864                  edm::ParameterDescription<edm::ParameterSetDescription>("electronIDSources", electronIDSourcesPSet, true)
00865                  )->setComment("input with electron ID variables");
00866 
00867 
00868   // IsoDeposit configurables
00869   edm::ParameterSetDescription isoDepositsPSet;
00870   isoDepositsPSet.addOptional<edm::InputTag>("tracker");
00871   isoDepositsPSet.addOptional<edm::InputTag>("ecal");
00872   isoDepositsPSet.addOptional<edm::InputTag>("hcal");
00873   isoDepositsPSet.addOptional<edm::InputTag>("pfAllParticles");
00874   isoDepositsPSet.addOptional<edm::InputTag>("pfChargedHadrons");
00875   isoDepositsPSet.addOptional<edm::InputTag>("pfChargedAll");
00876   isoDepositsPSet.addOptional<edm::InputTag>("pfPUChargedHadrons");
00877   isoDepositsPSet.addOptional<edm::InputTag>("pfNeutralHadrons");
00878   isoDepositsPSet.addOptional<edm::InputTag>("pfPhotons");
00879   isoDepositsPSet.addOptional<std::vector<edm::InputTag> >("user");
00880   iDesc.addOptional("isoDeposits", isoDepositsPSet);
00881 
00882   // isolation values configurables
00883   edm::ParameterSetDescription isolationValuesPSet;
00884   isolationValuesPSet.addOptional<edm::InputTag>("tracker");
00885   isolationValuesPSet.addOptional<edm::InputTag>("ecal");
00886   isolationValuesPSet.addOptional<edm::InputTag>("hcal");
00887   isolationValuesPSet.addOptional<edm::InputTag>("pfAllParticles");
00888   isolationValuesPSet.addOptional<edm::InputTag>("pfChargedHadrons");
00889   isolationValuesPSet.addOptional<edm::InputTag>("pfChargedAll");
00890   isolationValuesPSet.addOptional<edm::InputTag>("pfPUChargedHadrons");
00891   isolationValuesPSet.addOptional<edm::InputTag>("pfNeutralHadrons");
00892   isolationValuesPSet.addOptional<edm::InputTag>("pfPhotons");
00893   isolationValuesPSet.addOptional<std::vector<edm::InputTag> >("user");
00894   iDesc.addOptional("isolationValues", isolationValuesPSet);
00895 
00896   // isolation values configurables
00897   edm::ParameterSetDescription isolationValuesNoPFIdPSet;
00898   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("tracker");
00899   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("ecal");
00900   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("hcal");
00901   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("pfAllParticles");
00902   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("pfChargedHadrons");
00903   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("pfChargedAll");
00904   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("pfPUChargedHadrons");
00905   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("pfNeutralHadrons");
00906   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("pfPhotons");
00907   isolationValuesNoPFIdPSet.addOptional<std::vector<edm::InputTag> >("user");
00908   iDesc.addOptional("isolationValuesNoPFId", isolationValuesNoPFIdPSet);
00909 
00910   // Efficiency configurables
00911   edm::ParameterSetDescription efficienciesPSet;
00912   efficienciesPSet.setAllowAnything(); // TODO: the pat helper needs to implement a description.
00913   iDesc.add("efficiencies", efficienciesPSet);
00914   iDesc.add<bool>("addEfficiencies", false);
00915 
00916   // Check to see if the user wants to add user data
00917   edm::ParameterSetDescription userDataPSet;
00918   PATUserDataHelper<Electron>::fillDescription(userDataPSet);
00919   iDesc.addOptional("userData", userDataPSet);
00920 
00921   // electron shapes
00922   iDesc.add<bool>("addElectronShapes", true);
00923   iDesc.add<edm::InputTag>("reducedBarrelRecHitCollection", edm::InputTag("reducedEcalRecHitsEB"));
00924   iDesc.add<edm::InputTag>("reducedEndcapRecHitCollection", edm::InputTag("reducedEcalRecHitsEE"));
00925 
00926   edm::ParameterSetDescription isolationPSet;
00927   isolationPSet.setAllowAnything(); // TODO: the pat helper needs to implement a description.
00928   iDesc.add("userIsolation", isolationPSet);
00929 
00930   // Resolution configurables
00931   pat::helper::KinResolutionsLoader::fillDescription(iDesc);
00932 
00933   iDesc.add<bool>("embedHighLevelSelection", true)->setComment("embed high level selection");
00934   edm::ParameterSetDescription highLevelPSet;
00935   highLevelPSet.setAllowAnything();
00936   iDesc.addNode( edm::ParameterDescription<edm::InputTag>("beamLineSrc", edm::InputTag(), true)
00937                  )->setComment("input with high level selection");
00938   iDesc.addNode( edm::ParameterDescription<edm::InputTag>("pvSrc", edm::InputTag(), true)
00939                  )->setComment("input with high level selection");
00940   iDesc.addNode( edm::ParameterDescription<bool>("usePV", bool(), true)
00941                  )->setComment("input with high level selection, use primary vertex (true) or beam line (false)");
00942 
00943   descriptions.add("PATElectronProducer", iDesc);
00944 
00945 }
00946 
00947 
00948 
00949 void PATElectronProducer::readIsolationLabels( const edm::ParameterSet & iConfig,
00950                                                const char* psetName,
00951                                                IsolationLabels& labels) {
00952 
00953   labels.clear();
00954 
00955   if (iConfig.exists( psetName )) {
00956     edm::ParameterSet depconf
00957       = iConfig.getParameter<edm::ParameterSet>(psetName);
00958 
00959     if (depconf.exists("tracker")) labels.push_back(std::make_pair(pat::TrackIso, depconf.getParameter<edm::InputTag>("tracker")));
00960     if (depconf.exists("ecal"))    labels.push_back(std::make_pair(pat::EcalIso, depconf.getParameter<edm::InputTag>("ecal")));
00961     if (depconf.exists("hcal"))    labels.push_back(std::make_pair(pat::HcalIso, depconf.getParameter<edm::InputTag>("hcal")));
00962     if (depconf.exists("pfAllParticles"))  {
00963       labels.push_back(std::make_pair(pat::PfAllParticleIso, depconf.getParameter<edm::InputTag>("pfAllParticles")));
00964     }
00965     if (depconf.exists("pfChargedHadrons"))  {
00966       labels.push_back(std::make_pair(pat::PfChargedHadronIso, depconf.getParameter<edm::InputTag>("pfChargedHadrons")));
00967     }
00968     if (depconf.exists("pfChargedAll"))  {
00969       labels.push_back(std::make_pair(pat::PfChargedAllIso, depconf.getParameter<edm::InputTag>("pfChargedAll")));
00970     }
00971     if (depconf.exists("pfPUChargedHadrons"))  {
00972       labels.push_back(std::make_pair(pat::PfPUChargedHadronIso, depconf.getParameter<edm::InputTag>("pfPUChargedHadrons")));
00973     }
00974     if (depconf.exists("pfNeutralHadrons"))  {
00975       labels.push_back(std::make_pair(pat::PfNeutralHadronIso, depconf.getParameter<edm::InputTag>("pfNeutralHadrons")));
00976     }
00977     if (depconf.exists("pfPhotons")) {
00978       labels.push_back(std::make_pair(pat::PfGammaIso, depconf.getParameter<edm::InputTag>("pfPhotons")));
00979     }
00980     if (depconf.exists("user")) {
00981       std::vector<edm::InputTag> userdeps = depconf.getParameter<std::vector<edm::InputTag> >("user");
00982       std::vector<edm::InputTag>::const_iterator it = userdeps.begin(), ed = userdeps.end();
00983       int key = UserBaseIso;
00984       for ( ; it != ed; ++it, ++key) {
00985         labels.push_back(std::make_pair(IsolationKeys(key), *it));
00986       }
00987     }
00988   }
00989 
00990 
00991 }
00992 
00993 
00994 // embed various impact parameters with errors
00995 // embed high level selection
00996 void PATElectronProducer::embedHighLevel( pat::Electron & anElectron,
00997                                           reco::GsfTrackRef track,
00998                                           reco::TransientTrack & tt,
00999                                           reco::Vertex & primaryVertex,
01000                                           bool primaryVertexIsValid,
01001                                           reco::BeamSpot & beamspot,
01002                                           bool beamspotIsValid
01003                                           )
01004 {
01005   // Correct to PV
01006 
01007   // PV2D
01008   std::pair<bool,Measurement1D> result =
01009     IPTools::signedTransverseImpactParameter(tt,
01010                                              GlobalVector(track->px(),
01011                                                           track->py(),
01012                                                           track->pz()),
01013                                              primaryVertex);
01014   double d0_corr = result.second.value();
01015   double d0_err = primaryVertexIsValid ? result.second.error() : -1.0;
01016   anElectron.setDB( d0_corr, d0_err, pat::Electron::PV2D);
01017 
01018 
01019   // PV3D
01020   result =
01021     IPTools::signedImpactParameter3D(tt,
01022                                      GlobalVector(track->px(),
01023                                                   track->py(),
01024                                                   track->pz()),
01025                                      primaryVertex);
01026   d0_corr = result.second.value();
01027   d0_err = primaryVertexIsValid ? result.second.error() : -1.0;
01028   anElectron.setDB( d0_corr, d0_err, pat::Electron::PV3D);
01029 
01030 
01031   // Correct to beam spot
01032   // make a fake vertex out of beam spot
01033   reco::Vertex vBeamspot(beamspot.position(), beamspot.covariance3D());
01034 
01035   // BS2D
01036   result =
01037     IPTools::signedTransverseImpactParameter(tt,
01038                                              GlobalVector(track->px(),
01039                                                           track->py(),
01040                                                           track->pz()),
01041                                              vBeamspot);
01042   d0_corr = result.second.value();
01043   d0_err = beamspotIsValid ? result.second.error() : -1.0;
01044   anElectron.setDB( d0_corr, d0_err, pat::Electron::BS2D);
01045 
01046   // BS3D
01047   result =
01048     IPTools::signedImpactParameter3D(tt,
01049                                      GlobalVector(track->px(),
01050                                                   track->py(),
01051                                                   track->pz()),
01052                                      vBeamspot);
01053   d0_corr = result.second.value();
01054   d0_err = beamspotIsValid ? result.second.error() : -1.0;
01055   anElectron.setDB( d0_corr, d0_err, pat::Electron::BS3D);
01056 }
01057 
01058 #include "FWCore/Framework/interface/MakerMacros.h"
01059 
01060 DEFINE_FWK_MODULE(PATElectronProducer);