00001
00002 #include "RecoEgamma/EgammaElectronAlgos/interface/GsfElectronAlgo.h"
00003 #include "RecoEgamma/EgammaElectronAlgos/interface/EgAmbiguityTools.h"
00004 #include "RecoEgamma/EgammaElectronAlgos/interface/ElectronClassification.h"
00005 #include "RecoEgamma/EgammaElectronAlgos/interface/ElectronMomentumCorrector.h"
00006 #include "RecoEgamma/EgammaElectronAlgos/interface/ElectronEnergyCorrector.h"
00007 #include "RecoEgamma/EgammaElectronAlgos/interface/ElectronUtilities.h"
00008 #include "RecoEgamma/EgammaTools/interface/ConversionFinder.h"
00009
00010 #include "RecoEcal/EgammaCoreTools/interface/EcalClusterFunctionBaseClass.h"
00011 #include "RecoEcal/EgammaCoreTools/interface/EcalClusterTools.h"
00012
00013 #include "DataFormats/ParticleFlowReco/interface/GsfPFRecTrackFwd.h"
00014 #include "DataFormats/ParticleFlowReco/interface/GsfPFRecTrack.h"
00015 #include "DataFormats/EgammaReco/interface/BasicCluster.h"
00016 #include "DataFormats/EgammaReco/interface/ElectronSeed.h"
00017 #include "DataFormats/Math/interface/LorentzVector.h"
00018 #include "DataFormats/TrackingRecHit/interface/TrackingRecHitFwd.h"
00019 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
00020 #include "DataFormats/EcalDetId/interface/EBDetId.h"
00021 #include "DataFormats/EcalDetId/interface/EEDetId.h"
00022 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
00023 #include "DataFormats/GeometryVector/interface/GlobalVector.h"
00024
00025 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
00026 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00027 #include "Geometry/Records/interface/CaloTopologyRecord.h"
00028
00029 #include "TrackingTools/GsfTools/interface/MultiTrajectoryStateTransform.h"
00030 #include "TrackingTools/GsfTools/interface/MultiTrajectoryStateMode.h"
00031
00032
00033 #include "CondFormats/DataRecord/interface/EcalChannelStatusRcd.h"
00034
00035 #include "Geometry/CommonDetUnit/interface/TrackingGeometry.h"
00036 #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
00037
00038
00039 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00040
00041
00042
00043 #include <Math/Point3D.h>
00044 #include <sstream>
00045 #include <algorithm>
00046
00047
00048 using namespace edm ;
00049 using namespace std ;
00050 using namespace reco ;
00051
00052
00053
00054
00055
00056
00057
00058 struct GsfElectronAlgo::GeneralData
00059 {
00060
00061 GeneralData
00062 ( const InputTagsConfiguration &,
00063 const StrategyConfiguration &,
00064 const CutsConfiguration & cutsCfg,
00065 const CutsConfiguration & cutsCfgPflow,
00066 const ElectronHcalHelper::Configuration & hcalCfg,
00067 const ElectronHcalHelper::Configuration & hcalCfgPflow,
00068 const IsolationConfiguration &,
00069 const SpikeConfiguration &,
00070 EcalClusterFunctionBaseClass * superClusterErrorFunction ) ;
00071 ~GeneralData() ;
00072
00073
00074 const InputTagsConfiguration inputCfg ;
00075 const StrategyConfiguration strategyCfg ;
00076 const CutsConfiguration cutsCfg ;
00077 const CutsConfiguration cutsCfgPflow ;
00078 const IsolationConfiguration isoCfg ;
00079 const SpikeConfiguration spikeCfg ;
00080
00081
00082 ElectronHcalHelper * hcalHelper, * hcalHelperPflow ;
00083 EcalClusterFunctionBaseClass * superClusterErrorFunction ;
00084 } ;
00085
00086 GsfElectronAlgo::GeneralData::GeneralData
00087 ( const InputTagsConfiguration & inputConfig,
00088 const StrategyConfiguration & strategyConfig,
00089 const CutsConfiguration & cutsConfig,
00090 const CutsConfiguration & cutsConfigPflow,
00091 const ElectronHcalHelper::Configuration & hcalConfig,
00092 const ElectronHcalHelper::Configuration & hcalConfigPflow,
00093 const IsolationConfiguration & isoConfig,
00094 const SpikeConfiguration & spikeConfig,
00095 EcalClusterFunctionBaseClass * superClusterErrorFunc
00096 )
00097 : inputCfg(inputConfig),
00098 strategyCfg(strategyConfig),
00099 cutsCfg(cutsConfig),
00100 cutsCfgPflow(cutsConfigPflow),
00101 isoCfg(isoConfig),
00102 spikeCfg(spikeConfig),
00103 hcalHelper(new ElectronHcalHelper(hcalConfig)),
00104 hcalHelperPflow(new ElectronHcalHelper(hcalConfigPflow)),
00105 superClusterErrorFunction(superClusterErrorFunc)
00106 {}
00107
00108 GsfElectronAlgo::GeneralData::~GeneralData()
00109 {
00110 delete hcalHelper ;
00111 delete hcalHelperPflow ;
00112 }
00113
00114
00115
00116
00117
00118 struct GsfElectronAlgo::EventSetupData
00119 {
00120 EventSetupData() ;
00121 ~EventSetupData() ;
00122
00123 unsigned long long cacheIDGeom ;
00124 unsigned long long cacheIDTopo ;
00125 unsigned long long cacheIDTDGeom ;
00126 unsigned long long cacheIDMagField ;
00127 unsigned long long cacheChStatus ;
00128 unsigned long long cacheSevLevel ;
00129
00130 edm::ESHandle<MagneticField> magField ;
00131 edm::ESHandle<CaloGeometry> caloGeom ;
00132 edm::ESHandle<CaloTopology> caloTopo ;
00133 edm::ESHandle<TrackerGeometry> trackerHandle ;
00134 edm::ESHandle<EcalChannelStatus> chStatus ;
00135 edm::ESHandle<EcalSeverityLevelAlgo> sevLevel;
00136
00137 const MultiTrajectoryStateTransform * mtsTransform ;
00138 GsfConstraintAtVertex * constraintAtVtx ;
00139 const MultiTrajectoryStateMode * mtsMode ;
00140 } ;
00141
00142 GsfElectronAlgo::EventSetupData::EventSetupData()
00143 : cacheIDGeom(0), cacheIDTopo(0), cacheIDTDGeom(0), cacheIDMagField(0),cacheChStatus(0),
00144 cacheSevLevel(0), mtsTransform(0), constraintAtVtx(0), mtsMode(new MultiTrajectoryStateMode)
00145 {}
00146
00147 GsfElectronAlgo::EventSetupData::~EventSetupData()
00148 {
00149 delete mtsMode ;
00150 delete constraintAtVtx ;
00151 delete mtsTransform ;
00152 }
00153
00154
00155
00156
00157
00158
00159 struct GsfElectronAlgo::EventData
00160 {
00161
00162 edm::Event * event ;
00163 const reco::BeamSpot * beamspot ;
00164 GsfElectronPtrCollection * electrons ;
00165
00166 EventData() ;
00167 ~EventData() ;
00168
00169
00170 void retreiveOriginalTrackCollections
00171 ( const reco::TrackRef &, const reco::GsfTrackRef & ) ;
00172
00173
00174 edm::Handle<reco::GsfElectronCollection> previousElectrons ;
00175 edm::Handle<reco::GsfElectronCollection> pflowElectrons ;
00176 edm::Handle<reco::GsfElectronCoreCollection> coreElectrons ;
00177 edm::Handle<EcalRecHitCollection> reducedEBRecHits ;
00178 edm::Handle<EcalRecHitCollection> reducedEERecHits ;
00179 edm::Handle<reco::TrackCollection> currentCtfTracks ;
00180 edm::Handle<CaloTowerCollection> towers ;
00181 edm::Handle<edm::ValueMap<float> > pfMva ;
00182 edm::Handle<reco::ElectronSeedCollection> seeds ;
00183 edm::Handle<reco::GsfPFRecTrackCollection> gsfPfRecTracks ;
00184 bool originalCtfTrackCollectionRetreived ;
00185 bool originalGsfTrackCollectionRetreived ;
00186 edm::Handle<reco::TrackCollection> originalCtfTracks ;
00187 edm::Handle<reco::GsfTrackCollection> originalGsfTracks ;
00188
00189
00190 ElectronTkIsolation * tkIsolation03, * tkIsolation04 ;
00191 EgammaTowerIsolation * hadDepth1Isolation03, * hadDepth1Isolation04 ;
00192 EgammaTowerIsolation * hadDepth2Isolation03, * hadDepth2Isolation04 ;
00193 EgammaTowerIsolation * hadDepth1Isolation03Bc, * hadDepth1Isolation04Bc ;
00194 EgammaTowerIsolation * hadDepth2Isolation03Bc, * hadDepth2Isolation04Bc ;
00195 EcalRecHitMetaCollection * ecalBarrelHitsMeta ;
00196 EcalRecHitMetaCollection * ecalEndcapHitsMeta ;
00197 EgammaRecHitIsolation * ecalBarrelIsol03, * ecalBarrelIsol04 ;
00198 EgammaRecHitIsolation * ecalEndcapIsol03, * ecalEndcapIsol04 ;
00199 } ;
00200
00201 GsfElectronAlgo::EventData::EventData()
00202 : event(0), beamspot(0),
00203 originalCtfTrackCollectionRetreived(false),
00204 originalGsfTrackCollectionRetreived(false),
00205 tkIsolation03(0), tkIsolation04(0),
00206 hadDepth1Isolation03(0), hadDepth1Isolation04(0),
00207 hadDepth2Isolation03(0), hadDepth2Isolation04(0),
00208 ecalBarrelHitsMeta(0), ecalEndcapHitsMeta(0),
00209 ecalBarrelIsol03(0), ecalBarrelIsol04(0),
00210 ecalEndcapIsol03(0), ecalEndcapIsol04(0)
00211 {
00212 electrons = new GsfElectronPtrCollection ;
00213 }
00214
00215 GsfElectronAlgo::EventData::~EventData()
00216 {
00217 delete tkIsolation03 ;
00218 delete tkIsolation04 ;
00219 delete hadDepth1Isolation03 ;
00220 delete hadDepth1Isolation04 ;
00221 delete hadDepth2Isolation03 ;
00222 delete hadDepth2Isolation04 ;
00223 delete ecalBarrelHitsMeta ;
00224 delete ecalEndcapHitsMeta ;
00225 delete ecalBarrelIsol03 ;
00226 delete ecalBarrelIsol04 ;
00227 delete ecalEndcapIsol03 ;
00228 delete ecalEndcapIsol04 ;
00229
00230 GsfElectronPtrCollection::const_iterator it ;
00231 for ( it = electrons->begin() ; it != electrons->end() ; it++ )
00232 { delete (*it) ; }
00233 delete electrons ;
00234 }
00235
00236 void GsfElectronAlgo::EventData::retreiveOriginalTrackCollections
00237 ( const reco::TrackRef & ctfTrack, const reco::GsfTrackRef & gsfTrack )
00238 {
00239 if ((!originalCtfTrackCollectionRetreived)&&(ctfTrack.isNonnull()))
00240 {
00241 event->get(ctfTrack.id(),originalCtfTracks) ;
00242 originalCtfTrackCollectionRetreived = true ;
00243 }
00244 if ((!originalGsfTrackCollectionRetreived)&&(gsfTrack.isNonnull()))
00245 {
00246 event->get(gsfTrack.id(),originalGsfTracks) ;
00247 originalGsfTrackCollectionRetreived = true ;
00248 }
00249 }
00250
00251
00252
00253
00254
00255
00256 struct GsfElectronAlgo::ElectronData
00257 {
00258
00259 const reco::GsfElectronCoreRef coreRef ;
00260 const reco::GsfTrackRef gsfTrackRef ;
00261 const reco::SuperClusterRef superClusterRef ;
00262 reco::TrackRef ctfTrackRef ;
00263 float shFracInnerHits ;
00264 const reco::BeamSpot beamSpot ;
00265
00266
00267 ElectronData
00268 ( const reco::GsfElectronCoreRef & core,
00269 const reco::BeamSpot & bs ) ;
00270 ~ElectronData() ;
00271
00272
00273 void checkCtfTrack( edm::Handle<reco::TrackCollection> currentCtfTracks ) ;
00274 void computeCharge( int & charge, reco::GsfElectron::ChargeInfo & info ) ;
00275 CaloClusterPtr getEleBasicCluster( const MultiTrajectoryStateTransform * ) ;
00276 bool calculateTSOS( const MultiTrajectoryStateTransform *, GsfConstraintAtVertex * ) ;
00277 void calculateMode( const MultiTrajectoryStateMode * mtsMode ) ;
00278 Candidate::LorentzVector calculateMomentum() ;
00279
00280
00281 TrajectoryStateOnSurface innTSOS ;
00282 TrajectoryStateOnSurface outTSOS ;
00283 TrajectoryStateOnSurface vtxTSOS ;
00284 TrajectoryStateOnSurface sclTSOS ;
00285 TrajectoryStateOnSurface seedTSOS ;
00286 TrajectoryStateOnSurface eleTSOS ;
00287 TrajectoryStateOnSurface constrainedVtxTSOS ;
00288
00289
00290 GlobalVector innMom, seedMom, eleMom, sclMom, vtxMom, outMom ;
00291 GlobalPoint innPos, seedPos, elePos, sclPos, vtxPos, outPos ;
00292 GlobalVector vtxMomWithConstraint ;
00293 } ;
00294
00295 GsfElectronAlgo::ElectronData::ElectronData
00296 ( const reco::GsfElectronCoreRef & core,
00297 const reco::BeamSpot & bs )
00298 : coreRef(core),
00299 gsfTrackRef(coreRef->gsfTrack()),
00300 superClusterRef(coreRef->superCluster()),
00301 ctfTrackRef(coreRef->ctfTrack()), shFracInnerHits(coreRef->ctfGsfOverlap()),
00302 beamSpot(bs)
00303 {}
00304
00305 GsfElectronAlgo::ElectronData::~ElectronData()
00306 {}
00307
00308 void GsfElectronAlgo::ElectronData::checkCtfTrack( edm::Handle<reco::TrackCollection> currentCtfTracks )
00309 {
00310 if (!ctfTrackRef.isNull()) return ;
00311
00312
00313
00314 shFracInnerHits = 0 ;
00315 const TrackCollection * ctfTrackCollection = currentCtfTracks.product() ;
00316
00317
00318 const HitPattern & gsfHitPattern = gsfTrackRef->hitPattern() ;
00319
00320 unsigned int counter ;
00321 TrackCollection::const_iterator ctfTkIter ;
00322 for ( ctfTkIter = ctfTrackCollection->begin() , counter = 0 ;
00323 ctfTkIter != ctfTrackCollection->end() ; ctfTkIter++, counter++ )
00324 {
00325
00326 double dEta = gsfTrackRef->eta() - ctfTkIter->eta() ;
00327 double dPhi = gsfTrackRef->phi() - ctfTkIter->phi() ;
00328 double pi = acos(-1.);
00329 if(std::abs(dPhi) > pi) dPhi = 2*pi - std::abs(dPhi) ;
00330
00331
00332 if (sqrt(dEta*dEta + dPhi*dPhi) > 0.3) continue ;
00333
00334 unsigned int shared = 0 ;
00335 int gsfHitCounter = 0 ;
00336 int numGsfInnerHits = 0 ;
00337 int numCtfInnerHits = 0 ;
00338
00339
00340 const HitPattern & ctfHitPattern = ctfTkIter->hitPattern() ;
00341
00342 trackingRecHit_iterator elHitsIt ;
00343 for ( elHitsIt = gsfTrackRef->recHitsBegin() ;
00344 elHitsIt != gsfTrackRef->recHitsEnd() ;
00345 elHitsIt++, gsfHitCounter++ )
00346 {
00347 if (!((**elHitsIt).isValid()))
00348 { continue ; }
00349
00350
00351 uint32_t gsfHit = gsfHitPattern.getHitPattern(gsfHitCounter) ;
00352 if (!(gsfHitPattern.pixelHitFilter(gsfHit) ||
00353 gsfHitPattern.stripTIBHitFilter(gsfHit) ||
00354 gsfHitPattern.stripTIDHitFilter(gsfHit) ) )
00355 { continue ; }
00356
00357 numGsfInnerHits++ ;
00358
00359 int ctfHitsCounter = 0 ;
00360 numCtfInnerHits = 0 ;
00361 trackingRecHit_iterator ctfHitsIt ;
00362 for ( ctfHitsIt = ctfTkIter->recHitsBegin() ;
00363 ctfHitsIt != ctfTkIter->recHitsEnd() ;
00364 ctfHitsIt++, ctfHitsCounter++ )
00365 {
00366 if(!((**ctfHitsIt).isValid()))
00367 { continue ; }
00368
00369 uint32_t ctfHit = ctfHitPattern.getHitPattern(ctfHitsCounter);
00370 if( !(ctfHitPattern.pixelHitFilter(ctfHit) ||
00371 ctfHitPattern.stripTIBHitFilter(ctfHit) ||
00372 ctfHitPattern.stripTIDHitFilter(ctfHit) ) )
00373 { continue ; }
00374
00375 numCtfInnerHits++ ;
00376
00377 if( (**elHitsIt).sharesInput(&(**ctfHitsIt),TrackingRecHit::all) )
00378 {
00379 shared++ ;
00380 break ;
00381 }
00382
00383 }
00384
00385 }
00386
00387 if ((numGsfInnerHits==0)||(numCtfInnerHits==0))
00388 { continue ; }
00389
00390 if ( static_cast<float>(shared)/min(numGsfInnerHits,numCtfInnerHits) > shFracInnerHits )
00391 {
00392 shFracInnerHits = static_cast<float>(shared)/min(numGsfInnerHits, numCtfInnerHits);
00393 ctfTrackRef = TrackRef(currentCtfTracks,counter);
00394 }
00395 }
00396 }
00397
00398 void GsfElectronAlgo::ElectronData::computeCharge
00399 ( int & charge, GsfElectron::ChargeInfo & info )
00400 {
00401
00402 GlobalPoint orig, scpos ;
00403 ele_convert(beamSpot.position(),orig) ;
00404 ele_convert(superClusterRef->position(),scpos) ;
00405 GlobalVector scvect(scpos-orig) ;
00406 GlobalPoint inntkpos = innTSOS.globalPosition() ;
00407 GlobalVector inntkvect = GlobalVector(inntkpos-orig) ;
00408 float dPhiInnEle=normalized_phi(scvect.phi()-inntkvect.phi()) ;
00409 if(dPhiInnEle>0) info.scPixCharge = -1 ;
00410 else info.scPixCharge = 1 ;
00411
00412
00413 int chargeGsf = gsfTrackRef->charge() ;
00414 info.isGsfScPixConsistent = ((chargeGsf*info.scPixCharge)>0) ;
00415 info.isGsfCtfConsistent = (ctfTrackRef.isNonnull()&&((chargeGsf*ctfTrackRef->charge())>0)) ;
00416 info.isGsfCtfScPixConsistent = (info.isGsfScPixConsistent&&info.isGsfCtfConsistent) ;
00417
00418
00419 if (info.isGsfScPixConsistent||ctfTrackRef.isNull())
00420 { charge = info.scPixCharge ; }
00421 else
00422 { charge = ctfTrackRef->charge() ; }
00423 }
00424
00425 CaloClusterPtr GsfElectronAlgo::ElectronData::getEleBasicCluster
00426 ( const MultiTrajectoryStateTransform * mtsTransform )
00427 {
00428 CaloClusterPtr eleRef ;
00429 TrajectoryStateOnSurface tempTSOS ;
00430 TrajectoryStateOnSurface outTSOS = mtsTransform->outerStateOnSurface(*gsfTrackRef) ;
00431 float dphimin = 1.e30 ;
00432 for (CaloCluster_iterator bc=superClusterRef->clustersBegin(); bc!=superClusterRef->clustersEnd(); bc++)
00433 {
00434 GlobalPoint posclu((*bc)->position().x(),(*bc)->position().y(),(*bc)->position().z()) ;
00435 tempTSOS = mtsTransform->extrapolatedState(outTSOS,posclu) ;
00436 if (!tempTSOS.isValid()) tempTSOS=outTSOS ;
00437 GlobalPoint extrap = tempTSOS.globalPosition() ;
00438 float dphi = EleRelPointPair(posclu,extrap,beamSpot.position()).dPhi() ;
00439 if (std::abs(dphi)<dphimin)
00440 {
00441 dphimin = std::abs(dphi) ;
00442 eleRef = (*bc);
00443 eleTSOS = tempTSOS ;
00444 }
00445 }
00446 return eleRef ;
00447 }
00448
00449 bool GsfElectronAlgo::ElectronData::calculateTSOS
00450 ( const MultiTrajectoryStateTransform * mtsTransform, GsfConstraintAtVertex * constraintAtVtx )
00451 {
00452
00453 innTSOS = mtsTransform->innerStateOnSurface(*gsfTrackRef);
00454 if (!innTSOS.isValid()) return false;
00455
00456
00457
00458 GlobalPoint bsPos ;
00459 ele_convert(beamSpot.position(),bsPos) ;
00460 vtxTSOS = mtsTransform->extrapolatedState(innTSOS,bsPos) ;
00461 if (!vtxTSOS.isValid()) vtxTSOS=innTSOS;
00462
00463
00464 outTSOS = mtsTransform->outerStateOnSurface(*gsfTrackRef);
00465 if (!outTSOS.isValid()) return false;
00466
00467
00468 seedTSOS = mtsTransform->extrapolatedState(outTSOS,
00469 GlobalPoint(superClusterRef->seed()->position().x(),
00470 superClusterRef->seed()->position().y(),
00471 superClusterRef->seed()->position().z()));
00472 if (!seedTSOS.isValid()) seedTSOS=outTSOS;
00473
00474
00475 sclTSOS = mtsTransform->extrapolatedState(innTSOS,GlobalPoint(superClusterRef->x(),superClusterRef->y(),superClusterRef->z()));
00476 if (!sclTSOS.isValid()) sclTSOS=outTSOS;
00477
00478
00479 constrainedVtxTSOS = constraintAtVtx->constrainAtBeamSpot(*gsfTrackRef,beamSpot);
00480
00481 return true ;
00482 }
00483
00484 void GsfElectronAlgo::ElectronData::calculateMode( const MultiTrajectoryStateMode * mtsMode )
00485 {
00486 mtsMode->momentumFromModeCartesian(innTSOS,innMom) ;
00487 mtsMode->positionFromModeCartesian(innTSOS,innPos) ;
00488 mtsMode->momentumFromModeCartesian(seedTSOS,seedMom) ;
00489 mtsMode->positionFromModeCartesian(seedTSOS,seedPos) ;
00490 mtsMode->momentumFromModeCartesian(eleTSOS,eleMom) ;
00491 mtsMode->positionFromModeCartesian(eleTSOS,elePos) ;
00492 mtsMode->momentumFromModeCartesian(sclTSOS,sclMom) ;
00493 mtsMode->positionFromModeCartesian(sclTSOS,sclPos) ;
00494 mtsMode->momentumFromModeCartesian(vtxTSOS,vtxMom) ;
00495 mtsMode->positionFromModeCartesian(vtxTSOS,vtxPos) ;
00496 mtsMode->momentumFromModeCartesian(outTSOS,outMom);
00497 mtsMode->positionFromModeCartesian(outTSOS,outPos) ;
00498 mtsMode->momentumFromModeCartesian(constrainedVtxTSOS,vtxMomWithConstraint);
00499 }
00500
00501 Candidate::LorentzVector GsfElectronAlgo::ElectronData::calculateMomentum()
00502 {
00503 double scale = superClusterRef->energy()/vtxMom.mag() ;
00504 return Candidate::LorentzVector
00505 ( vtxMom.x()*scale,vtxMom.y()*scale,vtxMom.z()*scale,
00506 superClusterRef->energy() ) ;
00507 }
00508
00509 void GsfElectronAlgo::calculateShowerShape( const reco::SuperClusterRef & theClus, bool pflow, reco::GsfElectron::ShowerShape & showerShape )
00510 {
00511 const reco::CaloCluster & seedCluster = *(theClus->seed()) ;
00512
00513 DetId seedXtalId = seedCluster.hitsAndFractions()[0].first ;
00514 int detector = seedXtalId.subdetId() ;
00515
00516 const CaloTopology * topology = eventSetupData_->caloTopo.product() ;
00517 const CaloGeometry * geometry = eventSetupData_->caloGeom.product() ;
00518 const EcalRecHitCollection * reducedRecHits = 0 ;
00519 if (detector==EcalBarrel)
00520 { reducedRecHits = eventData_->reducedEBRecHits.product() ; }
00521 else
00522 { reducedRecHits = eventData_->reducedEERecHits.product() ; }
00523
00524 std::vector<float> covariances = EcalClusterTools::covariances(seedCluster,reducedRecHits,topology,geometry) ;
00525 std::vector<float> localCovariances = EcalClusterTools::localCovariances(seedCluster,reducedRecHits,topology) ;
00526 showerShape.sigmaEtaEta = sqrt(covariances[0]) ;
00527 showerShape.sigmaIetaIeta = sqrt(localCovariances[0]) ;
00528 showerShape.e1x5 = EcalClusterTools::e1x5(seedCluster,reducedRecHits,topology) ;
00529 showerShape.e2x5Max = EcalClusterTools::e2x5Max(seedCluster,reducedRecHits,topology) ;
00530 showerShape.e5x5 = EcalClusterTools::e5x5(seedCluster,reducedRecHits,topology) ;
00531
00532 if (pflow)
00533 {
00534 showerShape.hcalDepth1OverEcal = generalData_->hcalHelperPflow->hcalESumDepth1(*theClus)/theClus->energy() ;
00535 showerShape.hcalDepth2OverEcal = generalData_->hcalHelperPflow->hcalESumDepth2(*theClus)/theClus->energy() ;
00536 showerShape.hcalTowersBehindClusters = generalData_->hcalHelperPflow->hcalTowersBehindClusters(*theClus) ;
00537 showerShape.hcalDepth1OverEcalBc = generalData_->hcalHelperPflow->hcalESumDepth1BehindClusters(showerShape.hcalTowersBehindClusters)/theClus->energy() ;
00538 showerShape.hcalDepth2OverEcalBc = generalData_->hcalHelperPflow->hcalESumDepth2BehindClusters(showerShape.hcalTowersBehindClusters)/theClus->energy() ;
00539 }
00540 else
00541 {
00542 showerShape.hcalDepth1OverEcal = generalData_->hcalHelper->hcalESumDepth1(*theClus)/theClus->energy() ;
00543 showerShape.hcalDepth2OverEcal = generalData_->hcalHelper->hcalESumDepth2(*theClus)/theClus->energy() ;
00544 showerShape.hcalTowersBehindClusters = generalData_->hcalHelper->hcalTowersBehindClusters(*theClus) ;
00545 showerShape.hcalDepth1OverEcalBc = generalData_->hcalHelper->hcalESumDepth1BehindClusters(showerShape.hcalTowersBehindClusters)/theClus->energy() ;
00546 showerShape.hcalDepth2OverEcalBc = generalData_->hcalHelper->hcalESumDepth2BehindClusters(showerShape.hcalTowersBehindClusters)/theClus->energy() ;
00547 }
00548 }
00549
00550
00551
00552
00553
00554
00555 GsfElectronAlgo::GsfElectronAlgo
00556 ( const InputTagsConfiguration & inputCfg,
00557 const StrategyConfiguration & strategyCfg,
00558 const CutsConfiguration & cutsCfg,
00559 const CutsConfiguration & cutsCfgPflow,
00560 const ElectronHcalHelper::Configuration & hcalCfg,
00561 const ElectronHcalHelper::Configuration & hcalCfgPflow,
00562 const IsolationConfiguration & isoCfg,
00563 const SpikeConfiguration & spikeCfg,
00564 EcalClusterFunctionBaseClass * superClusterErrorFunction
00565 )
00566 : generalData_(new GeneralData(inputCfg,strategyCfg,cutsCfg,cutsCfgPflow,hcalCfg,hcalCfgPflow,isoCfg,spikeCfg,superClusterErrorFunction)),
00567 eventSetupData_(new EventSetupData),
00568 eventData_(0), electronData_(0)
00569 {}
00570
00571 GsfElectronAlgo::~GsfElectronAlgo()
00572 {
00573 delete generalData_ ;
00574 delete eventSetupData_ ;
00575 delete eventData_ ;
00576 delete electronData_ ;
00577 }
00578
00579 void GsfElectronAlgo::checkSetup( const edm::EventSetup & es )
00580 {
00581
00582 bool updateField(false);
00583 if (eventSetupData_->cacheIDMagField!=es.get<IdealMagneticFieldRecord>().cacheIdentifier()){
00584 updateField = true;
00585 eventSetupData_->cacheIDMagField=es.get<IdealMagneticFieldRecord>().cacheIdentifier();
00586 es.get<IdealMagneticFieldRecord>().get(eventSetupData_->magField);
00587 }
00588
00589 bool updateGeometry(false);
00590 if (eventSetupData_->cacheIDTDGeom!=es.get<TrackerDigiGeometryRecord>().cacheIdentifier()){
00591 updateGeometry = true;
00592 eventSetupData_->cacheIDTDGeom=es.get<TrackerDigiGeometryRecord>().cacheIdentifier();
00593 es.get<TrackerDigiGeometryRecord>().get(eventSetupData_->trackerHandle);
00594 }
00595
00596 if ( updateField || updateGeometry ) {
00597 delete eventSetupData_->mtsTransform ;
00598 eventSetupData_->mtsTransform = new MultiTrajectoryStateTransform(eventSetupData_->trackerHandle.product(),eventSetupData_->magField.product());
00599 delete eventSetupData_->constraintAtVtx ;
00600 eventSetupData_->constraintAtVtx = new GsfConstraintAtVertex(es) ;
00601 }
00602
00603 if (eventSetupData_->cacheIDGeom!=es.get<CaloGeometryRecord>().cacheIdentifier()){
00604 eventSetupData_->cacheIDGeom=es.get<CaloGeometryRecord>().cacheIdentifier();
00605 es.get<CaloGeometryRecord>().get(eventSetupData_->caloGeom);
00606 }
00607
00608 if (eventSetupData_->cacheIDTopo!=es.get<CaloTopologyRecord>().cacheIdentifier()){
00609 eventSetupData_->cacheIDTopo=es.get<CaloTopologyRecord>().cacheIdentifier();
00610 es.get<CaloTopologyRecord>().get(eventSetupData_->caloTopo);
00611 }
00612
00613 generalData_->hcalHelper->checkSetup(es) ;
00614 generalData_->hcalHelperPflow->checkSetup(es) ;
00615
00616 if (generalData_->superClusterErrorFunction)
00617 { generalData_->superClusterErrorFunction->init(es) ; }
00618
00619
00620 if(eventSetupData_->cacheChStatus!=es.get<EcalChannelStatusRcd>().cacheIdentifier()){
00621 eventSetupData_->cacheChStatus=es.get<EcalChannelStatusRcd>().cacheIdentifier();
00622 es.get<EcalChannelStatusRcd>().get(eventSetupData_->chStatus);
00623 }
00624
00625 if(eventSetupData_->cacheSevLevel != es.get<EcalSeverityLevelAlgoRcd>().cacheIdentifier()){
00626 eventSetupData_->cacheSevLevel = es.get<EcalSeverityLevelAlgoRcd>().cacheIdentifier();
00627 es.get<EcalSeverityLevelAlgoRcd>().get(eventSetupData_->sevLevel);
00628 }
00629 }
00630
00631 void GsfElectronAlgo::copyElectrons( GsfElectronCollection & outEle )
00632 {
00633 GsfElectronPtrCollection::const_iterator it ;
00634 for
00635 ( it = eventData_->electrons->begin() ;
00636 it != eventData_->electrons->end() ;
00637 it++ )
00638 { outEle.push_back(**it) ; }
00639 }
00640
00641 void GsfElectronAlgo::beginEvent( edm::Event & event )
00642 {
00643 if (eventData_!=0)
00644 { throw cms::Exception("GsfElectronAlgo|InternalError")<<"unexpected event data" ; }
00645 eventData_ = new EventData ;
00646
00647
00648 eventData_->event = &event ;
00649 event.getByLabel(generalData_->inputCfg.previousGsfElectrons,eventData_->previousElectrons) ;
00650 event.getByLabel(generalData_->inputCfg.pflowGsfElectronsTag,eventData_->pflowElectrons) ;
00651 event.getByLabel(generalData_->inputCfg.gsfElectronCores,eventData_->coreElectrons) ;
00652 event.getByLabel(generalData_->inputCfg.ctfTracks,eventData_->currentCtfTracks) ;
00653 event.getByLabel(generalData_->inputCfg.reducedBarrelRecHitCollection,eventData_->reducedEBRecHits) ;
00654 event.getByLabel(generalData_->inputCfg.reducedEndcapRecHitCollection,eventData_->reducedEERecHits) ;
00655 event.getByLabel(generalData_->inputCfg.hcalTowersTag,eventData_->towers) ;
00656 event.getByLabel(generalData_->inputCfg.pfMVA,eventData_->pfMva) ;
00657 event.getByLabel(generalData_->inputCfg.seedsTag,eventData_->seeds) ;
00658 if (generalData_->strategyCfg.useGsfPfRecTracks)
00659 { event.getByLabel(generalData_->inputCfg.gsfPfRecTracksTag,eventData_->gsfPfRecTracks) ; }
00660
00661
00662 edm::Handle<reco::BeamSpot> recoBeamSpotHandle ;
00663 event.getByLabel(generalData_->inputCfg.beamSpotTag,recoBeamSpotHandle) ;
00664 eventData_->beamspot = recoBeamSpotHandle.product() ;
00665
00666
00667 generalData_->hcalHelper->readEvent(event) ;
00668 generalData_->hcalHelperPflow->readEvent(event) ;
00669
00670
00671 float extRadiusSmall=0.3, extRadiusLarge=0.4 ;
00672 float intRadiusBarrel=generalData_->isoCfg.intRadiusBarrelTk, intRadiusEndcap=generalData_->isoCfg.intRadiusEndcapTk, stripBarrel=generalData_->isoCfg.stripBarrelTk, stripEndcap=generalData_->isoCfg.stripEndcapTk ;
00673 float ptMin=generalData_->isoCfg.ptMinTk, maxVtxDist=generalData_->isoCfg.maxVtxDistTk, drb=generalData_->isoCfg.maxDrbTk;
00674 eventData_->tkIsolation03 = new ElectronTkIsolation(extRadiusSmall,intRadiusBarrel,intRadiusEndcap,stripBarrel,stripEndcap,ptMin,maxVtxDist,drb,eventData_->currentCtfTracks.product(),eventData_->beamspot->position()) ;
00675 eventData_->tkIsolation04 = new ElectronTkIsolation(extRadiusLarge,intRadiusBarrel,intRadiusEndcap,stripBarrel,stripEndcap,ptMin,maxVtxDist,drb,eventData_->currentCtfTracks.product(),eventData_->beamspot->position()) ;
00676
00677 float egHcalIsoConeSizeOutSmall=0.3, egHcalIsoConeSizeOutLarge=0.4;
00678 float egHcalIsoConeSizeIn=generalData_->isoCfg.intRadiusHcal,egHcalIsoPtMin=generalData_->isoCfg.etMinHcal;
00679 int egHcalDepth1=1, egHcalDepth2=2;
00680 eventData_->hadDepth1Isolation03 = new EgammaTowerIsolation(egHcalIsoConeSizeOutSmall,egHcalIsoConeSizeIn,egHcalIsoPtMin,egHcalDepth1,eventData_->towers.product()) ;
00681 eventData_->hadDepth2Isolation03 = new EgammaTowerIsolation(egHcalIsoConeSizeOutSmall,egHcalIsoConeSizeIn,egHcalIsoPtMin,egHcalDepth2,eventData_->towers.product()) ;
00682 eventData_->hadDepth1Isolation04 = new EgammaTowerIsolation(egHcalIsoConeSizeOutLarge,egHcalIsoConeSizeIn,egHcalIsoPtMin,egHcalDepth1,eventData_->towers.product()) ;
00683 eventData_->hadDepth2Isolation04 = new EgammaTowerIsolation(egHcalIsoConeSizeOutLarge,egHcalIsoConeSizeIn,egHcalIsoPtMin,egHcalDepth2,eventData_->towers.product()) ;
00684 eventData_->hadDepth1Isolation03Bc = new EgammaTowerIsolation(egHcalIsoConeSizeOutSmall,0.,egHcalIsoPtMin,egHcalDepth1,eventData_->towers.product()) ;
00685 eventData_->hadDepth2Isolation03Bc = new EgammaTowerIsolation(egHcalIsoConeSizeOutSmall,0.,egHcalIsoPtMin,egHcalDepth2,eventData_->towers.product()) ;
00686 eventData_->hadDepth1Isolation04Bc = new EgammaTowerIsolation(egHcalIsoConeSizeOutLarge,0.,egHcalIsoPtMin,egHcalDepth1,eventData_->towers.product()) ;
00687 eventData_->hadDepth2Isolation04Bc = new EgammaTowerIsolation(egHcalIsoConeSizeOutLarge,0.,egHcalIsoPtMin,egHcalDepth2,eventData_->towers.product()) ;
00688
00689 float egIsoConeSizeOutSmall=0.3, egIsoConeSizeOutLarge=0.4, egIsoJurassicWidth=generalData_->isoCfg.jurassicWidth;
00690 float egIsoPtMinBarrel=generalData_->isoCfg.etMinBarrel,egIsoEMinBarrel=generalData_->isoCfg.eMinBarrel, egIsoConeSizeInBarrel=generalData_->isoCfg.intRadiusEcalBarrel;
00691 float egIsoPtMinEndcap=generalData_->isoCfg.etMinEndcaps,egIsoEMinEndcap=generalData_->isoCfg.eMinEndcaps, egIsoConeSizeInEndcap=generalData_->isoCfg.intRadiusEcalEndcaps;
00692 eventData_->ecalBarrelHitsMeta = new EcalRecHitMetaCollection(*eventData_->reducedEBRecHits) ;
00693 eventData_->ecalEndcapHitsMeta = new EcalRecHitMetaCollection(*eventData_->reducedEERecHits) ;
00694 eventData_->ecalBarrelIsol03 = new EgammaRecHitIsolation(egIsoConeSizeOutSmall,egIsoConeSizeInBarrel,egIsoJurassicWidth,egIsoPtMinBarrel,egIsoEMinBarrel,eventSetupData_->caloGeom,eventData_->ecalBarrelHitsMeta,eventSetupData_->sevLevel.product(),DetId::Ecal);
00695 eventData_->ecalBarrelIsol04 = new EgammaRecHitIsolation(egIsoConeSizeOutLarge,egIsoConeSizeInBarrel,egIsoJurassicWidth,egIsoPtMinBarrel,egIsoEMinBarrel,eventSetupData_->caloGeom,eventData_->ecalBarrelHitsMeta,eventSetupData_->sevLevel.product(),DetId::Ecal);
00696 eventData_->ecalEndcapIsol03 = new EgammaRecHitIsolation(egIsoConeSizeOutSmall,egIsoConeSizeInEndcap,egIsoJurassicWidth,egIsoPtMinEndcap,egIsoEMinEndcap,eventSetupData_->caloGeom,eventData_->ecalEndcapHitsMeta,eventSetupData_->sevLevel.product(),DetId::Ecal);
00697 eventData_->ecalEndcapIsol04 = new EgammaRecHitIsolation(egIsoConeSizeOutLarge,egIsoConeSizeInEndcap,egIsoJurassicWidth,egIsoPtMinEndcap,egIsoEMinEndcap,eventSetupData_->caloGeom,eventData_->ecalEndcapHitsMeta,eventSetupData_->sevLevel.product(),DetId::Ecal);
00698 eventData_->ecalBarrelIsol03->setUseNumCrystals(generalData_->isoCfg.useNumCrystals);
00699 eventData_->ecalBarrelIsol03->setVetoClustered(generalData_->isoCfg.vetoClustered);
00700
00701 eventData_->ecalBarrelIsol03->doSpikeRemoval(eventData_->reducedEBRecHits.product(),eventSetupData_->chStatus.product(),generalData_->spikeCfg.severityLevelCut);
00702 eventData_->ecalBarrelIsol03->doFlagChecks(generalData_->spikeCfg.recHitFlagsToBeExcluded);
00703 eventData_->ecalBarrelIsol04->setUseNumCrystals(generalData_->isoCfg.useNumCrystals);
00704 eventData_->ecalBarrelIsol04->setVetoClustered(generalData_->isoCfg.vetoClustered);
00705
00706 eventData_->ecalBarrelIsol04->doSpikeRemoval(eventData_->reducedEBRecHits.product(),eventSetupData_->chStatus.product(),generalData_->spikeCfg.severityLevelCut);
00707 eventData_->ecalBarrelIsol04->doFlagChecks(generalData_->spikeCfg.recHitFlagsToBeExcluded);
00708 eventData_->ecalEndcapIsol03->setUseNumCrystals(generalData_->isoCfg.useNumCrystals);
00709 eventData_->ecalEndcapIsol03->setVetoClustered(generalData_->isoCfg.vetoClustered);
00710 eventData_->ecalEndcapIsol03->doFlagChecks(generalData_->spikeCfg.recHitFlagsToBeExcluded);
00711 eventData_->ecalEndcapIsol04->setUseNumCrystals(generalData_->isoCfg.useNumCrystals);
00712 eventData_->ecalEndcapIsol04->setVetoClustered(generalData_->isoCfg.vetoClustered);
00713 eventData_->ecalEndcapIsol04->doFlagChecks(generalData_->spikeCfg.recHitFlagsToBeExcluded);
00714 }
00715
00716 void GsfElectronAlgo::endEvent()
00717 {
00718 if (eventData_==0)
00719 { throw cms::Exception("GsfElectronAlgo|InternalError")<<"lacking event data" ; }
00720 delete eventData_ ;
00721 eventData_ = 0 ;
00722 }
00723
00724 void GsfElectronAlgo::displayInternalElectrons( const std::string & title ) const
00725 {
00726 LogTrace("GsfElectronAlgo") << "========== " << title << " ==========";
00727 LogTrace("GsfElectronAlgo") << "Event: " << eventData_->event->id();
00728 LogTrace("GsfElectronAlgo") << "Number of electrons: " << eventData_->electrons->size() ;
00729 GsfElectronPtrCollection::const_iterator it ;
00730 for ( it = eventData_->electrons->begin(); it != eventData_->electrons->end(); it++ )
00731 {
00732 LogTrace("GsfElectronAlgo") << "Electron with charge, pt, eta, phi: " << (*it)->charge() << " , "
00733 << (*it)->pt() << " , " << (*it)->eta() << " , " << (*it)->phi();
00734 }
00735 LogTrace("GsfElectronAlgo") << "=================================================";
00736 }
00737
00738 void GsfElectronAlgo::completeElectrons()
00739 {
00740 if (electronData_!=0)
00741 { throw cms::Exception("GsfElectronAlgo|InternalError")<<"unexpected electron data" ; }
00742
00743 const GsfElectronCoreCollection * coreCollection = eventData_->coreElectrons.product() ;
00744 for ( unsigned int i=0 ; i<coreCollection->size() ; ++i )
00745 {
00746
00747 const GsfElectronCoreRef coreRef = edm::Ref<GsfElectronCoreCollection>(eventData_->coreElectrons,i) ;
00748 bool coreFound = false ;
00749 GsfElectronPtrCollection::const_iterator itrEle ;
00750 for
00751 ( itrEle = eventData_->electrons->begin() ;
00752 itrEle != eventData_->electrons->end() ;
00753 itrEle++ )
00754 {
00755 if ((*itrEle)->core()==coreRef)
00756 {
00757 coreFound = true ;
00758 break ;
00759 }
00760 }
00761 if (coreFound) continue ;
00762
00763
00764 if (coreRef->superCluster().isNull()) continue ;
00765
00766
00767 delete electronData_ ;
00768 electronData_ = new ElectronData(coreRef,*eventData_->beamspot) ;
00769
00770
00771 if ( !electronData_->calculateTSOS( eventSetupData_->mtsTransform, eventSetupData_->constraintAtVtx ) ) continue ;
00772
00773 createElectron() ;
00774
00775 }
00776
00777 delete electronData_ ;
00778 electronData_ = 0 ;
00779 }
00780
00781 void GsfElectronAlgo::clonePreviousElectrons()
00782 {
00783 const GsfElectronCollection * oldElectrons = eventData_->previousElectrons.product() ;
00784 const GsfElectronCoreCollection * newCores = eventData_->coreElectrons.product() ;
00785 GsfElectronCollection::const_iterator oldElectron ;
00786 for
00787 ( oldElectron = oldElectrons->begin() ;
00788 oldElectron != oldElectrons->end() ;
00789 ++oldElectron )
00790 {
00791 const GsfElectronCoreRef oldCoreRef = oldElectron->core() ;
00792 const GsfTrackRef oldElectronGsfTrackRef = oldCoreRef->gsfTrack() ;
00793 unsigned int icore ;
00794 for ( icore=0 ; icore<newCores->size() ; ++icore )
00795 {
00796 if (oldElectronGsfTrackRef==(*newCores)[icore].gsfTrack())
00797 {
00798 const GsfElectronCoreRef coreRef = edm::Ref<GsfElectronCoreCollection>(eventData_->coreElectrons,icore) ;
00799 eventData_->electrons->push_back(new GsfElectron(*oldElectron,coreRef)) ;
00800 break ;
00801 }
00802 }
00803 }
00804 }
00805
00806 void GsfElectronAlgo::addPflowInfo()
00807 {
00808 bool found ;
00809 const GsfElectronCollection * pfElectrons = eventData_->pflowElectrons.product() ;
00810 GsfElectronCollection::const_iterator pfElectron ;
00811
00812 GsfElectronPtrCollection::iterator el ;
00813 for
00814 ( el = eventData_->electrons->begin() ;
00815 el != eventData_->electrons->end() ;
00816 el++ )
00817 {
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831 found = false ;
00832 for
00833 ( pfElectron = pfElectrons->begin() ; pfElectron != pfElectrons->end() ; pfElectron++ )
00834 {
00835 if (pfElectron->gsfTrack()==(*el)->gsfTrack())
00836 {
00837 if (found)
00838 {
00839 edm::LogWarning("GsfElectronProducer")<<"associated pfGsfElectron already found" ;
00840 }
00841 else
00842 {
00843 found = true ;
00844 (*el)->setPfIsolationVariables(pfElectron->pfIsolationVariables()) ;
00845 (*el)->setMvaInput(pfElectron->mvaInput()) ;
00846 (*el)->setMvaOutput(pfElectron->mvaOutput()) ;
00847 if ((*el)->ecalDrivenSeed())
00848 { (*el)->setP4(GsfElectron::P4_PFLOW_COMBINATION,pfElectron->p4(GsfElectron::P4_PFLOW_COMBINATION),pfElectron->p4Error(GsfElectron::P4_PFLOW_COMBINATION),false) ; }
00849 else
00850 { (*el)->setP4(GsfElectron::P4_PFLOW_COMBINATION,pfElectron->p4(GsfElectron::P4_PFLOW_COMBINATION),pfElectron->p4Error(GsfElectron::P4_PFLOW_COMBINATION),true) ; }
00851 double noCutMin = -999999999 ;
00852 if ((*el)->mva()<noCutMin) { throw cms::Exception("GsfElectronAlgo|UnexpectedMvaValue")<<"unexpected MVA value: "<<(*el)->mva() ; }
00853 }
00854 }
00855 }
00856
00857
00858 setMvaPreselectionFlag(*el) ;
00859
00860
00861 if (!((*el)->pflowSuperCluster().isNull()))
00862 {
00863 reco::GsfElectron::ShowerShape pflowShowerShape ;
00864 calculateShowerShape((*el)->pflowSuperCluster(),true,pflowShowerShape) ;
00865 (*el)->setPfShowerShape(pflowShowerShape) ;
00866 }
00867 else if ((*el)->passingMvaPreselection())
00868 { edm::LogError("GsfElectronCoreProducer")<<"Preselected tracker driven GsfTrack with no associated pflow SuperCluster." ; }
00869 }
00870 }
00871
00872 bool GsfElectronAlgo::isPreselected( GsfElectron * ele )
00873 { return (ele->passingCutBasedPreselection()||ele->passingMvaPreselection()) ; }
00874
00875 void GsfElectronAlgo::removeNotPreselectedElectrons()
00876 {
00877 GsfElectronPtrCollection::size_type ei = 1, emax = eventData_->electrons->size() ;
00878 GsfElectronPtrCollection::iterator eitr = eventData_->electrons->begin() ;
00879 while (eitr!=eventData_->electrons->end())
00880 {
00881 LogTrace("GsfElectronAlgo")<<"========== removed not preselected "<<ei<<"/"<<emax<<"==========" ;
00882 if (isPreselected(*eitr))
00883 { ++eitr ; ++ei ; }
00884 else
00885 { delete (*eitr) ; eitr = eventData_->electrons->erase(eitr) ; ++ei ; }
00886 }
00887 }
00888
00889 void GsfElectronAlgo::setCutBasedPreselectionFlag( GsfElectron * ele, const reco::BeamSpot & bs )
00890 {
00891
00892 ele->setPassCutBasedPreselection(false) ;
00893
00894
00895 bool eg = ele->core()->ecalDrivenSeed() ;
00896 bool pf = ele->core()->trackerDrivenSeed() && !ele->core()->ecalDrivenSeed() ;
00897 if (eg&&pf) { throw cms::Exception("GsfElectronAlgo|BothEcalAndPureTrackerDriven")<<"An electron cannot be both egamma and purely pflow" ; }
00898 if ((!eg)&&(!pf)) { throw cms::Exception("GsfElectronAlgo|NeitherEcalNorPureTrackerDriven")<<"An electron cannot be neither egamma nor purely pflow" ; }
00899 const CutsConfiguration * cfg = (eg?&generalData_->cutsCfg:&generalData_->cutsCfgPflow) ;
00900
00901
00902 double etaValue = EleRelPoint(ele->superCluster()->position(),bs.position()).eta() ;
00903 double etValue = ele->superCluster()->energy()/cosh(etaValue) ;
00904 LogTrace("GsfElectronAlgo") << "Et : " << etValue ;
00905 if (ele->isEB() && (etValue < cfg->minSCEtBarrel)) return ;
00906 if (ele->isEE() && (etValue < cfg->minSCEtEndcaps)) return ;
00907 LogTrace("GsfElectronAlgo") << "Et criteria are satisfied";
00908
00909
00910 double eopValue = ele->eSuperClusterOverP() ;
00911 LogTrace("GsfElectronAlgo") << "E/p : " << eopValue ;
00912 if (ele->isEB() && (eopValue > cfg->maxEOverPBarrel)) return ;
00913 if (ele->isEE() && (eopValue > cfg->maxEOverPEndcaps)) return ;
00914 if (ele->isEB() && (eopValue < cfg->minEOverPBarrel)) return ;
00915 if (ele->isEE() && (eopValue < cfg->minEOverPEndcaps)) return ;
00916 LogTrace("GsfElectronAlgo") << "E/p criteria are satisfied";
00917
00918
00919 LogTrace("GsfElectronAlgo") << "HoE1 : " << ele->hcalDepth1OverEcal() << ", HoE2 : " << ele->hcalDepth2OverEcal();
00920 double had = ele->hcalOverEcal()*ele->superCluster()->energy() ;
00921 const reco::CaloCluster & seedCluster = *(ele->superCluster()->seed()) ;
00922 int detector = seedCluster.hitsAndFractions()[0].first.subdetId() ;
00923 bool HoEveto = false ;
00924 if (detector==EcalBarrel && (had<cfg->maxHBarrel || (had/ele->superCluster()->energy())<cfg->maxHOverEBarrel)) HoEveto=true;
00925 else if (detector==EcalEndcap && (had<cfg->maxHEndcaps || (had/ele->superCluster()->energy())<cfg->maxHOverEEndcaps)) HoEveto=true;
00926 if ( !HoEveto ) return ;
00927 LogTrace("GsfElectronAlgo") << "H/E criteria are satisfied";
00928
00929
00930 double deta = ele->deltaEtaSuperClusterTrackAtVtx() ;
00931 LogTrace("GsfElectronAlgo") << "delta eta : " << deta ;
00932 if (ele->isEB() && (std::abs(deta) > cfg->maxDeltaEtaBarrel)) return ;
00933 if (ele->isEE() && (std::abs(deta) > cfg->maxDeltaEtaEndcaps)) return ;
00934 LogTrace("GsfElectronAlgo") << "Delta eta criteria are satisfied";
00935
00936
00937 double dphi = ele->deltaPhiSuperClusterTrackAtVtx();
00938 LogTrace("GsfElectronAlgo") << "delta phi : " << dphi;
00939 if (ele->isEB() && (std::abs(dphi) > cfg->maxDeltaPhiBarrel)) return ;
00940 if (ele->isEE() && (std::abs(dphi) > cfg->maxDeltaPhiEndcaps)) return ;
00941 LogTrace("GsfElectronAlgo") << "Delta phi criteria are satisfied";
00942
00943
00944 LogTrace("GsfElectronAlgo") << "sigma ieta ieta : " << ele->sigmaIetaIeta();
00945 if (ele->isEB() && (ele->sigmaIetaIeta() > cfg->maxSigmaIetaIetaBarrel)) return ;
00946 if (ele->isEE() && (ele->sigmaIetaIeta() > cfg->maxSigmaIetaIetaEndcaps)) return ;
00947 LogTrace("GsfElectronAlgo") << "Sigma ieta ieta criteria are satisfied";
00948
00949
00950 if (!ele->isEB() && cfg->isBarrel) return ;
00951 if (!ele->isEE() && cfg->isEndcaps) return ;
00952 if (cfg->isFiducial && (ele->isEBEEGap()||ele->isEBEtaGap()||ele->isEBPhiGap()||ele->isEERingGap()||ele->isEEDeeGap())) return ;
00953 LogTrace("GsfElectronAlgo") << "Fiducial flags criteria are satisfied";
00954
00955
00956 edm::RefToBase<TrajectorySeed> seed = ele->gsfTrack()->extra()->seedRef() ;
00957 ElectronSeedRef elseed = seed.castTo<ElectronSeedRef>() ;
00958 if (eg && !generalData_->cutsCfg.seedFromTEC)
00959 {
00960 if (elseed.isNull())
00961 { throw cms::Exception("GsfElectronAlgo|NotElectronSeed")<<"The GsfTrack seed is not an ElectronSeed ?!" ; }
00962 else
00963 { if (elseed->subDet2()==6) return ; }
00964 }
00965
00966
00967 if (std::abs(ele->gsfTrack()->dxy(bs.position()))>cfg->maxTIP) return ;
00968 LogTrace("GsfElectronAlgo") << "TIP criterion is satisfied" ;
00969
00970 LogTrace("GsfElectronAlgo") << "All cut based criteria are satisfied" ;
00971 ele->setPassCutBasedPreselection(true) ;
00972 }
00973
00974 void GsfElectronAlgo::setMvaPreselectionFlag( GsfElectron * ele )
00975 {
00976 ele->setPassMvaPreselection(false) ;
00977 if (ele->core()->ecalDrivenSeed())
00978 { if (ele->mva()>=generalData_->cutsCfg.minMVA) ele->setPassMvaPreselection(true) ; }
00979 else
00980 { if (ele->mva()>=generalData_->cutsCfgPflow.minMVA) ele->setPassMvaPreselection(true) ; }
00981 if (ele->passingMvaPreselection())
00982 { LogTrace("GsfElectronAlgo") << "Mva criterion is satisfied" ; }
00983 }
00984
00985 void GsfElectronAlgo::createElectron()
00986 {
00987
00988 if (generalData_->strategyCfg.ctfTracksCheck)
00989 { electronData_->checkCtfTrack(eventData_->currentCtfTracks) ; }
00990
00991
00992 int eleCharge ;
00993 GsfElectron::ChargeInfo eleChargeInfo ;
00994 electronData_->computeCharge(eleCharge,eleChargeInfo) ;
00995
00996
00997 CaloClusterPtr elbcRef = electronData_->getEleBasicCluster(eventSetupData_->mtsTransform) ;
00998
00999
01000 const reco::CaloCluster & seedCluster = *(electronData_->superClusterRef->seed()) ;
01001
01002
01003
01004 DetId seedXtalId = seedCluster.hitsAndFractions()[0].first ;
01005
01006 electronData_->calculateMode(eventSetupData_->mtsMode) ;
01007
01008
01009
01010
01011
01012
01013 Candidate::LorentzVector momentum = electronData_->calculateMomentum() ;
01014
01015
01016
01017
01018
01019
01020 reco::GsfElectron::TrackClusterMatching tcMatching ;
01021 tcMatching.electronCluster = elbcRef ;
01022 tcMatching.eSuperClusterOverP = (electronData_->vtxMom.mag()>0)?(electronData_->superClusterRef->energy()/electronData_->vtxMom.mag()):(-1.) ;
01023 tcMatching.eSeedClusterOverP = (electronData_->vtxMom.mag()>0.)?(seedCluster.energy()/electronData_->vtxMom.mag()):(-1) ;
01024 tcMatching.eSeedClusterOverPout = (electronData_->seedMom.mag()>0.)?(seedCluster.energy()/electronData_->seedMom.mag()):(-1.) ;
01025 tcMatching.eEleClusterOverPout = (electronData_->eleMom.mag()>0.)?(elbcRef->energy()/electronData_->eleMom.mag()):(-1.) ;
01026
01027 EleRelPointPair scAtVtx(electronData_->superClusterRef->position(),electronData_->sclPos,eventData_->beamspot->position()) ;
01028 tcMatching.deltaEtaSuperClusterAtVtx = scAtVtx.dEta() ;
01029 tcMatching.deltaPhiSuperClusterAtVtx = scAtVtx.dPhi() ;
01030
01031 EleRelPointPair seedAtCalo(seedCluster.position(),electronData_->seedPos,eventData_->beamspot->position()) ;
01032 tcMatching.deltaEtaSeedClusterAtCalo = seedAtCalo.dEta() ;
01033 tcMatching.deltaPhiSeedClusterAtCalo = seedAtCalo.dPhi() ;
01034
01035 EleRelPointPair ecAtCalo(elbcRef->position(),electronData_->elePos,eventData_->beamspot->position()) ;
01036 tcMatching.deltaEtaEleClusterAtCalo = ecAtCalo.dEta() ;
01037 tcMatching.deltaPhiEleClusterAtCalo = ecAtCalo.dPhi() ;
01038
01039
01040
01041
01042
01043
01044 reco::GsfElectron::TrackExtrapolations tkExtra ;
01045 ele_convert(electronData_->vtxPos,tkExtra.positionAtVtx) ;
01046 ele_convert(electronData_->sclPos,tkExtra.positionAtCalo) ;
01047 ele_convert(electronData_->vtxMom,tkExtra.momentumAtVtx) ;
01048 ele_convert(electronData_->sclMom,tkExtra.momentumAtCalo) ;
01049 ele_convert(electronData_->seedMom,tkExtra.momentumOut) ;
01050 ele_convert(electronData_->eleMom,tkExtra.momentumAtEleClus) ;
01051 ele_convert(electronData_->vtxMomWithConstraint,tkExtra.momentumAtVtxWithConstraint) ;
01052
01053
01054
01055
01056
01057
01058 reco::GsfElectron::ClosestCtfTrack ctfInfo ;
01059 ctfInfo.ctfTrack = electronData_->ctfTrackRef ;
01060 ctfInfo.shFracInnerHits = electronData_->shFracInnerHits ;
01061
01062
01063
01064
01065
01066
01067 reco::GsfElectron::FiducialFlags fiducialFlags ;
01068 int detector = seedXtalId.subdetId() ;
01069 double feta=std::abs(electronData_->superClusterRef->position().eta()) ;
01070 if (detector==EcalBarrel)
01071 {
01072 fiducialFlags.isEB = true ;
01073 EBDetId ebdetid(seedXtalId);
01074 if (EBDetId::isNextToEtaBoundary(ebdetid))
01075 {
01076 if (ebdetid.ietaAbs()==85)
01077 { fiducialFlags.isEBEEGap = true ; }
01078 else
01079 { fiducialFlags.isEBEtaGap = true ; }
01080 }
01081 if (EBDetId::isNextToPhiBoundary(ebdetid))
01082 { fiducialFlags.isEBPhiGap = true ; }
01083 }
01084 else if (detector==EcalEndcap)
01085 {
01086 fiducialFlags.isEE = true ;
01087 EEDetId eedetid(seedXtalId);
01088 if (EEDetId::isNextToRingBoundary(eedetid))
01089 {
01090 if (std::abs(feta)<2.)
01091 { fiducialFlags.isEBEEGap = true ; }
01092 else
01093 { fiducialFlags.isEERingGap = true ; }
01094 }
01095 if (EEDetId::isNextToDBoundary(eedetid))
01096 { fiducialFlags.isEEDeeGap = true ; }
01097 }
01098 else
01099 { throw cms::Exception("GsfElectronAlgo|UnknownXtalRegion")<<"createElectron(): do not know if it is a barrel or endcap seed cluster !!!!" ; }
01100
01101
01102
01103
01104
01105
01106 reco::GsfElectron::ShowerShape showerShape ;
01107 calculateShowerShape(electronData_->superClusterRef,!(electronData_->coreRef->ecalDrivenSeed()),showerShape) ;
01108
01109
01110
01111
01112
01113
01114 eventData_->retreiveOriginalTrackCollections(electronData_->ctfTrackRef,electronData_->coreRef->gsfTrack()) ;
01115
01116 ConversionFinder conversionFinder ;
01117 double BInTesla = eventSetupData_->magField->inTesla(GlobalPoint(0.,0.,0.)).z() ;
01118 edm::Handle<reco::TrackCollection> ctfTracks = eventData_->originalCtfTracks ;
01119 if (!ctfTracks.isValid()) { ctfTracks = eventData_->currentCtfTracks ; }
01120
01121
01122
01123
01124
01125
01126
01127 ConversionInfo conversionInfo = conversionFinder.getConversionInfo
01128 (*electronData_->coreRef,ctfTracks,eventData_->originalGsfTracks,BInTesla) ;
01129
01130 reco::GsfElectron::ConversionRejection conversionVars ;
01131 conversionVars.flags = conversionInfo.flag() ;
01132 conversionVars.dist = conversionInfo.dist() ;
01133 conversionVars.dcot = conversionInfo.dcot() ;
01134 conversionVars.radius = conversionInfo.radiusOfConversion() ;
01135 if ((conversionVars.flags==0)or(conversionVars.flags==1))
01136 conversionVars.partner = TrackBaseRef(conversionInfo.conversionPartnerCtfTk()) ;
01137 else if ((conversionVars.flags==2)or(conversionVars.flags==3))
01138 conversionVars.partner = TrackBaseRef(conversionInfo.conversionPartnerGsfTk()) ;
01139
01140
01141
01142
01143
01144
01145 float fbrem = (electronData_->outMom.mag()>0.)?((electronData_->innMom.mag()-electronData_->outMom.mag())/electronData_->innMom.mag()):1.e30 ;
01146
01147
01148
01149
01150
01151
01152 GsfElectron * ele = new
01153 GsfElectron
01154 ( eleCharge,eleChargeInfo,electronData_->coreRef,
01155 tcMatching, tkExtra, ctfInfo,
01156 fiducialFlags,showerShape,
01157 conversionVars,
01158 fbrem) ;
01159 ele->setP4(GsfElectron::P4_FROM_SUPER_CLUSTER,momentum,0,true) ;
01160
01161
01162 ElectronClassification theClassifier;
01163 theClassifier.correct(*ele);
01164 ElectronEnergyCorrector theEnCorrector ;
01165 if (!generalData_->superClusterErrorFunction)
01166 { theEnCorrector.setEcalEnergyError(*ele) ; }
01167 else
01168 { ele->setEcalEnergyError(generalData_->superClusterErrorFunction->getValue(*(ele->superCluster()),0)) ; }
01169 if (ele->core()->ecalDrivenSeed())
01170 {
01171 theEnCorrector.correct(*ele,*eventData_->beamspot,generalData_->strategyCfg.applyEtaCorrection) ;
01172 ElectronMomentumCorrector theMomCorrector;
01173 theMomCorrector.correct(*ele,electronData_->vtxTSOS);
01174 }
01175
01176
01177 reco::GsfElectron::IsolationVariables dr03, dr04 ;
01178 dr03.tkSumPt = eventData_->tkIsolation03->getPtTracks(ele);
01179 dr03.hcalDepth1TowerSumEt = eventData_->hadDepth1Isolation03->getTowerEtSum(ele) ;
01180 dr03.hcalDepth2TowerSumEt = eventData_->hadDepth2Isolation03->getTowerEtSum(ele) ;
01181 dr03.hcalDepth1TowerSumEtBc = eventData_->hadDepth1Isolation03Bc->getTowerEtSum(ele,&(showerShape.hcalTowersBehindClusters)) ;
01182 dr03.hcalDepth2TowerSumEtBc = eventData_->hadDepth2Isolation03Bc->getTowerEtSum(ele,&(showerShape.hcalTowersBehindClusters)) ;
01183 dr03.ecalRecHitSumEt = eventData_->ecalBarrelIsol03->getEtSum(ele)+eventData_->ecalEndcapIsol03->getEtSum(ele);
01184 dr04.tkSumPt = eventData_->tkIsolation04->getPtTracks(ele);
01185 dr04.hcalDepth1TowerSumEt = eventData_->hadDepth1Isolation04->getTowerEtSum(ele);
01186 dr04.hcalDepth2TowerSumEt = eventData_->hadDepth2Isolation04->getTowerEtSum(ele);
01187 dr04.hcalDepth1TowerSumEtBc = eventData_->hadDepth1Isolation04Bc->getTowerEtSum(ele,&(showerShape.hcalTowersBehindClusters)) ;
01188 dr04.hcalDepth2TowerSumEtBc = eventData_->hadDepth2Isolation04Bc->getTowerEtSum(ele,&(showerShape.hcalTowersBehindClusters)) ;
01189 dr04.ecalRecHitSumEt = eventData_->ecalBarrelIsol04->getEtSum(ele)+eventData_->ecalEndcapIsol04->getEtSum(ele);
01190 ele->setIsolation03(dr03);
01191 ele->setIsolation04(dr04);
01192
01193
01194 setCutBasedPreselectionFlag(ele,*eventData_->beamspot) ;
01195
01196 LogTrace("GsfElectronAlgo")<<"Constructed new electron with energy "<< ele->p4().e() ;
01197
01198 eventData_->electrons->push_back(ele) ;
01199 }
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209 void GsfElectronAlgo::setAmbiguityData( bool ignoreNotPreselected )
01210 {
01211 GsfElectronPtrCollection::iterator e1, e2 ;
01212 if (generalData_->strategyCfg.ambSortingStrategy==0)
01213 { eventData_->electrons->sort(EgAmbiguityTools::isBetter) ; }
01214 else if (generalData_->strategyCfg.ambSortingStrategy==1)
01215 { eventData_->electrons->sort(EgAmbiguityTools::isInnerMost(eventSetupData_->trackerHandle)) ; }
01216 else
01217 { throw cms::Exception("GsfElectronAlgo|UnknownAmbiguitySortingStrategy")<<"value of generalData_->strategyCfg.ambSortingStrategy is : "<<generalData_->strategyCfg.ambSortingStrategy ; }
01218
01219
01220 for
01221 ( e1 = eventData_->electrons->begin() ;
01222 e1 != eventData_->electrons->end() ;
01223 ++e1 )
01224 {
01225 (*e1)->clearAmbiguousGsfTracks() ;
01226 (*e1)->setAmbiguous(false) ;
01227 }
01228
01229
01230 if (generalData_->strategyCfg.useGsfPfRecTracks)
01231 {
01232 for
01233 ( e1 = eventData_->electrons->begin() ;
01234 e1 != eventData_->electrons->end() ;
01235 ++e1 )
01236 {
01237 bool found = false ;
01238 const GsfPFRecTrackCollection * gsfPfRecTrackCollection = eventData_->gsfPfRecTracks.product() ;
01239 GsfPFRecTrackCollection::const_iterator gsfPfRecTrack ;
01240 for ( gsfPfRecTrack=gsfPfRecTrackCollection->begin() ;
01241 gsfPfRecTrack!=gsfPfRecTrackCollection->end() ;
01242 ++gsfPfRecTrack )
01243 {
01244 if (gsfPfRecTrack->gsfTrackRef()==(*e1)->gsfTrack())
01245 {
01246 if (found)
01247 {
01248 edm::LogWarning("GsfElectronAlgo")<<"associated gsfPfRecTrack already found" ;
01249 }
01250 else
01251 {
01252 found = true ;
01253 const std::vector<reco::GsfPFRecTrackRef> & duplicates(gsfPfRecTrack->convBremGsfPFRecTrackRef()) ;
01254 std::vector<reco::GsfPFRecTrackRef>::const_iterator duplicate ;
01255 for ( duplicate = duplicates.begin() ; duplicate != duplicates.end() ; duplicate ++ )
01256 { (*e1)->addAmbiguousGsfTrack((*duplicate)->gsfTrackRef()) ; }
01257 }
01258 }
01259 }
01260 }
01261 }
01262
01263 else
01264 {
01265 for
01266 ( e1 = eventData_->electrons->begin() ;
01267 e1 != eventData_->electrons->end() ;
01268 ++e1 )
01269 {
01270 if ((*e1)->ambiguous()) continue ;
01271 if ( ignoreNotPreselected && !isPreselected(*e1) ) continue ;
01272
01273 SuperClusterRef scRef1 = (*e1)->superCluster();
01274 CaloClusterPtr eleClu1 = (*e1)->electronCluster();
01275 LogDebug("GsfElectronAlgo")
01276 << "Blessing electron with E/P " << (*e1)->eSuperClusterOverP()
01277 << ", cluster " << scRef1.get()
01278 << " & track " << (*e1)->gsfTrack().get() ;
01279
01280 for
01281 ( e2 = e1, ++e2 ;
01282 e2 != eventData_->electrons->end() ;
01283 ++e2 )
01284 {
01285 if ((*e2)->ambiguous()) continue ;
01286 if ( ignoreNotPreselected && !isPreselected(*e2) ) continue ;
01287
01288 SuperClusterRef scRef2 = (*e2)->superCluster();
01289 CaloClusterPtr eleClu2 = (*e2)->electronCluster();
01290
01291
01292 bool sameCluster = false ;
01293 if (generalData_->strategyCfg.ambClustersOverlapStrategy==0)
01294 { sameCluster = (scRef1==scRef2) ; }
01295 else if (generalData_->strategyCfg.ambClustersOverlapStrategy==1)
01296 {
01297 float eMin = 1. ;
01298 float threshold = eMin*cosh(EleRelPoint(scRef1->position(),eventData_->beamspot->position()).eta()) ;
01299 sameCluster =
01300 ( (EgAmbiguityTools::sharedEnergy(&(*eleClu1),&(*eleClu2),eventData_->reducedEBRecHits,eventData_->reducedEERecHits)>=threshold) ||
01301 (EgAmbiguityTools::sharedEnergy(&(*scRef1->seed()),&(*eleClu2),eventData_->reducedEBRecHits,eventData_->reducedEERecHits)>=threshold) ||
01302 (EgAmbiguityTools::sharedEnergy(&(*eleClu1),&(*scRef2->seed()),eventData_->reducedEBRecHits,eventData_->reducedEERecHits)>=threshold) ||
01303 (EgAmbiguityTools::sharedEnergy(&(*scRef1->seed()),&(*scRef2->seed()),eventData_->reducedEBRecHits,eventData_->reducedEERecHits)>=threshold) ) ;
01304 }
01305 else
01306 { throw cms::Exception("GsfElectronAlgo|UnknownAmbiguityClustersOverlapStrategy")<<"value of generalData_->strategyCfg.ambClustersOverlapStrategy is : "<<generalData_->strategyCfg.ambClustersOverlapStrategy ; }
01307
01308
01309 if (sameCluster)
01310 {
01311 LogDebug("GsfElectronAlgo")
01312 << "Discarding electron with E/P " << (*e2)->eSuperClusterOverP()
01313 << ", cluster " << scRef2.get()
01314 << " and track " << (*e2)->gsfTrack().get() ;
01315 (*e1)->addAmbiguousGsfTrack((*e2)->gsfTrack()) ;
01316 (*e2)->setAmbiguous(true) ;
01317 }
01318 else if ((*e1)->gsfTrack()==(*e2)->gsfTrack())
01319 {
01320 edm::LogWarning("GsfElectronAlgo")
01321 << "Forgetting electron with E/P " << (*e2)->eSuperClusterOverP()
01322 << ", cluster " << scRef2.get()
01323 << " and track " << (*e2)->gsfTrack().get() ;
01324 (*e2)->setAmbiguous(true) ;
01325 }
01326 }
01327 }
01328 }
01329 }
01330
01331 void GsfElectronAlgo::removeAmbiguousElectrons()
01332 {
01333 GsfElectronPtrCollection::size_type ei = 1, emax = eventData_->electrons->size() ;
01334 GsfElectronPtrCollection::iterator eitr = eventData_->electrons->begin() ;
01335 while (eitr!=eventData_->electrons->end())
01336 {
01337 LogTrace("GsfElectronAlgo")<<"========== remove ambiguous "<<ei<<"/"<<emax<<"==========" ;
01338 if ((*eitr)->ambiguous())
01339 { delete (*eitr) ; eitr = eventData_->electrons->erase(eitr) ; ++ei ; }
01340 else
01341 { ++eitr ; ++ei ; }
01342 }
01343 }
01344
01345