CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_patch3/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   // Improved printout for electrons if PFCandidateElectronExtra is available
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; //low 32 bits are the index
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 //  Removed by F. Beaudette. Would like to be able to save the GsfTrackRef even for charged pions
00357 //  if( particleId() != e ) {
00358 //    string err;
00359 //    err += "PFCandidate::setGsfTrackRef: this is not an electron ! particleId_=";
00360 //    char num[4];
00361 //    sprintf( num, "%d", particleId());
00362 //    err += num;
00363 //
00364 //    throw cms::Exception("InconsistentReference",
00365 //                         err.c_str() );
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 }