CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_2_9/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   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   // proceed with various consistency checks
00091 
00092   // charged candidate: track ref and charge must be non null
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   //elementsInBlocks_.push_back( make_pair(blockref.key(), elementIndex) );
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; // pi+
00154   case e:     return thecharge*(-11);
00155   case mu:    return thecharge*(-13);
00156   case gamma: return 22;
00157   case h0:    return 130; // K_L0
00158   case h_HF:         return 1; // dummy pdg code 
00159   case egamma_HF:    return 2;  // dummy pdg code
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 //   PFBlockRef blockRef = c.block(); 
00245 //   int blockid = blockRef.key(); 
00246 //   const edm::OwnVector< reco::PFBlockElement >& elements = c.elements();
00247 //   out<< "\t# of elements " << elements.size() 
00248 //      <<" from block " << blockid << endl;
00249 
00250 //   // print each element in turn
00251   
00252 //   for(unsigned ie=0; ie<elements.size(); ie++) {
00253 //     out<<"\t"<< elements[ie] <<endl;
00254 //   }
00255 
00256   // Improved printout for electrons if PFCandidateElectronExtra is available
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; //low 32 bits are the index
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 //  Removed by F. Beaudette. Would like to be able to save the GsfTrackRef even for charged pions
00361 //  if( particleId() != e ) {
00362 //    string err;
00363 //    err += "PFCandidate::setGsfTrackRef: this is not an electron ! particleId_=";
00364 //    char num[4];
00365 //    sprintf( num, "%d", particleId());
00366 //    err += num;
00367 //
00368 //    throw cms::Exception("InconsistentReference",
00369 //                         err.c_str() );
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 }