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