00001 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
00002
00003
00004 #include "DataFormats/MuonReco/interface/Muon.h"
00005 #include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
00006 #include "DataFormats/ParticleFlowReco/interface/PFDisplacedVertex.h"
00007 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidateElectronExtra.h"
00008 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidatePhotonExtra.h"
00009 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidateEGammaExtra.h"
00010 #include "DataFormats/EgammaCandidates/interface/Conversion.h"
00011 #include "DataFormats/EgammaCandidates/interface/Photon.h"
00012
00013 #include "FWCore/Utilities/interface/Exception.h"
00014
00015 #include <ostream>
00016 #include <iomanip>
00017
00018 using namespace reco;
00019 using namespace std;
00020
00021
00022
00023 const float PFCandidate::bigMva_ = -999.;
00024
00025
00026 #include "DataFormats/ParticleFlowCandidate/src/CountBits.h"
00027
00028
00029
00030
00031 PFCandidate::PFCandidate() :
00032 ecalERatio_(1.),
00033 hcalERatio_(1.),
00034 hoERatio_(1.),
00035 rawEcalEnergy_(0.),
00036 rawHcalEnergy_(0.),
00037 rawHoEnergy_(0.),
00038 ps1Energy_(0.),
00039 ps2Energy_(0.),
00040 flags_(0),
00041 deltaP_(0.),
00042 vertexType_(kCandVertex),
00043 mva_e_pi_(bigMva_),
00044 mva_e_mu_(bigMva_),
00045 mva_pi_mu_(bigMva_),
00046 mva_nothing_gamma_(bigMva_),
00047 mva_nothing_nh_(bigMva_),
00048 mva_gamma_nh_(bigMva_),
00049 getter_(0),storedRefsBitPattern_(0)
00050 {
00051
00052 muonTrackType_ = reco::Muon::None;
00053
00054 setPdgId( translateTypeToPdgId( X ) );
00055 refsInfo_.reserve(3);
00056 }
00057
00058
00059 PFCandidate::PFCandidate( const PFCandidatePtr& sourcePtr ) {
00060 *this = *sourcePtr;
00061 sourcePtr_ = sourcePtr;
00062
00063 }
00064
00065
00066 PFCandidate::PFCandidate( Charge charge,
00067 const LorentzVector & p4,
00068 ParticleType partId ) :
00069
00070 CompositeCandidate(charge, p4),
00071 ecalERatio_(1.),
00072 hcalERatio_(1.),
00073 hoERatio_(1.),
00074 rawEcalEnergy_(0.),
00075 rawHcalEnergy_(0.),
00076 rawHoEnergy_(0.),
00077 ps1Energy_(0.),
00078 ps2Energy_(0.),
00079 flags_(0),
00080 deltaP_(0.),
00081 vertexType_(kCandVertex),
00082 mva_e_pi_(bigMva_),
00083 mva_e_mu_(bigMva_),
00084 mva_pi_mu_(bigMva_),
00085 mva_nothing_gamma_(bigMva_),
00086 mva_nothing_nh_(bigMva_),
00087 mva_gamma_nh_(bigMva_),
00088 getter_(0),storedRefsBitPattern_(0)
00089 {
00090 refsInfo_.reserve(3);
00091 blocksStorage_.reserve(10);
00092 elementsStorage_.reserve(10);
00093
00094 muonTrackType_ = reco::Muon::None;
00095
00096
00097
00098
00099 if( partId == h ||
00100 partId == e ||
00101 partId == mu ) {
00102
00103 if( charge == 0 ) {
00104 string err;
00105 err+="Attempt to construct a charged PFCandidate with a zero charge";
00106 throw cms::Exception("InconsistentValue",
00107 err.c_str() );
00108 }
00109 }
00110 else {
00111 if( charge ) {
00112 string err;
00113 err += "Attempt to construct a neutral PFCandidate ";
00114 err += "with a non-zero charge";
00115 throw cms::Exception("InconsistentValue",
00116 err.c_str() );
00117 }
00118 }
00119 setPdgId( translateTypeToPdgId( partId ) );
00120 }
00121
00122 PFCandidate::~PFCandidate() {}
00123
00124 PFCandidate * PFCandidate::clone() const {
00125 return new PFCandidate( * this );
00126 }
00127
00128
00129 void PFCandidate::addElementInBlock( const reco::PFBlockRef& blockref,
00130 unsigned elementIndex ) {
00131
00132 if (blocksStorage_.size()==0)
00133 blocksStorage_ =Blocks(blockref.id());
00134 blocksStorage_.push_back(blockref);
00135 elementsStorage_.push_back(elementIndex);
00136 }
00137
00138
00139
00140 PFCandidate::ParticleType PFCandidate::translatePdgIdToType(int pdgid) const {
00141 switch (std::abs(pdgid)) {
00142 case 211: return h;
00143 case 11: return e;
00144 case 13: return mu;
00145 case 22: return gamma;
00146 case 130: return h0;
00147 case 1: return h_HF;
00148 case 2: return egamma_HF;
00149 case 0: return X;
00150 default: return X;
00151 }
00152 }
00153
00154 int PFCandidate::translateTypeToPdgId( ParticleType type ) const {
00155
00156 int thecharge = charge();
00157
00158 switch( type ) {
00159 case h: return thecharge*211;
00160 case e: return thecharge*(-11);
00161 case mu: return thecharge*(-13);
00162 case gamma: return 22;
00163 case h0: return 130;
00164 case h_HF: return 1;
00165 case egamma_HF: return 2;
00166 case X:
00167 default: return 0;
00168 }
00169 }
00170
00171
00172 void PFCandidate::setParticleType( ParticleType type ) {
00173 setPdgId( translateTypeToPdgId( type ) );
00174 }
00175
00176
00177 bool PFCandidate::overlap(const reco::Candidate & other) const {
00178 CandidatePtr myPtr = sourceCandidatePtr(0);
00179 if (myPtr.isNull()) return false;
00180 for (size_t i = 0, n = other.numberOfSourceCandidatePtrs(); i < n; ++i) {
00181 CandidatePtr otherPtr = other.sourceCandidatePtr(i);
00182 if ((otherPtr == myPtr) ||
00183 (sourcePtr_.isNonnull() && otherPtr.isNonnull() && sourcePtr_->overlap(*otherPtr))) {
00184 return true;
00185 }
00186 }
00187 return false;
00188 }
00189
00190
00191
00192
00193
00194 void PFCandidate::rescaleMomentum( double rescaleFactor ) {
00195 LorentzVector rescaledp4 = p4();
00196 rescaledp4 *= rescaleFactor;
00197 setP4( rescaledp4 );
00198 }
00199
00200
00201 void PFCandidate::setFlag(Flags theFlag, bool value) {
00202
00203 if(value)
00204 flags_ = flags_ | (1<<theFlag);
00205 else
00206 flags_ = flags_ ^ (1<<theFlag);
00207 }
00208
00209
00210
00211 bool PFCandidate::flag(Flags theFlag) const {
00212
00213 return (flags_>>theFlag) & 1;
00214 }
00215
00216
00217
00218
00219 ostream& reco::operator<<(ostream& out,
00220 const PFCandidate& c ) {
00221
00222 if(!out) return out;
00223
00224 out<<"\tPFCandidate type: "<<c.particleId();
00225 out<<setiosflags(ios::right);
00226 out<<setiosflags(ios::fixed);
00227 out<<setprecision(3);
00228 out<<" E/pT/eta/phi "
00229 <<c.energy()<<"/"
00230 <<c.pt()<<"/"
00231 <<c.eta()<<"/"
00232 <<c.phi();
00233 if( c.flag( PFCandidate::T_FROM_DISP ) ) out<<", T_FROM_DISP" << endl;
00234 else if( c.flag( PFCandidate::T_TO_DISP ) ) out<<", T_TO_DISP" << endl;
00235 else if( c.flag( PFCandidate::T_FROM_GAMMACONV ) ) out<<", T_FROM_GAMMACONV" << endl;
00236 else if( c.flag( PFCandidate::GAMMA_TO_GAMMACONV ) ) out<<", GAMMA_TO_GAMMACONV" << endl;
00237
00238 out<<", blocks/iele: ";
00239
00240 PFCandidate::ElementsInBlocks eleInBlocks = c.elementsInBlocks();
00241 for(unsigned i=0; i<eleInBlocks.size(); i++) {
00242 PFBlockRef blockRef = eleInBlocks[i].first;
00243 unsigned indexInBlock = eleInBlocks[i].second;
00244
00245 out<<"("<<blockRef.key()<<"|"<<indexInBlock<<"), ";
00246 }
00247
00248 out<<" source:"<<c.sourcePtr_.id()<<"/"<<c.sourcePtr_.key();
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 if(c.particleId()==PFCandidate::e && c.electronExtraRef().isNonnull() && c.electronExtraRef().isAvailable()) {
00264 out << std::endl << *(c.electronExtraRef()) ;
00265 }
00266 out<<resetiosflags(ios::right|ios::fixed);
00267 return out;
00268 }
00269
00270 static unsigned long long bitPackRefInfo(const edm::RefCore& iCore, size_t iIndex){
00271 unsigned long long bitPack = iIndex;
00272 bitPack |= static_cast<unsigned long long>(iCore.id().productIndex())<<32;
00273 bitPack |= static_cast<unsigned long long>(iCore.id().processIndex())<<48;
00274 return bitPack;
00275 }
00276
00277 void PFCandidate::storeRefInfo(unsigned int iMask,
00278 unsigned int iBit,
00279 bool iIsValid,
00280 const edm::RefCore& iCore,
00281 size_t iKey,
00282 const edm::EDProductGetter* iGetter) {
00283
00284 size_t index = s_refsBefore[storedRefsBitPattern_ & iMask];
00285 if ( 0 == getter_) {
00286 getter_ = iGetter;
00287 }
00288
00289 if(iIsValid) {
00290 if(0 == (storedRefsBitPattern_ & iBit) ) {
00291 refsInfo_.insert(refsInfo_.begin()+index, bitPackRefInfo(iCore,iKey));
00292 if (iGetter==0)
00293 refsCollectionCache_.insert(refsCollectionCache_.begin()+index,
00294 (void*)iCore.productPtr());
00295 else
00296 refsCollectionCache_.insert(refsCollectionCache_.begin()+index,0);
00297 } else {
00298 assert(refsInfo_.size()>index);
00299 *(refsInfo_.begin()+index)=bitPackRefInfo(iCore,iKey);
00300 if (iGetter==0)
00301 *(refsCollectionCache_.begin()+index)=(void*)iCore.productPtr();
00302 else
00303 *(refsCollectionCache_.begin()+index)=0;
00304
00305 }
00306 storedRefsBitPattern_ |= iBit;
00307 } else{
00308 if( storedRefsBitPattern_ & iBit) {
00309 refsInfo_.erase(refsInfo_.begin()+index);
00310 refsCollectionCache_.erase(refsCollectionCache_.begin()+index);
00311 storedRefsBitPattern_ ^= iBit;
00312 }
00313 }
00314
00315 }
00316
00317 bool PFCandidate::getRefInfo(unsigned int iMask, unsigned int iBit,
00318 edm::ProductID& oProductID, size_t& oIndex, size_t& aIndex) const {
00319
00320 if( 0 == (iBit & storedRefsBitPattern_) ) {
00321 return false;
00322 }
00323 aIndex = s_refsBefore[storedRefsBitPattern_ & iMask];
00324 unsigned long long bitPacked = refsInfo_[aIndex];
00325 oIndex = bitPacked & 0xFFFFFFFFULL;
00326 unsigned short productIndex = (bitPacked & 0x0000FFFF00000000ULL)>>32;
00327 unsigned short processIndex = (bitPacked & 0xFFFF000000000000ULL)>>48;
00328 oProductID = edm::ProductID(processIndex,productIndex);
00329 return true;
00330 }
00331
00332 void PFCandidate::setTrackRef(const reco::TrackRef& iRef) {
00333 if(!charge()) {
00334 string err;
00335 err += "PFCandidate::setTrackRef: this is a neutral candidate! ";
00336 err += "particleId_=";
00337 char num[4];
00338 sprintf( num, "%d", particleId());
00339 err += num;
00340
00341 throw cms::Exception("InconsistentReference",
00342 err.c_str() );
00343 }
00344
00345 storeRefInfo(kRefTrackMask, kRefTrackBit, iRef.isNonnull(),
00346 iRef.refCore(), iRef.key(),iRef.productGetter());
00347 }
00348
00349 reco::TrackRef PFCandidate::trackRef() const { GETREF(reco::Track, kRefTrackMask, kRefTrackBit); }
00350
00351
00352 void PFCandidate::setMuonRef(reco::MuonRef const & iRef) {
00353
00354 if( trackRef() != iRef->track() ) {
00355 string err;
00356 err += "PFCandidate::setMuonRef: inconsistent track references!";
00357
00358 throw cms::Exception("InconsistentReference",
00359 err.c_str() );
00360 }
00361
00362 storeRefInfo(kRefMuonMask, kRefMuonBit, iRef.isNonnull(),
00363 iRef.refCore(), iRef.key(),iRef.productGetter());
00364 }
00365
00366 reco::MuonRef PFCandidate::muonRef() const { GETREF(reco::Muon, kRefMuonMask, kRefMuonBit); }
00367
00368
00370 void PFCandidate::setGsfTrackRef(reco::GsfTrackRef const & iRef) {
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 storeRefInfo(kRefGsfTrackMask, kRefGsfTrackBit, iRef.isNonnull(),
00384 iRef.refCore(), iRef.key(),iRef.productGetter());
00385 }
00386
00387 reco::GsfTrackRef PFCandidate::gsfTrackRef() const { GETREF(reco::GsfTrack, kRefGsfTrackMask, kRefGsfTrackBit); }
00388
00389
00391 void PFCandidate::setDisplacedVertexRef(const reco::PFDisplacedVertexRef& iRef, Flags type) {
00392
00393 if( particleId() != h ) {
00394 string err;
00395 err += "PFCandidate::setDisplacedVertexRef: this is not a hadron! particleId_=";
00396 char num[4];
00397 sprintf( num, "%d", particleId());
00398 err += num;
00399
00400 throw cms::Exception("InconsistentReference",
00401 err.c_str() );
00402 }
00403 else if( !flag( T_FROM_DISP ) && !flag( T_TO_DISP ) ) {
00404 string err;
00405 err += "PFCandidate::setDisplacedVertexRef: particule flag is neither T_FROM_DISP nor T_TO_DISP";
00406
00407 throw cms::Exception("InconsistentReference",
00408 err.c_str() );
00409 }
00410
00411
00412 if (type == T_TO_DISP && flag( T_TO_DISP ))
00413 storeRefInfo(kRefDisplacedVertexDauMask, kRefDisplacedVertexDauBit,
00414 iRef.isNonnull(),
00415 iRef.refCore(), iRef.key(),iRef.productGetter());
00416 else if (type == T_FROM_DISP && flag( T_FROM_DISP ))
00417 storeRefInfo(kRefDisplacedVertexMotMask, kRefDisplacedVertexMotBit,
00418 iRef.isNonnull(),
00419 iRef.refCore(), iRef.key(),iRef.productGetter());
00420 else if ( (type == T_FROM_DISP && !flag( T_FROM_DISP ))
00421 ||
00422 (type == T_TO_DISP && !flag( T_TO_DISP )) ){
00423 string err;
00424 err += "PFCandidate::setDisplacedVertexRef: particule flag is not switched on";
00425
00426 throw cms::Exception("InconsistentReference",
00427 err.c_str() );
00428 }
00429
00430 }
00431
00432
00433
00434
00435 reco::PFDisplacedVertexRef PFCandidate::displacedVertexRef(Flags type) const {
00436 if (type == T_TO_DISP) {
00437 GETREF(reco::PFDisplacedVertex, kRefDisplacedVertexDauMask, kRefDisplacedVertexDauBit);
00438 }
00439 else if (type == T_FROM_DISP) {
00440 GETREF(reco::PFDisplacedVertex, kRefDisplacedVertexMotMask, kRefDisplacedVertexMotBit);
00441 }
00442 return reco::PFDisplacedVertexRef();
00443 }
00444
00446 void PFCandidate::setConversionRef(reco::ConversionRef const & iRef) {
00447 if( particleId() != gamma ) {
00448 string err;
00449 err += "PFCandidate::setConversionRef: this is not a (converted) photon ! particleId_=";
00450 char num[4];
00451 sprintf( num, "%d", particleId());
00452 err += num;
00453
00454 throw cms::Exception("InconsistentReference",
00455 err.c_str() );
00456 }
00457 else if( !flag( GAMMA_TO_GAMMACONV ) ) {
00458 string err;
00459 err += "PFCandidate::setConversionRef: particule flag is not GAMMA_TO_GAMMACONV";
00460
00461 throw cms::Exception("InconsistentReference",
00462 err.c_str() );
00463 }
00464
00465 storeRefInfo(kRefConversionMask, kRefConversionBit, iRef.isNonnull(),
00466 iRef.refCore(), iRef.key(),iRef.productGetter());
00467 }
00468
00469
00470 reco::ConversionRef PFCandidate::conversionRef() const {
00471 GETREF(reco::Conversion, kRefConversionMask, kRefConversionBit);
00472 }
00473
00475 void PFCandidate::setV0Ref(reco::VertexCompositeCandidateRef const & iRef) {
00476 storeRefInfo(kRefV0Mask, kRefV0Bit, iRef.isNonnull(),
00477 iRef.refCore(), iRef.key(),iRef.productGetter());
00478 }
00479
00480 reco::VertexCompositeCandidateRef PFCandidate::v0Ref() const {
00481 GETREF(reco::VertexCompositeCandidate, kRefV0Mask, kRefV0Bit);
00482 }
00483
00485 void PFCandidate::setGsfElectronRef(reco::GsfElectronRef const & iRef) {
00486 storeRefInfo(kRefGsfElectronMask, kRefGsfElectronBit, iRef.isNonnull(),
00487 iRef.refCore(), iRef.key(),iRef.productGetter());
00488 }
00489
00490 reco::GsfElectronRef PFCandidate::gsfElectronRef() const {
00491 GETREF(reco::GsfElectron, kRefGsfElectronMask, kRefGsfElectronBit);
00492 }
00493
00495 void PFCandidate::setPFElectronExtraRef(reco::PFCandidateElectronExtraRef const & iRef) {
00496 storeRefInfo(kRefPFElectronExtraMask, kRefPFElectronExtraBit, iRef.isNonnull(),
00497 iRef.refCore(), iRef.key(),iRef.productGetter());
00498 }
00499
00500 reco::PFCandidateElectronExtraRef PFCandidate::electronExtraRef() const {
00501 GETREF(reco::PFCandidateElectronExtra, kRefPFElectronExtraMask, kRefPFElectronExtraBit);
00502 }
00503
00504 reco::PhotonRef PFCandidate::photonRef() const {
00505 GETREF(reco::Photon, kRefPhotonMask, kRefPhotonBit);
00506 }
00507
00508 reco::PFCandidatePhotonExtraRef PFCandidate::photonExtraRef() const {
00509 GETREF(reco::PFCandidatePhotonExtra, kRefPFPhotonExtraMask, kRefPFPhotonExtraBit);
00510 }
00511
00512 reco::PFCandidateEGammaExtraRef PFCandidate::egammaExtraRef() const {
00513 GETREF(reco::PFCandidateEGammaExtra, kRefPFEGammaExtraMask, kRefPFEGammaExtraBit);
00514 }
00515
00516 reco::SuperClusterRef PFCandidate::superClusterRef() const {
00517 GETREF(reco::SuperCluster, kRefSuperClusterMask, kRefSuperClusterBit);
00518 }
00519
00520 void PFCandidate::setPhotonRef(const reco::PhotonRef& iRef) {
00521 if( particleId() != gamma && particleId() != e) {
00522 string err;
00523 err += "PFCandidate::setSuperClusterRef: this is not an electron neither a photon ! particleId_=";
00524 char num[4];
00525 sprintf( num, "%d", particleId());
00526 err += num;
00527
00528 throw cms::Exception("InconsistentReference", err.c_str() );
00529 }
00530
00531 storeRefInfo(kRefPhotonMask, kRefPhotonBit, iRef.isNonnull(),
00532 iRef.refCore(), iRef.key(),iRef.productGetter());
00533
00534 }
00535
00536 void PFCandidate::setSuperClusterRef(const reco::SuperClusterRef& iRef) {
00537 if( particleId() != gamma && particleId() != e) {
00538 string err;
00539 err += "PFCandidate::setSuperClusterRef: this is not an electron neither a photon ! particleId_=";
00540 char num[4];
00541 sprintf( num, "%d", particleId());
00542 err += num;
00543
00544 throw cms::Exception("InconsistentReference", err.c_str() );
00545 }
00546
00547 storeRefInfo(kRefSuperClusterMask, kRefSuperClusterBit, iRef.isNonnull(),
00548 iRef.refCore(), iRef.key(),iRef.productGetter());
00549
00550 }
00551
00552 void PFCandidate::setPFPhotonExtraRef(const reco::PFCandidatePhotonExtraRef& iRef) {
00553 storeRefInfo(kRefPFPhotonExtraMask, kRefPFPhotonExtraBit, iRef.isNonnull(),
00554 iRef.refCore(), iRef.key(),iRef.productGetter());
00555 }
00556
00557 void PFCandidate::setPFEGammaExtraRef(const reco::PFCandidateEGammaExtraRef & iRef) {
00558
00559 storeRefInfo(kRefPFEGammaExtraMask, kRefPFEGammaExtraBit, iRef.isNonnull(),
00560 iRef.refCore(), iRef.key(),iRef.productGetter());
00561 }
00562
00563 const math::XYZPoint & PFCandidate::vertex() const {
00564 switch (vertexType_) {
00565 case kCandVertex:
00566 return vertex_;
00567 break;
00568 case kTrkVertex:
00569 return trackRef()->vertex();
00570 break;
00571 case kComMuonVertex:
00572 return muonRef()->combinedMuon()->vertex();
00573 break;
00574 case kSAMuonVertex:
00575 return muonRef()->standAloneMuon()->vertex();
00576 break;
00577 case kTrkMuonVertex:
00578 return muonRef()->track()->vertex();
00579 break;
00580 case kTPFMSMuonVertex:
00581 return muonRef()->tpfmsTrack()->vertex();
00582 break;
00583 case kPickyMuonVertex:
00584 return muonRef()->pickyTrack()->vertex();
00585 break;
00586
00587 case kGSFVertex:
00588 return gsfTrackRef()->vertex();
00589 break;
00590 }
00591 return vertex_;
00592 }