CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/PhysicsTools/PatAlgos/plugins/PATElectronProducer.cc

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