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