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