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