00001
00002
00003
00004
00005
00012
00013
00014
00015
00016
00017
00018
00019 #include "DataFormats/GsfTrackReco/interface/GsfTrackFwd.h"
00020
00021 #include "RecoEgamma/EgammaElectronAlgos/interface/GsfElectronAlgo.h"
00022 #include "RecoEgamma/EgammaElectronAlgos/interface/ElectronClassification.h"
00023 #include "RecoEgamma/EgammaElectronAlgos/interface/ElectronMomentumCorrector.h"
00024 #include "RecoEgamma/EgammaElectronAlgos/interface/ElectronEnergyCorrector.h"
00025 #include "RecoEgamma/EgammaTools/interface/ECALPositionCalculator.h"
00026 #include "RecoEgamma/EgammaTools/interface/HoECalculator.h"
00027
00028 #include "DataFormats/EgammaReco/interface/BasicCluster.h"
00029 #include "DataFormats/EgammaReco/interface/ElectronPixelSeed.h"
00030 #include "DataFormats/EgammaReco/interface/ElectronPixelSeedFwd.h"
00031 #include "DataFormats/TrackCandidate/interface/TrackCandidate.h"
00032 #include "DataFormats/TrackCandidate/interface/TrackCandidateCollection.h"
00033 #include "DataFormats/Math/interface/LorentzVector.h"
00034 #include "DataFormats/TrackingRecHit/interface/TrackingRecHitFwd.h"
00035 #include "DataFormats/HcalDetId/interface/HcalSubdetector.h"
00036 #include "DataFormats/HcalDetId/interface/HcalDetId.h"
00037 #include "DataFormats/HcalRecHit/interface/HcalRecHitCollections.h"
00038 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
00039
00040 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
00041 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00042 #include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
00043 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00044
00045
00046 #include "TrackingTools/PatternTools/interface/Trajectory.h"
00047 #include "TrackingTools/Records/interface/TrackingComponentsRecord.h"
00048 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
00049 #include "TrackingTools/PatternTools/interface/TransverseImpactPointExtrapolator.h"
00050 #include "TrackingTools/PatternTools/interface/TSCPBuilderNoMaterial.h"
00051 #include "TrackingTools/GsfTools/interface/MultiTrajectoryStateTransform.h"
00052 #include "TrackingTools/GsfTools/interface/GSUtilities.h"
00053 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
00054 #include "TrackingTools/GeomPropagators/interface/AnalyticalPropagator.h"
00055 #include "TrackingTools/GsfTools/interface/GsfPropagatorAdapter.h"
00056 #include "TrackingTools/GsfTools/interface/MultiGaussianStateTransform.h"
00057 #include "TrackingTools/GsfTools/interface/MultiGaussianState1D.h"
00058 #include "TrackingTools/GsfTools/interface/GaussianSumUtilities1D.h"
00059 #include "RecoCaloTools/Selectors/interface/CaloConeSelector.h"
00060
00061 #include "RecoTracker/Record/interface/TrackerRecoGeometryRecord.h"
00062 #include "RecoTracker/Record/interface/CkfComponentsRecord.h"
00063
00064 #include "Geometry/CommonDetUnit/interface/TrackingGeometry.h"
00065 #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
00066 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
00067 #include "DataFormats/GeometryVector/interface/GlobalVector.h"
00068 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
00069
00070 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00071 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00072
00073 #include "CLHEP/Units/PhysicalConstants.h"
00074 #include <TMath.h>
00075 #include <sstream>
00076 #include <Math/VectorUtil.h>
00077 #include <Math/Point3D.h>
00078
00079
00080 using namespace edm;
00081 using namespace std;
00082 using namespace reco;
00083
00084 GsfElectronAlgo::GsfElectronAlgo(const edm::ParameterSet& conf,
00085 double maxEOverPBarrel, double maxEOverPEndcaps,
00086 double minEOverPBarrel, double minEOverPEndcaps,
00087 double maxDeltaEta, double maxDeltaPhi,
00088 bool highPtPresel, double highPtMin,
00089 bool applyEtaCorrection, bool applyAmbResolution):
00090 maxEOverPBarrel_(maxEOverPBarrel), maxEOverPEndcaps_(maxEOverPEndcaps),
00091 minEOverPBarrel_(minEOverPBarrel), minEOverPEndcaps_(minEOverPEndcaps),
00092 maxDeltaEta_(maxDeltaEta), maxDeltaPhi_(maxDeltaPhi),
00093 highPtPreselection_(highPtPresel), highPtMin_(highPtMin),
00094 applyEtaCorrection_(applyEtaCorrection), applyAmbResolution_(applyAmbResolution),
00095 cacheIDGeom_(0),cacheIDTDGeom_(0),cacheIDMagField_(0)
00096 {
00097
00098
00099 mtsTransform_ = new MultiTrajectoryStateTransform;
00100 geomPropBw_=0;
00101 geomPropFw_=0;
00102
00103
00104 ParameterSet tise_params = conf.getParameter<ParameterSet>("TransientInitialStateEstimatorParameters") ;
00105
00106
00107 hcalRecHits_ = conf.getParameter<edm::InputTag>("hcalRecHits");
00108 tracks_ = conf.getParameter<edm::InputTag>("tracks");
00109
00110 }
00111
00112 GsfElectronAlgo::~GsfElectronAlgo() {
00113 delete geomPropBw_;
00114 delete geomPropFw_;
00115 delete mtsTransform_;
00116 }
00117
00118 void GsfElectronAlgo::setupES(const edm::EventSetup& es) {
00119
00120
00121 if (cacheIDMagField_!=es.get<IdealMagneticFieldRecord>().cacheIdentifier()){
00122 cacheIDMagField_=es.get<IdealMagneticFieldRecord>().cacheIdentifier();
00123 es.get<IdealMagneticFieldRecord>().get(theMagField);
00124 if (geomPropBw_) delete geomPropBw_;
00125 geomPropBw_ = new GsfPropagatorAdapter(AnalyticalPropagator(theMagField.product(), oppositeToMomentum));
00126 if (geomPropFw_) delete geomPropFw_;
00127 geomPropFw_ = new GsfPropagatorAdapter(AnalyticalPropagator(theMagField.product(), alongMomentum));
00128 }
00129 if (cacheIDTDGeom_!=es.get<TrackerDigiGeometryRecord>().cacheIdentifier()){
00130 cacheIDTDGeom_=es.get<TrackerDigiGeometryRecord>().cacheIdentifier();
00131 es.get<TrackerDigiGeometryRecord>().get(trackerHandle_);
00132 }
00133
00134 if (cacheIDGeom_!=es.get<CaloGeometryRecord>().cacheIdentifier()){
00135 cacheIDGeom_=es.get<CaloGeometryRecord>().cacheIdentifier();
00136 es.get<CaloGeometryRecord>().get(theCaloGeom);
00137 }
00138
00139
00140 }
00141
00142 void GsfElectronAlgo::run(Event& e, GsfElectronCollection & outEle) {
00143
00144
00145 edm::Handle<GsfTrackCollection> tracksH;
00146 e.getByLabel(tracks_,tracksH);
00147
00148
00149 edm::Handle<HBHERecHitCollection> hbhe;
00150 mhbhe_=0;
00151 bool got = e.getByLabel(hcalRecHits_,hbhe);
00152 if (got) mhbhe_= new HBHERecHitMetaCollection(*hbhe);
00153
00154
00155 edm::Handle<reco::BeamSpot> recoBeamSpotHandle;
00156 e.getByType(recoBeamSpotHandle);
00157 const math::XYZPoint bsPosition = recoBeamSpotHandle->position();
00158
00159
00160 std::vector<GsfElectron> tempEle;
00161
00162
00163 process(tracksH,bsPosition,tempEle);
00164
00165 std::ostringstream str;
00166
00167 str << "\n========== GsfElectronAlgo Info (before amb. solving) ==========";
00168 str << "\nEvent " << e.id();
00169 str << "\nNumber of final electron tracks: " << tracksH.product()->size();
00170 str << "\nNumber of final electrons: " << tempEle.size();
00171 for (vector<GsfElectron>::const_iterator it = tempEle.begin(); it != tempEle.end(); it++) {
00172 str << "\nNew electron with charge, pt, eta, phi : " << it->charge() << " , "
00173 << it->pt() << " , " << it->eta() << " , " << it->phi();
00174 }
00175
00176 str << "\n=================================================";
00177 LogDebug("GsfElectronAlgo") << str.str();
00178
00179 std::ostringstream str2;
00180
00181 if (applyAmbResolution_) {
00182
00183 resolveElectrons(tempEle, outEle);
00184
00185 str2 << "\n========== GsfElectronAlgo Info (after amb. solving) ==========";
00186 str2 << "\nEvent " << e.id();
00187 str2 << "\nNumber of final electron tracks: " << tracksH.product()->size();
00188 str2 << "\nNumber of final electrons: " << outEle.size();
00189 for (vector<GsfElectron>::const_iterator it = outEle.begin(); it != outEle.end(); it++) {
00190 str2 << "\nNew electron with charge, pt, eta, phi : " << it->charge() << " , "
00191 << it->pt() << " , " << it->eta() << " , " << it->phi();
00192 }
00193
00194 str2 << "\n=================================================";
00195 LogDebug("GsfElectronAlgo") << str2.str();
00196
00197 } else {
00198
00199 outEle = tempEle;
00200
00201 }
00202
00203 delete mhbhe_;
00204 return;
00205 }
00206
00207 void GsfElectronAlgo::process(edm::Handle<GsfTrackCollection> tracksH,
00208 const math::XYZPoint &bsPosition,
00209 GsfElectronCollection & outEle) {
00210
00211
00212 const GsfTrackCollection *tracks=tracksH.product();
00213 for (unsigned int i=0;i<tracks->size();++i) {
00214
00215
00216
00217 const GsfTrack & t=(*tracks)[i];
00218 const GsfTrackRef trackRef = edm::Ref<GsfTrackCollection>(tracksH,i);
00219 const SuperClusterRef & scRef=getTrSuperCluster(trackRef);
00220 const SuperCluster theClus=*scRef;
00221 std::vector<DetId> vecId=theClus.seed()->getHitsByDetId();
00222 subdet_ =vecId[0].subdetId();
00223
00224
00225 if (!calculateTSOS(t,theClus, bsPosition)) continue;
00226 vtxMom_=computeMode(vtxTSOS_);
00227 sclPos_=sclTSOS_.globalPosition();
00228 if (preSelection(theClus)) {
00229
00230
00231 createElectron(scRef,trackRef,outEle);
00232
00233 LogInfo("")<<"Constructed new electron with energy "<< scRef->energy();
00234 }
00235 }
00236 }
00237
00238 bool GsfElectronAlgo::preSelection(const SuperCluster& clus)
00239 {
00240
00241 LogDebug("")<< "========== preSelection ==========";
00242
00243 double rt2 = clus.x()*clus.x() + clus.y()*clus.y();
00244 double r2 = rt2 + clus.z()*clus.z();
00245 double Et =clus.energy()*sqrt(rt2/r2);
00246
00247
00248 LogDebug("") << "pT : " << vtxMom_.perp();
00249
00250
00251 LogDebug("") << "E/p : " << clus.energy()/vtxMom_.mag();
00252
00253
00254 if (!highPtPreselection_ || Et <= highPtMin_) {
00255 if ((subdet_==EcalBarrel) && (clus.energy()/vtxMom_.mag() > maxEOverPBarrel_)) return false;
00256 if ((subdet_==EcalEndcap) && (clus.energy()/vtxMom_.mag() > maxEOverPEndcaps_)) return false;
00257 if ((subdet_==EcalBarrel) && (clus.energy()/vtxMom_.mag() < minEOverPBarrel_)) return false;
00258 if ((subdet_==EcalEndcap) && (clus.energy()/vtxMom_.mag() < minEOverPEndcaps_)) return false;
00259 }
00260 LogDebug("") << "E/p criteria is satisfied ";
00261
00262
00263 double etaclu = clus.eta();
00264 double etatrk = sclPos_.eta();
00265 double deta = etaclu-etatrk;
00266 LogDebug("") << "delta eta : " << deta;
00267 if (fabs(deta) > maxDeltaEta_) return false;
00268 LogDebug("") << "Delta eta criteria is satisfied ";
00269
00270
00271 double phiclu = clus.phi();
00272 double phitrk = sclPos_.phi();
00273 double dphi = phiclu-phitrk;
00274 if (fabs(dphi)>CLHEP::pi)
00275 dphi = dphi < 0? (CLHEP::twopi) + dphi : dphi - CLHEP::twopi;
00276 LogDebug("") << "delta phi : " << dphi;
00277 if (fabs(dphi) > maxDeltaPhi_) return false;
00278 LogDebug("") << "Delta phi criteria is satisfied ";
00279
00280 LogDebug("") << "electron has passed preselection criteria ";
00281 LogDebug("") << "=================================================";
00282 return true;
00283
00284 }
00285
00286 GlobalVector GsfElectronAlgo::computeMode(const TrajectoryStateOnSurface &tsos) {
00287
00288
00289
00290 float mode_Px = 0.;
00291 float mode_Py = 0.;
00292 float mode_Pz = 0.;
00293 if ( tsos.isValid() ){
00294 std::vector<TrajectoryStateOnSurface> components(tsos.components());
00295 unsigned int numb = components.size();
00296 std::vector<SingleGaussianState1D> pxStates; pxStates.reserve(numb);
00297 std::vector<SingleGaussianState1D> pyStates; pyStates.reserve(numb);
00298 std::vector<SingleGaussianState1D> pzStates; pzStates.reserve(numb);
00299 for ( std::vector<TrajectoryStateOnSurface>::const_iterator ic=components.begin();
00300 ic!=components.end(); ++ic ) {
00301 GlobalVector momentum(ic->globalMomentum());
00302 AlgebraicSymMatrix66 cov(ic->cartesianError().matrix());
00303 pxStates.push_back(SingleGaussianState1D(momentum.x(),cov(3,3),ic->weight()));
00304 pyStates.push_back(SingleGaussianState1D(momentum.y(),cov(4,4),ic->weight()));
00305 pzStates.push_back(SingleGaussianState1D(momentum.z(),cov(5,5),ic->weight()));
00306 }
00307 MultiGaussianState1D pxState(pxStates);
00308 MultiGaussianState1D pyState(pyStates);
00309 MultiGaussianState1D pzState(pzStates);
00310 GaussianSumUtilities1D pxUtils(pxState);
00311 GaussianSumUtilities1D pyUtils(pyState);
00312 GaussianSumUtilities1D pzUtils(pzState);
00313 mode_Px = pxUtils.mode().mean();
00314 mode_Py = pyUtils.mode().mean();
00315 mode_Pz = pzUtils.mode().mean();
00316 } else edm::LogInfo("") << "tsos not valid!!";
00317 return GlobalVector(mode_Px,mode_Py,mode_Pz);
00318
00319 }
00320
00321
00322 void GsfElectronAlgo::createElectron(const SuperClusterRef & scRef, const GsfTrackRef &trackRef, GsfElectronCollection & outEle) {
00323 GlobalVector innMom=computeMode(innTSOS_);
00324 GlobalPoint innPos=innTSOS_.globalPosition();
00325 GlobalVector seedMom=computeMode(seedTSOS_);
00326 GlobalPoint seedPos=seedTSOS_.globalPosition();
00327 GlobalVector sclMom=computeMode(sclTSOS_);
00328
00329 GlobalPoint vtxPos=vtxTSOS_.globalPosition();
00330 GlobalVector outMom=computeMode(outTSOS_);
00331 GlobalPoint outPos=outTSOS_.globalPosition();
00332
00333
00334 double scale = (*scRef).energy()/vtxMom_.mag();
00335 math::XYZTLorentzVectorD momentum= math::XYZTLorentzVector(vtxMom_.x()*scale,
00336 vtxMom_.y()*scale,
00337 vtxMom_.z()*scale,
00338 (*scRef).energy());
00339
00340 HoECalculator calc(theCaloGeom);
00341 double HoE=calc(&(*scRef),mhbhe_);
00342 GsfElectron ele(momentum,scRef,trackRef,sclPos_,sclMom,seedPos,seedMom,innPos,innMom,vtxPos,vtxMom_,outPos,outMom,HoE);
00343
00344
00345 ECALPositionCalculator ecpc;
00346 float trackEta=ecpc.ecalEta(trackRef->innerMomentum(),trackRef->innerPosition());
00347 float trackPhi=ecpc.ecalPhi(theMagField.product(),trackRef->innerMomentum(),trackRef->innerPosition(),trackRef->charge());
00348
00349 ele.setDeltaEtaSuperClusterAtVtx((*scRef).position().eta() - trackEta);
00350 float dphi = (*scRef).position().phi() - trackPhi;
00351 if (fabs(dphi)>CLHEP::pi)
00352 dphi = dphi < 0? CLHEP::twopi + dphi : dphi - CLHEP::twopi;
00353 ele.setDeltaPhiSuperClusterAtVtx(dphi);
00354
00355
00356 ElectronClassification theClassifier;
00357 theClassifier.correct(ele);
00358 ElectronEnergyCorrector theEnCorrector;
00359 theEnCorrector.correct(ele, applyEtaCorrection_);
00360 ElectronMomentumCorrector theMomCorrector;
00361 theMomCorrector.correct(ele,vtxTSOS_);
00362
00363 outEle.push_back(ele);
00364 }
00365
00366 const SuperClusterRef GsfElectronAlgo::getTrSuperCluster(const GsfTrackRef & trackRef) {
00367 edm::RefToBase<TrajectorySeed> seed = trackRef->extra()->seedRef();
00368 ElectronPixelSeedRef elseed=seed.castTo<ElectronPixelSeedRef>();
00369 return elseed->superCluster();
00370 }
00371
00372 bool GsfElectronAlgo::calculateTSOS(const GsfTrack &t,const SuperCluster & theClus, const math::XYZPoint &
00373 bsPosition){
00374
00375
00376 innTSOS_ = mtsTransform_->innerStateOnSurface(t, *(trackerHandle_.product()), theMagField.product());
00377 if (!innTSOS_.isValid()) return false;
00378
00379
00380
00381 vtxTSOS_
00382 = TransverseImpactPointExtrapolator(*geomPropBw_).extrapolate(innTSOS_,GlobalPoint(bsPosition.x(),bsPosition.y(),bsPosition.z()));
00383 if (!vtxTSOS_.isValid()) vtxTSOS_=innTSOS_;
00384
00385
00386 outTSOS_
00387 = mtsTransform_->outerStateOnSurface(t, *(trackerHandle_.product()), theMagField.product());
00388 if (!outTSOS_.isValid()) return false;
00389
00390
00391 seedTSOS_
00392 = TransverseImpactPointExtrapolator(*geomPropFw_).extrapolate(outTSOS_,GlobalPoint(theClus.seed()->position().x(),theClus.seed()->position().y(),theClus.seed()->position().z()));
00393 if (!seedTSOS_.isValid()) seedTSOS_=outTSOS_;
00394
00395
00396 sclTSOS_
00397 = TransverseImpactPointExtrapolator(*geomPropFw_).extrapolate(innTSOS_,GlobalPoint(theClus.x(),theClus.y(),theClus.z()));
00398 if (!sclTSOS_.isValid()) sclTSOS_=outTSOS_;
00399 return true;
00400 }
00401
00402 void GsfElectronAlgo::resolveElectrons(std::vector<reco::GsfElectron> & tempEle, reco::GsfElectronCollection & outEle) {
00403
00404 typedef std::set<const reco::GsfElectron *> set_container;
00405 typedef std::vector<const reco::GsfElectron *> container;
00406 typedef container::const_iterator const_iterator;
00407 typedef set_container::const_iterator set_const_iterator;
00408
00409
00410 set_container resolved_el;
00411 std::multimap< const reco::GsfElectron *, const reco::GsfElectron *> ambigus_el;
00412 set_container ambigus;
00413
00414
00415
00416
00417
00418
00419 for( std::vector<reco::GsfElectron>::const_iterator el1 = tempEle.begin(); el1 != tempEle.end(); el1++ ) {
00420 for( std::vector<reco::GsfElectron>::const_iterator el2 = el1+1; el2 != tempEle.end(); el2++ ) {
00421 if((el1->caloEnergy() == el2->caloEnergy() &&
00422 el1->caloPosition() == el2->caloPosition()) ||
00423 (el1->gsfTrack()== el2->gsfTrack())) {
00424
00425
00426
00427
00428
00429
00430
00431 ambigus_el.insert(pair<const GsfElectron *,const GsfElectron *>(&(*el1),&(*el2)));
00432 ambigus.insert(&(*el1));
00433 ambigus.insert(&(*el2));
00434 }
00435 }
00436 set<const reco::GsfElectron *>::iterator it = ambigus.find(& * el1);
00437
00438 if (it == ambigus.end()) {
00439 resolved_el.insert(&(*el1));
00440 outEle.push_back(*el1);
00441 }
00442 }
00443
00444
00445 for (map< const reco::GsfElectron *, const reco::GsfElectron *>::iterator it2= ambigus_el.begin(); it2!=ambigus_el.end();it2++){
00446
00447 if (fabs(it2->first->eSuperClusterOverP()-1)<= fabs(it2->second->eSuperClusterOverP()-1)){
00448 set_const_iterator it= resolved_el.find(it2->first);
00449 if (it == resolved_el.end()) {
00450 resolved_el.insert(it2->first);
00451 outEle.push_back(*it2->first);
00452 }
00453 }
00454 else {
00455 set_const_iterator it= resolved_el.find(it2->second);
00456 if (it == resolved_el.end()){
00457 resolved_el.insert(it2->second);
00458 outEle.push_back(*it2->second);
00459
00460 }
00461 }
00462 }
00463
00464 }
00465