Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-10-01 01:01:51

0001 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
0002 //#include "DataFormats/ParticleFlowReco/interface/PFBlock.h"
0003 
0004 #include "DataFormats/MuonReco/interface/Muon.h"
0005 #include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
0006 #include "DataFormats/ParticleFlowReco/interface/PFDisplacedVertex.h"
0007 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidateElectronExtra.h"
0008 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidatePhotonExtra.h"
0009 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidateEGammaExtra.h"
0010 #include "DataFormats/EgammaCandidates/interface/Conversion.h"
0011 #include "DataFormats/EgammaCandidates/interface/Photon.h"
0012 
0013 #include "FWCore/Utilities/interface/Exception.h"
0014 
0015 #include <ostream>
0016 #include <iomanip>
0017 
0018 using namespace reco;
0019 using namespace std;
0020 
0021 #include "DataFormats/ParticleFlowCandidate/src/CountBits.h"
0022 
0023 PFCandidate::PFCandidate()
0024     : elementsInBlocks_(nullptr),
0025       ecalERatio_(1.),
0026       hcalERatio_(1.),
0027       hoERatio_(1.),
0028       rawEcalEnergy_(0.),
0029       rawHcalEnergy_(0.),
0030       rawHoEnergy_(0.),
0031       ps1Energy_(0.),
0032       ps2Energy_(0.),
0033       flags_(0),
0034       deltaP_(0.),
0035       vertexType_(kCandVertex),
0036       mva_Isolated_(PFCandidate::bigMva_),
0037       mva_e_pi_(PFCandidate::bigMva_),
0038       mva_e_mu_(PFCandidate::bigMva_),
0039       mva_pi_mu_(PFCandidate::bigMva_),
0040       mva_nothing_gamma_(PFCandidate::bigMva_),
0041       mva_nothing_nh_(PFCandidate::bigMva_),
0042       mva_gamma_nh_(PFCandidate::bigMva_),
0043       dnn_e_sigIsolated_(PFCandidate::bigMva_),
0044       dnn_e_sigNonIsolated_(PFCandidate::bigMva_),
0045       dnn_e_bkgNonIsolated_(PFCandidate::bigMva_),
0046       dnn_e_bkgTau_(PFCandidate::bigMva_),
0047       dnn_e_bkgPhoton_(PFCandidate::bigMva_),
0048       dnn_gamma_(PFCandidate::bigMva_),
0049       getter_(nullptr),
0050       storedRefsBitPattern_(0),
0051       time_(0.f),
0052       timeError_(-1.f) {
0053   muonTrackType_ = reco::Muon::None;
0054 
0055   setPdgId(translateTypeToPdgId(X));
0056   refsInfo_.reserve(3);
0057   std::fill(hcalDepthEnergyFractions_.begin(), hcalDepthEnergyFractions_.end(), 0.f);
0058 }
0059 
0060 const math::XYZPoint& PFCandidate::vertex() const { return vertexLegacy(vertexType_); }
0061 
0062 PFCandidate::PFCandidate(const PFCandidatePtr& sourcePtr) : PFCandidate(*sourcePtr) {
0063   sourcePtr_ = sourcePtr;
0064   hcalDepthEnergyFractions_ = sourcePtr->hcalDepthEnergyFractions_;  // GP not sure it's needed
0065 }
0066 
0067 PFCandidate::PFCandidate(Charge charge, const LorentzVector& p4, ParticleType partId)
0068     : CompositeCandidate(charge, p4),
0069       elementsInBlocks_(nullptr),
0070       ecalERatio_(1.),
0071       hcalERatio_(1.),
0072       hoERatio_(1.),
0073       rawEcalEnergy_(0.),
0074       rawHcalEnergy_(0.),
0075       rawHoEnergy_(0.),
0076       ps1Energy_(0.),
0077       ps2Energy_(0.),
0078       flags_(0),
0079       deltaP_(0.),
0080       vertexType_(kCandVertex),
0081       mva_Isolated_(PFCandidate::bigMva_),
0082       mva_e_pi_(PFCandidate::bigMva_),
0083       mva_e_mu_(PFCandidate::bigMva_),
0084       mva_pi_mu_(PFCandidate::bigMva_),
0085       mva_nothing_gamma_(PFCandidate::bigMva_),
0086       mva_nothing_nh_(PFCandidate::bigMva_),
0087       mva_gamma_nh_(PFCandidate::bigMva_),
0088       dnn_e_sigIsolated_(PFCandidate::bigMva_),
0089       dnn_e_sigNonIsolated_(PFCandidate::bigMva_),
0090       dnn_e_bkgNonIsolated_(PFCandidate::bigMva_),
0091       dnn_e_bkgTau_(PFCandidate::bigMva_),
0092       dnn_e_bkgPhoton_(PFCandidate::bigMva_),
0093       dnn_gamma_(PFCandidate::bigMva_),
0094       getter_(nullptr),
0095       storedRefsBitPattern_(0),
0096       time_(0.f),
0097       timeError_(-1.f) {
0098   refsInfo_.reserve(3);
0099   blocksStorage_.reserve(10);
0100   elementsStorage_.reserve(10);
0101   std::fill(hcalDepthEnergyFractions_.begin(), hcalDepthEnergyFractions_.end(), 0.f);
0102 
0103   muonTrackType_ = reco::Muon::None;
0104 
0105   // proceed with various consistency checks
0106 
0107   // charged candidate: track ref and charge must be non null
0108   if (partId == h || partId == e || partId == mu) {
0109     if (charge == 0) {
0110       string err;
0111       err += "Attempt to construct a charged PFCandidate with a zero charge";
0112       throw cms::Exception("InconsistentValue", err.c_str());
0113     }
0114   } else {
0115     if (charge) {
0116       string err;
0117       err += "Attempt to construct a neutral PFCandidate ";
0118       err += "with a non-zero charge";
0119       throw cms::Exception("InconsistentValue", err.c_str());
0120     }
0121   }
0122   setPdgId(translateTypeToPdgId(partId));
0123 }
0124 
0125 PFCandidate::PFCandidate(PFCandidate const& iOther)
0126     : CompositeCandidate(iOther),
0127       elementsInBlocks_(nullptr),
0128       blocksStorage_(iOther.blocksStorage_),
0129       elementsStorage_(iOther.elementsStorage_),
0130       sourcePtr_(iOther.sourcePtr_),
0131       muonTrackType_(iOther.muonTrackType_),
0132       ecalERatio_(iOther.ecalERatio_),
0133       hcalERatio_(iOther.hcalERatio_),
0134       hoERatio_(iOther.hoERatio_),
0135       rawEcalEnergy_(iOther.rawEcalEnergy_),
0136       rawHcalEnergy_(iOther.rawHcalEnergy_),
0137       rawHoEnergy_(iOther.rawHoEnergy_),
0138       ps1Energy_(iOther.ps1Energy_),
0139       ps2Energy_(iOther.ps2Energy_),
0140       flags_(iOther.flags_),
0141       deltaP_(iOther.deltaP_),
0142       vertexType_(iOther.vertexType_),
0143       mva_Isolated_(iOther.mva_Isolated_),
0144       mva_e_pi_(iOther.mva_e_pi_),
0145       mva_e_mu_(iOther.mva_e_mu_),
0146       mva_pi_mu_(iOther.mva_pi_mu_),
0147       mva_nothing_gamma_(iOther.mva_nothing_gamma_),
0148       mva_nothing_nh_(iOther.mva_nothing_nh_),
0149       mva_gamma_nh_(iOther.mva_gamma_nh_),
0150       dnn_e_sigIsolated_(iOther.dnn_e_sigIsolated_),
0151       dnn_e_sigNonIsolated_(iOther.dnn_e_sigNonIsolated_),
0152       dnn_e_bkgNonIsolated_(iOther.dnn_e_bkgNonIsolated_),
0153       dnn_e_bkgTau_(iOther.dnn_e_bkgTau_),
0154       dnn_e_bkgPhoton_(iOther.dnn_e_bkgPhoton_),
0155       dnn_gamma_(iOther.dnn_gamma_),
0156       positionAtECALEntrance_(iOther.positionAtECALEntrance_),
0157       getter_(iOther.getter_),
0158       storedRefsBitPattern_(iOther.storedRefsBitPattern_),
0159       refsInfo_(iOther.refsInfo_),
0160       refsCollectionCache_(iOther.refsCollectionCache_),
0161       time_(iOther.time_),
0162       timeError_(iOther.timeError_),
0163       hcalDepthEnergyFractions_(iOther.hcalDepthEnergyFractions_) {
0164   auto tmp = iOther.elementsInBlocks_.load(std::memory_order_acquire);
0165   if (nullptr != tmp) {
0166     elementsInBlocks_.store(new ElementsInBlocks{*tmp}, std::memory_order_release);
0167   }
0168 }
0169 
0170 PFCandidate& PFCandidate::operator=(PFCandidate const& iOther) {
0171   CompositeCandidate::operator=(iOther);
0172   auto tmp = iOther.elementsInBlocks_.load(std::memory_order_acquire);
0173   if (nullptr != tmp) {
0174     delete elementsInBlocks_.exchange(new ElementsInBlocks{*tmp}, std::memory_order_acq_rel);
0175   } else {
0176     delete elementsInBlocks_.exchange(nullptr, std::memory_order_acq_rel);
0177   }
0178   blocksStorage_ = iOther.blocksStorage_;
0179   elementsStorage_ = iOther.elementsStorage_;
0180   sourcePtr_ = iOther.sourcePtr_;
0181   muonTrackType_ = iOther.muonTrackType_;
0182   ecalERatio_ = iOther.ecalERatio_;
0183   hcalERatio_ = iOther.hcalERatio_;
0184   hoERatio_ = iOther.hoERatio_;
0185   rawEcalEnergy_ = iOther.rawEcalEnergy_;
0186   rawHcalEnergy_ = iOther.rawHcalEnergy_;
0187   rawHoEnergy_ = iOther.rawHoEnergy_;
0188   ps1Energy_ = iOther.ps1Energy_;
0189   ps2Energy_ = iOther.ps2Energy_;
0190   flags_ = iOther.flags_;
0191   deltaP_ = iOther.deltaP_;
0192   vertexType_ = iOther.vertexType_;
0193   mva_Isolated_ = iOther.mva_Isolated_;
0194   mva_e_pi_ = iOther.mva_e_pi_;
0195   mva_e_mu_ = iOther.mva_e_mu_;
0196   mva_pi_mu_ = iOther.mva_pi_mu_;
0197   mva_nothing_gamma_ = iOther.mva_nothing_gamma_;
0198   mva_nothing_nh_ = iOther.mva_nothing_nh_;
0199   mva_gamma_nh_ = iOther.mva_gamma_nh_;
0200   dnn_e_sigIsolated_ = iOther.dnn_e_sigIsolated_;
0201   dnn_e_sigNonIsolated_ = iOther.dnn_e_sigNonIsolated_;
0202   dnn_e_bkgNonIsolated_ = iOther.dnn_e_bkgNonIsolated_;
0203   dnn_e_bkgTau_ = iOther.dnn_e_bkgTau_;
0204   dnn_e_bkgPhoton_ = iOther.dnn_e_bkgPhoton_;
0205   dnn_gamma_ = iOther.dnn_gamma_;
0206   positionAtECALEntrance_ = iOther.positionAtECALEntrance_;
0207   getter_ = iOther.getter_;
0208   storedRefsBitPattern_ = iOther.storedRefsBitPattern_;
0209   refsInfo_ = iOther.refsInfo_;
0210   refsCollectionCache_ = iOther.refsCollectionCache_;
0211   time_ = iOther.time_;
0212   timeError_ = iOther.timeError_;
0213   hcalDepthEnergyFractions_ = iOther.hcalDepthEnergyFractions_;
0214   return *this;
0215 }
0216 
0217 PFCandidate::~PFCandidate() { delete elementsInBlocks_.load(std::memory_order_acquire); }
0218 
0219 PFCandidate* PFCandidate::clone() const { return new PFCandidate(*this); }
0220 
0221 void PFCandidate::addElementInBlock(const reco::PFBlockRef& blockref, unsigned elementIndex) {
0222   //elementsInBlocks_.push_back( make_pair(blockref.key(), elementIndex) );
0223   if (blocksStorage_.empty())
0224     blocksStorage_ = Blocks(blockref.id());
0225   blocksStorage_.push_back(blockref);
0226   elementsStorage_.push_back(elementIndex);
0227   auto ptr = elementsInBlocks_.exchange(nullptr);
0228   delete ptr;
0229 }
0230 
0231 PFCandidate::ParticleType PFCandidate::translatePdgIdToType(int pdgid) const {
0232   switch (std::abs(pdgid)) {
0233     case 211:
0234       return h;
0235     case 11:
0236       return e;
0237     case 13:
0238       return mu;
0239     case 22:
0240       return gamma;
0241     case 130:
0242       return h0;
0243     case 1:
0244       return h_HF;
0245     case 2:
0246       return egamma_HF;
0247     case 0:
0248       return X;
0249     default:
0250       return X;
0251   }
0252 }
0253 
0254 int PFCandidate::translateTypeToPdgId(ParticleType type) const {
0255   int thecharge = charge();
0256 
0257   switch (type) {
0258     case h:
0259       return thecharge * 211;  // pi+
0260     case e:
0261       return thecharge * (-11);
0262     case mu:
0263       return thecharge * (-13);
0264     case gamma:
0265       return 22;
0266     case h0:
0267       return 130;  // K_L0
0268     case h_HF:
0269       return 1;  // dummy pdg code
0270     case egamma_HF:
0271       return 2;  // dummy pdg code
0272     case X:
0273     default:
0274       return 0;
0275   }
0276 }
0277 
0278 void PFCandidate::setParticleType(ParticleType type) { setPdgId(translateTypeToPdgId(type)); }
0279 
0280 bool PFCandidate::overlap(const reco::Candidate& other) const {
0281   CandidatePtr myPtr = sourceCandidatePtr(0);
0282   if (myPtr.isNull())
0283     return false;
0284   for (size_t i = 0, n = other.numberOfSourceCandidatePtrs(); i < n; ++i) {
0285     CandidatePtr otherPtr = other.sourceCandidatePtr(i);
0286     if ((otherPtr == myPtr) || (sourcePtr_.isNonnull() && otherPtr.isNonnull() && sourcePtr_->overlap(*otherPtr))) {
0287       return true;
0288     }
0289   }
0290   return false;
0291 }
0292 
0293 // Rescale three-momentum, preserving mass
0294 void PFCandidate::rescaleMomentum(double rescaleFactor) {
0295   if (rescaleFactor < 0)
0296     throw cms::Exception(
0297         "NegativeScaling",
0298         "Scale factor " + std::to_string(rescaleFactor) + " is < 0. Cannot rescale momentum by this value");
0299   float rescaleE = std::sqrt(p() * p() * (rescaleFactor * rescaleFactor - 1) / (energy() * energy()) + 1);
0300   LorentzVector rescaledp4(rescaleFactor * px(), rescaleFactor * py(), rescaleFactor * pz(), rescaleE * energy());
0301   setP4(rescaledp4);
0302 }
0303 
0304 void PFCandidate::setFlag(Flags theFlag, bool value) {
0305   if (value)
0306     flags_ = flags_ | (1 << theFlag);
0307   else
0308     flags_ = flags_ ^ (1 << theFlag);
0309 }
0310 
0311 bool PFCandidate::flag(Flags theFlag) const { return (flags_ >> theFlag) & 1; }
0312 
0313 ostream& reco::operator<<(ostream& out, const PFCandidate& c) {
0314   if (!out)
0315     return out;
0316 
0317   out << "\tPFCandidate type: " << c.particleId();
0318   out << setiosflags(ios::right);
0319   out << setiosflags(ios::fixed);
0320   out << setprecision(3);
0321   out << " E/pT/eta/phi " << c.energy() << "/" << c.pt() << "/" << c.eta() << "/" << c.phi();
0322   if (c.flag(PFCandidate::T_FROM_DISP))
0323     out << ", T_FROM_DISP" << endl;
0324   else if (c.flag(PFCandidate::T_TO_DISP))
0325     out << ", T_TO_DISP" << endl;
0326   else if (c.flag(PFCandidate::T_FROM_GAMMACONV))
0327     out << ", T_FROM_GAMMACONV" << endl;
0328   else if (c.flag(PFCandidate::GAMMA_TO_GAMMACONV))
0329     out << ", GAMMA_TO_GAMMACONV" << endl;
0330 
0331   out << ", blocks/iele: ";
0332 
0333   PFCandidate::ElementsInBlocks eleInBlocks = c.elementsInBlocks();
0334   for (unsigned i = 0; i < eleInBlocks.size(); i++) {
0335     PFBlockRef blockRef = eleInBlocks[i].first;
0336     unsigned indexInBlock = eleInBlocks[i].second;
0337 
0338     out << "(" << blockRef.key() << "|" << indexInBlock << "), ";
0339   }
0340 
0341   out << " source:" << c.sourcePtr_.id() << "/" << c.sourcePtr_.key();
0342 
0343   //   PFBlockRef blockRef = c.block();
0344   //   int blockid = blockRef.key();
0345   //   const edm::OwnVector< reco::PFBlockElement >& elements = c.elements();
0346   //   out<< "\t# of elements " << elements.size()
0347   //      <<" from block " << blockid << endl;
0348 
0349   //   // print each element in turn
0350 
0351   //   for(unsigned ie=0; ie<elements.size(); ie++) {
0352   //     out<<"\t"<< elements[ie] <<endl;
0353   //   }
0354 
0355   // Improved printout for electrons if PFCandidateElectronExtra is available
0356   if (c.particleId() == PFCandidate::e && c.electronExtraRef().isNonnull() && c.electronExtraRef().isAvailable()) {
0357     out << std::endl << *(c.electronExtraRef());
0358   }
0359   out << resetiosflags(ios::right | ios::fixed);
0360   return out;
0361 }
0362 
0363 static unsigned long long bitPackRefInfo(const edm::RefCore& iCore, size_t iIndex) {
0364   unsigned long long bitPack = iIndex;
0365   bitPack |= static_cast<unsigned long long>(iCore.id().productIndex()) << 32;
0366   bitPack |= static_cast<unsigned long long>(iCore.id().processIndex()) << 48;
0367   return bitPack;
0368 }
0369 
0370 void PFCandidate::storeRefInfo(unsigned int iMask,
0371                                unsigned int iBit,
0372                                bool iIsValid,
0373                                const edm::RefCore& iCore,
0374                                size_t iKey,
0375                                const edm::EDProductGetter* iGetter) {
0376   size_t index = s_refsBefore[storedRefsBitPattern_ & iMask];
0377   if (nullptr == getter_) {
0378     getter_ = iGetter;
0379   }
0380 
0381   if (iIsValid) {
0382     if (0 == (storedRefsBitPattern_ & iBit)) {
0383       refsInfo_.insert(refsInfo_.begin() + index, bitPackRefInfo(iCore, iKey));
0384       if (iGetter == nullptr)
0385         refsCollectionCache_.insert(refsCollectionCache_.begin() + index, static_cast<void const*>(iCore.productPtr()));
0386       else
0387         refsCollectionCache_.insert(refsCollectionCache_.begin() + index, nullptr);
0388     } else {
0389       assert(refsInfo_.size() > index);
0390       *(refsInfo_.begin() + index) = bitPackRefInfo(iCore, iKey);
0391       if (iGetter == nullptr)
0392         *(refsCollectionCache_.begin() + index) = static_cast<void const*>(iCore.productPtr());
0393       else
0394         *(refsCollectionCache_.begin() + index) = nullptr;
0395     }
0396     storedRefsBitPattern_ |= iBit;
0397   } else {
0398     if (storedRefsBitPattern_ & iBit) {
0399       refsInfo_.erase(refsInfo_.begin() + index);
0400       refsCollectionCache_.erase(refsCollectionCache_.begin() + index);
0401       storedRefsBitPattern_ ^= iBit;
0402     }
0403   }
0404 }
0405 
0406 bool PFCandidate::getRefInfo(
0407     unsigned int iMask, unsigned int iBit, edm::ProductID& oProductID, size_t& oIndex, size_t& aIndex) const {
0408   if (0 == (iBit & storedRefsBitPattern_)) {
0409     return false;
0410   }
0411   aIndex = s_refsBefore[storedRefsBitPattern_ & iMask];
0412   unsigned long long bitPacked = refsInfo_[aIndex];
0413   oIndex = bitPacked & 0xFFFFFFFFULL;  //low 32 bits are the index
0414   unsigned short productIndex = (bitPacked & 0x0000FFFF00000000ULL) >> 32;
0415   unsigned short processIndex = (bitPacked & 0xFFFF000000000000ULL) >> 48;
0416   oProductID = edm::ProductID(processIndex, productIndex);
0417   return true;
0418 }
0419 
0420 void PFCandidate::setTrackRef(const reco::TrackRef& iRef) {
0421   if (!charge()) {
0422     string err;
0423     err += "PFCandidate::setTrackRef: this is a neutral candidate! ";
0424     err += "particleId_=";
0425     char num[4];
0426     sprintf(num, "%d", particleId());
0427     err += num;
0428 
0429     throw cms::Exception("InconsistentReference", err.c_str());
0430   }
0431 
0432   storeRefInfo(kRefTrackMask, kRefTrackBit, iRef.isNonnull(), iRef.refCore(), iRef.key(), iRef.productGetter());
0433 }
0434 
0435 reco::TrackRef PFCandidate::trackRef() const { GETREF(reco::Track, kRefTrackMask, kRefTrackBit); }
0436 
0437 void PFCandidate::setMuonRef(reco::MuonRef const& iRef) {
0438   if (trackRef() != iRef->track()) {
0439     string err;
0440     err += "PFCandidate::setMuonRef: inconsistent track references!";
0441 
0442     throw cms::Exception("InconsistentReference", err.c_str());
0443   }
0444 
0445   storeRefInfo(kRefMuonMask, kRefMuonBit, iRef.isNonnull(), iRef.refCore(), iRef.key(), iRef.productGetter());
0446 }
0447 
0448 reco::MuonRef PFCandidate::muonRef() const { GETREF(reco::Muon, kRefMuonMask, kRefMuonBit); }
0449 
0450 //////////////
0451 void PFCandidate::setGsfTrackRef(reco::GsfTrackRef const& iRef) {
0452   //  Removed by F. Beaudette. Would like to be able to save the GsfTrackRef even for charged pions
0453   //  if( particleId() != e ) {
0454   //    string err;
0455   //    err += "PFCandidate::setGsfTrackRef: this is not an electron ! particleId_=";
0456   //    char num[4];
0457   //    sprintf( num, "%d", particleId());
0458   //    err += num;
0459   //
0460   //    throw cms::Exception("InconsistentReference",
0461   //                         err.c_str() );
0462   //  }
0463 
0464   storeRefInfo(kRefGsfTrackMask, kRefGsfTrackBit, iRef.isNonnull(), iRef.refCore(), iRef.key(), iRef.productGetter());
0465 }
0466 
0467 reco::GsfTrackRef PFCandidate::gsfTrackRef() const { GETREF(reco::GsfTrack, kRefGsfTrackMask, kRefGsfTrackBit); }
0468 
0469 //////////////
0470 void PFCandidate::setDisplacedVertexRef(const reco::PFDisplacedVertexRef& iRef, Flags type) {
0471   if (particleId() != h) {
0472     string err;
0473     err += "PFCandidate::setDisplacedVertexRef: this is not a hadron! particleId_=";
0474     char num[4];
0475     sprintf(num, "%d", particleId());
0476     err += num;
0477 
0478     throw cms::Exception("InconsistentReference", err.c_str());
0479   } else if (!flag(T_FROM_DISP) && !flag(T_TO_DISP)) {
0480     string err;
0481     err += "PFCandidate::setDisplacedVertexRef: particule flag is neither T_FROM_DISP nor T_TO_DISP";
0482 
0483     throw cms::Exception("InconsistentReference", err.c_str());
0484   }
0485 
0486   if (type == T_TO_DISP && flag(T_TO_DISP))
0487     storeRefInfo(kRefDisplacedVertexDauMask,
0488                  kRefDisplacedVertexDauBit,
0489                  iRef.isNonnull(),
0490                  iRef.refCore(),
0491                  iRef.key(),
0492                  iRef.productGetter());
0493   else if (type == T_FROM_DISP && flag(T_FROM_DISP))
0494     storeRefInfo(kRefDisplacedVertexMotMask,
0495                  kRefDisplacedVertexMotBit,
0496                  iRef.isNonnull(),
0497                  iRef.refCore(),
0498                  iRef.key(),
0499                  iRef.productGetter());
0500   else if ((type == T_FROM_DISP && !flag(T_FROM_DISP)) || (type == T_TO_DISP && !flag(T_TO_DISP))) {
0501     string err;
0502     err += "PFCandidate::setDisplacedVertexRef: particule flag is not switched on";
0503 
0504     throw cms::Exception("InconsistentReference", err.c_str());
0505   }
0506 }
0507 
0508 reco::PFDisplacedVertexRef PFCandidate::displacedVertexRef(Flags type) const {
0509   if (type == T_TO_DISP) {
0510     GETREF(reco::PFDisplacedVertex, kRefDisplacedVertexDauMask, kRefDisplacedVertexDauBit);
0511   } else if (type == T_FROM_DISP) {
0512     GETREF(reco::PFDisplacedVertex, kRefDisplacedVertexMotMask, kRefDisplacedVertexMotBit);
0513   }
0514   return reco::PFDisplacedVertexRef();
0515 }
0516 
0517 //////////////
0518 void PFCandidate::setConversionRef(reco::ConversionRef const& iRef) {
0519   if (particleId() != gamma) {
0520     string err;
0521     err += "PFCandidate::setConversionRef: this is not a (converted) photon ! particleId_=";
0522     char num[4];
0523     sprintf(num, "%d", particleId());
0524     err += num;
0525 
0526     throw cms::Exception("InconsistentReference", err.c_str());
0527   } else if (!flag(GAMMA_TO_GAMMACONV)) {
0528     string err;
0529     err += "PFCandidate::setConversionRef: particule flag is not GAMMA_TO_GAMMACONV";
0530 
0531     throw cms::Exception("InconsistentReference", err.c_str());
0532   }
0533 
0534   storeRefInfo(
0535       kRefConversionMask, kRefConversionBit, iRef.isNonnull(), iRef.refCore(), iRef.key(), iRef.productGetter());
0536 }
0537 
0538 reco::ConversionRef PFCandidate::conversionRef() const {
0539   GETREF(reco::Conversion, kRefConversionMask, kRefConversionBit);
0540 }
0541 
0542 //////////////
0543 void PFCandidate::setV0Ref(reco::VertexCompositeCandidateRef const& iRef) {
0544   storeRefInfo(kRefV0Mask, kRefV0Bit, iRef.isNonnull(), iRef.refCore(), iRef.key(), iRef.productGetter());
0545 }
0546 
0547 reco::VertexCompositeCandidateRef PFCandidate::v0Ref() const {
0548   GETREF(reco::VertexCompositeCandidate, kRefV0Mask, kRefV0Bit);
0549 }
0550 
0551 //////////////
0552 void PFCandidate::setGsfElectronRef(reco::GsfElectronRef const& iRef) {
0553   storeRefInfo(
0554       kRefGsfElectronMask, kRefGsfElectronBit, iRef.isNonnull(), iRef.refCore(), iRef.key(), iRef.productGetter());
0555 }
0556 
0557 reco::GsfElectronRef PFCandidate::gsfElectronRef() const {
0558   GETREF(reco::GsfElectron, kRefGsfElectronMask, kRefGsfElectronBit);
0559 }
0560 
0561 //////////////
0562 void PFCandidate::setPFElectronExtraRef(reco::PFCandidateElectronExtraRef const& iRef) {
0563   storeRefInfo(kRefPFElectronExtraMask,
0564                kRefPFElectronExtraBit,
0565                iRef.isNonnull(),
0566                iRef.refCore(),
0567                iRef.key(),
0568                iRef.productGetter());
0569 }
0570 
0571 reco::PFCandidateElectronExtraRef PFCandidate::electronExtraRef() const {
0572   GETREF(reco::PFCandidateElectronExtra, kRefPFElectronExtraMask, kRefPFElectronExtraBit);
0573 }
0574 
0575 reco::PhotonRef PFCandidate::photonRef() const { GETREF(reco::Photon, kRefPhotonMask, kRefPhotonBit); }
0576 
0577 reco::PFCandidatePhotonExtraRef PFCandidate::photonExtraRef() const {
0578   GETREF(reco::PFCandidatePhotonExtra, kRefPFPhotonExtraMask, kRefPFPhotonExtraBit);
0579 }
0580 
0581 reco::PFCandidateEGammaExtraRef PFCandidate::egammaExtraRef() const {
0582   GETREF(reco::PFCandidateEGammaExtra, kRefPFEGammaExtraMask, kRefPFEGammaExtraBit);
0583 }
0584 
0585 reco::SuperClusterRef PFCandidate::superClusterRef() const {
0586   GETREF(reco::SuperCluster, kRefSuperClusterMask, kRefSuperClusterBit);
0587 }
0588 
0589 void PFCandidate::setPhotonRef(const reco::PhotonRef& iRef) {
0590   if (particleId() != gamma && particleId() != e) {
0591     string err;
0592     err += "PFCandidate::setSuperClusterRef: this is not an electron neither a photon ! particleId_=";
0593     char num[4];
0594     sprintf(num, "%d", particleId());
0595     err += num;
0596 
0597     throw cms::Exception("InconsistentReference", err.c_str());
0598   }
0599 
0600   storeRefInfo(kRefPhotonMask, kRefPhotonBit, iRef.isNonnull(), iRef.refCore(), iRef.key(), iRef.productGetter());
0601 }
0602 
0603 void PFCandidate::setSuperClusterRef(const reco::SuperClusterRef& iRef) {
0604   if (particleId() != gamma && particleId() != e) {
0605     string err;
0606     err += "PFCandidate::setSuperClusterRef: this is not an electron neither a photon ! particleId_=";
0607     char num[4];
0608     sprintf(num, "%d", particleId());
0609     err += num;
0610 
0611     throw cms::Exception("InconsistentReference", err.c_str());
0612   }
0613 
0614   storeRefInfo(
0615       kRefSuperClusterMask, kRefSuperClusterBit, iRef.isNonnull(), iRef.refCore(), iRef.key(), iRef.productGetter());
0616 }
0617 
0618 void PFCandidate::setPFPhotonExtraRef(const reco::PFCandidatePhotonExtraRef& iRef) {
0619   storeRefInfo(
0620       kRefPFPhotonExtraMask, kRefPFPhotonExtraBit, iRef.isNonnull(), iRef.refCore(), iRef.key(), iRef.productGetter());
0621 }
0622 
0623 void PFCandidate::setPFEGammaExtraRef(const reco::PFCandidateEGammaExtraRef& iRef) {
0624   storeRefInfo(
0625       kRefPFEGammaExtraMask, kRefPFEGammaExtraBit, iRef.isNonnull(), iRef.refCore(), iRef.key(), iRef.productGetter());
0626 }
0627 
0628 const math::XYZPoint& PFCandidate::vertexLegacy(PFCandidate::PFVertexType vertexType) const {
0629   switch (vertexType) {
0630     case kCandVertex:
0631       return LeafCandidate::vertex();
0632       break;
0633     //the following cases will only be called for legacy AOD which does not have an embedded vertex
0634     case kTrkVertex:
0635       return trackRef()->vertex();
0636       break;
0637     case kComMuonVertex:
0638       return muonRef()->combinedMuon()->vertex();
0639       break;
0640     case kSAMuonVertex:
0641       return muonRef()->standAloneMuon()->vertex();
0642       break;
0643     case kTrkMuonVertex:
0644       return muonRef()->track()->vertex();
0645       break;
0646     case kTPFMSMuonVertex:
0647       return muonRef()->tpfmsTrack()->vertex();
0648       break;
0649     case kPickyMuonVertex:
0650       return muonRef()->pickyTrack()->vertex();
0651       break;
0652     case kDYTMuonVertex:
0653       return muonRef()->dytTrack()->vertex();
0654       break;
0655 
0656     case kGSFVertex:
0657       return gsfTrackRef()->vertex();
0658       break;
0659   }
0660   return LeafCandidate::vertex();
0661 }
0662 
0663 const PFCandidate::ElementsInBlocks& PFCandidate::elementsInBlocks() const {
0664   if (nullptr == elementsInBlocks_.load(std::memory_order_acquire)) {
0665     std::unique_ptr<ElementsInBlocks> temp(new ElementsInBlocks(blocksStorage_.size()));
0666     for (unsigned int icopy = 0; icopy != blocksStorage_.size(); ++icopy)
0667       (*temp)[icopy] = std::make_pair(blocksStorage_[icopy], elementsStorage_[icopy]);
0668     ElementsInBlocks* expected = nullptr;
0669     if (elementsInBlocks_.compare_exchange_strong(expected, temp.get(), std::memory_order_acq_rel)) {
0670       temp.release();
0671     }
0672   }
0673   return *(elementsInBlocks_.load(std::memory_order_acquire));
0674 }