00001 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00002
00003 #include "RecoParticleFlow/PFProducer/interface/PFAlgo.h"
00004 #include "RecoParticleFlow/PFProducer/interface/PFMuonAlgo.h"
00005 #include "RecoParticleFlow/PFProducer/interface/PFElectronAlgo.h"
00006 #include "RecoParticleFlow/PFProducer/interface/PFPhotonAlgo.h"
00007 #include "RecoParticleFlow/PFProducer/interface/PFElectronExtraEqual.h"
00008
00009 #include "RecoParticleFlow/PFClusterTools/interface/PFEnergyCalibration.h"
00010 #include "RecoParticleFlow/PFClusterTools/interface/PFEnergyCalibrationHF.h"
00011 #include "RecoParticleFlow/PFClusterTools/interface/PFSCEnergyCalibration.h"
00012
00013 #include "DataFormats/ParticleFlowReco/interface/PFRecHit.h"
00014 #include "DataFormats/ParticleFlowReco/interface/PFBlock.h"
00015 #include "DataFormats/ParticleFlowReco/interface/PFBlockElementTrack.h"
00016 #include "DataFormats/ParticleFlowReco/interface/PFBlockElementCluster.h"
00017 #include "DataFormats/ParticleFlowReco/interface/PFRecTrack.h"
00018 #include "DataFormats/ParticleFlowReco/interface/PFCluster.h"
00019 #include "DataFormats/ParticleFlowReco/interface/PFLayer.h"
00020
00021 #include "DataFormats/VertexReco/interface/Vertex.h"
00022 #include "DataFormats/TrackReco/interface/Track.h"
00023 #include "DataFormats/MuonReco/interface/Muon.h"
00024
00025
00026 #include "DataFormats/Common/interface/OrphanHandle.h"
00027
00028 #include "DataFormats/Provenance/interface/ProductID.h"
00029 #include "DataFormats/Math/interface/LorentzVector.h"
00030
00031
00032 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
00033 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidateFwd.h"
00034
00035 #include "DataFormats/ParticleFlowReco/interface/PFDisplacedVertex.h"
00036 #include "DataFormats/ParticleFlowReco/interface/PFDisplacedVertexFwd.h"
00037
00038
00039 #include "Math/PxPyPzM4D.h"
00040 #include "Math/LorentzVector.h"
00041 #include "Math/DisplacementVector3D.h"
00042 #include "Math/SMatrix.h"
00043 #include "TDecompChol.h"
00044
00045 #include "boost/graph/adjacency_matrix.hpp"
00046 #include "boost/graph/graph_utility.hpp"
00047
00048
00049 using namespace std;
00050 using namespace reco;
00051 using namespace boost;
00052
00053 typedef std::list< reco::PFBlockRef >::iterator IBR;
00054
00055
00056
00057 PFAlgo::PFAlgo()
00058 : pfCandidates_( new PFCandidateCollection),
00059 nSigmaECAL_(0),
00060 nSigmaHCAL_(1),
00061 algo_(1),
00062 debug_(false),
00063 pfele_(0),
00064 pfpho_(0),
00065 useVertices_(false)
00066 {}
00067
00068 PFAlgo::~PFAlgo() {
00069 if (usePFElectrons_) delete pfele_;
00070 if (usePFPhotons_) delete pfpho_;
00071 }
00072
00073
00074 void
00075 PFAlgo::setParameters(double nSigmaECAL,
00076 double nSigmaHCAL,
00077 const boost::shared_ptr<PFEnergyCalibration>& calibration,
00078 const boost::shared_ptr<PFEnergyCalibrationHF>& thepfEnergyCalibrationHF) {
00079
00080 nSigmaECAL_ = nSigmaECAL;
00081 nSigmaHCAL_ = nSigmaHCAL;
00082
00083 calibration_ = calibration;
00084 thepfEnergyCalibrationHF_ = thepfEnergyCalibrationHF;
00085
00086 }
00087
00088
00089 void
00090 PFAlgo::setPFEleParameters(double mvaEleCut,
00091 string mvaWeightFileEleID,
00092 bool usePFElectrons,
00093 const boost::shared_ptr<PFSCEnergyCalibration>& thePFSCEnergyCalibration,
00094 const boost::shared_ptr<PFEnergyCalibration>& thePFEnergyCalibration,
00095 double sumEtEcalIsoForEgammaSC_barrel,
00096 double sumEtEcalIsoForEgammaSC_endcap,
00097 double coneEcalIsoForEgammaSC,
00098 double sumPtTrackIsoForEgammaSC_barrel,
00099 double sumPtTrackIsoForEgammaSC_endcap,
00100 unsigned int nTrackIsoForEgammaSC,
00101 double coneTrackIsoForEgammaSC,
00102 bool applyCrackCorrections,
00103 bool usePFSCEleCalib,
00104 bool useEGElectrons,
00105 bool useEGammaSupercluster) {
00106
00107 mvaEleCut_ = mvaEleCut;
00108 usePFElectrons_ = usePFElectrons;
00109 applyCrackCorrectionsElectrons_ = applyCrackCorrections;
00110 usePFSCEleCalib_ = usePFSCEleCalib;
00111 thePFSCEnergyCalibration_ = thePFSCEnergyCalibration;
00112 useEGElectrons_ = useEGElectrons;
00113 useEGammaSupercluster_ = useEGammaSupercluster;
00114 sumEtEcalIsoForEgammaSC_barrel_ = sumEtEcalIsoForEgammaSC_barrel;
00115 sumEtEcalIsoForEgammaSC_endcap_ = sumEtEcalIsoForEgammaSC_endcap;
00116 coneEcalIsoForEgammaSC_ = coneEcalIsoForEgammaSC;
00117 sumPtTrackIsoForEgammaSC_barrel_ = sumPtTrackIsoForEgammaSC_barrel;
00118 sumPtTrackIsoForEgammaSC_endcap_ = sumPtTrackIsoForEgammaSC_endcap;
00119 coneTrackIsoForEgammaSC_ = coneTrackIsoForEgammaSC;
00120 nTrackIsoForEgammaSC_ = nTrackIsoForEgammaSC;
00121
00122
00123 if(!usePFElectrons_) return;
00124 mvaWeightFileEleID_ = mvaWeightFileEleID;
00125 FILE * fileEleID = fopen(mvaWeightFileEleID_.c_str(), "r");
00126 if (fileEleID) {
00127 fclose(fileEleID);
00128 }
00129 else {
00130 string err = "PFAlgo: cannot open weight file '";
00131 err += mvaWeightFileEleID;
00132 err += "'";
00133 throw invalid_argument( err );
00134 }
00135 pfele_= new PFElectronAlgo(mvaEleCut_,mvaWeightFileEleID_,
00136 thePFSCEnergyCalibration_,
00137 thePFEnergyCalibration,
00138 applyCrackCorrectionsElectrons_,
00139 usePFSCEleCalib_,
00140 useEGElectrons_,
00141 useEGammaSupercluster_,
00142 sumEtEcalIsoForEgammaSC_barrel_,
00143 sumEtEcalIsoForEgammaSC_endcap_,
00144 coneEcalIsoForEgammaSC_,
00145 sumPtTrackIsoForEgammaSC_barrel_,
00146 sumPtTrackIsoForEgammaSC_endcap_,
00147 nTrackIsoForEgammaSC_,
00148 coneTrackIsoForEgammaSC_);
00149 }
00150
00151 void
00152 PFAlgo::setPFPhotonParameters(bool usePFPhotons,
00153 std::string mvaWeightFileConvID,
00154 double mvaConvCut,
00155 bool useReg,
00156 std::string X0_Map,
00157 const boost::shared_ptr<PFEnergyCalibration>& thePFEnergyCalibration,
00158 double sumPtTrackIsoForPhoton,
00159 double sumPtTrackIsoSlopeForPhoton)
00160 {
00161
00162 usePFPhotons_ = usePFPhotons;
00163
00164
00165 reco::Vertex dummy;
00166 const reco::Vertex* pv=&dummy;
00167 if(useVertices_)
00168 {
00169 dummy = primaryVertex_;
00170 }
00171 else {
00172 reco::Vertex::Error e;
00173 e(0, 0) = 0.0015 * 0.0015;
00174 e(1, 1) = 0.0015 * 0.0015;
00175 e(2, 2) = 15. * 15.;
00176 reco::Vertex::Point p(0, 0, 0);
00177 dummy = reco::Vertex(p, e, 0, 0, 0);
00178 }
00179
00180 if(! usePFPhotons_) return;
00181 FILE * filePhotonConvID = fopen(mvaWeightFileConvID.c_str(), "r");
00182 if (filePhotonConvID) {
00183 fclose(filePhotonConvID);
00184 }
00185 else {
00186 string err = "PFAlgo: cannot open weight file '";
00187 err += mvaWeightFileConvID;
00188 err += "'";
00189 throw invalid_argument( err );
00190 }
00191
00192
00193 pfpho_ = new PFPhotonAlgo(mvaWeightFileConvID,
00194 mvaConvCut,
00195 useReg,
00196 X0_Map,
00197 *pv,
00198 thePFEnergyCalibration,
00199 sumPtTrackIsoForPhoton,
00200 sumPtTrackIsoSlopeForPhoton
00201 );
00202 return;
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 void PFAlgo::setPFPhotonRegWeights(
00215 const GBRForest *LCorrForestEB,
00216 const GBRForest *LCorrForestEE,
00217 const GBRForest *GCorrForestBarrel,
00218 const GBRForest *GCorrForestEndcapHr9,
00219 const GBRForest *GCorrForestEndcapLr9, const GBRForest *PFEcalResolution
00220 ){
00221
00222 pfpho_->setGBRForest(LCorrForestEB,LCorrForestEE,
00223 GCorrForestBarrel, GCorrForestEndcapHr9,
00224 GCorrForestEndcapLr9, PFEcalResolution);
00225 }
00226 void
00227 PFAlgo::setPFMuonAndFakeParameters(std::vector<double> muonHCAL,
00228 std::vector<double> muonECAL,
00229 std::vector<double> muonHO,
00230 double nSigmaTRACK,
00231 double ptError,
00232 std::vector<double> factors45,
00233 bool usePFMuonMomAssign,
00234 bool useBestMuonTrack)
00235 {
00236 muonHCAL_ = muonHCAL;
00237 muonECAL_ = muonECAL;
00238 muonHO_ = muonHO;
00239 nSigmaTRACK_ = nSigmaTRACK;
00240 ptError_ = ptError;
00241 factors45_ = factors45;
00242 usePFMuonMomAssign_ = usePFMuonMomAssign;
00243 useBestMuonTrack_ = useBestMuonTrack;
00244 }
00245
00246 void
00247 PFAlgo::setPostHFCleaningParameters(bool postHFCleaning,
00248 double minHFCleaningPt,
00249 double minSignificance,
00250 double maxSignificance,
00251 double minSignificanceReduction,
00252 double maxDeltaPhiPt,
00253 double minDeltaMet) {
00254 postHFCleaning_ = postHFCleaning;
00255 minHFCleaningPt_ = minHFCleaningPt;
00256 minSignificance_ = minSignificance;
00257 maxSignificance_ = maxSignificance;
00258 minSignificanceReduction_= minSignificanceReduction;
00259 maxDeltaPhiPt_ = maxDeltaPhiPt;
00260 minDeltaMet_ = minDeltaMet;
00261 }
00262
00263 void
00264 PFAlgo::setDisplacedVerticesParameters(bool rejectTracks_Bad,
00265 bool rejectTracks_Step45,
00266 bool usePFNuclearInteractions,
00267 bool usePFConversions,
00268 bool usePFDecays,
00269 double dptRel_DispVtx){
00270
00271 rejectTracks_Bad_ = rejectTracks_Bad;
00272 rejectTracks_Step45_ = rejectTracks_Step45;
00273 usePFNuclearInteractions_ = usePFNuclearInteractions;
00274 usePFConversions_ = usePFConversions;
00275 usePFDecays_ = usePFDecays;
00276 dptRel_DispVtx_ = dptRel_DispVtx;
00277
00278 }
00279
00280
00281 void
00282 PFAlgo::setPFVertexParameters(bool useVertex,
00283 const reco::VertexCollection& primaryVertices) {
00284 useVertices_ = useVertex;
00285
00286 bool primaryVertexFound = false;
00287 int nVtx=primaryVertices.size();
00288 if(usePFPhotons_)pfpho_->setnPU(nVtx);
00289
00290 for (unsigned short i=0 ;i<primaryVertices.size();++i)
00291 {
00292 if(primaryVertices[i].isValid()&&(!primaryVertices[i].isFake()))
00293 {
00294 primaryVertex_ = primaryVertices[i];
00295 primaryVertexFound = true;
00296 break;
00297 }
00298 }
00299
00300 useVertices_ = useVertex && primaryVertexFound;
00301
00302 }
00303
00304
00305 void PFAlgo::reconstructParticles( const reco::PFBlockHandle& blockHandle ) {
00306
00307 blockHandle_ = blockHandle;
00308 reconstructParticles( *blockHandle_ );
00309 }
00310
00311
00312
00313 void PFAlgo::reconstructParticles( const reco::PFBlockCollection& blocks ) {
00314
00315
00316 if(pfCandidates_.get() )
00317 pfCandidates_->clear();
00318 else
00319 pfCandidates_.reset( new reco::PFCandidateCollection );
00320
00321 if(pfElectronCandidates_.get() )
00322 pfElectronCandidates_->clear();
00323 else
00324 pfElectronCandidates_.reset( new reco::PFCandidateCollection);
00325
00326
00327 if( pfPhotonCandidates_.get() )
00328 pfPhotonCandidates_->clear();
00329 else
00330 pfPhotonCandidates_.reset( new reco::PFCandidateCollection);
00331
00332 if(pfCleanedCandidates_.get() )
00333 pfCleanedCandidates_->clear();
00334 else
00335 pfCleanedCandidates_.reset( new reco::PFCandidateCollection );
00336
00337 if(pfCosmicsMuonCleanedCandidates_.get() )
00338 pfCosmicsMuonCleanedCandidates_->clear();
00339 else
00340 pfCosmicsMuonCleanedCandidates_.reset( new reco::PFCandidateCollection );
00341
00342 if(pfCleanedTrackerAndGlobalMuonCandidates_.get() )
00343 pfCleanedTrackerAndGlobalMuonCandidates_->clear();
00344 else
00345 pfCleanedTrackerAndGlobalMuonCandidates_.reset( new reco::PFCandidateCollection );
00346
00347 if(pfFakeMuonCleanedCandidates_.get() )
00348 pfFakeMuonCleanedCandidates_->clear();
00349 else
00350 pfFakeMuonCleanedCandidates_.reset( new reco::PFCandidateCollection );
00351
00352 if(pfPunchThroughMuonCleanedCandidates_.get() )
00353 pfPunchThroughMuonCleanedCandidates_->clear();
00354 else
00355 pfPunchThroughMuonCleanedCandidates_.reset( new reco::PFCandidateCollection );
00356
00357 if(pfPunchThroughHadronCleanedCandidates_.get() )
00358 pfPunchThroughHadronCleanedCandidates_->clear();
00359 else
00360 pfPunchThroughHadronCleanedCandidates_.reset( new reco::PFCandidateCollection );
00361
00362 if(pfAddedMuonCandidates_.get() )
00363 pfAddedMuonCandidates_->clear();
00364 else
00365 pfAddedMuonCandidates_.reset( new reco::PFCandidateCollection );
00366
00367
00368 pfElectronExtra_.clear();
00369 pfPhotonExtra_.clear();
00370
00371 if( debug_ ) {
00372 cout<<"*********************************************************"<<endl;
00373 cout<<"***** Particle flow algorithm *****"<<endl;
00374 cout<<"*********************************************************"<<endl;
00375 }
00376
00377
00378 std::list< reco::PFBlockRef > hcalBlockRefs;
00379 std::list< reco::PFBlockRef > ecalBlockRefs;
00380 std::list< reco::PFBlockRef > hoBlockRefs;
00381 std::list< reco::PFBlockRef > otherBlockRefs;
00382
00383 for( unsigned i=0; i<blocks.size(); ++i ) {
00384
00385 reco::PFBlockRef blockref = createBlockRef( blocks, i);
00386
00387 const reco::PFBlock& block = *blockref;
00388 const edm::OwnVector< reco::PFBlockElement >&
00389 elements = block.elements();
00390
00391 bool singleEcalOrHcal = false;
00392 if( elements.size() == 1 ){
00393 if( elements[0].type() == reco::PFBlockElement::ECAL ){
00394 ecalBlockRefs.push_back( blockref );
00395 singleEcalOrHcal = true;
00396 }
00397 if( elements[0].type() == reco::PFBlockElement::HCAL ){
00398 hcalBlockRefs.push_back( blockref );
00399 singleEcalOrHcal = true;
00400 }
00401 if( elements[0].type() == reco::PFBlockElement::HO ){
00402
00403 hoBlockRefs.push_back( blockref );
00404 singleEcalOrHcal = true;
00405 }
00406 }
00407
00408 if(!singleEcalOrHcal) {
00409 otherBlockRefs.push_back( blockref );
00410 }
00411 }
00412
00413 if( debug_ ){
00414 cout<<"# Ecal blocks: "<<ecalBlockRefs.size()
00415 <<", # Hcal blocks: "<<hcalBlockRefs.size()
00416 <<", # HO blocks: "<<hoBlockRefs.size()
00417 <<", # Other blocks: "<<otherBlockRefs.size()<<endl;
00418 }
00419
00420
00421
00422
00423
00424 unsigned nblcks = 0;
00425 for( IBR io = otherBlockRefs.begin(); io!=otherBlockRefs.end(); ++io) {
00426 if ( debug_ ) std::cout << "Block number " << nblcks++ << std::endl;
00427 processBlock( *io, hcalBlockRefs, ecalBlockRefs );
00428 }
00429
00430 std::list< reco::PFBlockRef > empty;
00431
00432 unsigned hblcks = 0;
00433
00434 for( IBR ih = hcalBlockRefs.begin(); ih!=hcalBlockRefs.end(); ++ih) {
00435 if ( debug_ ) std::cout << "HCAL block number " << hblcks++ << std::endl;
00436 processBlock( *ih, empty, empty );
00437 }
00438
00439 unsigned eblcks = 0;
00440
00441 for( IBR ie = ecalBlockRefs.begin(); ie!=ecalBlockRefs.end(); ++ie) {
00442 if ( debug_ ) std::cout << "ECAL block number " << eblcks++ << std::endl;
00443 processBlock( *ie, empty, empty );
00444 }
00445
00446
00447 postCleaning();
00448 }
00449
00450
00451 void PFAlgo::processBlock( const reco::PFBlockRef& blockref,
00452 std::list<reco::PFBlockRef>& hcalBlockRefs,
00453 std::list<reco::PFBlockRef>& ecalBlockRefs ) {
00454
00455
00456 assert(!blockref.isNull() );
00457 const reco::PFBlock& block = *blockref;
00458
00459 typedef std::multimap<double, unsigned>::iterator IE;
00460 typedef std::multimap<double, std::pair<unsigned,math::XYZVector> >::iterator IS;
00461 typedef std::multimap<double, std::pair<unsigned,bool> >::iterator IT;
00462 typedef std::multimap< unsigned, std::pair<double, unsigned> >::iterator II;
00463
00464 if(debug_) {
00465 cout<<"#########################################################"<<endl;
00466 cout<<"##### Process Block: #####"<<endl;
00467 cout<<"#########################################################"<<endl;
00468 cout<<block<<endl;
00469 }
00470
00471
00472 const edm::OwnVector< reco::PFBlockElement >& elements = block.elements();
00473
00474 PFBlock::LinkData linkData = block.linkData();
00475
00476
00477 vector<bool> active( elements.size(), true );
00478
00479
00480
00481
00482 std::vector<reco::PFCandidate> tempElectronCandidates;
00483 tempElectronCandidates.clear();
00484 if (usePFElectrons_) {
00485 if (pfele_->isElectronValidCandidate(blockref,active, primaryVertex_ )){
00486
00487 const std::vector<reco::PFCandidate> PFElectCandidates_(pfele_->getElectronCandidates());
00488 for ( std::vector<reco::PFCandidate>::const_iterator ec=PFElectCandidates_.begin(); ec != PFElectCandidates_.end(); ++ec )tempElectronCandidates.push_back(*ec);
00489
00490
00491
00492
00493 }
00494
00495
00496 pfElectronCandidates_->insert(pfElectronCandidates_->end(),
00497 pfele_->getAllElectronCandidates().begin(),
00498 pfele_->getAllElectronCandidates().end());
00499
00500 pfElectronExtra_.insert(pfElectronExtra_.end(),
00501 pfele_->getElectronExtra().begin(),
00502 pfele_->getElectronExtra().end());
00503
00504 }
00505 if( usePFPhotons_ ) {
00506
00507 if(debug_)
00508 cout<<endl<<"--------------- entering PFPhotonAlgo ----------------"<<endl;
00509 vector<PFCandidatePhotonExtra> pfPhotonExtraCand;
00510 if ( pfpho_->isPhotonValidCandidate(blockref,
00511 active,
00512 pfPhotonCandidates_,
00513 pfPhotonExtraCand,
00514 tempElectronCandidates
00515
00516 ) ) {
00517 if(debug_)
00518 std::cout<< " In this PFBlock we found "<<pfPhotonCandidates_->size()<<" Photon Candidates."<<std::endl;
00519
00520
00521
00522
00523
00524 unsigned int extracand =0;
00525 PFCandidateCollection::const_iterator cand = pfPhotonCandidates_->begin();
00526 for( ; cand != pfPhotonCandidates_->end(); ++cand, ++extracand) {
00527 pfCandidates_->push_back(*cand);
00528 pfPhotonExtra_.push_back(pfPhotonExtraCand[extracand]);
00529 }
00530
00531 }
00532 pfPhotonExtraCand.clear();
00533 pfPhotonCandidates_->clear();
00534 }
00535
00536
00537 if (usePFConversions_ )
00538 {
00539 for(unsigned iEle=0; iEle<elements.size(); iEle++) {
00540 PFBlockElement::Type type = elements[iEle].type();
00541 if(type==PFBlockElement::TRACK)
00542 {
00543 if(elements[iEle].trackRef()->algo() == 12)
00544 active[iEle]=false;
00545 if(elements[iEle].trackRef()->quality(reco::TrackBase::highPurity))continue;
00546 const reco::PFBlockElementTrack * trackRef = dynamic_cast<const reco::PFBlockElementTrack*>((&elements[iEle]));
00547 if(!(trackRef->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)))continue;
00548 if(elements[iEle].convRef().isNonnull())active[iEle]=false;
00549 }
00550 }
00551 }
00552 for ( std::vector<reco::PFCandidate>::const_iterator ec=tempElectronCandidates.begin(); ec != tempElectronCandidates.end(); ++ec ){
00553 pfCandidates_->push_back(*ec);
00554 }
00555 tempElectronCandidates.clear();
00556
00557
00558 if(debug_)
00559 cout<<endl<<"--------------- loop 1 ------------------"<<endl;
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586 vector<unsigned> hcalIs;
00587 vector<unsigned> hoIs;
00588 vector<unsigned> ecalIs;
00589 vector<unsigned> trackIs;
00590 vector<unsigned> ps1Is;
00591 vector<unsigned> ps2Is;
00592
00593 vector<unsigned> hfEmIs;
00594 vector<unsigned> hfHadIs;
00595
00596
00597 for(unsigned iEle=0; iEle<elements.size(); iEle++) {
00598 PFBlockElement::Type type = elements[iEle].type();
00599
00600 if(debug_ && type != PFBlockElement::BREM ) cout<<endl<<elements[iEle];
00601
00602 switch( type ) {
00603 case PFBlockElement::TRACK:
00604 if ( active[iEle] ) {
00605 trackIs.push_back( iEle );
00606 if(debug_) cout<<"TRACK, stored index, continue"<<endl;
00607 }
00608 break;
00609 case PFBlockElement::ECAL:
00610 if ( active[iEle] ) {
00611 ecalIs.push_back( iEle );
00612 if(debug_) cout<<"ECAL, stored index, continue"<<endl;
00613 }
00614 continue;
00615 case PFBlockElement::HCAL:
00616 if ( active[iEle] ) {
00617 hcalIs.push_back( iEle );
00618 if(debug_) cout<<"HCAL, stored index, continue"<<endl;
00619 }
00620 continue;
00621 case PFBlockElement::HO:
00622 if (useHO_) {
00623 if ( active[iEle] ) {
00624 hoIs.push_back( iEle );
00625 if(debug_) cout<<"HO, stored index, continue"<<endl;
00626 }
00627 }
00628 continue;
00629 case PFBlockElement::HFEM:
00630 if ( active[iEle] ) {
00631 hfEmIs.push_back( iEle );
00632 if(debug_) cout<<"HFEM, stored index, continue"<<endl;
00633 }
00634 continue;
00635 case PFBlockElement::HFHAD:
00636 if ( active[iEle] ) {
00637 hfHadIs.push_back( iEle );
00638 if(debug_) cout<<"HFHAD, stored index, continue"<<endl;
00639 }
00640 continue;
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656 default:
00657 continue;
00658 }
00659
00660
00661 unsigned iTrack = iEle;
00662 reco::MuonRef muonRef = elements[iTrack].muonRef();
00663
00664
00665 if (active[iTrack] && isFromSecInt(elements[iEle], "primary")){
00666 bool isPrimaryTrack = elements[iEle].displacedVertexRef(PFBlockElement::T_TO_DISP)->displacedVertexRef()->isTherePrimaryTracks();
00667 if (isPrimaryTrack) {
00668 if (debug_) cout << "Primary Track reconstructed alone" << endl;
00669 unsigned tmpi = reconstructTrack(elements[iEle]);
00670 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iEle );
00671 active[iTrack] = false;
00672 }
00673 }
00674
00675
00676 if(debug_) {
00677 if ( !active[iTrack] )
00678 cout << "Already used by electrons, muons, conversions" << endl;
00679 }
00680
00681
00682
00683 if ( ! active[iTrack] ) continue;
00684
00685 reco::TrackRef trackRef = elements[iTrack].trackRef();
00686 assert( !trackRef.isNull() );
00687
00688 if (debug_ ) {
00689 cout <<"PFAlgo:processBlock "<<" "<<trackIs.size()<<" "<<ecalIs.size()<<" "<<hcalIs.size()<<" "<<hoIs.size()<<endl;
00690 }
00691
00692
00693
00694
00695
00696 std::multimap<double, unsigned> ecalElems;
00697 block.associatedElements( iTrack, linkData,
00698 ecalElems ,
00699 reco::PFBlockElement::ECAL,
00700 reco::PFBlock::LINKTEST_ALL );
00701
00702 std::multimap<double, unsigned> hcalElems;
00703 block.associatedElements( iTrack, linkData,
00704 hcalElems,
00705 reco::PFBlockElement::HCAL,
00706 reco::PFBlock::LINKTEST_ALL );
00707
00708
00709
00710
00711 if ( hcalElems.empty() && !ecalElems.empty() ) {
00712
00713 unsigned ntt = 1;
00714 unsigned index = ecalElems.begin()->second;
00715 std::multimap<double, unsigned> sortedTracks;
00716 block.associatedElements( index, linkData,
00717 sortedTracks,
00718 reco::PFBlockElement::TRACK,
00719 reco::PFBlock::LINKTEST_ALL );
00720
00721
00722
00723 for(IE ie = sortedTracks.begin(); ie != sortedTracks.end(); ++ie ) {
00724 unsigned jTrack = ie->second;
00725
00726
00727 if ( !active[jTrack] ) continue;
00728
00729
00730
00731 if ( jTrack == iTrack ) continue;
00732
00733
00734
00735
00736 std::multimap<double, unsigned> sortedECAL;
00737 block.associatedElements( jTrack, linkData,
00738 sortedECAL,
00739 reco::PFBlockElement::ECAL,
00740 reco::PFBlock::LINKTEST_ALL );
00741 if ( sortedECAL.begin()->second != index ) continue;
00742
00743
00744
00745
00746 std::multimap<double, unsigned> sortedHCAL;
00747 block.associatedElements( jTrack, linkData,
00748 sortedHCAL,
00749 reco::PFBlockElement::HCAL,
00750 reco::PFBlock::LINKTEST_ALL );
00751 if ( !sortedHCAL.size() ) continue;
00752
00753 ntt++;
00754
00755
00756 block.setLink( iTrack,
00757 sortedHCAL.begin()->second,
00758 sortedECAL.begin()->first,
00759 linkData,
00760 PFBlock::LINKTEST_RECHIT );
00761
00762 }
00763
00764
00765 block.associatedElements( iTrack, linkData,
00766 hcalElems,
00767 reco::PFBlockElement::HCAL,
00768 reco::PFBlock::LINKTEST_ALL );
00769
00770 if ( debug_ && hcalElems.size() )
00771 std::cout << "Track linked back to HCAL due to ECAL sharing with other tracks" << std::endl;
00772 }
00773
00774
00775
00776
00777
00778
00779
00780
00781 std::multimap<double,unsigned> gsfElems;
00782 if (usePFElectrons_ == false) {
00783 block.associatedElements( iTrack, linkData,
00784 gsfElems ,
00785 reco::PFBlockElement::GSF );
00786 }
00787
00788
00789 if(hcalElems.empty() && debug_) {
00790 cout<<"no hcal element connected to track "<<iTrack<<endl;
00791 }
00792
00793
00794
00795
00796 bool hcalFound = false;
00797
00798 if(debug_)
00799 cout<<"now looping on elements associated to the track"<<endl;
00800
00801
00802
00803 for(IE ie = ecalElems.begin(); ie != ecalElems.end(); ++ie ) {
00804
00805 unsigned index = ie->second;
00806
00807 PFBlockElement::Type type = elements[index].type();
00808 if(debug_) {
00809 double dist = ie->first;
00810 cout<<"\telement "<<elements[index]<<" linked with distance = "<< dist <<endl;
00811 if ( ! active[index] ) cout << "This ECAL is already used - skip it" << endl;
00812 }
00813 assert( type == PFBlockElement::ECAL );
00814
00815
00816 if ( ! active[index] ) continue;
00817
00818
00819
00820
00821
00822 if( !hcalElems.empty() && debug_)
00823 cout<<"\t\tat least one hcal element connected to the track."
00824 <<" Sparing Ecal cluster for the hcal loop"<<endl;
00825
00826 }
00827
00828
00829
00830
00831
00832 if( hcalElems.empty() ) {
00833
00834 if ( debug_ )
00835 std::cout << "Now deals with tracks linked to no HCAL clusters" << std::endl;
00836
00837
00838
00839
00840 double trackMomentum = elements[iTrack].trackRef()->p();
00841 if ( debug_ )
00842 std::cout << elements[iTrack] << std::endl;
00843
00844
00845 bool thisIsAMuon = PFMuonAlgo::isMuon(elements[iTrack]);
00846 if ( thisIsAMuon ) trackMomentum = 0.;
00847
00848
00849 bool rejectFake = false;
00850 if ( !thisIsAMuon && elements[iTrack].trackRef()->ptError() > ptError_ ) {
00851
00852 double deficit = trackMomentum;
00853 double resol = neutralHadronEnergyResolution(trackMomentum,
00854 elements[iTrack].trackRef()->eta());
00855 resol *= trackMomentum;
00856
00857 if ( !ecalElems.empty() ) {
00858 unsigned thisEcal = ecalElems.begin()->second;
00859 reco::PFClusterRef clusterRef = elements[thisEcal].clusterRef();
00860 deficit -= clusterRef->energy();
00861 resol = neutralHadronEnergyResolution(trackMomentum,
00862 clusterRef->positionREP().Eta());
00863 resol *= trackMomentum;
00864 }
00865
00866 bool isPrimary = isFromSecInt(elements[iTrack], "primary");
00867
00868 if ( deficit > nSigmaTRACK_*resol && !isPrimary) {
00869 rejectFake = true;
00870 active[iTrack] = false;
00871 if ( debug_ )
00872 std::cout << elements[iTrack] << std::endl
00873 << "is probably a fake (1) --> lock the track"
00874 << std::endl;
00875 }
00876 }
00877
00878 if ( rejectFake ) continue;
00879
00880
00881
00882
00883 std::vector<unsigned> tmpi;
00884 std::vector<unsigned> kTrack;
00885
00886
00887 double Dpt = trackRef->ptError();
00888
00889 if ( rejectTracks_Step45_ && ecalElems.empty() &&
00890 trackMomentum > 30. && Dpt > 0.5 &&
00891 ( trackRef->algo() == TrackBase::iter4 ||
00892 trackRef->algo() == TrackBase::iter5 ||
00893 trackRef->algo() == TrackBase::iter6 ) ) {
00894
00895
00896 double dptRel = Dpt/trackRef->pt()*100;
00897 bool isPrimaryOrSecondary = isFromSecInt(elements[iTrack], "all");
00898
00899 if ( isPrimaryOrSecondary && dptRel < dptRel_DispVtx_) continue;
00900 unsigned nHits = elements[iTrack].trackRef()->hitPattern().trackerLayersWithMeasurement();
00901 unsigned int NLostHit = trackRef->hitPattern().trackerLayersWithoutMeasurement();
00902
00903 if ( debug_ )
00904 std::cout << "A track (algo = " << trackRef->algo() << ") with momentum " << trackMomentum
00905 << " / " << elements[iTrack].trackRef()->pt() << " +/- " << Dpt
00906 << " / " << elements[iTrack].trackRef()->eta()
00907 << " without any link to ECAL/HCAL and with " << nHits << " (" << NLostHit
00908 << ") hits (lost hits) has been cleaned" << std::endl;
00909 active[iTrack] = false;
00910 continue;
00911 }
00912
00913
00914 tmpi.push_back(reconstructTrack( elements[iTrack]));
00915 kTrack.push_back(iTrack);
00916 active[iTrack] = false;
00917
00918
00919 if ( ecalElems.empty() ) {
00920 (*pfCandidates_)[tmpi[0]].setEcalEnergy( 0., 0. );
00921 (*pfCandidates_)[tmpi[0]].setHcalEnergy( 0., 0. );
00922 (*pfCandidates_)[tmpi[0]].setHoEnergy( 0., 0. );
00923 (*pfCandidates_)[tmpi[0]].setPs1Energy( 0 );
00924 (*pfCandidates_)[tmpi[0]].setPs2Energy( 0 );
00925 (*pfCandidates_)[tmpi[0]].addElementInBlock( blockref, kTrack[0] );
00926 continue;
00927 }
00928
00929
00930 unsigned thisEcal = ecalElems.begin()->second;
00931 reco::PFClusterRef clusterRef = elements[thisEcal].clusterRef();
00932 if ( debug_ ) std::cout << " is associated to " << elements[thisEcal] << std::endl;
00933
00934
00935 if ( thisIsAMuon ) {
00936 (*pfCandidates_)[tmpi[0]].setEcalEnergy( clusterRef->energy(),
00937 std::min(clusterRef->energy(), muonECAL_[0]) );
00938 (*pfCandidates_)[tmpi[0]].setHcalEnergy( 0., 0. );
00939 (*pfCandidates_)[tmpi[0]].setHoEnergy( 0., 0. );
00940 (*pfCandidates_)[tmpi[0]].setPs1Energy( 0 );
00941 (*pfCandidates_)[tmpi[0]].setPs2Energy( 0 );
00942 (*pfCandidates_)[tmpi[0]].addElementInBlock( blockref, kTrack[0] );
00943 }
00944
00945 double slopeEcal = 1.;
00946 bool connectedToEcal = false;
00947 unsigned iEcal = 99999;
00948 double calibEcal = 0.;
00949 double calibHcal = 0.;
00950 double totalEcal = thisIsAMuon ? -muonECAL_[0] : 0.;
00951
00952
00953 std::multimap<double, unsigned> sortedTracks;
00954 block.associatedElements( thisEcal, linkData,
00955 sortedTracks,
00956 reco::PFBlockElement::TRACK,
00957 reco::PFBlock::LINKTEST_ALL );
00958
00959 for(IE ie = sortedTracks.begin(); ie != sortedTracks.end(); ++ie ) {
00960 unsigned jTrack = ie->second;
00961
00962
00963 if ( !active[jTrack] ) continue;
00964
00965
00966 if ( jTrack == iTrack ) continue;
00967
00968
00969
00970
00971 std::multimap<double, unsigned> sortedECAL;
00972 block.associatedElements( jTrack, linkData,
00973 sortedECAL,
00974 reco::PFBlockElement::ECAL,
00975 reco::PFBlock::LINKTEST_ALL );
00976 if ( sortedECAL.begin()->second != thisEcal ) continue;
00977
00978
00979 bool thatIsAMuon = PFMuonAlgo::isMuon(elements[jTrack]);
00980
00981
00982 bool rejectFake = false;
00983 reco::TrackRef trackRef = elements[jTrack].trackRef();
00984 if ( !thatIsAMuon && trackRef->ptError() > ptError_) {
00985 double deficit = trackMomentum + trackRef->p() - clusterRef->energy();
00986 double resol = nSigmaTRACK_*neutralHadronEnergyResolution(trackMomentum+trackRef->p(),
00987 clusterRef->positionREP().Eta());
00988 resol *= (trackMomentum+trackRef->p());
00989 if ( deficit > nSigmaTRACK_*resol ) {
00990 rejectFake = true;
00991 kTrack.push_back(jTrack);
00992 active[jTrack] = false;
00993 if ( debug_ )
00994 std::cout << elements[jTrack] << std::endl
00995 << "is probably a fake (2) --> lock the track"
00996 << std::endl;
00997 }
00998 }
00999 if ( rejectFake ) continue;
01000
01001
01002
01003
01004
01005 if ( !thatIsAMuon ) {
01006 if ( debug_ )
01007 std::cout << "Track momentum increased from " << trackMomentum << " GeV ";
01008 trackMomentum += trackRef->p();
01009 if ( debug_ ) {
01010 std::cout << "to " << trackMomentum << " GeV." << std::endl;
01011 std::cout << "with " << elements[jTrack] << std::endl;
01012 }
01013 } else {
01014 totalEcal -= muonECAL_[0];
01015 totalEcal = std::max(totalEcal, 0.);
01016 }
01017
01018
01019 tmpi.push_back(reconstructTrack( elements[jTrack] ));
01020 kTrack.push_back(jTrack);
01021 active[jTrack] = false;
01022
01023 if ( thatIsAMuon ) {
01024 (*pfCandidates_)[tmpi.back()].setEcalEnergy(clusterRef->energy(),
01025 std::min(clusterRef->energy(),muonECAL_[0]));
01026 (*pfCandidates_)[tmpi.back()].setHcalEnergy( 0., 0. );
01027 (*pfCandidates_)[tmpi.back()].setHoEnergy( 0., 0. );
01028 (*pfCandidates_)[tmpi.back()].setPs1Energy( 0 );
01029 (*pfCandidates_)[tmpi.back()].setPs2Energy( 0 );
01030 (*pfCandidates_)[tmpi.back()].addElementInBlock( blockref, kTrack.back() );
01031 }
01032 }
01033
01034
01035 if ( debug_ ) std::cout << "Loop over all associated ECAL clusters" << std::endl;
01036
01037 for(IE ie = ecalElems.begin(); ie != ecalElems.end(); ++ie ) {
01038
01039 unsigned index = ie->second;
01040 PFBlockElement::Type type = elements[index].type();
01041 assert( type == PFBlockElement::ECAL );
01042 if ( debug_ ) std::cout << elements[index] << std::endl;
01043
01044
01045 if ( debug_ && ! active[index] ) std::cout << "is not active - ignore " << std::endl;
01046 if ( ! active[index] ) continue;
01047
01048
01049
01050 block.associatedElements( index, linkData,
01051 sortedTracks,
01052 reco::PFBlockElement::TRACK,
01053 reco::PFBlock::LINKTEST_ALL );
01054 bool skip = true;
01055 for (unsigned ic=0; ic<kTrack.size();++ic) {
01056 if ( sortedTracks.begin()->second == kTrack[ic] ) {
01057 skip = false;
01058 break;
01059 }
01060 }
01061 if ( debug_ && skip ) std::cout << "is closer to another track - ignore " << std::endl;
01062 if ( skip ) continue;
01063
01064
01065
01066 reco::PFClusterRef clusterRef = elements[index].clusterRef();
01067 assert( !clusterRef.isNull() );
01068
01069 if ( debug_ ) {
01070 double dist = ie->first;
01071 std::cout <<"Ecal cluster with raw energy = " << clusterRef->energy()
01072 <<" linked with distance = " << dist << std::endl;
01073 }
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085 vector<double> ps1Ene(1,static_cast<double>(0.));
01086 associatePSClusters(index, reco::PFBlockElement::PS1, block, elements, linkData, active, ps1Ene);
01087 vector<double> ps2Ene(1,static_cast<double>(0.));
01088 associatePSClusters(index, reco::PFBlockElement::PS2, block, elements, linkData, active, ps2Ene);
01089
01090
01091 bool crackCorrection = false;
01092 double ecalEnergy = calibration_->energyEm(*clusterRef,ps1Ene,ps2Ene,crackCorrection);
01093 if ( debug_ )
01094 std::cout << "Corrected ECAL(+PS) energy = " << ecalEnergy << std::endl;
01095
01096
01097
01098 totalEcal += ecalEnergy;
01099 double previousCalibEcal = calibEcal;
01100 double previousSlopeEcal = slopeEcal;
01101 calibEcal = std::max(totalEcal,0.);
01102 calibHcal = 0.;
01103 calibration_->energyEmHad(trackMomentum,calibEcal,calibHcal,
01104 clusterRef->positionREP().Eta(),
01105 clusterRef->positionREP().Phi());
01106 if ( totalEcal > 0.) slopeEcal = calibEcal/totalEcal;
01107
01108 if ( debug_ )
01109 std::cout << "The total calibrated energy so far amounts to = " << calibEcal << std::endl;
01110
01111
01112
01113 if ( connectedToEcal && calibEcal - trackMomentum >= 0. ) {
01114
01115
01116 calibEcal = previousCalibEcal;
01117 slopeEcal = previousSlopeEcal;
01118 totalEcal = calibEcal/slopeEcal;
01119
01120
01121
01122 active[index] = false;
01123
01124
01125 std::multimap<double, unsigned> assTracks;
01126 block.associatedElements( index, linkData,
01127 assTracks,
01128 reco::PFBlockElement::TRACK,
01129 reco::PFBlock::LINKTEST_ALL );
01130
01131
01132 unsigned tmpe = reconstructCluster( *clusterRef, ecalEnergy );
01133 (*pfCandidates_)[tmpe].setEcalEnergy( clusterRef->energy(), ecalEnergy );
01134 (*pfCandidates_)[tmpe].setHcalEnergy( 0., 0. );
01135 (*pfCandidates_)[tmpe].setHoEnergy( 0., 0. );
01136 (*pfCandidates_)[tmpe].setPs1Energy( ps1Ene[0] );
01137 (*pfCandidates_)[tmpe].setPs2Energy( ps2Ene[0] );
01138 (*pfCandidates_)[tmpe].addElementInBlock( blockref, index );
01139
01140 if(assTracks.size()) {
01141 (*pfCandidates_)[tmpe].addElementInBlock( blockref, assTracks.begin()->second );
01142
01143
01144 const math::XYZPointF& chargedPosition =
01145 dynamic_cast<const reco::PFBlockElementTrack*>(&elements[assTracks.begin()->second])->positionAtECALEntrance();
01146 (*pfCandidates_)[tmpe].setPositionAtECALEntrance(chargedPosition);
01147 }
01148 break;
01149 }
01150
01151
01152 connectedToEcal = true;
01153 iEcal = index;
01154 active[index] = false;
01155 for (unsigned ic=0; ic<tmpi.size();++ic)
01156 (*pfCandidates_)[tmpi[ic]].addElementInBlock( blockref, iEcal );
01157
01158
01159 }
01160
01161 bool bNeutralProduced = false;
01162
01163
01164 if( connectedToEcal ) {
01165 reco::PFClusterRef pivotalRef = elements[iEcal].clusterRef();
01166
01167 double neutralEnergy = calibEcal - trackMomentum;
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203 double resol = neutralHadronEnergyResolution(trackMomentum,pivotalRef->positionREP().Eta());
01204 resol *= trackMomentum;
01205 if ( neutralEnergy > std::max(0.5,nSigmaECAL_*resol) ) {
01206 neutralEnergy /= slopeEcal;
01207 unsigned tmpj = reconstructCluster( *pivotalRef, neutralEnergy );
01208 (*pfCandidates_)[tmpj].setEcalEnergy( pivotalRef->energy(), neutralEnergy );
01209 (*pfCandidates_)[tmpj].setHcalEnergy( 0., 0. );
01210 (*pfCandidates_)[tmpj].setHoEnergy( 0., 0. );
01211 (*pfCandidates_)[tmpj].setPs1Energy( 0. );
01212 (*pfCandidates_)[tmpj].setPs2Energy( 0. );
01213 (*pfCandidates_)[tmpj].addElementInBlock(blockref, iEcal);
01214 bNeutralProduced = true;
01215 for (unsigned ic=0; ic<kTrack.size();++ic)
01216 (*pfCandidates_)[tmpj].addElementInBlock( blockref, kTrack[ic] );
01217 }
01218
01219
01220 for (unsigned ic=0; ic<tmpi.size();++ic) {
01221
01222
01223 if ( (*pfCandidates_)[tmpi[ic]].particleId() == reco::PFCandidate::mu ) continue;
01224
01225 double fraction = (*pfCandidates_)[tmpi[ic]].trackRef()->p()/trackMomentum;
01226 double ecalCal = bNeutralProduced ?
01227 (calibEcal-neutralEnergy*slopeEcal)*fraction : calibEcal*fraction;
01228 double ecalRaw = totalEcal*fraction;
01229
01230 if (debug_) cout << "The fraction after photon supression is " << fraction << " calibrated ecal = " << ecalCal << endl;
01231
01232 (*pfCandidates_)[tmpi[ic]].setEcalEnergy( ecalRaw, ecalCal );
01233 (*pfCandidates_)[tmpi[ic]].setHcalEnergy( 0., 0. );
01234 (*pfCandidates_)[tmpi[ic]].setHoEnergy( 0., 0. );
01235 (*pfCandidates_)[tmpi[ic]].setPs1Energy( 0 );
01236 (*pfCandidates_)[tmpi[ic]].setPs2Energy( 0 );
01237 (*pfCandidates_)[tmpi[ic]].addElementInBlock( blockref, kTrack[ic] );
01238 }
01239
01240 }
01241
01242
01243 for (unsigned ic=0; ic<tmpi.size();++ic) {
01244 const PFCandidate& pfc = (*pfCandidates_)[tmpi[ic]];
01245 const PFCandidate::ElementsInBlocks& eleInBlocks = pfc.elementsInBlocks();
01246 if ( eleInBlocks.size() == 0 ) {
01247 if ( debug_ )std::cout << "Single track / Fill element in block! " << std::endl;
01248 (*pfCandidates_)[tmpi[ic]].addElementInBlock( blockref, kTrack[ic] );
01249 }
01250 }
01251
01252 }
01253
01254
01255
01256
01257 for(IE ie = hcalElems.begin(); ie != hcalElems.end(); ++ie ) {
01258
01259 unsigned index = ie->second;
01260
01261 PFBlockElement::Type type = elements[index].type();
01262
01263 if(debug_) {
01264 double dist = block.dist(iTrack,index,linkData,reco::PFBlock::LINKTEST_ALL);
01265 cout<<"\telement "<<elements[index]<<" linked with distance "<< dist <<endl;
01266 }
01267
01268 assert( type == PFBlockElement::HCAL );
01269
01270
01271
01272 if( !hcalFound ) {
01273 if(debug_)
01274 cout<<"\t\tclosest hcal cluster, doing nothing"<<endl;
01275
01276 hcalFound = true;
01277
01278
01279
01280 }
01281 else {
01282
01283 if(debug_)
01284 cout<<"\t\tsecondary hcal cluster. unlinking"<<endl;
01285 block.setLink( iTrack, index, -1., linkData,
01286 PFBlock::LINKTEST_RECHIT );
01287 }
01288 }
01289 }
01290
01291
01292
01293
01294 if( !(hfEmIs.empty() && hfHadIs.empty() ) ) {
01295
01296
01297 assert( hfEmIs.size() + hfHadIs.size() == elements.size() );
01298
01299 if( elements.size() == 1 ) {
01300
01301 reco::PFClusterRef clusterRef = elements[0].clusterRef();
01302 double energyHF = 0.;
01303 double uncalibratedenergyHF = 0.;
01304 unsigned tmpi = 0;
01305 switch( clusterRef->layer() ) {
01306 case PFLayer::HF_EM:
01307
01308 energyHF = clusterRef->energy();
01309 uncalibratedenergyHF = energyHF;
01310 if(thepfEnergyCalibrationHF_->getcalibHF_use()==true){
01311 energyHF = thepfEnergyCalibrationHF_->energyEm(uncalibratedenergyHF,
01312 clusterRef->positionREP().Eta(),
01313 clusterRef->positionREP().Phi());
01314 }
01315 tmpi = reconstructCluster( *clusterRef, energyHF );
01316 (*pfCandidates_)[tmpi].setEcalEnergy( uncalibratedenergyHF, energyHF );
01317 (*pfCandidates_)[tmpi].setHcalEnergy( 0., 0.);
01318 (*pfCandidates_)[tmpi].setHoEnergy( 0., 0.);
01319 (*pfCandidates_)[tmpi].setPs1Energy( 0. );
01320 (*pfCandidates_)[tmpi].setPs2Energy( 0. );
01321 (*pfCandidates_)[tmpi].addElementInBlock( blockref, hfEmIs[0] );
01322
01323 break;
01324 case PFLayer::HF_HAD:
01325
01326 energyHF = clusterRef->energy();
01327 uncalibratedenergyHF = energyHF;
01328 if(thepfEnergyCalibrationHF_->getcalibHF_use()==true){
01329 energyHF = thepfEnergyCalibrationHF_->energyHad(uncalibratedenergyHF,
01330 clusterRef->positionREP().Eta(),
01331 clusterRef->positionREP().Phi());
01332 }
01333 tmpi = reconstructCluster( *clusterRef, energyHF );
01334 (*pfCandidates_)[tmpi].setHcalEnergy( uncalibratedenergyHF, energyHF );
01335 (*pfCandidates_)[tmpi].setEcalEnergy( 0., 0.);
01336 (*pfCandidates_)[tmpi].setHoEnergy( 0., 0.);
01337 (*pfCandidates_)[tmpi].setPs1Energy( 0. );
01338 (*pfCandidates_)[tmpi].setPs2Energy( 0. );
01339 (*pfCandidates_)[tmpi].addElementInBlock( blockref, hfHadIs[0] );
01340
01341 break;
01342 default:
01343 assert(0);
01344 }
01345 }
01346 else if( elements.size() == 2 ) {
01347
01348 reco::PFClusterRef c0 = elements[0].clusterRef();
01349 reco::PFClusterRef c1 = elements[1].clusterRef();
01350
01351 reco::PFClusterRef cem = c1;
01352 reco::PFClusterRef chad = c0;
01353
01354 if( c0->layer()== PFLayer::HF_EM ) {
01355 if ( c1->layer()== PFLayer::HF_HAD ) {
01356 cem = c0; chad = c1;
01357 } else {
01358 assert(0);
01359 }
01360
01361 double energyHfEm = cem->energy();
01362 double energyHfHad = chad->energy();
01363 double uncalibratedenergyHFEm = energyHfEm;
01364 double uncalibratedenergyHFHad = energyHfHad;
01365 if(thepfEnergyCalibrationHF_->getcalibHF_use()==true){
01366
01367 energyHfEm = thepfEnergyCalibrationHF_->energyEmHad(uncalibratedenergyHFEm,
01368 0.0,
01369 c0->positionREP().Eta(),
01370 c0->positionREP().Phi());
01371 energyHfHad = thepfEnergyCalibrationHF_->energyEmHad(0.0,
01372 uncalibratedenergyHFHad,
01373 c1->positionREP().Eta(),
01374 c1->positionREP().Phi());
01375 }
01376 unsigned tmpi = reconstructCluster( *chad, energyHfEm+energyHfHad );
01377 (*pfCandidates_)[tmpi].setEcalEnergy( uncalibratedenergyHFEm, energyHfEm );
01378 (*pfCandidates_)[tmpi].setHcalEnergy( uncalibratedenergyHFHad, energyHfHad);
01379 (*pfCandidates_)[tmpi].setHoEnergy( 0., 0.);
01380 (*pfCandidates_)[tmpi].setPs1Energy( 0. );
01381 (*pfCandidates_)[tmpi].setPs2Energy( 0. );
01382 (*pfCandidates_)[tmpi].addElementInBlock( blockref, hfEmIs[0] );
01383 (*pfCandidates_)[tmpi].addElementInBlock( blockref, hfHadIs[0] );
01384
01385
01386 }
01387 else {
01388 cerr<<"Warning: 2 elements, but not 1 HFEM and 1 HFHAD"<<endl;
01389 cerr<<block<<endl;
01390
01391
01392 }
01393 }
01394 else {
01395
01396
01397 cerr<<"Warning: HF, but n elem different from 1 or 2"<<endl;
01398 cerr<<block<<endl;
01399
01400
01401 }
01402 }
01403
01404
01405
01406 if(debug_) {
01407 cout<<endl;
01408 cout<<endl<<"--------------- loop hcal ---------------------"<<endl;
01409 }
01410
01411
01412
01413
01414
01415
01416
01417 for(unsigned i=0; i<hcalIs.size(); i++) {
01418
01419 unsigned iHcal= hcalIs[i];
01420 PFBlockElement::Type type = elements[iHcal].type();
01421
01422 assert( type == PFBlockElement::HCAL );
01423
01424 if(debug_) cout<<endl<<elements[iHcal]<<endl;
01425
01426
01427
01428
01429
01430 std::multimap<double, unsigned> sortedTracks;
01431 block.associatedElements( iHcal, linkData,
01432 sortedTracks,
01433 reco::PFBlockElement::TRACK,
01434 reco::PFBlock::LINKTEST_ALL );
01435
01436 std::multimap< unsigned, std::pair<double, unsigned> > associatedEcals;
01437
01438 std::map< unsigned, std::pair<double, double> > associatedPSs;
01439
01440 std::multimap<double, std::pair<unsigned,bool> > associatedTracks;
01441
01442
01443 std::multimap<double,std::pair<unsigned,math::XYZVector> > ecalSatellites;
01444 std::pair<unsigned,math::XYZVector> fakeSatellite = make_pair(iHcal,math::XYZVector(0.,0.,0.));
01445 ecalSatellites.insert( make_pair(-1., fakeSatellite) );
01446
01447 std::multimap< unsigned, std::pair<double, unsigned> > associatedHOs;
01448
01449 PFClusterRef hclusterref = elements[iHcal].clusterRef();
01450 assert(!hclusterref.isNull() );
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460 if( sortedTracks.empty() ) {
01461 if(debug_)
01462 cout<<"\tno associated tracks, keep for later"<<endl;
01463 continue;
01464 }
01465
01466
01467 active[iHcal] = false;
01468
01469
01470
01471
01472
01473
01474
01475 if(debug_) cout<<"\t"<<sortedTracks.size()<<" associated tracks:"<<endl;
01476
01477 double totalChargedMomentum = 0;
01478 double sumpError2 = 0.;
01479 double totalHO = 0.;
01480 double totalEcal = 0.;
01481 double totalHcal = hclusterref->energy();
01482 vector<double> hcalP;
01483 vector<double> hcalDP;
01484 vector<unsigned> tkIs;
01485 double maxDPovP = -9999.;
01486
01487
01488 vector< unsigned > chargedHadronsIndices;
01489 vector< unsigned > chargedHadronsInBlock;
01490 double mergedNeutralHadronEnergy = 0;
01491 double mergedPhotonEnergy = 0;
01492 double muonHCALEnergy = 0.;
01493 double muonECALEnergy = 0.;
01494 double muonHCALError = 0.;
01495 double muonECALError = 0.;
01496 unsigned nMuons = 0;
01497
01498
01499 math::XYZVector photonAtECAL(0.,0.,0.);
01500 math::XYZVector hadronDirection(hclusterref->position().X(),
01501 hclusterref->position().Y(),
01502 hclusterref->position().Z());
01503 hadronDirection = hadronDirection.Unit();
01504 math::XYZVector hadronAtECAL = totalHcal * hadronDirection;
01505
01506
01507 for(IE ie = sortedTracks.begin(); ie != sortedTracks.end(); ++ie ) {
01508
01509 unsigned iTrack = ie->second;
01510
01511
01512 if ( !active[iTrack] ) continue;
01513
01514 PFBlockElement::Type type = elements[iTrack].type();
01515 assert( type == reco::PFBlockElement::TRACK );
01516
01517 reco::TrackRef trackRef = elements[iTrack].trackRef();
01518 assert( !trackRef.isNull() );
01519
01520
01521 const math::XYZPointF& chargedPosition =
01522 dynamic_cast<const reco::PFBlockElementTrack*>(&elements[iTrack])->positionAtECALEntrance();
01523 math::XYZVector chargedDirection(chargedPosition.X(),chargedPosition.Y(),chargedPosition.Z());
01524 chargedDirection = chargedDirection.Unit();
01525
01526
01527 std::multimap<double, unsigned> sortedEcals;
01528 block.associatedElements( iTrack, linkData,
01529 sortedEcals,
01530 reco::PFBlockElement::ECAL,
01531 reco::PFBlock::LINKTEST_ALL );
01532
01533 if(debug_) cout<<"\t\t\tnumber of Ecal elements linked to this track: "
01534 <<sortedEcals.size()<<endl;
01535
01536
01537 std::multimap<double, unsigned> sortedHOs;
01538 if (useHO_) {
01539 block.associatedElements( iTrack, linkData,
01540 sortedHOs,
01541 reco::PFBlockElement::HO,
01542 reco::PFBlock::LINKTEST_ALL );
01543
01544 }
01545 if(debug_)
01546 cout<<"PFAlgo : number of HO elements linked to this track: "
01547 <<sortedHOs.size()<<endl;
01548
01549
01550 reco::MuonRef muonRef = elements[iTrack].muonRef();
01551 bool thisIsAMuon = PFMuonAlgo::isMuon(elements[iTrack]);
01552 bool thisIsAnIsolatedMuon = PFMuonAlgo::isIsolatedMuon(elements[iTrack]);
01553 bool thisIsALooseMuon = false;
01554
01555 if(!thisIsAMuon ) {
01556 thisIsALooseMuon = PFMuonAlgo::isLooseMuon(elements[iTrack]);
01557 }
01558 if ( thisIsAMuon ) {
01559 if ( debug_ ) {
01560 std::cout << "\t\tThis track is identified as a muon - remove it from the stack" << std::endl;
01561 std::cout << "\t\t" << elements[iTrack] << std::endl;
01562 }
01563
01564
01565 unsigned tmpi = reconstructTrack( elements[iTrack] );
01566 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iTrack );
01567 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iHcal );
01568 double muonHcal = std::min(muonHCAL_[0]+muonHCAL_[1],totalHcal);
01569
01570
01571
01572
01573 bool letMuonEatCaloEnergy = false;
01574
01575 if(thisIsAnIsolatedMuon){
01576
01577 double totalCaloEnergy = totalHcal / 1.30;
01578 unsigned iEcal = 0;
01579 if( !sortedEcals.empty() ) {
01580 iEcal = sortedEcals.begin()->second;
01581 PFClusterRef eclusterref = elements[iEcal].clusterRef();
01582 totalCaloEnergy += eclusterref->energy();
01583 }
01584
01585 if (useHO_) {
01586
01587 unsigned iHO = 0;
01588 if( !sortedHOs.empty() ) {
01589 iHO = sortedHOs.begin()->second;
01590 PFClusterRef eclusterref = elements[iHO].clusterRef();
01591 totalCaloEnergy += eclusterref->energy() / 1.30;
01592 }
01593 }
01594
01595
01596
01597 if( (pfCandidates_->back()).p() > totalCaloEnergy ) letMuonEatCaloEnergy = true;
01598 }
01599
01600 if(letMuonEatCaloEnergy) muonHcal = totalHcal;
01601 double muonEcal =0.;
01602 unsigned iEcal = 0;
01603 if( !sortedEcals.empty() ) {
01604 iEcal = sortedEcals.begin()->second;
01605 PFClusterRef eclusterref = elements[iEcal].clusterRef();
01606 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iEcal);
01607 muonEcal = std::min(muonECAL_[0]+muonECAL_[1],eclusterref->energy());
01608 if(letMuonEatCaloEnergy) muonEcal = eclusterref->energy();
01609
01610 if ( eclusterref->energy() - muonEcal < 0.2 ) active[iEcal] = false;
01611 (*pfCandidates_)[tmpi].setEcalEnergy(eclusterref->energy(), muonEcal);
01612 }
01613 unsigned iHO = 0;
01614 double muonHO =0.;
01615 if (useHO_) {
01616 if( !sortedHOs.empty() ) {
01617 iHO = sortedHOs.begin()->second;
01618 PFClusterRef hoclusterref = elements[iHO].clusterRef();
01619 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iHO);
01620 muonHO = std::min(muonHO_[0]+muonHO_[1],hoclusterref->energy());
01621 if(letMuonEatCaloEnergy) muonHO = hoclusterref->energy();
01622
01623 if ( hoclusterref->energy() - muonHO < 0.2 ) active[iHO] = false;
01624 (*pfCandidates_)[tmpi].setHcalEnergy(totalHcal, muonHcal);
01625 (*pfCandidates_)[tmpi].setHoEnergy(hoclusterref->energy(), muonHO);
01626 }
01627 } else {
01628 (*pfCandidates_)[tmpi].setHcalEnergy(totalHcal, muonHcal);
01629 }
01630
01631 if(letMuonEatCaloEnergy){
01632 muonHCALEnergy += totalHcal;
01633 if (useHO_) muonHCALEnergy +=muonHO;
01634 muonHCALError += 0.;
01635 muonECALEnergy += muonEcal;
01636 muonECALError += 0.;
01637 photonAtECAL -= muonEcal*chargedDirection;
01638 hadronAtECAL -= totalHcal*chargedDirection;
01639 if ( !sortedEcals.empty() ) active[iEcal] = false;
01640 active[iHcal] = false;
01641 if (useHO_ && !sortedHOs.empty() ) active[iHO] = false;
01642 }
01643 else{
01644
01645 muonHCALEnergy += muonHCAL_[0];
01646 muonHCALError += muonHCAL_[1]*muonHCAL_[1];
01647 if ( muonHO > 0. ) {
01648 muonHCALEnergy += muonHO_[0];
01649 muonHCALError += muonHO_[1]*muonHO_[1];
01650 }
01651 muonECALEnergy += muonECAL_[0];
01652 muonECALError += muonECAL_[1]*muonECAL_[1];
01653
01654 photonAtECAL -= muonECAL_[0]*chargedDirection;
01655 hadronAtECAL -= muonHCAL_[0]*chargedDirection;
01656 }
01657
01658
01659 active[iTrack] = false;
01660
01661 continue;
01662 }
01663
01664
01665
01666 if(debug_) cout<<"\t\t"<<elements[iTrack]<<endl;
01667
01668
01669 double trackMomentum = trackRef->p();
01670 totalChargedMomentum += trackMomentum;
01671
01672
01673
01674 if ( thisIsALooseMuon && !thisIsAMuon ) nMuons += 1;
01675
01676
01677
01678
01679 double Dpt = trackRef->ptError();
01680 double blowError = 1.;
01681 switch (trackRef->algo()) {
01682 case TrackBase::ctf:
01683 case TrackBase::iter0:
01684 case TrackBase::iter1:
01685 case TrackBase::iter2:
01686 case TrackBase::iter3:
01687 case TrackBase::iter4:
01688 blowError = 1.;
01689 break;
01690 case TrackBase::iter5:
01691 blowError = factors45_[0];
01692 break;
01693 case TrackBase::iter6:
01694 blowError = factors45_[1];
01695 break;
01696 default:
01697 blowError = 1E9;
01698 break;
01699 }
01700
01701 bool isPrimaryOrSecondary = isFromSecInt(elements[iTrack], "all");
01702
01703 if ( isPrimaryOrSecondary ) blowError = 1.;
01704
01705 std::pair<unsigned,bool> tkmuon = make_pair(iTrack,thisIsALooseMuon);
01706 associatedTracks.insert( make_pair(-Dpt*blowError, tkmuon) );
01707
01708
01709 double Dp = trackRef->qoverpError()*trackMomentum*trackMomentum;
01710 sumpError2 += Dp*Dp;
01711
01712 bool connectedToEcal = false;
01713 if( !sortedEcals.empty() )
01714 {
01715
01716
01717 for ( IE iec=sortedEcals.begin();
01718 iec!=sortedEcals.end(); ++iec ) {
01719
01720 unsigned iEcal = iec->second;
01721 double dist = iec->first;
01722
01723
01724 if( !active[iEcal] ) {
01725 if(debug_) cout<<"\t\tcluster locked"<<endl;
01726 continue;
01727 }
01728
01729
01730 PFBlockElement::Type type = elements[ iEcal ].type();
01731 assert( type == PFBlockElement::ECAL );
01732 PFClusterRef eclusterref = elements[iEcal].clusterRef();
01733 assert(!eclusterref.isNull() );
01734
01735
01736 std::multimap<double, unsigned> sortedTracksEcal;
01737 block.associatedElements( iEcal, linkData,
01738 sortedTracksEcal,
01739 reco::PFBlockElement::TRACK,
01740 reco::PFBlock::LINKTEST_ALL );
01741 unsigned jTrack = sortedTracksEcal.begin()->second;
01742 if ( jTrack != iTrack ) continue;
01743
01744
01745
01746 double distEcal = block.dist(jTrack,iEcal,linkData,
01747 reco::PFBlock::LINKTEST_ALL);
01748
01749
01750
01751
01752
01753
01754 vector<double> ps1Ene(1,static_cast<double>(0.));
01755 associatePSClusters(iEcal, reco::PFBlockElement::PS1,
01756 block, elements, linkData, active,
01757 ps1Ene);
01758 vector<double> ps2Ene(1,static_cast<double>(0.));
01759 associatePSClusters(iEcal, reco::PFBlockElement::PS2,
01760 block, elements, linkData, active,
01761 ps2Ene);
01762 std::pair<double,double> psEnes = make_pair(ps1Ene[0],
01763 ps2Ene[0]);
01764 associatedPSs.insert(make_pair(iEcal,psEnes));
01765
01766
01767 bool crackCorrection = false;
01768 float ecalEnergyCalibrated = calibration_->energyEm(*eclusterref,ps1Ene,ps2Ene,crackCorrection);
01769 math::XYZVector photonDirection(eclusterref->position().X(),
01770 eclusterref->position().Y(),
01771 eclusterref->position().Z());
01772 photonDirection = photonDirection.Unit();
01773
01774 if ( !connectedToEcal ) {
01775
01776 if(debug_) cout<<"\t\t\tclosest: "
01777 <<elements[iEcal]<<endl;
01778
01779 connectedToEcal = true;
01780
01781
01782
01783 std::pair<unsigned,math::XYZVector> satellite =
01784 make_pair(iEcal,ecalEnergyCalibrated*photonDirection);
01785 ecalSatellites.insert( make_pair(-1., satellite) );
01786
01787 } else {
01788
01789 std::pair<unsigned,math::XYZVector> satellite =
01790 make_pair(iEcal,ecalEnergyCalibrated*photonDirection);
01791 ecalSatellites.insert( make_pair(dist, satellite) );
01792
01793 }
01794
01795 std::pair<double, unsigned> associatedEcal
01796 = make_pair( distEcal, iEcal );
01797 associatedEcals.insert( make_pair(iTrack, associatedEcal) );
01798
01799 }
01800 }
01801
01802 if( useHO_ && !sortedHOs.empty() )
01803 {
01804
01805
01806 for ( IE ieho=sortedHOs.begin(); ieho!=sortedHOs.end(); ++ieho ) {
01807
01808 unsigned iHO = ieho->second;
01809 double distHO = ieho->first;
01810
01811
01812 if( !active[iHO] ) {
01813 if(debug_) cout<<"\t\tcluster locked"<<endl;
01814 continue;
01815 }
01816
01817
01818 PFBlockElement::Type type = elements[ iHO ].type();
01819 assert( type == PFBlockElement::HO );
01820 PFClusterRef hoclusterref = elements[iHO].clusterRef();
01821 assert(!hoclusterref.isNull() );
01822
01823
01824 std::multimap<double, unsigned> sortedTracksHO;
01825 block.associatedElements( iHO, linkData,
01826 sortedTracksHO,
01827 reco::PFBlockElement::TRACK,
01828 reco::PFBlock::LINKTEST_ALL );
01829 unsigned jTrack = sortedTracksHO.begin()->second;
01830 if ( jTrack != iTrack ) continue;
01831
01832
01833
01834
01835
01836
01837
01838 totalHO += hoclusterref->energy();
01839 active[iHO] = false;
01840
01841 std::pair<double, unsigned> associatedHO
01842 = make_pair( distHO, iHO );
01843 associatedHOs.insert( make_pair(iTrack, associatedHO) );
01844
01845 }
01846 }
01847
01848
01849 }
01850
01851
01852 totalHcal += totalHO;
01853
01854
01855
01856 double caloEnergy = 0.;
01857 double slopeEcal = 1.0;
01858 double calibEcal = 0.;
01859 double calibHcal = 0.;
01860 hadronDirection = hadronAtECAL.Unit();
01861
01862
01863 double Caloresolution = neutralHadronEnergyResolution( totalChargedMomentum, hclusterref->positionREP().Eta());
01864 Caloresolution *= totalChargedMomentum;
01865
01866 Caloresolution = std::sqrt(Caloresolution*Caloresolution + muonHCALError + muonECALError);
01867 totalEcal -= std::min(totalEcal,muonECALEnergy);
01868 totalHcal -= std::min(totalHcal,muonHCALEnergy);
01869 if ( totalEcal < 1E-9 ) photonAtECAL = math::XYZVector(0.,0.,0.);
01870 if ( totalHcal < 1E-9 ) hadronAtECAL = math::XYZVector(0.,0.,0.);
01871
01872
01873
01874
01875
01876 for ( IS is = ecalSatellites.begin(); is != ecalSatellites.end(); ++is ) {
01877
01878
01879 double previousCalibEcal = calibEcal;
01880 double previousCalibHcal = calibHcal;
01881 double previousCaloEnergy = caloEnergy;
01882 double previousSlopeEcal = slopeEcal;
01883 math::XYZVector previousHadronAtECAL = hadronAtECAL;
01884
01885 totalEcal += sqrt(is->second.second.Mag2());
01886 photonAtECAL += is->second.second;
01887 calibEcal = std::max(0.,totalEcal);
01888 calibHcal = std::max(0.,totalHcal);
01889 hadronAtECAL = calibHcal * hadronDirection;
01890
01891 calibration_->energyEmHad(totalChargedMomentum,calibEcal,calibHcal,
01892 hclusterref->positionREP().Eta(),
01893 hclusterref->positionREP().Phi());
01894 caloEnergy = calibEcal+calibHcal;
01895 if ( totalEcal > 0.) slopeEcal = calibEcal/totalEcal;
01896
01897 hadronAtECAL = calibHcal * hadronDirection;
01898
01899
01900
01901 if ( is->first < 0. || caloEnergy - totalChargedMomentum <= 0. ) {
01902 if(debug_) cout<<"\t\t\tactive, adding "<<is->second.second
01903 <<" to ECAL energy, and locking"<<endl;
01904 active[is->second.first] = false;
01905 continue;
01906 }
01907
01908
01909
01910 totalEcal -= sqrt(is->second.second.Mag2());
01911 photonAtECAL -= is->second.second;
01912 calibEcal = previousCalibEcal;
01913 calibHcal = previousCalibHcal;
01914 hadronAtECAL = previousHadronAtECAL;
01915 slopeEcal = previousSlopeEcal;
01916 caloEnergy = previousCaloEnergy;
01917
01918 break;
01919
01920 }
01921
01922
01923 assert(caloEnergy>=0);
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936 double TotalError = sqrt(sumpError2 + Caloresolution*Caloresolution);
01937
01938
01940 if ( totalChargedMomentum - caloEnergy > nSigmaTRACK_*Caloresolution ) {
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954 if ( nMuons > 0 ) {
01955 for ( IT it = associatedTracks.begin(); it != associatedTracks.end(); ++it ) {
01956 unsigned iTrack = it->second.first;
01957
01958 if ( !active[iTrack] ) continue;
01959
01960 if ( !it->second.second ) continue;
01961
01962 bool isTrack = elements[it->second.first].muonRef()->isTrackerMuon();
01963 double trackMomentum = elements[it->second.first].trackRef()->p();
01964
01965
01966 std::multimap<double, unsigned> sortedEcals;
01967 block.associatedElements( iTrack, linkData,
01968 sortedEcals,
01969 reco::PFBlockElement::ECAL,
01970 reco::PFBlock::LINKTEST_ALL );
01971 std::multimap<double, unsigned> sortedHOs;
01972 block.associatedElements( iTrack, linkData,
01973 sortedHOs,
01974 reco::PFBlockElement::HO,
01975 reco::PFBlock::LINKTEST_ALL );
01976
01977 unsigned tmpi = reconstructTrack( elements[iTrack] );
01978 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iTrack );
01979 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iHcal );
01980 double muonHcal = std::min(muonHCAL_[0]+muonHCAL_[1],totalHcal-totalHO);
01981 double muonHO = 0.;
01982 (*pfCandidates_)[tmpi].setHcalEnergy(totalHcal,muonHcal);
01983 if( !sortedEcals.empty() ) {
01984 unsigned iEcal = sortedEcals.begin()->second;
01985 PFClusterRef eclusterref = elements[iEcal].clusterRef();
01986 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iEcal);
01987 double muonEcal = std::min(muonECAL_[0]+muonECAL_[1],eclusterref->energy());
01988 (*pfCandidates_)[tmpi].setEcalEnergy(eclusterref->energy(),muonEcal);
01989 }
01990 if( useHO_ && !sortedHOs.empty() ) {
01991 unsigned iHO = sortedHOs.begin()->second;
01992 PFClusterRef hoclusterref = elements[iHO].clusterRef();
01993 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iHO);
01994 muonHO = std::min(muonHO_[0]+muonHO_[1],hoclusterref->energy());
01995 (*pfCandidates_)[tmpi].setHcalEnergy(totalHcal-totalHO,muonHcal);
01996 (*pfCandidates_)[tmpi].setHoEnergy(hoclusterref->energy(),muonHO);
01997 }
01998 reco::PFCandidate::ParticleType particleType = reco::PFCandidate::mu;
01999 (*pfCandidates_)[tmpi].setParticleType(particleType);
02000
02001 if(PFMuonAlgo::isGlobalLooseMuon(elements[it->second.first].muonRef())){
02002
02003 reco::TrackRef bestMuTrack = elements[it->second.first].muonRef()->muonBestTrack();
02004 if(!useBestMuonTrack_)
02005 bestMuTrack = elements[it->second.first].muonRef()->combinedMuon();
02006
02007 double muonMomentum = bestMuTrack->p();
02008 double muonPtError = bestMuTrack->ptError();
02009
02010 double staMomentum = elements[it->second.first].muonRef()->standAloneMuon()->p();
02011 double staPtError = elements[it->second.first].muonRef()->standAloneMuon()->ptError();
02012 double trackPtError = elements[it->second.first].trackRef()->ptError();
02013
02014
02015 double globalCorr = 1;
02016
02017
02018 if(!isTrack || muonPtError < trackPtError || staPtError < trackPtError){
02019 if(muonPtError < staPtError) globalCorr = muonMomentum/trackMomentum;
02020 else globalCorr = staMomentum/trackMomentum;
02021 }
02022 (*pfCandidates_)[tmpi].rescaleMomentum(globalCorr);
02023
02024 if (debug_){
02025 std::cout << "\tElement " << elements[iTrack] << std::endl
02026 << "PFAlgo: particle type set to muon (global, loose), pT = "<<elements[it->second.first].muonRef()->pt()<<std::endl;
02027 PFMuonAlgo::printMuonProperties(elements[it->second.first].muonRef());
02028 }
02029 }
02030 else{
02031 if (debug_){
02032 std::cout << "\tElement " << elements[iTrack] << std::endl
02033 << "PFAlgo: particle type set to muon (tracker, loose), pT = "<<elements[it->second.first].muonRef()->pt()<<std::endl;
02034 PFMuonAlgo::printMuonProperties(elements[it->second.first].muonRef());
02035 }
02036 }
02037
02038
02039 const math::XYZPointF& chargedPosition =
02040 dynamic_cast<const reco::PFBlockElementTrack*>(&elements[it->second.first])->positionAtECALEntrance();
02041 math::XYZVector chargedDirection(chargedPosition.X(), chargedPosition.Y(), chargedPosition.Z());
02042 chargedDirection = chargedDirection.Unit();
02043 totalChargedMomentum -= trackMomentum;
02044
02045 if ( totalEcal > 0. )
02046 calibEcal -= std::min(calibEcal,muonECAL_[0]*calibEcal/totalEcal);
02047 if ( totalHcal > 0. )
02048 calibHcal -= std::min(calibHcal,muonHCAL_[0]*calibHcal/totalHcal);
02049 totalEcal -= std::min(totalEcal,muonECAL_[0]);
02050 totalHcal -= std::min(totalHcal,muonHCAL_[0]);
02051 if ( totalEcal > muonECAL_[0] ) photonAtECAL -= muonECAL_[0] * chargedDirection;
02052 if ( totalHcal > muonHCAL_[0] ) hadronAtECAL -= muonHCAL_[0]*calibHcal/totalHcal * chargedDirection;
02053 caloEnergy = calibEcal+calibHcal;
02054 muonHCALEnergy += muonHCAL_[0];
02055 muonHCALError += muonHCAL_[1]*muonHCAL_[1];
02056 if ( muonHO > 0. ) {
02057 muonHCALEnergy += muonHO_[0];
02058 muonHCALError += muonHO_[1]*muonHO_[1];
02059 if ( totalHcal > 0. ) {
02060 calibHcal -= std::min(calibHcal,muonHO_[0]*calibHcal/totalHcal);
02061 totalHcal -= std::min(totalHcal,muonHO_[0]);
02062 }
02063 }
02064 muonECALEnergy += muonECAL_[0];
02065 muonECALError += muonECAL_[1]*muonECAL_[1];
02066 active[iTrack] = false;
02067
02068
02069
02070 }
02071
02072 Caloresolution = neutralHadronEnergyResolution( totalChargedMomentum, hclusterref->positionREP().Eta());
02073 Caloresolution *= totalChargedMomentum;
02074 Caloresolution = std::sqrt(Caloresolution*Caloresolution + muonHCALError + muonECALError);
02075 }
02076 }
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092 unsigned corrTrack = 10000000;
02093 double corrFact = 1.;
02094
02095 if (rejectTracks_Bad_ &&
02096 totalChargedMomentum - caloEnergy > nSigmaTRACK_*Caloresolution) {
02097
02098 for ( IT it = associatedTracks.begin(); it != associatedTracks.end(); ++it ) {
02099 unsigned iTrack = it->second.first;
02100
02101 if ( !active[iTrack] ) continue;
02102 const reco::TrackRef& trackref = elements[it->second.first].trackRef();
02103
02104 double dptRel = fabs(it->first)/trackref->pt()*100;
02105 bool isSecondary = isFromSecInt(elements[iTrack], "secondary");
02106 bool isPrimary = isFromSecInt(elements[iTrack], "primary");
02107
02108 if ( isSecondary && dptRel < dptRel_DispVtx_ ) continue;
02109
02110 if ( fabs(it->first) < ptError_ ) break;
02111
02112 double wouldBeTotalChargedMomentum =
02113 totalChargedMomentum - trackref->p();
02114
02115
02116
02117 if ( wouldBeTotalChargedMomentum > caloEnergy ) {
02118
02119 if (debug_ && isSecondary) {
02120 cout << "In bad track rejection step dptRel = " << dptRel << " dptRel_DispVtx_ = " << dptRel_DispVtx_ << endl;
02121 cout << "The calo energy would be still smaller even without this track but it is attached to a NI"<< endl;
02122 }
02123
02124
02125 if(isPrimary || (isSecondary && dptRel < dptRel_DispVtx_)) continue;
02126 active[iTrack] = false;
02127 totalChargedMomentum = wouldBeTotalChargedMomentum;
02128 if ( debug_ )
02129 std::cout << "\tElement " << elements[iTrack]
02130 << " rejected (Dpt = " << -it->first
02131 << " GeV/c, algo = " << trackref->algo() << ")" << std::endl;
02132
02133 } else {
02134 if(isPrimary) break;
02135 corrTrack = iTrack;
02136 corrFact = (caloEnergy - wouldBeTotalChargedMomentum)/elements[it->second.first].trackRef()->p();
02137 if ( trackref->p()*corrFact < 0.05 ) {
02138 corrFact = 0.;
02139 active[iTrack] = false;
02140 }
02141 totalChargedMomentum -= trackref->p()*(1.-corrFact);
02142 if ( debug_ )
02143 std::cout << "\tElement " << elements[iTrack]
02144 << " (Dpt = " << -it->first
02145 << " GeV/c, algo = " << trackref->algo()
02146 << ") rescaled by " << corrFact
02147 << " Now the total charged momentum is " << totalChargedMomentum << endl;
02148 break;
02149 }
02150 }
02151 }
02152
02153
02154 Caloresolution = neutralHadronEnergyResolution( totalChargedMomentum, hclusterref->positionREP().Eta());
02155 Caloresolution *= totalChargedMomentum;
02156 Caloresolution = std::sqrt(Caloresolution*Caloresolution + muonHCALError + muonECALError);
02157
02158
02159
02160
02161 if ( rejectTracks_Step45_ &&
02162 sortedTracks.size() > 1 &&
02163 totalChargedMomentum - caloEnergy > nSigmaTRACK_*Caloresolution ) {
02164 for ( IT it = associatedTracks.begin(); it != associatedTracks.end(); ++it ) {
02165 unsigned iTrack = it->second.first;
02166 reco::TrackRef trackref = elements[iTrack].trackRef();
02167 if ( !active[iTrack] ) continue;
02168
02169 double dptRel = fabs(it->first)/trackref->pt()*100;
02170 bool isPrimaryOrSecondary = isFromSecInt(elements[iTrack], "all");
02171
02172
02173
02174
02175 if (isPrimaryOrSecondary && dptRel < dptRel_DispVtx_) continue;
02176
02177 switch (trackref->algo()) {
02178 case TrackBase::ctf:
02179 case TrackBase::iter0:
02180 case TrackBase::iter1:
02181 case TrackBase::iter2:
02182 case TrackBase::iter3:
02183 case TrackBase::iter4:
02184 break;
02185 case TrackBase::iter5:
02186 case TrackBase::iter6:
02187 active[iTrack] = false;
02188 totalChargedMomentum -= trackref->p();
02189
02190 if ( debug_ )
02191 std::cout << "\tElement " << elements[iTrack]
02192 << " rejected (Dpt = " << -it->first
02193 << " GeV/c, algo = " << trackref->algo() << ")" << std::endl;
02194 break;
02195 default:
02196 break;
02197 }
02198 }
02199 }
02200
02201
02202 Caloresolution = neutralHadronEnergyResolution( totalChargedMomentum, hclusterref->positionREP().Eta());
02203 Caloresolution *= totalChargedMomentum;
02204 Caloresolution = std::sqrt(Caloresolution*Caloresolution + muonHCALError + muonECALError);
02205
02206
02207 sumpError2 = 0.;
02208 for ( IT it = associatedTracks.begin(); it != associatedTracks.end(); ++it ) {
02209 unsigned iTrack = it->second.first;
02210 if ( !active[iTrack] ) continue;
02211 reco::TrackRef trackRef = elements[iTrack].trackRef();
02212 double trackMomentum = trackRef->p();
02213 double Dp = trackRef->qoverpError()*trackMomentum*trackMomentum;
02214 unsigned tmpi = reconstructTrack( elements[iTrack] );
02215 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iTrack );
02216 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iHcal );
02217 std::pair<II,II> myEcals = associatedEcals.equal_range(iTrack);
02218 for (II ii=myEcals.first; ii!=myEcals.second; ++ii ) {
02219 unsigned iEcal = ii->second.second;
02220 if ( active[iEcal] ) continue;
02221 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iEcal );
02222 }
02223
02224 if (useHO_) {
02225 std::pair<II,II> myHOs = associatedHOs.equal_range(iTrack);
02226 for (II ii=myHOs.first; ii!=myHOs.second; ++ii ) {
02227 unsigned iHO = ii->second.second;
02228 if ( active[iHO] ) continue;
02229 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iHO );
02230 }
02231 }
02232
02233 if ( iTrack == corrTrack ) {
02234 (*pfCandidates_)[tmpi].rescaleMomentum(corrFact);
02235 trackMomentum *= corrFact;
02236 }
02237 chargedHadronsIndices.push_back( tmpi );
02238 chargedHadronsInBlock.push_back( iTrack );
02239 active[iTrack] = false;
02240 hcalP.push_back(trackMomentum);
02241 hcalDP.push_back(Dp);
02242 if (Dp/trackMomentum > maxDPovP) maxDPovP = Dp/trackMomentum;
02243 sumpError2 += Dp*Dp;
02244 }
02245
02246
02247 TotalError = sqrt(sumpError2 + Caloresolution*Caloresolution);
02248
02249 if ( debug_ ) {
02250 cout<<"\tCompare Calo Energy to total charged momentum "<<endl;
02251 cout<<"\t\tsum p = "<<totalChargedMomentum<<" +- "<<sqrt(sumpError2)<<endl;
02252 cout<<"\t\tsum ecal = "<<totalEcal<<endl;
02253 cout<<"\t\tsum hcal = "<<totalHcal<<endl;
02254 cout<<"\t\t => Calo Energy = "<<caloEnergy<<" +- "<<Caloresolution<<endl;
02255 cout<<"\t\t => Calo Energy- total charged momentum = "
02256 <<caloEnergy-totalChargedMomentum<<" +- "<<TotalError<<endl;
02257 cout<<endl;
02258 }
02259
02260
02261
02263 double nsigma = nSigmaHCAL(totalChargedMomentum,hclusterref->positionREP().Eta());
02264
02265 if ( abs(totalChargedMomentum-caloEnergy)<nsigma*TotalError ) {
02266
02267
02268
02269
02270 if(debug_) {
02271 cout<<"\t\tcase 1: COMPATIBLE "
02272 <<"|Calo Energy- total charged momentum| = "
02273 <<abs(caloEnergy-totalChargedMomentum)
02274 <<" < "<<nsigma<<" x "<<TotalError<<endl;
02275 if (maxDPovP < 0.1 )
02276 cout<<"\t\t\tmax DP/P = "<< maxDPovP
02277 <<" less than 0.1: do nothing "<<endl;
02278 else
02279 cout<<"\t\t\tmax DP/P = "<< maxDPovP
02280 <<" > 0.1: take weighted averages "<<endl;
02281 }
02282
02283
02284 if (maxDPovP > 0.1) {
02285
02286
02287
02288 int nrows = chargedHadronsIndices.size();
02289 TMatrixTSym<double> a (nrows);
02290 TVectorD b (nrows);
02291 TVectorD check(nrows);
02292 double sigma2E = Caloresolution*Caloresolution;
02293 for(int i=0; i<nrows; i++) {
02294 double sigma2i = hcalDP[i]*hcalDP[i];
02295 if (debug_){
02296 cout<<"\t\t\ttrack associated to hcal "<<i
02297 <<" P = "<<hcalP[i]<<" +- "
02298 <<hcalDP[i]<<endl;
02299 }
02300 a(i,i) = 1./sigma2i + 1./sigma2E;
02301 b(i) = hcalP[i]/sigma2i + caloEnergy/sigma2E;
02302 for(int j=0; j<nrows; j++) {
02303 if (i==j) continue;
02304 a(i,j) = 1./sigma2E;
02305 }
02306 }
02307
02308
02309
02310
02311
02312
02313
02314
02315 TDecompChol decomp(a);
02316 bool ok = false;
02317 TVectorD x = decomp.Solve(b, ok);
02318
02319
02320 if (ok) {
02321 for (int i=0; i<nrows; i++){
02322
02323 unsigned ich = chargedHadronsIndices[i];
02324 double rescaleFactor = x(i)/hcalP[i];
02325 (*pfCandidates_)[ich].rescaleMomentum( rescaleFactor );
02326
02327 if(debug_){
02328 cout<<"\t\t\told p "<<hcalP[i]
02329 <<" new p "<<x(i)
02330 <<" rescale "<<rescaleFactor<<endl;
02331 }
02332 }
02333 }
02334 else {
02335 cerr<<"not ok!"<<endl;
02336 assert(0);
02337 }
02338 }
02339 }
02340
02342 else if( caloEnergy > totalChargedMomentum ) {
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361 double eNeutralHadron = caloEnergy - totalChargedMomentum;
02362 double ePhoton = (caloEnergy - totalChargedMomentum) / slopeEcal;
02363
02364 if(debug_) {
02365 if(!sortedTracks.empty() ){
02366 cout<<"\t\tcase 2: NEUTRAL DETECTION "
02367 <<caloEnergy<<" > "<<nsigma<<"x"<<TotalError
02368 <<" + "<<totalChargedMomentum<<endl;
02369 cout<<"\t\tneutral activity detected: "<<endl
02370 <<"\t\t\t photon = "<<ePhoton<<endl
02371 <<"\t\t\tor neutral hadron = "<<eNeutralHadron<<endl;
02372
02373 cout<<"\t\tphoton or hadron ?"<<endl;}
02374
02375 if(sortedTracks.empty() )
02376 cout<<"\t\tno track -> hadron "<<endl;
02377 else
02378 cout<<"\t\t"<<sortedTracks.size()
02379 <<"tracks -> check if the excess is photonic or hadronic"<<endl;
02380 }
02381
02382
02383 double ratioMax = 0.;
02384 reco::PFClusterRef maxEcalRef;
02385 unsigned maxiEcal= 9999;
02386
02387
02388
02389 for(IE ie = sortedTracks.begin(); ie != sortedTracks.end(); ++ie ) {
02390
02391 unsigned iTrack = ie->second;
02392
02393 PFBlockElement::Type type = elements[iTrack].type();
02394 assert( type == reco::PFBlockElement::TRACK );
02395
02396 reco::TrackRef trackRef = elements[iTrack].trackRef();
02397 assert( !trackRef.isNull() );
02398
02399 II iae = associatedEcals.find(iTrack);
02400
02401 if( iae == associatedEcals.end() ) continue;
02402
02403
02404 unsigned iEcal = iae->second.second;
02405
02406 PFBlockElement::Type typeEcal = elements[iEcal].type();
02407 assert(typeEcal == reco::PFBlockElement::ECAL);
02408
02409 reco::PFClusterRef clusterRef = elements[iEcal].clusterRef();
02410 assert( !clusterRef.isNull() );
02411
02412 double pTrack = trackRef->p();
02413 double eECAL = clusterRef->energy();
02414 double eECALOverpTrack = eECAL / pTrack;
02415
02416 if ( eECALOverpTrack > ratioMax ) {
02417 ratioMax = eECALOverpTrack;
02418 maxEcalRef = clusterRef;
02419 maxiEcal = iEcal;
02420 }
02421
02422 }
02423
02424 std::vector<reco::PFClusterRef> pivotalClusterRef;
02425 std::vector<unsigned> iPivotal;
02426 std::vector<double> particleEnergy, ecalEnergy, hcalEnergy, rawecalEnergy, rawhcalEnergy;
02427 std::vector<math::XYZVector> particleDirection;
02428
02429
02430
02431 if ( ePhoton < totalEcal || eNeutralHadron-calibEcal < 1E-10 ) {
02432
02433 if ( !maxEcalRef.isNull() ) {
02434 particleEnergy.push_back(ePhoton);
02435 particleDirection.push_back(photonAtECAL);
02436 ecalEnergy.push_back(ePhoton);
02437 hcalEnergy.push_back(0.);
02438 rawecalEnergy.push_back(totalEcal);
02439 rawhcalEnergy.push_back(totalHcal);
02440 pivotalClusterRef.push_back(maxEcalRef);
02441 iPivotal.push_back(maxiEcal);
02442
02443 mergedPhotonEnergy = ePhoton;
02444 }
02445
02446 } else {
02447
02448
02449 if ( !maxEcalRef.isNull() ) {
02450 pivotalClusterRef.push_back(maxEcalRef);
02451 particleEnergy.push_back(totalEcal);
02452 particleDirection.push_back(photonAtECAL);
02453 ecalEnergy.push_back(totalEcal);
02454 hcalEnergy.push_back(0.);
02455 rawecalEnergy.push_back(totalEcal);
02456 rawhcalEnergy.push_back(totalHcal);
02457 iPivotal.push_back(maxiEcal);
02458
02459 mergedPhotonEnergy = totalEcal;
02460 }
02461
02462
02463 mergedNeutralHadronEnergy = eNeutralHadron-calibEcal;
02464 if ( mergedNeutralHadronEnergy > 1.0 ) {
02465 pivotalClusterRef.push_back(hclusterref);
02466 particleEnergy.push_back(mergedNeutralHadronEnergy);
02467 particleDirection.push_back(hadronAtECAL);
02468 ecalEnergy.push_back(0.);
02469 hcalEnergy.push_back(mergedNeutralHadronEnergy);
02470 rawecalEnergy.push_back(totalEcal);
02471 rawhcalEnergy.push_back(totalHcal);
02472 iPivotal.push_back(iHcal);
02473 }
02474
02475 }
02476
02477
02478
02479
02480
02481
02482 for ( unsigned iPivot=0; iPivot<iPivotal.size(); ++iPivot ) {
02483
02484 if ( particleEnergy[iPivot] < 0. )
02485 std::cout << "ALARM = Negative energy ! "
02486 << particleEnergy[iPivot] << std::endl;
02487
02488 bool useDirection = true;
02489 unsigned tmpi = reconstructCluster( *pivotalClusterRef[iPivot],
02490 particleEnergy[iPivot],
02491 useDirection,
02492 particleDirection[iPivot].X(),
02493 particleDirection[iPivot].Y(),
02494 particleDirection[iPivot].Z());
02495
02496
02497 (*pfCandidates_)[tmpi].setEcalEnergy( rawecalEnergy[iPivot],ecalEnergy[iPivot] );
02498 if ( !useHO_ ) {
02499 (*pfCandidates_)[tmpi].setHcalEnergy( rawhcalEnergy[iPivot],hcalEnergy[iPivot] );
02500 (*pfCandidates_)[tmpi].setHoEnergy(0., 0.);
02501 } else {
02502 (*pfCandidates_)[tmpi].setHcalEnergy( rawhcalEnergy[iPivot]-totalHO,hcalEnergy[iPivot]*(1.-totalHO/rawhcalEnergy[iPivot]));
02503 (*pfCandidates_)[tmpi].setHoEnergy(totalHO, totalHO * hcalEnergy[iPivot]/rawhcalEnergy[iPivot]);
02504 }
02505 (*pfCandidates_)[tmpi].setPs1Energy( 0. );
02506 (*pfCandidates_)[tmpi].setPs2Energy( 0. );
02507 (*pfCandidates_)[tmpi].set_mva_nothing_gamma( -1. );
02508
02509
02510 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iHcal );
02511 for ( unsigned ich=0; ich<chargedHadronsInBlock.size(); ++ich) {
02512 unsigned iTrack = chargedHadronsInBlock[ich];
02513 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iTrack );
02514
02515 const math::XYZPointF& chargedPosition =
02516 dynamic_cast<const reco::PFBlockElementTrack*>(&elements[iTrack])->positionAtECALEntrance();
02517 (*pfCandidates_)[tmpi].setPositionAtECALEntrance(chargedPosition);
02518
02519 std::pair<II,II> myEcals = associatedEcals.equal_range(iTrack);
02520 for (II ii=myEcals.first; ii!=myEcals.second; ++ii ) {
02521 unsigned iEcal = ii->second.second;
02522 if ( active[iEcal] ) continue;
02523 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iEcal );
02524 }
02525 }
02526
02527 }
02528
02529 }
02530
02531
02532
02533
02534
02535 double totalHcalEnergyCalibrated = calibHcal;
02536 double totalEcalEnergyCalibrated = calibEcal;
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551 totalHcalEnergyCalibrated -= mergedNeutralHadronEnergy;
02552
02553 totalEcalEnergyCalibrated -= mergedPhotonEnergy;
02554
02555
02556
02557
02558 double chargedHadronsTotalEnergy = 0;
02559 for( unsigned ich=0; ich<chargedHadronsIndices.size(); ++ich ) {
02560 unsigned index = chargedHadronsIndices[ich];
02561 reco::PFCandidate& chargedHadron = (*pfCandidates_)[index];
02562 chargedHadronsTotalEnergy += chargedHadron.energy();
02563 }
02564
02565 for( unsigned ich=0; ich<chargedHadronsIndices.size(); ++ich ) {
02566 unsigned index = chargedHadronsIndices[ich];
02567 reco::PFCandidate& chargedHadron = (*pfCandidates_)[index];
02568 float fraction = chargedHadron.energy()/chargedHadronsTotalEnergy;
02569
02570 if ( !useHO_ ) {
02571 chargedHadron.setHcalEnergy( fraction * totalHcal, fraction * totalHcalEnergyCalibrated );
02572 chargedHadron.setHoEnergy( 0., 0. );
02573 } else {
02574 chargedHadron.setHcalEnergy( fraction * (totalHcal-totalHO), fraction * totalHcalEnergyCalibrated * (1.-totalHO/totalHcal) );
02575 chargedHadron.setHoEnergy( fraction * totalHO, fraction * totalHO * totalHcalEnergyCalibrated / totalHcal );
02576 }
02577
02578 chargedHadron.setEcalEnergy( fraction * totalEcal, fraction * totalEcalEnergyCalibrated );
02579 }
02580
02581
02582 for ( IS is = ecalSatellites.begin(); is != ecalSatellites.end(); ++is ) {
02583
02584
02585 unsigned iEcal = is->second.first;
02586 if ( !active[iEcal] ) continue;
02587
02588
02589 PFBlockElement::Type type = elements[ iEcal ].type();
02590 assert( type == PFBlockElement::ECAL );
02591 PFClusterRef eclusterref = elements[iEcal].clusterRef();
02592 assert(!eclusterref.isNull() );
02593
02594
02595 active[iEcal] = false;
02596
02597
02598 std::multimap<double, unsigned> assTracks;
02599 block.associatedElements( iEcal, linkData,
02600 assTracks,
02601 reco::PFBlockElement::TRACK,
02602 reco::PFBlock::LINKTEST_ALL );
02603
02604
02605 unsigned tmpi = reconstructCluster( *eclusterref, sqrt(is->second.second.Mag2()) );
02606 (*pfCandidates_)[tmpi].setEcalEnergy( eclusterref->energy(),sqrt(is->second.second.Mag2()) );
02607 (*pfCandidates_)[tmpi].setHcalEnergy( 0., 0. );
02608 (*pfCandidates_)[tmpi].setHoEnergy( 0., 0. );
02609 (*pfCandidates_)[tmpi].setPs1Energy( associatedPSs[iEcal].first );
02610 (*pfCandidates_)[tmpi].setPs2Energy( associatedPSs[iEcal].second );
02611 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iEcal );
02612 (*pfCandidates_)[tmpi].addElementInBlock( blockref, sortedTracks.begin()->second) ;
02613 }
02614
02615
02616 }
02617
02618
02619
02620
02621
02622 if(debug_) {
02623 cout<<endl;
02624 if(debug_)
02625 cout<<endl
02626 <<"---- loop remaining hcal ------- "<<endl;
02627 }
02628
02629
02630
02631
02632 for(unsigned ihcluster=0; ihcluster<hcalIs.size(); ihcluster++) {
02633 unsigned iHcal = hcalIs[ihcluster];
02634
02635
02636 std::vector<unsigned> ecalRefs;
02637 std::vector<unsigned> hoRefs;
02638
02639 if(debug_)
02640 cout<<endl<<elements[iHcal]<<" ";
02641
02642
02643 if( !active[iHcal] ) {
02644 if(debug_)
02645 cout<<"not active"<<endl;
02646 continue;
02647 }
02648
02649
02650 std::multimap<double, unsigned> ecalElems;
02651 block.associatedElements( iHcal, linkData,
02652 ecalElems ,
02653 reco::PFBlockElement::ECAL,
02654 reco::PFBlock::LINKTEST_ALL );
02655
02656
02657 float totalEcal = 0.;
02658 float ecalMax = 0.;
02659 reco::PFClusterRef eClusterRef;
02660 for(IE ie = ecalElems.begin(); ie != ecalElems.end(); ++ie ) {
02661
02662 unsigned iEcal = ie->second;
02663 double dist = ie->first;
02664 PFBlockElement::Type type = elements[iEcal].type();
02665 assert( type == PFBlockElement::ECAL );
02666
02667
02668 if( !active[iEcal] ) continue;
02669
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689 std::multimap<double, unsigned> hcalElems;
02690 block.associatedElements( iEcal, linkData,
02691 hcalElems ,
02692 reco::PFBlockElement::HCAL,
02693 reco::PFBlock::LINKTEST_ALL );
02694
02695 bool isClosest = true;
02696 for(IE ih = hcalElems.begin(); ih != hcalElems.end(); ++ih ) {
02697
02698 unsigned jHcal = ih->second;
02699 double distH = ih->first;
02700
02701 if ( !active[jHcal] ) continue;
02702
02703 if ( distH < dist ) {
02704 isClosest = false;
02705 break;
02706 }
02707
02708 }
02709
02710 if (!isClosest) continue;
02711
02712
02713 if(debug_) {
02714 cout<<"\telement "<<elements[iEcal]<<" linked with dist "<< dist<<endl;
02715 cout<<"Added to HCAL cluster to form a neutral hadron"<<endl;
02716 }
02717
02718 reco::PFClusterRef eclusterRef = elements[iEcal].clusterRef();
02719 assert( !eclusterRef.isNull() );
02720
02721
02722 vector<double> ps1Ene(1,static_cast<double>(0.));
02723 associatePSClusters(iEcal, reco::PFBlockElement::PS1, block, elements, linkData, active, ps1Ene);
02724 vector<double> ps2Ene(1,static_cast<double>(0.));
02725 associatePSClusters(iEcal, reco::PFBlockElement::PS2, block, elements, linkData, active, ps2Ene);
02726 bool crackCorrection = false;
02727 double ecalEnergy = calibration_->energyEm(*eclusterRef,ps1Ene,ps2Ene,crackCorrection);
02728
02729
02730
02731 totalEcal += ecalEnergy;
02732 if ( ecalEnergy > ecalMax ) {
02733 ecalMax = ecalEnergy;
02734 eClusterRef = eclusterRef;
02735 }
02736
02737 ecalRefs.push_back(iEcal);
02738 active[iEcal] = false;
02739
02740
02741 }
02742
02743
02744 double totalHO = 0.;
02745 double hoMax = 0.;
02746
02747 if (useHO_) {
02748 std::multimap<double, unsigned> hoElems;
02749 block.associatedElements( iHcal, linkData,
02750 hoElems ,
02751 reco::PFBlockElement::HO,
02752 reco::PFBlock::LINKTEST_ALL );
02753
02754
02755
02756
02757
02758 reco::PFClusterRef hoClusterRef;
02759 for(IE ie = hoElems.begin(); ie != hoElems.end(); ++ie ) {
02760
02761 unsigned iHO = ie->second;
02762 double dist = ie->first;
02763 PFBlockElement::Type type = elements[iHO].type();
02764 assert( type == PFBlockElement::HO );
02765
02766
02767 if( !active[iHO] ) continue;
02768
02769
02770
02771
02772
02773 std::multimap<double, unsigned> hcalElems;
02774 block.associatedElements( iHO, linkData,
02775 hcalElems ,
02776 reco::PFBlockElement::HCAL,
02777 reco::PFBlock::LINKTEST_ALL );
02778
02779 bool isClosest = true;
02780 for(IE ih = hcalElems.begin(); ih != hcalElems.end(); ++ih ) {
02781
02782 unsigned jHcal = ih->second;
02783 double distH = ih->first;
02784
02785 if ( !active[jHcal] ) continue;
02786
02787 if ( distH < dist ) {
02788 isClosest = false;
02789 break;
02790 }
02791
02792 }
02793
02794 if (!isClosest) continue;
02795
02796 if(debug_ && useHO_) {
02797 cout<<"\telement "<<elements[iHO]<<" linked with dist "<< dist<<endl;
02798 cout<<"Added to HCAL cluster to form a neutral hadron"<<endl;
02799 }
02800
02801 reco::PFClusterRef hoclusterRef = elements[iHO].clusterRef();
02802 assert( !hoclusterRef.isNull() );
02803
02804 double hoEnergy = hoclusterRef->energy();
02805
02806 totalHO += hoEnergy;
02807 if ( hoEnergy > hoMax ) {
02808 hoMax = hoEnergy;
02809 hoClusterRef = hoclusterRef;
02810
02811 }
02812
02813 hoRefs.push_back(iHO);
02814 active[iHO] = false;
02815
02816 }
02817 }
02818
02819 PFClusterRef hclusterRef
02820 = elements[iHcal].clusterRef();
02821 assert( !hclusterRef.isNull() );
02822
02823
02824 double totalHcal = hclusterRef->energy();
02825
02826 if ( useHO_ ) totalHcal += totalHO;
02827
02828
02829
02830
02831
02832
02833
02834 double calibEcal = totalEcal > 0. ? totalEcal : 0.;
02835 double calibHcal = std::max(0.,totalHcal);
02836 if ( hclusterRef->layer() == PFLayer::HF_HAD ||
02837 hclusterRef->layer() == PFLayer::HF_EM ) {
02838
02839 calibEcal = totalEcal;
02840 } else {
02841 calibration_->energyEmHad(-1.,calibEcal,calibHcal,
02842 hclusterRef->positionREP().Eta(),
02843 hclusterRef->positionREP().Phi());
02844
02845 }
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855 unsigned tmpi = reconstructCluster( *hclusterRef,
02856 calibEcal+calibHcal );
02857
02858
02859 (*pfCandidates_)[tmpi].setEcalEnergy( totalEcal, calibEcal );
02860 if ( !useHO_ ) {
02861 (*pfCandidates_)[tmpi].setHcalEnergy( totalHcal, calibHcal );
02862 (*pfCandidates_)[tmpi].setHoEnergy(0.,0.);
02863 } else {
02864 (*pfCandidates_)[tmpi].setHcalEnergy( totalHcal-totalHO, calibHcal*(1.-totalHO/totalHcal));
02865 (*pfCandidates_)[tmpi].setHoEnergy(totalHO,totalHO*calibHcal/totalHcal);
02866 }
02867 (*pfCandidates_)[tmpi].setPs1Energy( 0. );
02868 (*pfCandidates_)[tmpi].setPs2Energy( 0. );
02869 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iHcal );
02870 for (unsigned iec=0; iec<ecalRefs.size(); ++iec)
02871 (*pfCandidates_)[tmpi].addElementInBlock( blockref, ecalRefs[iec] );
02872 for (unsigned iho=0; iho<hoRefs.size(); ++iho)
02873 (*pfCandidates_)[tmpi].addElementInBlock( blockref, hoRefs[iho] );
02874
02875 }
02876
02877
02878
02879
02880 if(debug_) {
02881 cout<<endl;
02882 if(debug_) cout<<endl<<"---- loop ecal------- "<<endl;
02883 }
02884
02885
02886
02887 for(unsigned i=0; i<ecalIs.size(); i++) {
02888 unsigned iEcal = ecalIs[i];
02889
02890 if(debug_)
02891 cout<<endl<<elements[iEcal]<<" ";
02892
02893 if( ! active[iEcal] ) {
02894 if(debug_)
02895 cout<<"not active"<<endl;
02896 continue;
02897 }
02898
02899 PFBlockElement::Type type = elements[ iEcal ].type();
02900 assert( type == PFBlockElement::ECAL );
02901
02902 PFClusterRef clusterref = elements[iEcal].clusterRef();
02903 assert(!clusterref.isNull() );
02904
02905 active[iEcal] = false;
02906
02907
02908 vector<double> ps1Ene(1,static_cast<double>(0.));
02909 associatePSClusters(iEcal, reco::PFBlockElement::PS1, block, elements, linkData, active, ps1Ene);
02910 vector<double> ps2Ene(1,static_cast<double>(0.));
02911 associatePSClusters(iEcal, reco::PFBlockElement::PS2, block, elements, linkData, active, ps2Ene);
02912 bool crackCorrection = false;
02913 float ecalEnergy = calibration_->energyEm(*clusterref,ps1Ene,ps2Ene,crackCorrection);
02914
02915 double particleEnergy = ecalEnergy;
02916
02917 unsigned tmpi = reconstructCluster( *clusterref,
02918 particleEnergy );
02919
02920 (*pfCandidates_)[tmpi].setEcalEnergy( clusterref->energy(),ecalEnergy );
02921 (*pfCandidates_)[tmpi].setHcalEnergy( 0., 0. );
02922 (*pfCandidates_)[tmpi].setHoEnergy( 0., 0. );
02923 (*pfCandidates_)[tmpi].setPs1Energy( 0. );
02924 (*pfCandidates_)[tmpi].setPs2Energy( 0. );
02925 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iEcal );
02926
02927
02928 }
02929
02930 }
02931
02932
02933
02934 unsigned PFAlgo::reconstructTrack( const reco::PFBlockElement& elt ) {
02935
02936 const reco::PFBlockElementTrack* eltTrack
02937 = dynamic_cast<const reco::PFBlockElementTrack*>(&elt);
02938
02939 reco::TrackRef trackRef = eltTrack->trackRef();
02940 const reco::Track& track = *trackRef;
02941
02942 reco::MuonRef muonRef = eltTrack->muonRef();
02943
02944 int charge = track.charge()>0 ? 1 : -1;
02945
02946
02947 double px = track.px();
02948 double py = track.py();
02949 double pz = track.pz();
02950 double energy = sqrt(track.p()*track.p() + 0.13957*0.13957);
02951
02952
02953
02954 bool thisIsAMuon = PFMuonAlgo::isMuon(elt);
02955 bool thisIsAnIsolatedMuon = PFMuonAlgo::isIsolatedMuon(elt);
02956 bool thisIsAGlobalTightMuon = PFMuonAlgo::isGlobalTightMuon(elt);
02957 bool thisIsATrackerTightMuon = PFMuonAlgo::isTrackerTightMuon(elt);
02958
02959
02960 bool isFromDisp = isFromSecInt(elt, "secondary");
02961 bool isToDisp = isFromSecInt(elt, "primary");
02962
02963 bool globalFitUsed = false;
02964
02965 if ( thisIsAMuon ) {
02966
02967
02968 px = muonRef->px();
02969 py = muonRef->py();
02970 pz = muonRef->pz();
02971 energy = sqrt(muonRef->p()*muonRef->p() + 0.1057*0.1057);
02972
02973 reco::TrackBase::TrackQuality trackQualityHighPurity = TrackBase::qualityByName("highPurity");
02974 if(debug_)if(!trackRef->quality(trackQualityHighPurity))cout<<" Low Purity Track "<<endl;
02975
02976 if(muonRef->isGlobalMuon() && !usePFMuonMomAssign_){
02977
02978 reco::TrackRef bestMuTrack = muonRef->muonBestTrack();
02979 if(!useBestMuonTrack_)
02980 bestMuTrack = muonRef->combinedMuon();
02981
02982
02983 bool useGlobalFit = false;
02984
02985 if(thisIsAnIsolatedMuon && (!muonRef->isTrackerMuon() || (muonRef->pt() > bestMuTrack->pt() && track.ptError() > 5.0*bestMuTrack->ptError()))) useGlobalFit = true;
02986 else if(!trackRef->quality(trackQualityHighPurity)) useGlobalFit = true;
02987 else if(muonRef->pt() > bestMuTrack->pt() &&
02988 (track.hitPattern().numberOfValidTrackerHits() < 8 || track.hitPattern().numberOfValidPixelHits() == 0 ) &&
02989 track.ptError() > 5.0*bestMuTrack->ptError()) useGlobalFit = true;
02990
02991 if(useGlobalFit){
02992 px = bestMuTrack->px();
02993 py = bestMuTrack->py();
02994 pz = bestMuTrack->pz();
02995 energy = sqrt(bestMuTrack->p()*bestMuTrack->p() + 0.1057*0.1057);
02996 globalFitUsed = true;
02997 }
02998 }
02999 else if(usePFMuonMomAssign_){
03000
03001 if(thisIsAGlobalTightMuon)
03002 {
03003
03004 if(muonRef->isTrackerMuon()){
03005 if(sqrt(px*px+py*py) > 10){
03006
03007 reco::TrackRef bestMuTrack = muonRef->muonBestTrack();
03008 if(!useBestMuonTrack_)
03009 bestMuTrack = muonRef->combinedMuon();
03010
03011 px = bestMuTrack->px();
03012 py = bestMuTrack->py();
03013 pz = bestMuTrack->pz();
03014 energy = sqrt(bestMuTrack->p()*bestMuTrack->p() + 0.1057*0.1057);
03015 globalFitUsed = true;
03016 }
03017 }
03018 else{
03019
03020 reco::TrackRef bestMuTrack = muonRef->combinedMuon()->normalizedChi2() < muonRef->standAloneMuon()->normalizedChi2() ?
03021 muonRef->muonBestTrack() :
03022 muonRef->standAloneMuon() ;
03023
03024 if(!useBestMuonTrack_)
03025 bestMuTrack =
03026 muonRef->combinedMuon()->normalizedChi2() < muonRef->standAloneMuon()->normalizedChi2() ?
03027 muonRef->combinedMuon() :
03028 muonRef->standAloneMuon() ;
03029
03030 px = bestMuTrack->px();
03031 py = bestMuTrack->py();
03032 pz = bestMuTrack->pz();
03033 energy = sqrt(bestMuTrack->p()*bestMuTrack->p() + 0.1057*0.1057);
03034 globalFitUsed = true;
03035 }
03036 }
03037 }
03038 }
03039 else if (isFromDisp) {
03040 double Dpt = trackRef->ptError();
03041 double dptRel = Dpt/trackRef->pt()*100;
03042
03043
03044
03045 if (dptRel < dptRel_DispVtx_){
03046
03047 if (debug_)
03048 cout << "Not refitted px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
03049
03050 reco::PFDisplacedVertexRef vRef = eltTrack->displacedVertexRef(reco::PFBlockElement::T_FROM_DISP)->displacedVertexRef();
03051 reco::Track trackRefit = vRef->refittedTrack(trackRef);
03052 px = trackRefit.px();
03053 py = trackRefit.py();
03054 pz = trackRefit.pz();
03055 energy = sqrt(trackRefit.p()*trackRefit.p() + 0.13957*0.13957);
03056 if (debug_)
03057 cout << "Refitted px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
03058
03059 }
03060 }
03061
03062 if ((isFromDisp || isToDisp) && debug_) cout << "Final px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
03063
03064
03065 math::XYZTLorentzVector momentum(px,py,pz,energy);
03066 reco::PFCandidate::ParticleType particleType
03067 = reco::PFCandidate::h;
03068
03069
03070 pfCandidates_->push_back( PFCandidate( charge,
03071 momentum,
03072 particleType ) );
03073
03074
03075 if( isFromDisp ) {
03076 pfCandidates_->back().setFlag( reco::PFCandidate::T_FROM_DISP, true);
03077 pfCandidates_->back().setDisplacedVertexRef( eltTrack->displacedVertexRef(reco::PFBlockElement::T_FROM_DISP)->displacedVertexRef(), reco::PFCandidate::T_FROM_DISP);
03078 }
03079
03080
03081 if( isToDisp && !thisIsAMuon ) {
03082 pfCandidates_->back().setFlag( reco::PFCandidate::T_TO_DISP, true);
03083 pfCandidates_->back().setDisplacedVertexRef( eltTrack->displacedVertexRef(reco::PFBlockElement::T_TO_DISP)->displacedVertexRef(), reco::PFCandidate::T_TO_DISP);
03084 }
03085
03086
03087
03088 if ( thisIsAMuon && globalFitUsed )
03089 pfCandidates_->back().setVertexSource( PFCandidate::kComMuonVertex );
03090 else
03091 pfCandidates_->back().setVertexSource( PFCandidate::kTrkVertex );
03092
03093 pfCandidates_->back().setTrackRef( trackRef );
03094 pfCandidates_->back().setPositionAtECALEntrance( eltTrack->positionAtECALEntrance());
03095
03096
03097
03098
03099 if (muonRef.isNonnull()) {
03100 pfCandidates_->back().setMuonRef( muonRef );
03101
03102 if ( thisIsAMuon) {
03103 particleType = reco::PFCandidate::mu;
03104 pfCandidates_->back().setParticleType( particleType );
03105 if (debug_) {
03106 if(thisIsAGlobalTightMuon) cout << "PFAlgo: particle type set to muon (global, tight), pT = " <<muonRef->pt()<< endl;
03107 else if(thisIsATrackerTightMuon) cout << "PFAlgo: particle type set to muon (tracker, tight), pT = " <<muonRef->pt()<< endl;
03108 else if(thisIsAnIsolatedMuon) cout << "PFAlgo: particle type set to muon (isolated), pT = " <<muonRef->pt()<< endl;
03109 else cout<<" problem with muon assignment "<<endl;
03110 PFMuonAlgo::printMuonProperties( muonRef );
03111 }
03112 }
03113 }
03114
03115
03116
03117 if(debug_)
03118 cout<<"** candidate: "<<pfCandidates_->back()<<endl;
03119
03120
03121 return pfCandidates_->size()-1;
03122 }
03123
03124
03125
03126
03127
03128 unsigned
03129 PFAlgo::reconstructCluster(const reco::PFCluster& cluster,
03130 double particleEnergy,
03131 bool useDirection,
03132 double particleX,
03133 double particleY,
03134 double particleZ) {
03135
03136 reco::PFCandidate::ParticleType particleType = reco::PFCandidate::X;
03137
03138
03139
03140
03141
03142 double factor = 1.;
03143 if ( useDirection ) {
03144 switch( cluster.layer() ) {
03145 case PFLayer::ECAL_BARREL:
03146 case PFLayer::HCAL_BARREL1:
03147 factor = std::sqrt(cluster.position().Perp2()/(particleX*particleX+particleY*particleY));
03148 break;
03149 case PFLayer::ECAL_ENDCAP:
03150 case PFLayer::HCAL_ENDCAP:
03151 case PFLayer::HF_HAD:
03152 case PFLayer::HF_EM:
03153 factor = cluster.position().Z()/particleZ;
03154 break;
03155 default:
03156 assert(0);
03157 }
03158 }
03159
03160 math::XYZPoint vertexPos;
03161 if(useVertices_)
03162 vertexPos = math::XYZPoint(primaryVertex_.x(),primaryVertex_.y(),primaryVertex_.z());
03163 else
03164 vertexPos = math::XYZPoint(0.0,0.0,0.0);
03165
03166
03167 math::XYZVector clusterPos( cluster.position().X()-vertexPos.X(),
03168 cluster.position().Y()-vertexPos.Y(),
03169 cluster.position().Z()-vertexPos.Z());
03170 math::XYZVector particleDirection ( particleX*factor-vertexPos.X(),
03171 particleY*factor-vertexPos.Y(),
03172 particleZ*factor-vertexPos.Z() );
03173
03174
03175
03176
03177 clusterPos = useDirection ? particleDirection.Unit() : clusterPos.Unit();
03178 clusterPos *= particleEnergy;
03179
03180
03181
03182
03183 double mass = 0;
03184 ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double> >
03185 momentum( clusterPos.X(), clusterPos.Y(), clusterPos.Z(), mass);
03186
03187 math::XYZTLorentzVector tmp;
03188
03189 tmp = momentum;
03190
03191
03192 int charge = 0;
03193
03194
03195 switch( cluster.layer() ) {
03196 case PFLayer::ECAL_BARREL:
03197 case PFLayer::ECAL_ENDCAP:
03198 particleType = PFCandidate::gamma;
03199 break;
03200 case PFLayer::HCAL_BARREL1:
03201 case PFLayer::HCAL_ENDCAP:
03202 particleType = PFCandidate::h0;
03203 break;
03204 case PFLayer::HF_HAD:
03205 particleType = PFCandidate::h_HF;
03206 break;
03207 case PFLayer::HF_EM:
03208 particleType = PFCandidate::egamma_HF;
03209 break;
03210 default:
03211 assert(0);
03212 }
03213
03214
03215 pfCandidates_->push_back( PFCandidate( charge,
03216 tmp,
03217 particleType ) );
03218
03219
03220
03221 pfCandidates_->back().
03222 setPositionAtECALEntrance(math::XYZPointF(cluster.position().X(),
03223 cluster.position().Y(),
03224 cluster.position().Z()));
03225
03226
03227 pfCandidates_->back().setVertex(vertexPos);
03228
03229 if(debug_)
03230 cout<<"** candidate: "<<pfCandidates_->back()<<endl;
03231
03232
03233 return pfCandidates_->size()-1;
03234
03235 }
03236
03237
03238
03239
03240 double
03241 PFAlgo::neutralHadronEnergyResolution(double clusterEnergyHCAL, double eta) const {
03242
03243
03244 if ( clusterEnergyHCAL < 1. ) clusterEnergyHCAL = 1.;
03245
03246 double resol = fabs(eta) < 1.48 ?
03247 sqrt (1.02*1.02/clusterEnergyHCAL + 0.065*0.065)
03248 :
03249 sqrt (1.20*1.20/clusterEnergyHCAL + 0.028*0.028);
03250
03251 return resol;
03252
03253 }
03254
03255 double
03256 PFAlgo::nSigmaHCAL(double clusterEnergyHCAL, double eta) const {
03257 double nS = fabs(eta) < 1.48 ?
03258 nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL/100.))
03259 :
03260 nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL/100.));
03261
03262 return nS;
03263 }
03264
03265
03266 ostream& operator<<(ostream& out, const PFAlgo& algo) {
03267 if(!out ) return out;
03268
03269 out<<"====== Particle Flow Algorithm ======= ";
03270 out<<endl;
03271 out<<"nSigmaECAL_ "<<algo.nSigmaECAL_<<endl;
03272 out<<"nSigmaHCAL_ "<<algo.nSigmaHCAL_<<endl;
03273 out<<endl;
03274 out<<(*(algo.calibration_))<<endl;
03275 out<<endl;
03276 out<<"reconstructed particles: "<<endl;
03277
03278 const std::auto_ptr< reco::PFCandidateCollection >&
03279 candidates = algo.pfCandidates();
03280
03281 if(!candidates.get() ) {
03282 out<<"candidates already transfered"<<endl;
03283 return out;
03284 }
03285 for(PFCandidateConstIterator ic=algo.pfCandidates_->begin();
03286 ic != algo.pfCandidates_->end(); ic++) {
03287 out<<(*ic)<<endl;
03288 }
03289
03290 return out;
03291 }
03292
03293 reco::PFBlockRef
03294 PFAlgo::createBlockRef( const reco::PFBlockCollection& blocks,
03295 unsigned bi ) {
03296
03297 if( blockHandle_.isValid() ) {
03298 return reco::PFBlockRef( blockHandle_, bi );
03299 }
03300 else {
03301 return reco::PFBlockRef( &blocks, bi );
03302 }
03303 }
03304
03305 void
03306 PFAlgo::associatePSClusters(unsigned iEcal,
03307 reco::PFBlockElement::Type psElementType,
03308 const reco::PFBlock& block,
03309 const edm::OwnVector< reco::PFBlockElement >& elements,
03310 const reco::PFBlock::LinkData& linkData,
03311 std::vector<bool>& active,
03312 std::vector<double>& psEne) {
03313
03314
03315
03316
03317
03318
03319
03320 std::multimap<double, unsigned> sortedPS;
03321 typedef std::multimap<double, unsigned>::iterator IE;
03322 block.associatedElements( iEcal, linkData,
03323 sortedPS, psElementType,
03324 reco::PFBlock::LINKTEST_ALL );
03325
03326
03327 double totalPS = 0.;
03328 for ( IE ips=sortedPS.begin(); ips!=sortedPS.end(); ++ips ) {
03329
03330
03331 unsigned iPS = ips->second;
03332
03333
03334
03335 if (!active[iPS]) continue;
03336
03337
03338 std::multimap<double, unsigned> sortedECAL;
03339 block.associatedElements( iPS, linkData,
03340 sortedECAL,
03341 reco::PFBlockElement::ECAL,
03342 reco::PFBlock::LINKTEST_ALL );
03343 unsigned jEcal = sortedECAL.begin()->second;
03344 if ( jEcal != iEcal ) continue;
03345
03346
03347 PFBlockElement::Type pstype = elements[ iPS ].type();
03348 assert( pstype == psElementType );
03349 PFClusterRef psclusterref = elements[iPS].clusterRef();
03350 assert(!psclusterref.isNull() );
03351 totalPS += psclusterref->energy();
03352 psEne[0] += psclusterref->energy();
03353 active[iPS] = false;
03354 }
03355
03356
03357 }
03358
03359
03360 bool
03361 PFAlgo::isFromSecInt(const reco::PFBlockElement& eTrack, string order) const {
03362
03363 reco::PFBlockElement::TrackType T_TO_DISP = reco::PFBlockElement::T_TO_DISP;
03364 reco::PFBlockElement::TrackType T_FROM_DISP = reco::PFBlockElement::T_FROM_DISP;
03365
03366 reco::PFBlockElement::TrackType T_FROM_V0 = reco::PFBlockElement::T_FROM_V0;
03367
03368 bool bPrimary = (order.find("primary") != string::npos);
03369 bool bSecondary = (order.find("secondary") != string::npos);
03370 bool bAll = (order.find("all") != string::npos);
03371
03372 bool isToDisp = usePFNuclearInteractions_ && eTrack.trackType(T_TO_DISP);
03373 bool isFromDisp = usePFNuclearInteractions_ && eTrack.trackType(T_FROM_DISP);
03374
03375 if (bPrimary && isToDisp) return true;
03376 if (bSecondary && isFromDisp ) return true;
03377 if (bAll && ( isToDisp || isFromDisp ) ) return true;
03378
03379
03380
03381
03382
03383 bool isFromDecay = (bAll || bSecondary) && usePFDecays_ && eTrack.trackType(T_FROM_V0);
03384
03385 return isFromDecay;
03386
03387
03388 }
03389
03390
03391 void
03392 PFAlgo::setEGElectronCollection(const reco::GsfElectronCollection & egelectrons) {
03393 if(useEGElectrons_ && pfele_) pfele_->setEGElectronCollection(egelectrons);
03394 }
03395
03396 void
03397 PFAlgo::postCleaning() {
03398
03399
03400 if ( !postHFCleaning_ ) return;
03401
03402
03403 double metX = 0.;
03404 double metY = 0.;
03405 double sumet = 0;
03406 std::vector<unsigned int> pfCandidatesToBeRemoved;
03407 for(unsigned i=0; i<pfCandidates_->size(); i++) {
03408 const PFCandidate& pfc = (*pfCandidates_)[i];
03409 metX += pfc.px();
03410 metY += pfc.py();
03411 sumet += pfc.pt();
03412 }
03413 double met2 = metX*metX+metY*metY;
03414
03415 double significance = std::sqrt(met2/sumet);
03416 double significanceCor = significance;
03417 if ( significance > minSignificance_ ) {
03418
03419 double metXCor = metX;
03420 double metYCor = metY;
03421 double sumetCor = sumet;
03422 double met2Cor = met2;
03423 double deltaPhi = 3.14159;
03424 double deltaPhiPt = 100.;
03425 bool next = true;
03426 unsigned iCor = 1E9;
03427
03428
03429 while ( next ) {
03430
03431 double metReduc = -1.;
03432
03433 for(unsigned i=0; i<pfCandidates_->size(); ++i) {
03434 const PFCandidate& pfc = (*pfCandidates_)[i];
03435
03436
03437 if ( pfc.particleId() != reco::PFCandidate::h_HF &&
03438 pfc.particleId() != reco::PFCandidate::egamma_HF ) continue;
03439
03440
03441 if ( pfc.pt() < minHFCleaningPt_ ) continue;
03442
03443
03444 bool skip = false;
03445 for(unsigned j=0; j<pfCandidatesToBeRemoved.size(); ++j) {
03446 if ( i == pfCandidatesToBeRemoved[j] ) skip = true;
03447 if ( skip ) break;
03448 }
03449 if ( skip ) continue;
03450
03451
03452 deltaPhi = std::acos((metX*pfc.px()+metY*pfc.py())/(pfc.pt()*std::sqrt(met2)));
03453 deltaPhiPt = deltaPhi*pfc.pt();
03454 if ( deltaPhiPt > maxDeltaPhiPt_ ) continue;
03455
03456
03457 double metXInt = metX - pfc.px();
03458 double metYInt = metY - pfc.py();
03459 double sumetInt = sumet - pfc.pt();
03460 double met2Int = metXInt*metXInt+metYInt*metYInt;
03461 if ( met2Int < met2Cor ) {
03462 metXCor = metXInt;
03463 metYCor = metYInt;
03464 metReduc = (met2-met2Int)/met2Int;
03465 met2Cor = met2Int;
03466 sumetCor = sumetInt;
03467 significanceCor = std::sqrt(met2Cor/sumetCor);
03468 iCor = i;
03469 }
03470 }
03471
03472
03473 if ( metReduc > minDeltaMet_ ) {
03474 pfCandidatesToBeRemoved.push_back(iCor);
03475 metX = metXCor;
03476 metY = metYCor;
03477 sumet = sumetCor;
03478 met2 = met2Cor;
03479 } else {
03480
03481 next = false;
03482 }
03483 }
03484
03485
03486 if ( significance - significanceCor > minSignificanceReduction_ &&
03487 significanceCor < maxSignificance_ ) {
03488 std::cout << "Significance reduction = " << significance << " -> "
03489 << significanceCor << " = " << significanceCor - significance
03490 << std::endl;
03491 for(unsigned j=0; j<pfCandidatesToBeRemoved.size(); ++j) {
03492 std::cout << "Removed : " << (*pfCandidates_)[pfCandidatesToBeRemoved[j]] << std::endl;
03493 pfCleanedCandidates_->push_back( (*pfCandidates_)[ pfCandidatesToBeRemoved[j] ] );
03494 (*pfCandidates_)[pfCandidatesToBeRemoved[j]].rescaleMomentum(1E-6);
03495
03496
03497 }
03498 }
03499 }
03500
03501 }
03502
03503 void
03504 PFAlgo::checkCleaning( const reco::PFRecHitCollection& cleanedHits ) {
03505
03506
03507
03508 if ( !cleanedHits.size() ) return;
03509
03510
03511 double metX = 0.;
03512 double metY = 0.;
03513 double sumet = 0;
03514 std::vector<unsigned int> hitsToBeAdded;
03515 for(unsigned i=0; i<pfCandidates_->size(); i++) {
03516 const PFCandidate& pfc = (*pfCandidates_)[i];
03517 metX += pfc.px();
03518 metY += pfc.py();
03519 sumet += pfc.pt();
03520 }
03521 double met2 = metX*metX+metY*metY;
03522 double met2_Original = met2;
03523
03524
03525
03526 double metXCor = metX;
03527 double metYCor = metY;
03528 double sumetCor = sumet;
03529 double met2Cor = met2;
03530 bool next = true;
03531 unsigned iCor = 1E9;
03532
03533
03534 while ( next ) {
03535
03536 double metReduc = -1.;
03537
03538 for(unsigned i=0; i<cleanedHits.size(); ++i) {
03539 const PFRecHit& hit = cleanedHits[i];
03540 double length = std::sqrt(hit.position().Mag2());
03541 double px = hit.energy() * hit.position().x()/length;
03542 double py = hit.energy() * hit.position().y()/length;
03543 double pt = std::sqrt(px*px + py*py);
03544
03545
03546 bool skip = false;
03547 for(unsigned j=0; j<hitsToBeAdded.size(); ++j) {
03548 if ( i == hitsToBeAdded[j] ) skip = true;
03549 if ( skip ) break;
03550 }
03551 if ( skip ) continue;
03552
03553
03554 double metXInt = metX + px;
03555 double metYInt = metY + py;
03556 double sumetInt = sumet + pt;
03557 double met2Int = metXInt*metXInt+metYInt*metYInt;
03558
03559
03560 if ( met2Int < met2Cor ) {
03561 metXCor = metXInt;
03562 metYCor = metYInt;
03563 metReduc = (met2-met2Int)/met2Int;
03564 met2Cor = met2Int;
03565 sumetCor = sumetInt;
03566
03567 iCor = i;
03568 }
03569 }
03570
03571
03572
03573 if ( metReduc > minDeltaMet_ ) {
03574 hitsToBeAdded.push_back(iCor);
03575 metX = metXCor;
03576 metY = metYCor;
03577 sumet = sumetCor;
03578 met2 = met2Cor;
03579 } else {
03580
03581 next = false;
03582 }
03583 }
03584
03585
03586 if ( std::sqrt(met2_Original) - std::sqrt(met2) > 5. ) {
03587 if ( debug_ ) {
03588 std::cout << hitsToBeAdded.size() << " hits were re-added " << std::endl;
03589 std::cout << "MET reduction = " << std::sqrt(met2_Original) << " -> "
03590 << std::sqrt(met2Cor) << " = " << std::sqrt(met2Cor) - std::sqrt(met2_Original)
03591 << std::endl;
03592 std::cout << "Added after cleaning check : " << std::endl;
03593 }
03594 for(unsigned j=0; j<hitsToBeAdded.size(); ++j) {
03595 const PFRecHit& hit = cleanedHits[hitsToBeAdded[j]];
03596 PFCluster cluster(hit.layer(), hit.energy(),
03597 hit.position().x(), hit.position().y(), hit.position().z() );
03598 reconstructCluster(cluster,hit.energy());
03599 if ( debug_ ) {
03600 std::cout << pfCandidates_->back() << ". time = " << hit.time() << std::endl;
03601 }
03602 }
03603 }
03604
03605 }
03606
03607
03608 void
03609 PFAlgo::postMuonCleaning( const edm::Handle<reco::MuonCollection>& muonh,
03610 const reco::VertexCollection& primaryVertices) {
03611
03612
03613 bool printout = false;
03614
03615
03616
03617
03618 double sumetPU = 0.;
03619 for (unsigned short i=1 ;i<primaryVertices.size();++i ) {
03620 if ( !primaryVertices[i].isValid() || primaryVertices[i].isFake() ) continue;
03621 primaryVertices[i];
03622 for ( reco::Vertex::trackRef_iterator itr = primaryVertices[i].tracks_begin();
03623 itr < primaryVertices[i].tracks_end(); ++itr ) {
03624 sumetPU += (*itr)->pt();
03625 }
03626 }
03627 sumetPU /= 0.65;
03628
03629
03630
03631 double metX = 0.;
03632 double metY = 0.;
03633 double sumet = 0;
03634 double metXCosmics = 0.;
03635 double metYCosmics = 0.;
03636 double sumetCosmics = 0.;
03637
03638 std::map<double,unsigned int> pfMuons;
03639 std::map<double,unsigned int> pfCosmics;
03640 typedef std::multimap<double, unsigned int>::iterator IE;
03641
03642 for(unsigned i=0; i<pfCandidates_->size(); i++) {
03643 const PFCandidate& pfc = (*pfCandidates_)[i];
03644 double origin =
03645 (pfc.vx()-primaryVertex_.x())*(pfc.vx()-primaryVertex_.x()) +
03646 (pfc.vy()-primaryVertex_.y())*(pfc.vy()-primaryVertex_.y());
03647
03648
03649 metX += pfc.px();
03650 metY += pfc.py();
03651 sumet += pfc.pt();
03652
03653
03654
03655 if ( pfc.particleId() == reco::PFCandidate::mu ) {
03656 pfMuons.insert(std::pair<double,unsigned int>(-pfc.pt(),i));
03657 if ( origin > 1.0 ) {
03658 pfCosmics.insert(std::pair<double,unsigned int>(-pfc.pt(),i));
03659 metXCosmics += pfc.px();
03660 metYCosmics += pfc.py();
03661 sumetCosmics += pfc.pt();
03662 }
03663 }
03664
03665 }
03666
03667 double met2 = metX*metX+metY*metY;
03668 double met2Cosmics = (metX-metXCosmics)*(metX-metXCosmics)+(metY-metYCosmics)*(metY-metYCosmics);
03669
03670
03671 if ( sumetCosmics > (sumet-sumetPU)/10. && met2Cosmics < met2 ) {
03672 if ( printout )
03673 std::cout << "MEX,MEY,MET Before (Cosmics)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
03674 for ( IE imu = pfCosmics.begin(); imu != pfCosmics.end(); ++imu ) {
03675 const PFCandidate& pfc = (*pfCandidates_)[imu->second];
03676
03677 pfCosmicsMuonCleanedCandidates_->push_back(pfc);
03678 if ( printout )
03679 std::cout << "Muon cleaned (cosmic). pt/d0 = " << pfc.pt() << " "
03680 << std::sqrt(pfc.vx()*pfc.vx() + pfc.vy()*pfc.vy()) << std::endl;
03681 metX -= pfc.px();
03682 metY -= pfc.py();
03683 sumet -= pfc.pt();
03684 (*pfCandidates_)[imu->second].rescaleMomentum(1E-6);
03685 }
03686 met2 = metX*metX+metY*metY;
03687 if ( printout )
03688 std::cout << "MEX,MEY,MET After (Cosmics)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
03689 }
03690
03691
03692
03693
03694
03695 for ( IE imu = pfMuons.begin(); imu != pfMuons.end(); ++imu ) {
03696 const PFCandidate& pfc = (*pfCandidates_)[imu->second];
03697
03698
03699 if ( pfc.pt() < 20. ) continue;
03700
03701 double metXNO = metX - pfc.px();
03702 double metYNO = metY - pfc.py();
03703 double met2NO = metXNO*metXNO + metYNO*metYNO;
03704 double sumetNO = sumet - pfc.pt();
03705 double factor = std::max(2.,2000./sumetNO);
03706
03707 reco::MuonRef muonRef = pfc.muonRef();
03708 reco::TrackRef bestMuTrack = muonRef->muonBestTrack();
03709 if(!useBestMuonTrack_)
03710 bestMuTrack = muonRef->combinedMuon();
03711 reco::TrackRef trackerMu = muonRef->track();
03712 reco::TrackRef standAloneMu = muonRef->standAloneMuon();
03713
03714 if ( !bestMuTrack || !trackerMu ) {
03715 if ( sumetNO-sumetPU > 500. && met2NO < met2/4.) {
03716 pfFakeMuonCleanedCandidates_->push_back(pfc);
03717 if ( printout ) {
03718 std::cout << "Muon cleaned (NO-bad) " << sumetNO << std::endl;
03719 std::cout << "sumet NO " << sumetNO << std::endl;
03720 }
03721 (*pfCandidates_)[imu->second].rescaleMomentum(1E-6);
03722 if ( printout )
03723 std::cout << "MEX,MEY,MET " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
03724 metX = metXNO;
03725 metY = metYNO;
03726 met2 = met2NO;
03727 sumet = sumetNO;
03728 if ( printout ) {
03729 std::cout << "Muon cleaned (NO/TK) ! " << std::endl;
03730 std::cout << "MEX,MEY,MET Now (NO/TK)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
03731 }
03732 }
03733 } else {
03734
03735
03736
03737
03738
03739
03740
03741
03742 double metXTK = metXNO + trackerMu->px();
03743 double metYTK = metYNO + trackerMu->py();
03744 double met2TK = metXTK*metXTK + metYTK*metYTK;
03745
03746 double metXGL = metXNO + bestMuTrack->px();
03747 double metYGL = metYNO + bestMuTrack->py();
03748 double met2GL = metXGL*metXGL + metYGL*metYGL;
03749
03750
03751
03752
03753
03754
03755
03756
03757
03758
03759
03760
03761
03762
03763
03764
03765 if ( ( sumetNO-sumetPU > 250. && met2TK < met2/4. && met2TK < met2GL ) ||
03766 ( met2TK < met2/2. && trackerMu->pt() < bestMuTrack->pt()/4. && met2TK < met2GL ) ) {
03767 pfCleanedTrackerAndGlobalMuonCandidates_->push_back(pfc);
03768 math::XYZTLorentzVectorD p4(trackerMu->px(),trackerMu->py(),trackerMu->pz(),
03769 std::sqrt(trackerMu->p()*trackerMu->p()+0.1057*0.1057));
03770 if ( printout )
03771 std::cout << "Muon cleaned (TK) ! " << met2TK/met2 << " " << trackerMu->pt() / bestMuTrack->pt() << std::endl;
03772 (*pfCandidates_)[imu->second].setP4(p4);
03773 if ( printout )
03774 std::cout << "MEX,MEY,MET Before (TK)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
03775 metX = metXTK;
03776 metY = metYTK;
03777 met2 = met2TK;
03778
03779 if ( printout )
03780 std::cout << "MEX,MEY,MET Now (TK)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
03781 }
03782
03783 else if ( ( sumetNO-sumetPU > 250. && met2GL < met2/4. && met2GL < met2TK ) ||
03784 ( met2GL < met2/2. && bestMuTrack->pt() < trackerMu->pt()/4.&& met2GL < met2TK ) ) {
03785 pfCleanedTrackerAndGlobalMuonCandidates_->push_back(pfc);
03786 math::XYZTLorentzVectorD p4(bestMuTrack->px(),bestMuTrack->py(),bestMuTrack->pz(),
03787 std::sqrt(bestMuTrack->p()*bestMuTrack->p()+0.1057*0.1057));
03788 if ( printout )
03789 std::cout << "Muon cleaned (GL) ! " << met2GL/met2 << " " << bestMuTrack->pt()/trackerMu->pt() << std::endl;
03790 (*pfCandidates_)[imu->second].setP4(p4);
03791 if ( printout )
03792 std::cout << "MEX,MEY,MET before (GL)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
03793 metX = metXGL;
03794 metY = metYGL;
03795 met2 = met2GL;
03796
03797 if ( printout )
03798 std::cout << "MEX,MEY,MET Now (GL)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
03799 }
03800
03801
03802 bool fake =
03803 fabs ( pfc.eta() ) > 2.15 &&
03804 met2NO < met2/25. &&
03805 (met2GL < met2TK/2. || met2TK < met2GL/2.) &&
03806 standAloneMu->pt() < bestMuTrack->pt()/10. &&
03807 standAloneMu->pt() < trackerMu->pt()/10.;
03808
03809
03810 bool punchthrough1 =
03811 ( sumetNO-sumetPU > 250. && met2NO < met2/4. && (met2GL < met2TK/factor || met2TK < met2GL/factor) );
03812
03813
03814 bool punchthrough2 =
03815 pfc.p() > 100. && pfc.rawHcalEnergy() > 100. &&
03816 pfc.rawEcalEnergy()+pfc.rawHcalEnergy() > pfc.p()/3. &&
03817 !PFMuonAlgo::isIsolatedMuon(muonRef) && met2NO < met2/4.;
03818
03819 if ( punchthrough1 || punchthrough2 || fake ) {
03820
03821
03822 const PFCandidate::ElementsInBlocks& eleInBlocks = pfc.elementsInBlocks();
03823 if ( !eleInBlocks.size() ) {
03824 ostringstream err;
03825 err<<"A muon has no associated elements in block. Cannot proceed with postMuonCleaning()";
03826 edm::LogError("PFAlgo")<<err.str()<<endl;
03827 } else {
03828 PFBlockRef blockRefMuon = eleInBlocks[0].first;
03829 unsigned indexMuon = eleInBlocks[0].second;
03830 for ( unsigned iele = 1; iele < eleInBlocks.size(); ++iele ) {
03831 indexMuon = eleInBlocks[iele].second;
03832 break;
03833 }
03834
03835
03836 double iHad = 1E9;
03837 bool hadron = false;
03838 for ( unsigned i = imu->second+1; i < pfCandidates_->size(); ++i ) {
03839 const PFCandidate& pfcn = (*pfCandidates_)[i];
03840 const PFCandidate::ElementsInBlocks& ele = pfcn.elementsInBlocks();
03841 if ( !ele.size() ) {
03842 ostringstream err2;
03843 err2<<"A pfCandidate has no associated elements in block. Cannot proceed with postMuonCleaning()";
03844 edm::LogError("PFAlgo")<<err2.str()<<endl;
03845 continue;
03846 }
03847 PFBlockRef blockRefHadron = ele[0].first;
03848 unsigned indexHadron = ele[0].second;
03849
03850 if ( blockRefHadron.key() != blockRefMuon.key() ) break;
03851
03852 if ( indexHadron == indexMuon &&
03853 pfcn.particleId() == reco::PFCandidate::h0 ) {
03854 iHad = i;
03855 hadron = true;
03856 }
03857 if ( hadron ) break;
03858 }
03859
03860 if ( hadron ) {
03861 const PFCandidate& pfch = (*pfCandidates_)[iHad];
03862 pfPunchThroughMuonCleanedCandidates_->push_back(pfc);
03863 pfPunchThroughHadronCleanedCandidates_->push_back(pfch);
03864 if ( printout ) {
03865 std::cout << pfc << std::endl;
03866 std::cout << "Raw ecal/hcal : " << pfc.rawEcalEnergy() << " " << pfc.rawHcalEnergy() << std::endl;
03867 std::cout << "Hadron: " << (*pfCandidates_)[iHad] << std::endl;
03868 }
03869 double rescaleFactor = (*pfCandidates_)[iHad].p()/(*pfCandidates_)[imu->second].p();
03870 metX -= (*pfCandidates_)[imu->second].px() + (*pfCandidates_)[iHad].px();
03871 metY -= (*pfCandidates_)[imu->second].py() + (*pfCandidates_)[iHad].py();
03872 (*pfCandidates_)[imu->second].rescaleMomentum(rescaleFactor);
03873 (*pfCandidates_)[iHad].rescaleMomentum(1E-6);
03874 (*pfCandidates_)[imu->second].setParticleType(reco::PFCandidate::h);
03875 if ( printout )
03876 std::cout << "MEX,MEY,MET Before " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
03877 metX += (*pfCandidates_)[imu->second].px();
03878 metY += (*pfCandidates_)[imu->second].py();
03879 met2 = metX*metX + metY*metY;
03880 if ( printout ) {
03881 std::cout << "Muon changed to charged hadron" << std::endl;
03882 std::cout << "MEX,MEY,MET Now (NO)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
03883 }
03884 } else if ( punchthrough1 || fake ) {
03885 const PFCandidate& pfc = (*pfCandidates_)[imu->second];
03886 pfFakeMuonCleanedCandidates_->push_back(pfc);
03887 if ( printout )
03888 std::cout << "MEX,MEY,MET Before " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
03889 metX -= (*pfCandidates_)[imu->second].px();
03890 metY -= (*pfCandidates_)[imu->second].py();
03891 met2 = metX*metX + metY*metY;
03892 (*pfCandidates_)[imu->second].rescaleMomentum(1E-6);
03893 if ( printout ) {
03894 std::cout << "Muon cleaned (NO)" << std::endl;
03895 std::cout << "MEX,MEY,MET Now (NO)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
03896 }
03897 }
03898 }
03899 }
03900
03901
03902
03903
03904
03905
03906
03907
03908
03909
03910 }
03911
03912 }
03913
03914
03915 for ( unsigned imu = 0; imu < muonh->size(); ++imu ) {
03916 reco::MuonRef muonRef( muonh, imu );
03917
03918 reco::TrackRef bestMuTrack = muonRef->muonBestTrack();
03919 if(!useBestMuonTrack_)
03920 bestMuTrack = muonRef->combinedMuon();
03921 reco::TrackRef trackerMu = muonRef->track();
03922 reco::TrackRef standAloneMu = muonRef->standAloneMuon();
03923
03924
03925 bool used = false;
03926 bool hadron = false;
03927 for(unsigned i=0; i<pfCandidates_->size(); i++) {
03928 const PFCandidate& pfc = (*pfCandidates_)[i];
03929 if ( !pfc.trackRef().isNonnull() ) continue;
03930
03931 if ( pfc.trackRef().isNonnull() && pfc.trackRef() == trackerMu ) {
03932 hadron = true;
03933 }
03934
03935
03936
03937 if ( !pfc.muonRef().isNonnull() ) continue;
03938
03939
03940 if ( pfc.muonRef()->track() == trackerMu || pfc.muonRef()->combinedMuon() == bestMuTrack ) {
03941 if ( printout ) {
03942 std::cout << "This muon is already used ..." << std::endl;
03943 std::cout << pfc << std::endl;
03944 std::cout << muonRef->p() << " " << muonRef->pt() << " " << muonRef->eta() << " " << muonRef->phi() << std::endl;
03945 }
03946 used = true;
03947 }
03948 else {
03949
03950
03951 if ( pfc.muonRef()->isStandAloneMuon() && muonRef->isStandAloneMuon() ) {
03952 double dEta = pfc.muonRef()->standAloneMuon()->eta() - standAloneMu->eta();
03953 double dPhi = pfc.muonRef()->standAloneMuon()->phi() - standAloneMu->phi();
03954 double dR = sqrt(dEta*dEta + dPhi*dPhi);
03955 if ( printout ) {
03956 std::cout << "StandAlone to be added ? " << std::endl;
03957 std::cout << " eta = " << pfc.muonRef()->standAloneMuon()->eta() << " " << standAloneMu->eta() << std::endl;
03958 std::cout << " phi = " << pfc.muonRef()->standAloneMuon()->phi() << " " << standAloneMu->phi() << std::endl;
03959 std::cout << " pt = " << pfc.muonRef()->standAloneMuon()->pt() << " " << standAloneMu->pt() << std::endl;
03960 std::cout << " Delta R = " << dR << std::endl;
03961 }
03962 if ( dR < 0.005 ) {
03963 used = true;
03964 if ( printout ) std::cout << "Not removed !" << std::endl;
03965 }
03966 }
03967 }
03968 if ( used ) break;
03969
03970 }
03971
03972 if ( used ) continue;
03973
03974 double ptGL = muonRef->isGlobalMuon() ? bestMuTrack->pt() : 0.;
03975 double pxGL = muonRef->isGlobalMuon() ? bestMuTrack->px() : 0.;
03976 double pyGL = muonRef->isGlobalMuon() ? bestMuTrack->py() : 0.;
03977 double pzGL = muonRef->isGlobalMuon() ? bestMuTrack->pz() : 0.;
03978
03979 double ptTK = muonRef->isTrackerMuon() ? trackerMu->pt() : 0.;
03980 double pxTK = muonRef->isTrackerMuon() ? trackerMu->px() : 0.;
03981 double pyTK = muonRef->isTrackerMuon() ? trackerMu->py() : 0.;
03982 double pzTK = muonRef->isTrackerMuon() ? trackerMu->pz() : 0.;
03983
03984 double ptST = muonRef->isStandAloneMuon() ? standAloneMu->pt() : 0.;
03985 double pxST = muonRef->isStandAloneMuon() ? standAloneMu->px() : 0.;
03986 double pyST = muonRef->isStandAloneMuon() ? standAloneMu->py() : 0.;
03987 double pzST = muonRef->isStandAloneMuon() ? standAloneMu->pz() : 0.;
03988
03989
03990
03991 double metXTK = metX + pxTK;
03992 double metYTK = metY + pyTK;
03993 double met2TK = metXTK*metXTK + metYTK*metYTK;
03994
03995 double metXGL = metX + pxGL;
03996 double metYGL = metY + pyGL;
03997 double met2GL = metXGL*metXGL + metYGL*metYGL;
03998
03999 double metXST = metX + pxST;
04000 double metYST = metY + pyST;
04001 double met2ST = metXST*metXST + metYST*metYST;
04002
04003
04004
04005
04006 if ( ptTK > 20. && met2TK < met2/4. && met2TK < met2GL && met2TK < met2ST ) {
04007 double energy = std::sqrt(pxTK*pxTK+pyTK*pyTK+pzTK*pzTK+0.1057*0.1057);
04008 int charge = trackerMu->charge()>0 ? 1 : -1;
04009 math::XYZTLorentzVector momentum(pxTK,pyTK,pzTK,energy);
04010 reco::PFCandidate::ParticleType particleType =
04011 ptGL > 20. ? reco::PFCandidate::mu : reco::PFCandidate::h;
04012 double radius = std::sqrt(
04013 (trackerMu->vertex().x()-primaryVertex_.x())*(trackerMu->vertex().x()-primaryVertex_.x())+
04014 (trackerMu->vertex().y()-primaryVertex_.y())*(trackerMu->vertex().y()-primaryVertex_.y()));
04015
04016
04017 if ( !hadron && radius < 1.0 ) {
04018 pfCandidates_->push_back( PFCandidate( charge,
04019 momentum,
04020 particleType ) );
04021
04022 pfCandidates_->back().setVertexSource( PFCandidate::kTrkMuonVertex );
04023 pfCandidates_->back().setTrackRef( trackerMu );
04024 pfCandidates_->back().setMuonRef( muonRef );
04025
04026 if ( printout ) {
04027 std::cout << "MEX,MEY,MET before " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
04028 std::cout << "Muon TK added " << std::endl;
04029 std::cout << "pT TK/GL/ST : " << ptTK << " " << ptGL << " " << ptST << std::endl;
04030 }
04031 metX += pfCandidates_->back().px();
04032 metY += pfCandidates_->back().py();
04033 met2 = metX*metX + metY*metY;
04034 if ( printout ) {
04035 std::cout << pfCandidates_->back() << std::endl;
04036 std::cout << "MEX,MEY,MET now " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
04037 }
04038
04039 const PFCandidate& pfc = pfCandidates_->back();
04040 pfAddedMuonCandidates_->push_back(pfc);
04041
04042 }
04043
04044 } else if ( ptGL > 20. && met2GL < met2/4. && met2GL < met2TK && met2GL < met2ST ) {
04045
04046 double energy = std::sqrt(pxGL*pxGL+pyGL*pyGL+pzGL*pzGL+0.1057*0.1057);
04047 int charge = bestMuTrack->charge()>0 ? 1 : -1;
04048 math::XYZTLorentzVector momentum(pxGL,pyGL,pzGL,energy);
04049 reco::PFCandidate::ParticleType particleType = reco::PFCandidate::mu;
04050 double radius = std::sqrt(
04051 (bestMuTrack->vertex().x()-primaryVertex_.x())*(bestMuTrack->vertex().x()-primaryVertex_.x())+
04052 (bestMuTrack->vertex().y()-primaryVertex_.y())*(bestMuTrack->vertex().y()-primaryVertex_.y()));
04053
04054
04055 if ( radius < 1.0 ) {
04056 pfCandidates_->push_back( PFCandidate( charge,
04057 momentum,
04058 particleType ) );
04059
04060 pfCandidates_->back().setVertexSource( PFCandidate::kComMuonVertex );
04061
04062 if (trackerMu.isNonnull() ) pfCandidates_->back().setTrackRef( trackerMu );
04063 pfCandidates_->back().setMuonRef( muonRef );
04064
04065 if ( printout ) {
04066 std::cout << "MEX,MEY,MET before " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
04067 std::cout << "Muon GL added " << std::endl;
04068 std::cout << "pT TK/GL/ST : " << ptTK << " " << ptGL << " " << ptST << std::endl;
04069 }
04070
04071 metX += pfCandidates_->back().px();
04072 metY += pfCandidates_->back().py();
04073 met2 = metX*metX + metY*metY;
04074
04075 if ( printout ) {
04076 std::cout << pfCandidates_->back() << std::endl;
04077 std::cout << "MEX,MEY,MET now " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
04078 }
04079
04080 const PFCandidate& pfc = pfCandidates_->back();
04081 pfAddedMuonCandidates_->push_back(pfc);
04082
04083 }
04084
04085 } else if ( ptST > 20. && met2ST < met2/4. && met2ST < met2TK && met2ST < met2GL ) {
04086
04087 double energy = std::sqrt(pxST*pxST+pyST*pyST+pzST*pzST+0.1057*0.1057);
04088 int charge = standAloneMu->charge()>0 ? 1 : -1;
04089 math::XYZTLorentzVector momentum(pxST,pyST,pzST,energy);
04090 reco::PFCandidate::ParticleType particleType = reco::PFCandidate::mu;
04091 double radius = std::sqrt(
04092 (standAloneMu->vertex().x()-primaryVertex_.x())*(standAloneMu->vertex().x()-primaryVertex_.x())+
04093 (standAloneMu->vertex().y()-primaryVertex_.y())*(standAloneMu->vertex().y()-primaryVertex_.y()));
04094
04095
04096 if ( radius < 1.0 ) {
04097 pfCandidates_->push_back( PFCandidate( charge,
04098 momentum,
04099 particleType ) );
04100
04101 pfCandidates_->back().setVertexSource( PFCandidate::kSAMuonVertex);
04102 if (trackerMu.isNonnull() ) pfCandidates_->back().setTrackRef( trackerMu );
04103 pfCandidates_->back().setMuonRef( muonRef );
04104
04105 if ( printout ) {
04106 std::cout << "MEX,MEY,MET before " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
04107 std::cout << "Muon ST added " << std::endl;
04108 std::cout << "pT TK/GL/ST : " << ptTK << " " << ptGL << " " << ptST << std::endl;
04109 }
04110
04111 metX += pfCandidates_->back().px();
04112 metY += pfCandidates_->back().py();
04113 met2 = metX*metX + metY*metY;
04114
04115 if ( printout ) {
04116 std::cout << pfCandidates_->back() << std::endl;
04117 std::cout << "MEX,MEY,MET now " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
04118 }
04119
04120 const PFCandidate& pfc = pfCandidates_->back();
04121 pfAddedMuonCandidates_->push_back(pfc);
04122
04123 }
04124 }
04125
04126 }
04127
04128
04129
04130
04131
04132
04133
04134
04135 }
04136
04137 void PFAlgo::setElectronExtraRef(const edm::OrphanHandle<reco::PFCandidateElectronExtraCollection >& extrah) {
04138 if(!usePFElectrons_) return;
04139
04140 unsigned size=pfCandidates_->size();
04141
04142 for(unsigned ic=0;ic<size;++ic) {
04143
04144 if((*pfCandidates_)[ic].particleId()==PFCandidate::e) {
04145
04146 PFElectronExtraEqual myExtraEqual((*pfCandidates_)[ic].gsfTrackRef());
04147 std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
04148 if(it!=pfElectronExtra_.end()) {
04149
04150 reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
04151 (*pfCandidates_)[ic].setPFElectronExtraRef(theRef);
04152 }
04153 else {
04154 (*pfCandidates_)[ic].setPFElectronExtraRef(PFCandidateElectronExtraRef());
04155 }
04156 }
04157 else
04158 {
04159 if((*pfCandidates_)[ic].trackRef().isNonnull()) {
04160 PFElectronExtraKfEqual myExtraEqual((*pfCandidates_)[ic].trackRef());
04161 std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
04162 if(it!=pfElectronExtra_.end()) {
04163 (*pfCandidates_)[ic].set_mva_e_pi(it->mvaVariable(PFCandidateElectronExtra::MVA_MVA));
04164 reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
04165 (*pfCandidates_)[ic].setPFElectronExtraRef(theRef);
04166 (*pfCandidates_)[ic].setGsfTrackRef(it->gsfTrackRef());
04167 }
04168 }
04169 }
04170
04171 }
04172
04173 size=pfElectronCandidates_->size();
04174 for(unsigned ic=0;ic<size;++ic) {
04175
04176 if((*pfElectronCandidates_)[ic].particleId()==PFCandidate::e) {
04177
04178 PFElectronExtraEqual myExtraEqual((*pfElectronCandidates_)[ic].gsfTrackRef());
04179 std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
04180 if(it!=pfElectronExtra_.end()) {
04181 reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
04182 (*pfElectronCandidates_)[ic].setPFElectronExtraRef(theRef);
04183
04184 }
04185 }
04186 }
04187
04188 }
04189 void PFAlgo::setPhotonExtraRef(const edm::OrphanHandle<reco::PFCandidatePhotonExtraCollection >& ph_extrah) {
04190 if(!usePFPhotons_) return;
04191 unsigned int size=pfCandidates_->size();
04192 unsigned int sizePhExtra = pfPhotonExtra_.size();
04193 for(unsigned ic=0;ic<size;++ic) {
04194
04195 if((*pfCandidates_)[ic].particleId()==PFCandidate::gamma && (*pfCandidates_)[ic].mva_nothing_gamma() > 0.99) {
04196 if((*pfCandidates_)[ic].superClusterRef().isNonnull()) {
04197 bool found = false;
04198 for(unsigned pcextra=0;pcextra<sizePhExtra;++pcextra) {
04199 if((*pfCandidates_)[ic].superClusterRef() == pfPhotonExtra_[pcextra].superClusterRef()) {
04200 reco::PFCandidatePhotonExtraRef theRef(ph_extrah,pcextra);
04201 (*pfCandidates_)[ic].setPFPhotonExtraRef(theRef);
04202 found = true;
04203 break;
04204 }
04205 }
04206 if(!found)
04207 (*pfCandidates_)[ic].setPFPhotonExtraRef((PFCandidatePhotonExtraRef()));
04208 }
04209 else {
04210 (*pfCandidates_)[ic].setPFPhotonExtraRef((PFCandidatePhotonExtraRef()));
04211 }
04212 }
04213 }
04214 }