CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/DataFormats/ParticleFlowCandidate/src/PFCandidate.cc

Go to the documentation of this file.
00001 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
00002 //#include "DataFormats/ParticleFlowReco/interface/PFBlock.h"
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   // proceed with various consistency checks
00087 
00088   // charged candidate: track ref and charge must be non null
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   //elementsInBlocks_.push_back( make_pair(blockref.key(), elementIndex) );
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; // pi+
00150   case e:     return thecharge*(-11);
00151   case mu:    return thecharge*(-13);
00152   case gamma: return 22;
00153   case h0:    return 130; // K_L0
00154   case h_HF:         return 1; // dummy pdg code 
00155   case egamma_HF:    return 2;  // dummy pdg code
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 //   PFBlockRef blockRef = c.block(); 
00241 //   int blockid = blockRef.key(); 
00242 //   const edm::OwnVector< reco::PFBlockElement >& elements = c.elements();
00243 //   out<< "\t# of elements " << elements.size() 
00244 //      <<" from block " << blockid << endl;
00245 
00246 //   // print each element in turn
00247   
00248 //   for(unsigned ie=0; ie<elements.size(); ie++) {
00249 //     out<<"\t"<< elements[ie] <<endl;
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; //low 32 bits are the index
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 //  Removed by F. Beaudette. Would like to be able to save the GsfTrackRef even for charged pions
00353 //  if( particleId() != e ) {
00354 //    string err;
00355 //    err += "PFCandidate::setGsfTrackRef: this is not an electron ! particleId_=";
00356 //    char num[4];
00357 //    sprintf( num, "%d", particleId());
00358 //    err += num;
00359 //
00360 //    throw cms::Exception("InconsistentReference",
00361 //                         err.c_str() );
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 }