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 out<<resetiosflags(ios::right|ios::fixed);
00253 return out;
00254 }
00255
00256 static unsigned long long bitPackRefInfo(const edm::RefCore& iCore, size_t iIndex){
00257 unsigned long long bitPack = iIndex;
00258 bitPack |= static_cast<unsigned long long>(iCore.id().productIndex())<<32;
00259 bitPack |= static_cast<unsigned long long>(iCore.id().processIndex())<<48;
00260 return bitPack;
00261 }
00262
00263 void PFCandidate::storeRefInfo(unsigned int iMask, unsigned int iBit, bool iIsValid,
00264 const edm::RefCore& iCore, size_t iKey,
00265 const edm::EDProductGetter* iGetter) {
00266
00267 size_t index = s_refsBefore[storedRefsBitPattern_ & iMask];
00268 if ( 0 == getter_) {
00269 getter_ = iGetter;
00270 }
00271
00272 if(iIsValid) {
00273 if(0 == (storedRefsBitPattern_ & iBit) ) {
00274 refsInfo_.insert(refsInfo_.begin()+index, bitPackRefInfo(iCore,iKey));
00275 if (iGetter==0)
00276 refsCollectionCache_.insert(refsCollectionCache_.begin()+index,(void*)iCore.productPtr());
00277 else
00278 refsCollectionCache_.insert(refsCollectionCache_.begin()+index,0);
00279 } else {
00280 assert(refsInfo_.size()>index);
00281 *(refsInfo_.begin()+index)=bitPackRefInfo(iCore,iKey);
00282 if (iGetter==0)
00283 *(refsCollectionCache_.begin()+index)=(void*)iCore.productPtr();
00284 else
00285 *(refsCollectionCache_.begin()+index)=0;
00286
00287 }
00288 storedRefsBitPattern_ |= iBit;
00289 } else{
00290 if( storedRefsBitPattern_ & iBit) {
00291 refsInfo_.erase(refsInfo_.begin()+index);
00292 refsCollectionCache_.erase(refsCollectionCache_.begin()+index);
00293 storedRefsBitPattern_ ^= iBit;
00294 }
00295 }
00296
00297 }
00298
00299 bool PFCandidate::getRefInfo(unsigned int iMask, unsigned int iBit,
00300 edm::ProductID& oProductID, size_t& oIndex, size_t& aIndex) const {
00301
00302 if( 0 == (iBit & storedRefsBitPattern_) ) {
00303 return false;
00304 }
00305 aIndex = s_refsBefore[storedRefsBitPattern_ & iMask];
00306 unsigned long long bitPacked = refsInfo_[aIndex];
00307 oIndex = bitPacked & 0xFFFFFFFFULL;
00308 unsigned short productIndex = (bitPacked & 0x0000FFFF00000000ULL)>>32;
00309 unsigned short processIndex = (bitPacked & 0xFFFF000000000000ULL)>>48;
00310 oProductID = edm::ProductID(processIndex,productIndex);
00311 return true;
00312 }
00313
00314 void PFCandidate::setTrackRef(const reco::TrackRef& iRef) {
00315 if(!charge()) {
00316 string err;
00317 err += "PFCandidate::setTrackRef: this is a neutral candidate! ";
00318 err += "particleId_=";
00319 char num[4];
00320 sprintf( num, "%d", particleId());
00321 err += num;
00322
00323 throw cms::Exception("InconsistentReference",
00324 err.c_str() );
00325 }
00326
00327 storeRefInfo(kRefTrackMask, kRefTrackBit, iRef.isNonnull(),
00328 iRef.refCore(), iRef.key(),iRef.productGetter());
00329 }
00330
00331 reco::TrackRef PFCandidate::trackRef() const { GETREF(reco::Track, kRefTrackMask, kRefTrackBit); }
00332
00333
00334 void PFCandidate::setMuonRef(reco::MuonRef const & iRef) {
00335 if( trackRef() != iRef->track() ) {
00336 string err;
00337 err += "PFCandidate::setMuonRef: inconsistent track references!";
00338
00339 throw cms::Exception("InconsistentReference",
00340 err.c_str() );
00341 }
00342
00343 storeRefInfo(kRefMuonMask, kRefMuonBit, iRef.isNonnull(),
00344 iRef.refCore(), iRef.key(),iRef.productGetter());
00345 }
00346
00347 reco::MuonRef PFCandidate::muonRef() const { GETREF(reco::Muon, kRefMuonMask, kRefMuonBit); }
00348
00349
00351 void PFCandidate::setGsfTrackRef(reco::GsfTrackRef const & iRef) {
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 storeRefInfo(kRefGsfTrackMask, kRefGsfTrackBit, iRef.isNonnull(),
00365 iRef.refCore(), iRef.key(),iRef.productGetter());
00366 }
00367
00368 reco::GsfTrackRef PFCandidate::gsfTrackRef() const { GETREF(reco::GsfTrack, kRefGsfTrackMask, kRefGsfTrackBit); }
00369
00370
00372 void PFCandidate::setDisplacedVertexRef(const reco::PFDisplacedVertexRef& iRef, Flags type) {
00373
00374 if( particleId() != h ) {
00375 string err;
00376 err += "PFCandidate::setDisplacedVertexRef: this is not a hadron! particleId_=";
00377 char num[4];
00378 sprintf( num, "%d", particleId());
00379 err += num;
00380
00381 throw cms::Exception("InconsistentReference",
00382 err.c_str() );
00383 }
00384 else if( !flag( T_FROM_DISP ) && !flag( T_TO_DISP ) ) {
00385 string err;
00386 err += "PFCandidate::setDisplacedVertexRef: particule flag is neither T_FROM_DISP nor T_TO_DISP";
00387
00388 throw cms::Exception("InconsistentReference",
00389 err.c_str() );
00390 }
00391
00392
00393 if (type == T_TO_DISP && flag( T_TO_DISP ))
00394 storeRefInfo(kRefDisplacedVertexDauMask, kRefDisplacedVertexDauBit,
00395 iRef.isNonnull(),
00396 iRef.refCore(), iRef.key(),iRef.productGetter());
00397 else if (type == T_FROM_DISP && flag( T_FROM_DISP ))
00398 storeRefInfo(kRefDisplacedVertexMotMask, kRefDisplacedVertexMotBit,
00399 iRef.isNonnull(),
00400 iRef.refCore(), iRef.key(),iRef.productGetter());
00401 else if ( (type == T_FROM_DISP && !flag( T_FROM_DISP ))
00402 ||
00403 (type == T_TO_DISP && !flag( T_TO_DISP )) ){
00404 string err;
00405 err += "PFCandidate::setDisplacedVertexRef: particule flag is not switched on";
00406
00407 throw cms::Exception("InconsistentReference",
00408 err.c_str() );
00409 }
00410
00411 }
00412
00413
00414
00415
00416 reco::PFDisplacedVertexRef PFCandidate::displacedVertexRef(Flags type) const {
00417 if (type == T_TO_DISP) {
00418 GETREF(reco::PFDisplacedVertex, kRefDisplacedVertexDauMask, kRefDisplacedVertexDauBit);
00419 }
00420 else if (type == T_FROM_DISP) {
00421 GETREF(reco::PFDisplacedVertex, kRefDisplacedVertexMotMask, kRefDisplacedVertexMotBit);
00422 }
00423 return reco::PFDisplacedVertexRef();
00424 }
00425
00427 void PFCandidate::setConversionRef(reco::ConversionRef const & iRef) {
00428 if( particleId() != gamma ) {
00429 string err;
00430 err += "PFCandidate::setConversionRef: this is not a (converted) photon ! particleId_=";
00431 char num[4];
00432 sprintf( num, "%d", particleId());
00433 err += num;
00434
00435 throw cms::Exception("InconsistentReference",
00436 err.c_str() );
00437 }
00438 else if( !flag( GAMMA_TO_GAMMACONV ) ) {
00439 string err;
00440 err += "PFCandidate::setConversionRef: particule flag is not GAMMA_TO_GAMMACONV";
00441
00442 throw cms::Exception("InconsistentReference",
00443 err.c_str() );
00444 }
00445
00446 storeRefInfo(kRefConversionMask, kRefConversionBit, iRef.isNonnull(),
00447 iRef.refCore(), iRef.key(),iRef.productGetter());
00448 }
00449
00450
00451 reco::ConversionRef PFCandidate::conversionRef() const {
00452 GETREF(reco::Conversion, kRefConversionMask, kRefConversionBit);
00453 }
00454
00456 void PFCandidate::setV0Ref(reco::VertexCompositeCandidateRef const & iRef) {
00457 storeRefInfo(kRefV0Mask, kRefV0Bit, iRef.isNonnull(),
00458 iRef.refCore(), iRef.key(),iRef.productGetter());
00459 }
00460
00461 reco::VertexCompositeCandidateRef PFCandidate::v0Ref() const {
00462 GETREF(reco::VertexCompositeCandidate, kRefV0Mask, kRefV0Bit);
00463 }
00464
00466 void PFCandidate::setGsfElectronRef(reco::GsfElectronRef const & iRef) {
00467 storeRefInfo(kRefGsfElectronMask, kRefGsfElectronBit, iRef.isNonnull(),
00468 iRef.refCore(), iRef.key(),iRef.productGetter());
00469 }
00470
00471 reco::GsfElectronRef PFCandidate::gsfElectronRef() const {
00472 GETREF(reco::GsfElectron, kRefGsfElectronMask, kRefGsfElectronBit);
00473 }
00474
00476 void PFCandidate::setPFElectronExtraRef(reco::PFCandidateElectronExtraRef const & iRef) {
00477 storeRefInfo(kRefPFElectronExtraMask, kRefPFElectronExtraBit, iRef.isNonnull(),
00478 iRef.refCore(), iRef.key(),iRef.productGetter());
00479 }
00480
00481 reco::PFCandidateElectronExtraRef PFCandidate::electronExtraRef() const {
00482 GETREF(reco::PFCandidateElectronExtra, kRefPFElectronExtraMask, kRefPFElectronExtraBit);
00483 }
00484
00485
00486 reco::PhotonRef PFCandidate::photonRef() const {
00487 GETREF(reco::Photon, kRefPhotonMask, kRefPhotonBit);
00488 }
00489
00490 reco::PFCandidatePhotonExtraRef PFCandidate::photonExtraRef() const {
00491 GETREF(reco::PFCandidatePhotonExtra, kRefPFPhotonExtraMask, kRefPFPhotonExtraBit);
00492 }
00493
00494 reco::SuperClusterRef PFCandidate::superClusterRef() const {
00495 GETREF(reco::SuperCluster, kRefSuperClusterMask, kRefSuperClusterBit);
00496 }
00497
00498 void PFCandidate::setPhotonRef(const reco::PhotonRef& iRef) {
00499 if( particleId() != gamma && particleId() != e) {
00500 string err;
00501 err += "PFCandidate::setSuperClusterRef: this is not an electron neither a photon ! particleId_=";
00502 char num[4];
00503 sprintf( num, "%d", particleId());
00504 err += num;
00505
00506 throw cms::Exception("InconsistentReference", err.c_str() );
00507 }
00508
00509 storeRefInfo(kRefPhotonMask, kRefPhotonBit, iRef.isNonnull(),
00510 iRef.refCore(), iRef.key(),iRef.productGetter());
00511
00512 }
00513
00514 void PFCandidate::setSuperClusterRef(const reco::SuperClusterRef& iRef) {
00515 if( particleId() != gamma && particleId() != e) {
00516 string err;
00517 err += "PFCandidate::setSuperClusterRef: this is not an electron neither a photon ! particleId_=";
00518 char num[4];
00519 sprintf( num, "%d", particleId());
00520 err += num;
00521
00522 throw cms::Exception("InconsistentReference", err.c_str() );
00523 }
00524
00525 storeRefInfo(kRefSuperClusterMask, kRefSuperClusterBit, iRef.isNonnull(),
00526 iRef.refCore(), iRef.key(),iRef.productGetter());
00527
00528 }
00529
00530 void PFCandidate::setPFPhotonExtraRef(const reco::PFCandidatePhotonExtraRef& iRef) {
00531 storeRefInfo(kRefPFPhotonExtraMask, kRefPFPhotonExtraBit, iRef.isNonnull(),
00532 iRef.refCore(), iRef.key(),iRef.productGetter());
00533 }
00534
00535
00536
00537
00538 const math::XYZPoint & PFCandidate::vertex() const {
00539 switch (vertexType_) {
00540 case kCandVertex:
00541 return vertex_;
00542 break;
00543 case kTrkVertex:
00544 return trackRef()->vertex();
00545 break;
00546 case kComMuonVertex:
00547 return muonRef()->combinedMuon()->vertex();
00548 break;
00549 case kSAMuonVertex:
00550 return muonRef()->standAloneMuon()->vertex();
00551 break;
00552 case kTrkMuonVertex:
00553 return muonRef()->track()->vertex();
00554 break;
00555 case kGSFVertex:
00556 return gsfTrackRef()->vertex();
00557 break;
00558 }
00559 return vertex_;
00560 }