CMS 3D CMS Logo

List of all members | Public Member Functions | Private Member Functions | Private Attributes | Friends
PFAlgo Class Reference

#include <PFAlgo.h>

Public Member Functions

void checkCleaning (const reco::PFRecHitCollection &cleanedHF)
 Check HF Cleaning. More...
 
reco::PFCandidateCollectiongetCleanedCandidates ()
 
PFMuonAlgogetPFMuonAlgo ()
 
reco::PFCandidateCollection makeConnectedCandidates ()
 
 PFAlgo (double nSigmaECAL, double nSigmaHCAL, double nSigmaHFEM, double nSigmaHFHAD, std::vector< double > resolHF_square, PFEnergyCalibration &calibration, PFEnergyCalibrationHF &thepfEnergyCalibrationHF, const edm::ParameterSet &pset)
 constructor More...
 
void reconstructParticles (const reco::PFBlockHandle &blockHandle, PFEGammaFilters const *pfegamma)
 reconstruct particles More...
 
void setCandConnectorParameters (bool bCorrect, bool bCalibPrimary, double dptRel_PrimaryTrack, double dptRel_MergedTrack, double ptErrorSecondary, const std::vector< double > &nuclCalibFactors)
 
void setCandConnectorParameters (const edm::ParameterSet &iCfgCandConnector)
 
void setDisplacedVerticesParameters (bool rejectTracks_Bad, bool rejectTracks_Step45, bool usePFNuclearInteractions, bool usePFConversions, bool usePFDecays, double dptRel_DispVtx)
 
void setEGammaCollections (const edm::View< reco::PFCandidate > &pfEgammaCandidates, const edm::ValueMap< reco::GsfElectronRef > &valueMapGedElectrons, const edm::ValueMap< reco::PhotonRef > &valueMapGedPhotons)
 
void setEGammaParameters (bool use_EGammaFilters, bool useProtectionsForJetMET)
 
void setEGElectronCollection (const reco::GsfElectronCollection &egelectrons)
 
void setHOTag (bool ho)
 
void setMuonHandle (const edm::Handle< reco::MuonCollection > &)
 
void setPFVertexParameters (bool useVertex, reco::VertexCollection const &primaryVertices)
 
void setPostHFCleaningParameters (bool postHFCleaning, const edm::ParameterSet &pfHFCleaningParams)
 

Private Member Functions

void associatePSClusters (unsigned iEcal, reco::PFBlockElement::Type psElementType, const reco::PFBlock &block, const edm::OwnVector< reco::PFBlockElement > &elements, const reco::PFBlock::LinkData &linkData, std::vector< bool > &active, std::vector< double > &psEne)
 Associate PS clusters to a given ECAL cluster, and return their energy. More...
 
bool checkAndReconstructSecondaryInteraction (const reco::PFBlockRef &blockref, const edm::OwnVector< reco::PFBlockElement > &elements, bool isActive, int iElement)
 
bool checkGoodTrackDeadHcal (const reco::TrackRef &trackRef, bool hasDeadHcal)
 
bool checkHasDeadHcal (const std::multimap< double, unsigned > &hcalElems, const std::vector< bool > &deadArea)
 
void conversionAlgo (const edm::OwnVector< reco::PFBlockElement > &elements, std::vector< bool > &active)
 
void createCandidatesECAL (const reco::PFBlock &block, reco::PFBlock::LinkData &linkData, const edm::OwnVector< reco::PFBlockElement > &elements, std::vector< bool > &active, const reco::PFBlockRef &blockref, ElementIndices &inds, std::vector< bool > &deadArea)
 
void createCandidatesHCAL (const reco::PFBlock &block, reco::PFBlock::LinkData &linkData, const edm::OwnVector< reco::PFBlockElement > &elements, std::vector< bool > &active, const reco::PFBlockRef &blockref, ElementIndices &inds, std::vector< bool > &deadArea)
 
void createCandidatesHCALUnlinked (const reco::PFBlock &block, reco::PFBlock::LinkData &linkData, const edm::OwnVector< reco::PFBlockElement > &elements, std::vector< bool > &active, const reco::PFBlockRef &blockref, ElementIndices &inds, std::vector< bool > &deadArea)
 
void createCandidatesHF (const reco::PFBlock &block, reco::PFBlock::LinkData &linkData, const edm::OwnVector< reco::PFBlockElement > &elements, std::vector< bool > &active, const reco::PFBlockRef &blockref, ElementIndices &inds)
 
int decideType (const edm::OwnVector< reco::PFBlockElement > &elements, const reco::PFBlockElement::Type type, std::vector< bool > &active, ElementIndices &inds, std::vector< bool > &deadArea, unsigned int iEle)
 
void egammaFilters (const reco::PFBlockRef &blockref, std::vector< bool > &active, PFEGammaFilters const *pfegamma)
 
void elementLoop (const reco::PFBlock &block, reco::PFBlock::LinkData &linkData, const edm::OwnVector< reco::PFBlockElement > &elements, std::vector< bool > &active, const reco::PFBlockRef &blockref, ElementIndices &inds, std::vector< bool > &deadArea)
 
double hfEnergyResolution (double clusterEnergy) const
 
bool isFromSecInt (const reco::PFBlockElement &eTrack, std::string order) const
 
double neutralHadronEnergyResolution (double clusterEnergy, double clusterEta) const
 todo: use PFClusterTools for this More...
 
double nSigmaHCAL (double clusterEnergy, double clusterEta) const
 
double nSigmaHFEM (double clusterEnergy) const
 
double nSigmaHFHAD (double clusterEnergy) const
 
void postCleaning ()
 
void processBlock (const reco::PFBlockRef &blockref, std::list< reco::PFBlockRef > &hcalBlockRefs, std::list< reco::PFBlockRef > &ecalBlockRefs, PFEGammaFilters const *pfegamma)
 
unsigned reconstructCluster (const reco::PFCluster &cluster, double particleEnergy, bool useDirection=false, double particleX=0., double particleY=0., double particleZ=0.)
 
unsigned reconstructTrack (const reco::PFBlockElement &elt, bool allowLoose=false)
 
bool recoTracksNotHCAL (const reco::PFBlock &block, reco::PFBlock::LinkData &linkData, const edm::OwnVector< reco::PFBlockElement > &elements, const reco::PFBlockRef &blockref, std::vector< bool > &active, bool goodTrackDeadHcal, bool hasDeadHcal, unsigned int iTrack, std::multimap< double, unsigned > &ecalElems, reco::TrackRef &trackRef)
 
void relinkTrackToHcal (const reco::PFBlock &block, std::multimap< double, unsigned > &ecalElems, std::multimap< double, unsigned > &hcalElems, const std::vector< bool > &active, reco::PFBlock::LinkData &linkData, unsigned int iTrack)
 
void setHcalDepthInfo (reco::PFCandidate &cand, const reco::PFCluster &cluster) const
 

Private Attributes

PFEnergyCalibrationcalibration_
 
PFCandConnector connector_
 
double dptRel_DispVtx_
 
std::vector< double > factors45_
 
float goodPixelTrackDeadHcal_chi2n_
 
float goodPixelTrackDeadHcal_dxy_
 
float goodPixelTrackDeadHcal_dz_
 
int goodPixelTrackDeadHcal_maxLost3Hit_
 
int goodPixelTrackDeadHcal_maxLost4Hit_
 
float goodPixelTrackDeadHcal_maxPt_
 
float goodPixelTrackDeadHcal_minEta_
 
float goodPixelTrackDeadHcal_ptErrRel_
 
float goodTrackDeadHcal_chi2n_
 
float goodTrackDeadHcal_dxy_
 
int goodTrackDeadHcal_layers_
 
float goodTrackDeadHcal_ptErrRel_
 Variables for track cleaning in bad HCal areas. More...
 
float goodTrackDeadHcal_validFr_
 
double maxDeltaPhiPt_
 
double maxSignificance_
 
double minDeltaMet_
 
double minHFCleaningPt_
 
double minSignificance_
 
double minSignificanceReduction_
 
std::vector< double > muonECAL_
 
edm::Handle< reco::MuonCollectionmuonHandle_
 
std::vector< double > muonHCAL_
 Variables for muons and fakes. More...
 
std::vector< double > muonHO_
 
const double nSigmaECAL_
 number of sigma to judge energy excess in ECAL More...
 
const double nSigmaEConstHCAL = 100.
 
const double nSigmaEConstHFEM = 100.
 
const double nSigmaEConstHFHAD = 100.
 
const double nSigmaHCAL_
 number of sigma to judge energy excess in HCAL More...
 
const double nSigmaHFEM_
 number of sigma to judge energy excess in HF More...
 
const double nSigmaHFHAD_
 
double nSigmaTRACK_
 
int nVtx_
 
std::unique_ptr< reco::PFCandidateCollectionpfCandidates_
 
reco::PFCandidateCollection pfCleanedCandidates_
 
const edm::View< reco::PFCandidate > * pfEgammaCandidates_
 
std::unique_ptr< PFMuonAlgopfmu_
 
bool postHFCleaning_
 
bool postMuonCleaning_
 
reco::Vertex primaryVertex_
 
double ptError_
 
bool rejectTracks_Bad_
 
bool rejectTracks_Step45_
 
const std::vector< double > resolHF_square_
 
PFEnergyCalibrationHFthepfEnergyCalibrationHF_
 
double useBestMuonTrack_
 
bool useEGammaFilters_
 Variables for NEW EGAMMA selection. More...
 
bool useHO_
 
bool usePFConversions_
 
bool usePFDecays_
 
bool usePFMuonMomAssign_
 
bool usePFNuclearInteractions_
 
bool useProtectionsForJetMET_
 
bool useVertices_ = false
 
const edm::ValueMap< reco::GsfElectronRef > * valueMapGedElectrons_
 
const edm::ValueMap< reco::PhotonRef > * valueMapGedPhotons_
 

Friends

std::ostream & operator<< (std::ostream &out, const PFAlgo &algo)
 

Detailed Description

Definition at line 53 of file PFAlgo.h.

Constructor & Destructor Documentation

◆ PFAlgo()

PFAlgo::PFAlgo ( double  nSigmaECAL,
double  nSigmaHCAL,
double  nSigmaHFEM,
double  nSigmaHFHAD,
std::vector< double >  resolHF_square,
PFEnergyCalibration calibration,
PFEnergyCalibrationHF thepfEnergyCalibrationHF,
const edm::ParameterSet pset 
)

constructor

Definition at line 15 of file PFAlgo.cc.

24  nSigmaECAL_(nSigmaECAL),
30  thepfEnergyCalibrationHF_(thepfEnergyCalibrationHF),
31  connector_() {
32  const edm::ParameterSet pfMuonAlgoParams = pset.getParameter<edm::ParameterSet>("PFMuonAlgoParameters");
33  bool postMuonCleaning = pset.getParameter<bool>("postMuonCleaning");
34  pfmu_ = std::make_unique<PFMuonAlgo>(pfMuonAlgoParams, postMuonCleaning);
35 
36  // HF resolution parameters
37  assert(resolHF_square_.size() == 3); // make sure that stochastic, constant, noise (i.e. three) terms are specified.
38 
39  // Muon parameters
40  muonHCAL_ = pset.getParameter<std::vector<double>>("muon_HCAL");
41  muonECAL_ = pset.getParameter<std::vector<double>>("muon_ECAL");
42  muonHO_ = pset.getParameter<std::vector<double>>("muon_HO");
43  assert(muonHCAL_.size() == 2 && muonECAL_.size() == 2 && muonHO_.size() == 2);
44  nSigmaTRACK_ = pset.getParameter<double>("nsigma_TRACK");
45  ptError_ = pset.getParameter<double>("pt_Error");
46  factors45_ = pset.getParameter<std::vector<double>>("factors_45");
47  assert(factors45_.size() == 2);
48 
49  // Bad Hcal Track Parameters
50  goodTrackDeadHcal_ptErrRel_ = pset.getParameter<double>("goodTrackDeadHcal_ptErrRel");
51  goodTrackDeadHcal_chi2n_ = pset.getParameter<double>("goodTrackDeadHcal_chi2n");
52  goodTrackDeadHcal_layers_ = pset.getParameter<uint32_t>("goodTrackDeadHcal_layers");
53  goodTrackDeadHcal_validFr_ = pset.getParameter<double>("goodTrackDeadHcal_validFr");
54  goodTrackDeadHcal_dxy_ = pset.getParameter<double>("goodTrackDeadHcal_dxy");
55 
56  goodPixelTrackDeadHcal_minEta_ = pset.getParameter<double>("goodPixelTrackDeadHcal_minEta");
57  goodPixelTrackDeadHcal_maxPt_ = pset.getParameter<double>("goodPixelTrackDeadHcal_maxPt");
58  goodPixelTrackDeadHcal_ptErrRel_ = pset.getParameter<double>("goodPixelTrackDeadHcal_ptErrRel");
59  goodPixelTrackDeadHcal_chi2n_ = pset.getParameter<double>("goodPixelTrackDeadHcal_chi2n");
60  goodPixelTrackDeadHcal_maxLost3Hit_ = pset.getParameter<int32_t>("goodPixelTrackDeadHcal_maxLost3Hit");
61  goodPixelTrackDeadHcal_maxLost4Hit_ = pset.getParameter<int32_t>("goodPixelTrackDeadHcal_maxLost4Hit");
62  goodPixelTrackDeadHcal_dxy_ = pset.getParameter<double>("goodPixelTrackDeadHcal_dxy");
63  goodPixelTrackDeadHcal_dz_ = pset.getParameter<double>("goodPixelTrackDeadHcal_dz");
64 }

References cms::cuda::assert(), factors45_, goodPixelTrackDeadHcal_chi2n_, goodPixelTrackDeadHcal_dxy_, goodPixelTrackDeadHcal_dz_, goodPixelTrackDeadHcal_maxLost3Hit_, goodPixelTrackDeadHcal_maxLost4Hit_, goodPixelTrackDeadHcal_maxPt_, goodPixelTrackDeadHcal_minEta_, goodPixelTrackDeadHcal_ptErrRel_, goodTrackDeadHcal_chi2n_, goodTrackDeadHcal_dxy_, goodTrackDeadHcal_layers_, goodTrackDeadHcal_ptErrRel_, goodTrackDeadHcal_validFr_, muonECAL_, muonHCAL_, muonHO_, nSigmaTRACK_, pfmu_, HLT_2018_cff::postMuonCleaning, muonDTDigis_cfi::pset, ptError_, and resolHF_square_.

Member Function Documentation

◆ associatePSClusters()

void PFAlgo::associatePSClusters ( unsigned  iEcal,
reco::PFBlockElement::Type  psElementType,
const reco::PFBlock block,
const edm::OwnVector< reco::PFBlockElement > &  elements,
const reco::PFBlock::LinkData linkData,
std::vector< bool > &  active,
std::vector< double > &  psEne 
)
private

Associate PS clusters to a given ECAL cluster, and return their energy.

Definition at line 3419 of file PFAlgo.cc.

3425  {
3426  // Find all PS clusters with type psElement associated to ECAL cluster iEcal,
3427  // within all PFBlockElement "elements" of a given PFBlock "block"
3428  // psElement can be reco::PFBlockElement::PS1 or reco::PFBlockElement::PS2
3429  // Returns a vector of PS cluster energies, and updates the "active" vector.
3430 
3431  // Find all PS clusters linked to the iEcal cluster
3432  std::multimap<double, unsigned> sortedPS;
3433  block.associatedElements(iEcal, linkData, sortedPS, psElementType, reco::PFBlock::LINKTEST_ALL);
3434 
3435  // Loop over these PS clusters
3436  double totalPS = 0.;
3437  for (auto const& ps : sortedPS) {
3438  // CLuster index and distance to iEcal
3439  unsigned iPS = ps.second;
3440  // double distPS = ps.first;
3441 
3442  // Ignore clusters already in use
3443  if (!active[iPS])
3444  continue;
3445 
3446  // Check that this cluster is not closer to another ECAL cluster
3447  std::multimap<double, unsigned> sortedECAL;
3448  block.associatedElements(iPS, linkData, sortedECAL, reco::PFBlockElement::ECAL, reco::PFBlock::LINKTEST_ALL);
3449  unsigned jEcal = sortedECAL.begin()->second;
3450  if (jEcal != iEcal)
3451  continue;
3452 
3453  // Update PS energy
3454  PFBlockElement::Type pstype = elements[iPS].type();
3455  assert(pstype == psElementType);
3456  PFClusterRef psclusterref = elements[iPS].clusterRef();
3457  assert(!psclusterref.isNull());
3458  totalPS += psclusterref->energy();
3459  psEne[0] += psclusterref->energy();
3460  active[iPS] = false;
3461  }
3462 }

References cms::cuda::assert(), groupFilesInBlocks::block, reco::PFBlockElement::ECAL, bookConverter::elements, edm::Ref< C, T, F >::isNull(), and reco::PFBlock::LINKTEST_ALL.

Referenced by recoTracksNotHCAL().

◆ checkAndReconstructSecondaryInteraction()

bool PFAlgo::checkAndReconstructSecondaryInteraction ( const reco::PFBlockRef blockref,
const edm::OwnVector< reco::PFBlockElement > &  elements,
bool  isActive,
int  iElement 
)
private

Definition at line 849 of file PFAlgo.cc.

852  {
853  bool ret = isActive;
854  if (isActive && isFromSecInt(elements[iElement], "primary")) {
855  bool isPrimaryTrack =
856  elements[iElement].displacedVertexRef(PFBlockElement::T_TO_DISP)->displacedVertexRef()->isTherePrimaryTracks();
857  if (isPrimaryTrack) {
858  LogTrace("PFAlgo|elementLoop") << "Primary Track reconstructed alone";
859 
860  unsigned tmpi = reconstructTrack(elements[iElement]);
861  (*pfCandidates_)[tmpi].addElementInBlock(blockref, iElement);
862  ret = false;
863  }
864  }
865 
866  return ret;
867 }

References bookConverter::elements, isFromSecInt(), LogTrace, reconstructTrack(), and runTheMatrix::ret.

Referenced by elementLoop().

◆ checkCleaning()

void PFAlgo::checkCleaning ( const reco::PFRecHitCollection cleanedHF)

Check HF Cleaning.

Definition at line 3589 of file PFAlgo.cc.

3589  {
3590  // No hits to recover, leave.
3591  if (cleanedHits.empty())
3592  return;
3593 
3594  //Compute met and met significance (met/sqrt(SumEt))
3595  double metX = 0.;
3596  double metY = 0.;
3597  double sumet = 0;
3598  std::vector<unsigned int> hitsToBeAdded;
3599  for (auto const& pfc : *pfCandidates_) {
3600  metX += pfc.px();
3601  metY += pfc.py();
3602  sumet += pfc.pt();
3603  }
3604  double met2 = metX * metX + metY * metY;
3605  double met2_Original = met2;
3606  // Select events with large MET significance.
3607  // double significance = std::sqrt(met2/sumet);
3608  // double significanceCor = significance;
3609  double metXCor = metX;
3610  double metYCor = metY;
3611  double sumetCor = sumet;
3612  double met2Cor = met2;
3613  bool next = true;
3614  unsigned iCor = 1E9;
3615 
3616  // Find the cleaned hit with the largest effect on the MET
3617  while (next) {
3618  double metReduc = -1.;
3619  // Loop on the candidates
3620  for (unsigned i = 0; i < cleanedHits.size(); ++i) {
3621  const PFRecHit& hit = cleanedHits[i];
3622  double length = std::sqrt(hit.position().mag2());
3623  double px = hit.energy() * hit.position().x() / length;
3624  double py = hit.energy() * hit.position().y() / length;
3625  double pt = std::sqrt(px * px + py * py);
3626 
3627  // Check that it is not already scheculed to be cleaned
3628  bool skip = false;
3629  for (unsigned int hitIdx : hitsToBeAdded) {
3630  if (i == hitIdx)
3631  skip = true;
3632  if (skip)
3633  break;
3634  }
3635  if (skip)
3636  continue;
3637 
3638  // Now add the candidate to the MET
3639  double metXInt = metX + px;
3640  double metYInt = metY + py;
3641  double sumetInt = sumet + pt;
3642  double met2Int = metXInt * metXInt + metYInt * metYInt;
3643 
3644  // And check if it could contribute to a MET reduction
3645  if (met2Int < met2Cor) {
3646  metXCor = metXInt;
3647  metYCor = metYInt;
3648  metReduc = (met2 - met2Int) / met2Int;
3649  met2Cor = met2Int;
3650  sumetCor = sumetInt;
3651  // significanceCor = std::sqrt(met2Cor/sumetCor);
3652  iCor = i;
3653  }
3654  }
3655  //
3656  // If the MET must be significanly reduced, schedule the candidate to be added
3657  //
3658  if (metReduc > minDeltaMet_) {
3659  hitsToBeAdded.push_back(iCor);
3660  metX = metXCor;
3661  metY = metYCor;
3662  sumet = sumetCor;
3663  met2 = met2Cor;
3664  } else {
3665  // Otherwise just stop the loop
3666  next = false;
3667  }
3668  }
3669  //
3670  // At least 10 GeV MET reduction
3671  if (std::sqrt(met2_Original) - std::sqrt(met2) > 5.) {
3672  LogTrace("PFAlgo|checkCleaning") << hitsToBeAdded.size() << " hits were re-added ";
3673  LogTrace("PFAlgo|checkCleaning") << "MET reduction = " << std::sqrt(met2_Original) << " -> " << std::sqrt(met2Cor)
3674  << " = " << std::sqrt(met2Cor) - std::sqrt(met2_Original);
3675  LogTrace("PFAlgo|checkCleaning") << "Added after cleaning check : ";
3676  for (unsigned int hitIdx : hitsToBeAdded) {
3677  const PFRecHit& hit = cleanedHits[hitIdx];
3678  PFCluster cluster(hit.layer(), hit.energy(), hit.position().x(), hit.position().y(), hit.position().z());
3679  reconstructCluster(cluster, hit.energy());
3680  LogTrace("PFAlgo|checkCleaning") << pfCandidates_->back() << ". time = " << hit.time();
3681  }
3682  }
3683 } //PFAlgo::checkCleaning

References mps_fire::i, LogTrace, minDeltaMet_, GetRecoTauVFromDQM_MC_cff::next, pfCandidates_, DiDispStaMuonMonitor_cfi::pt, multPhiCorr_741_25nsDY_cfi::px, multPhiCorr_741_25nsDY_cfi::py, reconstructCluster(), optionsL1T::skip, mathSSE::sqrt(), hit::x, hit::y, and hit::z.

Referenced by PFProducer::produce().

◆ checkGoodTrackDeadHcal()

bool PFAlgo::checkGoodTrackDeadHcal ( const reco::TrackRef trackRef,
bool  hasDeadHcal 
)
private

Definition at line 896 of file PFAlgo.cc.

896  {
897  bool goodTrackDeadHcal = false;
898  if (hasDeadHcal) {
899  goodTrackDeadHcal = (trackRef->ptError() < goodTrackDeadHcal_ptErrRel_ * trackRef->pt() &&
900  trackRef->normalizedChi2() < goodTrackDeadHcal_chi2n_ &&
901  trackRef->hitPattern().trackerLayersWithMeasurement() >= goodTrackDeadHcal_layers_ &&
902  trackRef->validFraction() > goodTrackDeadHcal_validFr_ &&
904  // now we add an extra block for tracks at high |eta|
905  if (!goodTrackDeadHcal && std::abs(trackRef->eta()) > goodPixelTrackDeadHcal_minEta_ && // high eta
906  trackRef->hitPattern().pixelLayersWithMeasurement() >= 3 && // pixel track
907  trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS) == 0 &&
908  trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_INNER_HITS) == 0 &&
909  trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_OUTER_HITS) <=
910  (trackRef->hitPattern().pixelLayersWithMeasurement() > 3 ? goodPixelTrackDeadHcal_maxLost4Hit_
912  trackRef->normalizedChi2() < goodPixelTrackDeadHcal_chi2n_ && // tighter cut
915  trackRef->ptError() < goodPixelTrackDeadHcal_ptErrRel_ * trackRef->pt() && // sanity
916  trackRef->pt() < goodPixelTrackDeadHcal_maxPt_) { // sanity
917  goodTrackDeadHcal = true;
918  // FIXME: may decide to do something to the track pT
919  }
920  //if (!goodTrackDeadHcal && trackRef->hitPattern().trackerLayersWithMeasurement() == 4 && trackRef->validFraction() == 1
921  LogTrace("PFAlgo|elementLoop")
922  << " track pt " << trackRef->pt() << " +- " << trackRef->ptError() << " layers valid "
923  << trackRef->hitPattern().trackerLayersWithMeasurement() << ", lost "
924  << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS) << ", lost outer "
925  << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_OUTER_HITS) << ", lost inner "
926  << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_INNER_HITS) << "(valid fraction "
927  << trackRef->validFraction() << ")"
928  << " chi2/ndf " << trackRef->normalizedChi2() << " |dxy| " << std::abs(trackRef->dxy(primaryVertex_.position()))
929  << " +- " << trackRef->dxyError() << " |dz| " << std::abs(trackRef->dz(primaryVertex_.position())) << " +- "
930  << trackRef->dzError() << (goodTrackDeadHcal ? " passes " : " fails ") << "quality cuts";
931  }
932  return goodTrackDeadHcal;
933 }

References funct::abs(), goodPixelTrackDeadHcal_chi2n_, goodPixelTrackDeadHcal_dxy_, goodPixelTrackDeadHcal_dz_, goodPixelTrackDeadHcal_maxLost3Hit_, goodPixelTrackDeadHcal_maxLost4Hit_, goodPixelTrackDeadHcal_maxPt_, goodPixelTrackDeadHcal_minEta_, goodPixelTrackDeadHcal_ptErrRel_, goodTrackDeadHcal_chi2n_, goodTrackDeadHcal_dxy_, goodTrackDeadHcal_layers_, goodTrackDeadHcal_ptErrRel_, goodTrackDeadHcal_validFr_, LogTrace, reco::Vertex::position(), and primaryVertex_.

Referenced by elementLoop().

◆ checkHasDeadHcal()

bool PFAlgo::checkHasDeadHcal ( const std::multimap< double, unsigned > &  hcalElems,
const std::vector< bool > &  deadArea 
)
private

Definition at line 869 of file PFAlgo.cc.

869  {
870  // there's 3 possible options possible here, in principle:
871  // 1) flag everything that may be associated to a dead hcal marker
872  // 2) flag everything whose closest hcal link is a dead hcal marker
873  // 3) flag only things that are linked only to dead hcal marker
874  // in our first test we go for (2)
875  //--- option (1) --
876  //bool hasDeadHcal = false;
877  //for (auto it = hcalElems.begin(), ed = hcalElems.end(); it != ed; /*NOTE NO ++it HERE */ ) {
878  // if (deadArea[it->second]) { hasDeadHcal = true; it = hcalElems.erase(it); } // std::multimap::erase returns iterator to next
879  // else ++it;
880  //}
881  //--- option (2) --
882  bool hasDeadHcal = false;
883  if (!hcalElems.empty() && deadArea[hcalElems.begin()->second]) {
884  hasDeadHcal = true;
885  }
886  //--- option (3) --
887  //bool hasDeadHcal = true;
888  //for (auto it = hcalElems.begin(), ed = hcalElems.end(); it != ed; /*NOTE NO ++it HERE */ ) {
889  // if (deadArea[it->second]) { it = hcalElems.erase(it); } // std::multimap::erase returns iterator to next
890  // else { hasDeadHcal = false; }
891  //}
892  return hasDeadHcal;
893 }

Referenced by elementLoop().

◆ conversionAlgo()

void PFAlgo::conversionAlgo ( const edm::OwnVector< reco::PFBlockElement > &  elements,
std::vector< bool > &  active 
)
private

Definition at line 364 of file PFAlgo.cc.

364  {
365  LogTrace("PFAlgo|conversionAlgo") << "start of function PFAlgo::conversionAlgo(), elements.size()="
366  << elements.size();
367  for (unsigned iEle = 0; iEle < elements.size(); iEle++) {
368  PFBlockElement::Type type = elements[iEle].type();
369  if (type == PFBlockElement::TRACK) {
370  LogTrace("PFAlgo|conversionAlgo") << "elements[" << iEle << "].type() == TRACK, active[" << iEle
371  << "]=" << active[iEle];
372  if (elements[iEle].trackRef()->algo() == reco::TrackBase::conversionStep) {
373  active[iEle] = false;
374  }
375  if (elements[iEle].trackRef()->quality(reco::TrackBase::highPurity)) {
376  LogTrace("PFAlgo|conversionAlgo") << "Track is high purity";
377  continue;
378  }
379  const auto* trackRef = dynamic_cast<const reco::PFBlockElementTrack*>((&elements[iEle]));
380  if (!(trackRef->trackType(reco::PFBlockElement::T_FROM_GAMMACONV))) {
381  LogTrace("PFAlgo|conversionAlgo") << "!trackType(T_FROM_GAMMACONV)";
382  continue;
383  }
384  if (!elements[iEle].convRefs().empty()) {
385  active[iEle] = false;
386  }
387  LogTrace("PFAlgo|conversionAlgo") << "active[iEle=" << iEle << "]=" << active[iEle];
388  }
389  }
390  LogTrace("PFAlgo|conversionAlgo") << "end of function PFAlgo::conversionAlgo";
391 }

References reco::TrackBase::conversionStep, bookConverter::elements, relativeConstraints::empty, reco::TrackBase::highPurity, LogTrace, qcdUeDQM_cfi::quality, and reco::PFBlockElement::T_FROM_GAMMACONV.

Referenced by processBlock().

◆ createCandidatesECAL()

void PFAlgo::createCandidatesECAL ( const reco::PFBlock block,
reco::PFBlock::LinkData linkData,
const edm::OwnVector< reco::PFBlockElement > &  elements,
std::vector< bool > &  active,
const reco::PFBlockRef blockref,
ElementIndices inds,
std::vector< bool > &  deadArea 
)
private

Definition at line 3006 of file PFAlgo.cc.

3012  {
3013  LogTrace("PFAlgo|createCandidatesECAL")
3014  << "start of function PFAlgo::createCandidatesECAL(), ecalIs.size()=" << inds.ecalIs.size();
3015 
3016  // --------------- loop ecal ------------------
3017 
3018  // for each ecal element iEcal = ecalIs[i] in turn:
3019 
3020  for (unsigned i = 0; i < inds.ecalIs.size(); i++) {
3021  unsigned iEcal = inds.ecalIs[i];
3022 
3023  LogTrace("PFAlgo|createCandidatesECAL") << "elements[" << iEcal << "]=" << elements[iEcal];
3024 
3025  if (!active[iEcal]) {
3026  LogTrace("PFAlgo|createCandidatesECAL") << "iEcal=" << iEcal << " not active";
3027  continue;
3028  }
3029 
3030  PFBlockElement::Type type = elements[iEcal].type();
3032 
3033  PFClusterRef clusterref = elements[iEcal].clusterRef();
3034  assert(!clusterref.isNull());
3035 
3036  active[iEcal] = false;
3037 
3038  float ecalEnergy = clusterref->correctedEnergy();
3039  // float ecalEnergy = calibration_.energyEm( clusterref->energy() );
3040  double particleEnergy = ecalEnergy;
3041 
3042  auto& cand = (*pfCandidates_)[reconstructCluster(*clusterref, particleEnergy)];
3043 
3044  cand.setEcalEnergy(clusterref->energy(), ecalEnergy);
3045  cand.setHcalEnergy(0., 0.);
3046  cand.setHoEnergy(0., 0.);
3047  cand.setPs1Energy(0.);
3048  cand.setPs2Energy(0.);
3049  cand.addElementInBlock(blockref, iEcal);
3050 
3051  } // end loop on ecal elements iEcal = ecalIs[i]
3052  LogTrace("PFAlgo|createCandidatesECAL") << "end of function PFALgo::createCandidatesECAL";
3053 }

References cms::cuda::assert(), ECAL, ElementIndices::ecalIs, bookConverter::elements, mps_fire::i, edm::Ref< C, T, F >::isNull(), LogTrace, and reconstructCluster().

Referenced by processBlock().

◆ createCandidatesHCAL()

void PFAlgo::createCandidatesHCAL ( const reco::PFBlock block,
reco::PFBlock::LinkData linkData,
const edm::OwnVector< reco::PFBlockElement > &  elements,
std::vector< bool > &  active,
const reco::PFBlockRef blockref,
ElementIndices inds,
std::vector< bool > &  deadArea 
)
private

Definition at line 1696 of file PFAlgo.cc.

1702  {
1703  LogTrace("PFAlgo|createCandidatesHCAL")
1704  << "start of function PFAlgo::createCandidatesHCAL, inds.hcalIs.size()=" << inds.hcalIs.size();
1705 
1706  // --------------- loop hcal ------------------
1707 
1708  for (unsigned iHcal : inds.hcalIs) {
1709  PFBlockElement::Type type = elements[iHcal].type();
1710 
1712 
1713  LogTrace("PFAlgo|createCandidatesHCAL") << "elements[" << iHcal << "]=" << elements[iHcal];
1714 
1715  // associated tracks
1716  std::multimap<double, unsigned> sortedTracks;
1717  block.associatedElements(iHcal, linkData, sortedTracks, reco::PFBlockElement::TRACK, reco::PFBlock::LINKTEST_ALL);
1718 
1719  std::multimap<unsigned, std::pair<double, unsigned>> associatedEcals;
1720 
1721  std::map<unsigned, std::pair<double, double>> associatedPSs;
1722 
1723  std::multimap<double, std::pair<unsigned, bool>> associatedTracks;
1724 
1725  // A temporary maps for ECAL satellite clusters
1726  std::multimap<double, std::tuple<unsigned, ::math::XYZVector, double>>
1727  ecalSatellites; // last element (double) : correction under the egamma hypothesis
1728  std::tuple<unsigned, ::math::XYZVector, double> fakeSatellite(iHcal, ::math::XYZVector(0., 0., 0.), 1.);
1729  ecalSatellites.emplace(-1., fakeSatellite);
1730 
1731  std::multimap<unsigned, std::pair<double, unsigned>> associatedHOs;
1732 
1733  PFClusterRef hclusterref = elements[iHcal].clusterRef();
1734  assert(!hclusterref.isNull());
1735 
1736  //if there is no track attached to that HCAL, then do not
1737  //reconstruct an HCAL alone, check if it can be recovered
1738  //first
1739 
1740  // if no associated tracks, create a neutral hadron
1741  //if(sortedTracks.empty() ) {
1742 
1743  if (sortedTracks.empty()) {
1744  LogTrace("PFAlgo|createCandidatesHCAL") << "\tno associated tracks, keep for later";
1745  continue;
1746  }
1747 
1748  // Lock the HCAL cluster
1749  active[iHcal] = false;
1750 
1751  // in the following, tracks are associated to this hcal cluster.
1752  // will look for an excess of energy in the calorimeters w/r to
1753  // the charged energy, and turn this excess into a neutral hadron or
1754  // a photon.
1755 
1756  LogTrace("PFAlgo|createCandidatesHCAL") << sortedTracks.size() << " associated tracks:";
1757 
1758  double totalChargedMomentum = 0;
1759  double sumpError2 = 0.;
1760  double totalHO = 0.;
1761  double totalEcal = 0.;
1762  double totalEcalEGMCalib = 0.;
1763  double totalHcal = hclusterref->energy();
1764  vector<double> hcalP;
1765  vector<double> hcalDP;
1766  vector<unsigned> tkIs;
1767  double maxDPovP = -9999.;
1768 
1769  //Keep track of how much energy is assigned to calorimeter-vs-track energy/momentum excess
1770  vector<unsigned> chargedHadronsIndices;
1771  vector<unsigned> chargedHadronsInBlock;
1772  double mergedNeutralHadronEnergy = 0;
1773  double mergedPhotonEnergy = 0;
1774  double muonHCALEnergy = 0.;
1775  double muonECALEnergy = 0.;
1776  double muonHCALError = 0.;
1777  double muonECALError = 0.;
1778  unsigned nMuons = 0;
1779 
1780  ::math::XYZVector photonAtECAL(0., 0., 0.);
1781  std::vector<std::tuple<unsigned, ::math::XYZVector, double>>
1782  ecalClusters; // last element (double) : correction under the egamma hypothesis
1783  double sumEcalClusters = 0;
1784  ::math::XYZVector hadronDirection(
1785  hclusterref->position().X(), hclusterref->position().Y(), hclusterref->position().Z());
1786  hadronDirection = hadronDirection.Unit();
1787  ::math::XYZVector hadronAtECAL = totalHcal * hadronDirection;
1788 
1789  // Loop over all tracks associated to this HCAL cluster
1790  for (auto const& trk : sortedTracks) {
1791  unsigned iTrack = trk.second;
1792 
1793  // Check the track has not already been used (e.g., in electrons, conversions...)
1794  if (!active[iTrack])
1795  continue;
1796  // Sanity check 1
1797  PFBlockElement::Type type = elements[iTrack].type();
1799  // Sanity check 2
1800  reco::TrackRef trackRef = elements[iTrack].trackRef();
1801  assert(!trackRef.isNull());
1802 
1803  // The direction at ECAL entrance
1804  const ::math::XYZPointF& chargedPosition =
1805  dynamic_cast<const reco::PFBlockElementTrack*>(&elements[iTrack])->positionAtECALEntrance();
1806  ::math::XYZVector chargedDirection(chargedPosition.X(), chargedPosition.Y(), chargedPosition.Z());
1807  chargedDirection = chargedDirection.Unit();
1808 
1809  // look for ECAL elements associated to iTrack (associated to iHcal)
1810  std::multimap<double, unsigned> sortedEcals;
1811  block.associatedElements(iTrack, linkData, sortedEcals, reco::PFBlockElement::ECAL, reco::PFBlock::LINKTEST_ALL);
1812 
1813  LogTrace("PFAlgo|createCandidatesHCAL") << "number of Ecal elements linked to this track: " << sortedEcals.size();
1814 
1815  // look for HO elements associated to iTrack (associated to iHcal)
1816  std::multimap<double, unsigned> sortedHOs;
1817  if (useHO_) {
1818  block.associatedElements(iTrack, linkData, sortedHOs, reco::PFBlockElement::HO, reco::PFBlock::LINKTEST_ALL);
1819  }
1820  LogTrace("PFAlgo|createCandidatesHCAL")
1821  << "PFAlgo : number of HO elements linked to this track: " << sortedHOs.size();
1822 
1823  // Create a PF Candidate right away if the track is a tight muon
1824  reco::MuonRef muonRef = elements[iTrack].muonRef();
1825 
1826  bool thisIsAMuon = PFMuonAlgo::isMuon(elements[iTrack]);
1827  bool thisIsAnIsolatedMuon = PFMuonAlgo::isIsolatedMuon(elements[iTrack]);
1828  bool thisIsALooseMuon = false;
1829 
1830  if (!thisIsAMuon) {
1831  thisIsALooseMuon = PFMuonAlgo::isLooseMuon(elements[iTrack]);
1832  }
1833 
1834  if (thisIsAMuon) {
1835  LogTrace("PFAlgo|createCandidatesHCAL") << "This track is identified as a muon - remove it from the stack";
1836  LogTrace("PFAlgo|createCandidatesHCAL") << elements[iTrack];
1837 
1838  // Create a muon.
1839 
1840  unsigned tmpi = reconstructTrack(elements[iTrack]);
1841 
1842  (*pfCandidates_)[tmpi].addElementInBlock(blockref, iTrack);
1843  (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHcal);
1844  double muonHcal = std::min(muonHCAL_[0] + muonHCAL_[1], totalHcal);
1845 
1846  // if muon is isolated and muon momentum exceeds the calo energy, absorb the calo energy
1847  // rationale : there has been a EM showering by the muon in the calorimeter - or the coil -
1848  // and we don't want to double count the energy
1849  bool letMuonEatCaloEnergy = false;
1850 
1851  if (thisIsAnIsolatedMuon) {
1852  // The factor 1.3 is the e/pi factor in HCAL...
1853  double totalCaloEnergy = totalHcal / 1.30;
1854  unsigned iEcal = 0;
1855  if (!sortedEcals.empty()) {
1856  iEcal = sortedEcals.begin()->second;
1857  PFClusterRef eclusterref = elements[iEcal].clusterRef();
1858  totalCaloEnergy += eclusterref->energy();
1859  }
1860 
1861  if (useHO_) {
1862  // The factor 1.3 is assumed to be the e/pi factor in HO, too.
1863  unsigned iHO = 0;
1864  if (!sortedHOs.empty()) {
1865  iHO = sortedHOs.begin()->second;
1866  PFClusterRef eclusterref = elements[iHO].clusterRef();
1867  totalCaloEnergy += eclusterref->energy() / 1.30;
1868  }
1869  }
1870 
1871  if ((pfCandidates_->back()).p() > totalCaloEnergy)
1872  letMuonEatCaloEnergy = true;
1873  }
1874 
1875  if (letMuonEatCaloEnergy)
1876  muonHcal = totalHcal;
1877  double muonEcal = 0.;
1878  unsigned iEcal = 0;
1879  if (!sortedEcals.empty()) {
1880  iEcal = sortedEcals.begin()->second;
1881  PFClusterRef eclusterref = elements[iEcal].clusterRef();
1882  (*pfCandidates_)[tmpi].addElementInBlock(blockref, iEcal);
1883  muonEcal = std::min(muonECAL_[0] + muonECAL_[1], eclusterref->energy());
1884  if (letMuonEatCaloEnergy)
1885  muonEcal = eclusterref->energy();
1886  // If the muon expected energy accounts for the whole ecal cluster energy, lock the ecal cluster
1887  if (eclusterref->energy() - muonEcal < 0.2)
1888  active[iEcal] = false;
1889  (*pfCandidates_)[tmpi].setEcalEnergy(eclusterref->energy(), muonEcal);
1890  }
1891  unsigned iHO = 0;
1892  double muonHO = 0.;
1893  if (useHO_) {
1894  if (!sortedHOs.empty()) {
1895  iHO = sortedHOs.begin()->second;
1896  PFClusterRef hoclusterref = elements[iHO].clusterRef();
1897  (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHO);
1898  muonHO = std::min(muonHO_[0] + muonHO_[1], hoclusterref->energy());
1899  if (letMuonEatCaloEnergy)
1900  muonHO = hoclusterref->energy();
1901  // If the muon expected energy accounts for the whole HO cluster energy, lock the HO cluster
1902  if (hoclusterref->energy() - muonHO < 0.2)
1903  active[iHO] = false;
1904  (*pfCandidates_)[tmpi].setHcalEnergy(totalHcal, muonHcal);
1905  (*pfCandidates_)[tmpi].setHoEnergy(hoclusterref->energy(), muonHO);
1906  }
1907  } else {
1908  (*pfCandidates_)[tmpi].setHcalEnergy(totalHcal, muonHcal);
1909  }
1910  setHcalDepthInfo((*pfCandidates_)[tmpi], *hclusterref);
1911 
1912  if (letMuonEatCaloEnergy) {
1913  muonHCALEnergy += totalHcal;
1914  if (useHO_)
1915  muonHCALEnergy += muonHO;
1916  muonHCALError += 0.;
1917  muonECALEnergy += muonEcal;
1918  muonECALError += 0.;
1919  photonAtECAL -= muonEcal * chargedDirection;
1920  hadronAtECAL -= totalHcal * chargedDirection;
1921  if (!sortedEcals.empty())
1922  active[iEcal] = false;
1923  active[iHcal] = false;
1924  if (useHO_ && !sortedHOs.empty())
1925  active[iHO] = false;
1926  } else {
1927  // Estimate of the energy deposit & resolution in the calorimeters
1928  muonHCALEnergy += muonHCAL_[0];
1929  muonHCALError += muonHCAL_[1] * muonHCAL_[1];
1930  if (muonHO > 0.) {
1931  muonHCALEnergy += muonHO_[0];
1932  muonHCALError += muonHO_[1] * muonHO_[1];
1933  }
1934  muonECALEnergy += muonECAL_[0];
1935  muonECALError += muonECAL_[1] * muonECAL_[1];
1936  // ... as well as the equivalent "momentum" at ECAL entrance
1937  photonAtECAL -= muonECAL_[0] * chargedDirection;
1938  hadronAtECAL -= muonHCAL_[0] * chargedDirection;
1939  }
1940 
1941  // Remove it from the stack
1942  active[iTrack] = false;
1943  // Go to next track
1944  continue;
1945  }
1946 
1947  //
1948 
1949  LogTrace("PFAlgo|createCandidatesHCAL") << "elements[iTrack=" << iTrack << "]=" << elements[iTrack];
1950 
1951  // introduce tracking errors
1952  double trackMomentum = trackRef->p();
1953  totalChargedMomentum += trackMomentum;
1954 
1955  // If the track is not a tight muon, but still resembles a muon
1956  // keep it for later for blocks with too large a charged energy
1957  if (thisIsALooseMuon && !thisIsAMuon)
1958  nMuons += 1;
1959 
1960  // ... and keep anyway the pt error for possible fake rejection
1961  // ... blow up errors of 5th and 4th iteration, to reject those
1962  // ... tracks first (in case it's needed)
1963  double dpt = trackRef->ptError();
1964  double blowError = PFTrackAlgoTools::errorScale(trackRef->algo(), factors45_);
1965  // except if it is from an interaction
1966  bool isPrimaryOrSecondary = isFromSecInt(elements[iTrack], "all");
1967 
1968  if (isPrimaryOrSecondary)
1969  blowError = 1.;
1970 
1971  std::pair<unsigned, bool> tkmuon(iTrack, thisIsALooseMuon);
1972  associatedTracks.emplace(-dpt * blowError, tkmuon);
1973 
1974  // Also keep the total track momentum error for comparison with the calo energy
1975  double dp = trackRef->qoverpError() * trackMomentum * trackMomentum;
1976  sumpError2 += dp * dp;
1977 
1978  bool connectedToEcal = false; // Will become true if there is at least one ECAL cluster connected
1979  if (!sortedEcals.empty()) { // start case: at least one ecal element associated to iTrack
1980 
1981  // Loop over all connected ECAL clusters
1982  for (auto const& ecal : sortedEcals) {
1983  unsigned iEcal = ecal.second;
1984  double dist = ecal.first;
1985 
1986  // Ignore ECAL cluters already used
1987  if (!active[iEcal]) {
1988  LogTrace("PFAlgo|createCandidatesHCAL") << "cluster locked";
1989  continue;
1990  }
1991 
1992  // Sanity checks
1993  PFBlockElement::Type type = elements[iEcal].type();
1995  PFClusterRef eclusterref = elements[iEcal].clusterRef();
1996  assert(!eclusterref.isNull());
1997 
1998  // Check if this ECAL is not closer to another track - ignore it in that case
1999  std::multimap<double, unsigned> sortedTracksEcal;
2000  block.associatedElements(
2001  iEcal, linkData, sortedTracksEcal, reco::PFBlockElement::TRACK, reco::PFBlock::LINKTEST_ALL);
2002  unsigned jTrack = sortedTracksEcal.begin()->second;
2003  if (jTrack != iTrack)
2004  continue;
2005 
2006  double distEcal = block.dist(jTrack, iEcal, linkData, reco::PFBlock::LINKTEST_ALL);
2007 
2008  float ecalEnergyCalibrated = eclusterref->correctedEnergy(); // calibrated based on the egamma hypothesis
2009  float ecalEnergy = eclusterref->energy();
2010  ::math::XYZVector photonDirection(
2011  eclusterref->position().X(), eclusterref->position().Y(), eclusterref->position().Z());
2012  photonDirection = photonDirection.Unit();
2013 
2014  if (!connectedToEcal) { // This is the closest ECAL cluster - will add its energy later
2015 
2016  LogTrace("PFAlgo|createCandidatesHCAL") << "closest: " << elements[iEcal];
2017 
2018  connectedToEcal = true;
2019  // PJ 1st-April-09 : To be done somewhere !!! (Had to comment it, but it is needed)
2020  // currentChargedHadron.addElementInBlock( blockref, iEcal );
2021 
2022  // KH: we don't know if this satellite is due to egamma or hadron shower. use raw energy for PF hadron calibration._ store also calibration constant.
2023  double ecalCalibFactor = (ecalEnergy > 1E-9) ? ecalEnergyCalibrated / ecalEnergy : 1.;
2024  std::tuple<unsigned, ::math::XYZVector, double> satellite(
2025  iEcal, ecalEnergy * photonDirection, ecalCalibFactor);
2026  ecalSatellites.emplace(-1., satellite);
2027 
2028  } else { // Keep satellite clusters for later
2029 
2030  // KH: same as above.
2031  double ecalCalibFactor = (ecalEnergy > 1E-9) ? ecalEnergyCalibrated / ecalEnergy : 1.;
2032  std::tuple<unsigned, ::math::XYZVector, double> satellite(
2033  iEcal, ecalEnergy * photonDirection, ecalCalibFactor);
2034  ecalSatellites.emplace(dist, satellite);
2035  }
2036 
2037  std::pair<double, unsigned> associatedEcal(distEcal, iEcal);
2038  associatedEcals.emplace(iTrack, associatedEcal);
2039 
2040  } // End loop ecal associated to iTrack
2041  } // end case: at least one ecal element associated to iTrack
2042 
2043  if (useHO_ && !sortedHOs.empty()) { // start case: at least one ho element associated to iTrack
2044 
2045  // Loop over all connected HO clusters
2046  for (auto const& ho : sortedHOs) {
2047  unsigned iHO = ho.second;
2048  double distHO = ho.first;
2049 
2050  // Ignore HO cluters already used
2051  if (!active[iHO]) {
2052  LogTrace("PFAlgo|createCandidatesHCAL") << "cluster locked";
2053  continue;
2054  }
2055 
2056  // Sanity checks
2057  PFBlockElement::Type type = elements[iHO].type();
2059  PFClusterRef hoclusterref = elements[iHO].clusterRef();
2060  assert(!hoclusterref.isNull());
2061 
2062  // Check if this HO is not closer to another track - ignore it in that case
2063  std::multimap<double, unsigned> sortedTracksHO;
2064  block.associatedElements(
2065  iHO, linkData, sortedTracksHO, reco::PFBlockElement::TRACK, reco::PFBlock::LINKTEST_ALL);
2066  unsigned jTrack = sortedTracksHO.begin()->second;
2067  if (jTrack != iTrack)
2068  continue;
2069 
2070  // double chi2HO = block.chi2(jTrack,iHO,linkData,
2071  // reco::PFBlock::LINKTEST_ALL);
2072  //double distHO = block.dist(jTrack,iHO,linkData,
2073  // reco::PFBlock::LINKTEST_ALL);
2074 
2075  // Increment the total energy by the energy of this HO cluster
2076  totalHO += hoclusterref->energy();
2077  active[iHO] = false;
2078  // Keep track for later reference in the PFCandidate.
2079  std::pair<double, unsigned> associatedHO(distHO, iHO);
2080  associatedHOs.emplace(iTrack, associatedHO);
2081 
2082  } // End loop ho associated to iTrack
2083  } // end case: at least one ho element associated to iTrack
2084 
2085  } // end loop on tracks associated to hcal element iHcal
2086 
2087  // Include totalHO in totalHCAL for the time being (it will be calibrated as HCAL energy)
2088  totalHcal += totalHO;
2089 
2090  // test compatibility between calo and tracker. //////////////
2091 
2092  double caloEnergy = 0.;
2093  double slopeEcal = 1.0;
2094  double calibEcal = 0.;
2095  double calibHcal = 0.;
2096  hadronDirection = hadronAtECAL.Unit();
2097 
2098  // Determine the expected calo resolution from the total charged momentum
2099  double caloResolution = neutralHadronEnergyResolution(totalChargedMomentum, hclusterref->positionREP().Eta());
2100  caloResolution *= totalChargedMomentum;
2101  // Account for muons
2102  caloResolution = std::sqrt(caloResolution * caloResolution + muonHCALError + muonECALError);
2103  totalEcal -= std::min(totalEcal, muonECALEnergy);
2104  totalEcalEGMCalib -= std::min(totalEcalEGMCalib, muonECALEnergy);
2105  totalHcal -= std::min(totalHcal, muonHCALEnergy);
2106  if (totalEcal < 1E-9)
2107  photonAtECAL = ::math::XYZVector(0., 0., 0.);
2108  if (totalHcal < 1E-9)
2109  hadronAtECAL = ::math::XYZVector(0., 0., 0.);
2110 
2111  // Loop over all ECAL satellites, starting for the closest to the various tracks
2112  // and adding other satellites until saturation of the total track momentum
2113  // Note : for code simplicity, the first element of the loop is the HCAL cluster
2114  // with 0 energy in the ECAL
2115  for (auto const& ecalSatellite : ecalSatellites) {
2116  // Add the energy of this ECAL cluster
2117  double previousCalibEcal = calibEcal;
2118  double previousCalibHcal = calibHcal;
2119  double previousCaloEnergy = caloEnergy;
2120  double previousSlopeEcal = slopeEcal;
2121  ::math::XYZVector previousHadronAtECAL = hadronAtECAL;
2122  //
2123  totalEcal +=
2124  sqrt(std::get<1>(ecalSatellite.second).Mag2()); // KH: raw ECAL energy for input to PF hadron calibration
2125  totalEcalEGMCalib += sqrt(std::get<1>(ecalSatellite.second).Mag2()) *
2126  std::get<2>(ecalSatellite.second); // KH: calibrated ECAL energy under the egamma hypothesis
2127  photonAtECAL += std::get<1>(ecalSatellite.second) *
2128  std::get<2>(ecalSatellite.second); // KH: calibrated ECAL energy under the egamma hypothesis
2129  calibEcal = std::max(0., totalEcal); // KH: preparing for hadron calibration
2130  calibHcal = std::max(0., totalHcal);
2131  hadronAtECAL = calibHcal * hadronDirection;
2132  // Calibrate ECAL and HCAL energy under the hadron hypothesis.
2133  calibration_.energyEmHad(totalChargedMomentum,
2134  calibEcal,
2135  calibHcal,
2136  hclusterref->positionREP().Eta(),
2137  hclusterref->positionREP().Phi());
2138  caloEnergy = calibEcal + calibHcal;
2139  if (totalEcal > 0.)
2140  slopeEcal = calibEcal / totalEcal;
2141 
2142  hadronAtECAL = calibHcal * hadronDirection;
2143 
2144  // Continue looping until all closest clusters are exhausted and as long as
2145  // the calorimetric energy does not saturate the total momentum.
2146  if (ecalSatellite.first < 0. || caloEnergy - totalChargedMomentum <= 0.) {
2147  LogTrace("PFAlgo|createCandidatesHCAL")
2148  << "\t\t\tactive, adding " << std::get<1>(ecalSatellite.second) << " to ECAL energy, and locking";
2149  active[std::get<0>(ecalSatellite.second)] = false;
2150  double clusterEnergy =
2151  sqrt(std::get<1>(ecalSatellite.second).Mag2()) *
2152  std::get<2>(ecalSatellite.second); // KH: ECAL energy calibrated under the egamma hypothesis
2153  if (clusterEnergy > 50) { // KH: used to split energetic ecal clusters (E>50 GeV)
2154  ecalClusters.push_back(ecalSatellite.second);
2155  sumEcalClusters += clusterEnergy;
2156  }
2157  continue;
2158  }
2159 
2160  // Otherwise, do not consider the last cluster examined and exit.
2161  // active[is->second.first] = true;
2162  totalEcal -= sqrt(std::get<1>(ecalSatellite.second).Mag2());
2163  totalEcalEGMCalib -= sqrt(std::get<1>(ecalSatellite.second).Mag2()) * std::get<2>(ecalSatellite.second);
2164  photonAtECAL -= std::get<1>(ecalSatellite.second) * std::get<2>(ecalSatellite.second);
2165  calibEcal = previousCalibEcal;
2166  calibHcal = previousCalibHcal;
2167  hadronAtECAL = previousHadronAtECAL;
2168  slopeEcal = previousSlopeEcal;
2169  caloEnergy = previousCaloEnergy;
2170 
2171  break;
2172  }
2173 
2174  // Sanity check !
2175  assert(caloEnergy >= 0);
2176 
2177  // And now check for hadronic energy excess...
2178 
2179  //colin: resolution should be measured on the ecal+hcal case.
2180  // however, the result will be close.
2181  // double caloResolution = neutralHadronEnergyResolution( caloEnergy );
2182  // caloResolution *= caloEnergy;
2183  // PJ The resolution is on the expected charged calo energy !
2184  //double caloResolution = neutralHadronEnergyResolution( totalChargedMomentum, hclusterref->positionREP().Eta());
2185  //caloResolution *= totalChargedMomentum;
2186  // that of the charged particles linked to the cluster!
2187 
2189  if (totalChargedMomentum - caloEnergy > nSigmaTRACK_ * caloResolution) {
2190  // First consider loose muons
2191  if (nMuons > 0) {
2192  for (auto const& trk : associatedTracks) {
2193  // Only muons
2194  if (!trk.second.second)
2195  continue;
2196 
2197  const unsigned int iTrack = trk.second.first;
2198  // Only active tracks
2199  if (!active[iTrack])
2200  continue;
2201 
2202  const double trackMomentum = elements[trk.second.first].trackRef()->p();
2203 
2204  // look for ECAL elements associated to iTrack (associated to iHcal)
2205  std::multimap<double, unsigned> sortedEcals;
2206  block.associatedElements(
2207  iTrack, linkData, sortedEcals, reco::PFBlockElement::ECAL, reco::PFBlock::LINKTEST_ALL);
2208  std::multimap<double, unsigned> sortedHOs;
2209  block.associatedElements(iTrack, linkData, sortedHOs, reco::PFBlockElement::HO, reco::PFBlock::LINKTEST_ALL);
2210 
2211  //Here allow for loose muons!
2212  auto& muon = (*pfCandidates_)[reconstructTrack(elements[iTrack], true)];
2213 
2214  muon.addElementInBlock(blockref, iTrack);
2215  muon.addElementInBlock(blockref, iHcal);
2216  const double muonHcal = std::min(muonHCAL_[0] + muonHCAL_[1], totalHcal - totalHO);
2217  double muonHO = 0.;
2218  muon.setHcalEnergy(totalHcal, muonHcal);
2219  if (!sortedEcals.empty()) {
2220  const unsigned int iEcal = sortedEcals.begin()->second;
2221  PFClusterRef eclusterref = elements[iEcal].clusterRef();
2222  muon.addElementInBlock(blockref, iEcal);
2223  const double muonEcal = std::min(muonECAL_[0] + muonECAL_[1], eclusterref->energy());
2224  muon.setEcalEnergy(eclusterref->energy(), muonEcal);
2225  }
2226  if (useHO_ && !sortedHOs.empty()) {
2227  const unsigned int iHO = sortedHOs.begin()->second;
2228  PFClusterRef hoclusterref = elements[iHO].clusterRef();
2229  muon.addElementInBlock(blockref, iHO);
2230  muonHO = std::min(muonHO_[0] + muonHO_[1], hoclusterref->energy());
2231  muon.setHcalEnergy(max(totalHcal - totalHO, 0.0), muonHcal);
2232  muon.setHoEnergy(hoclusterref->energy(), muonHO);
2233  }
2234  setHcalDepthInfo(muon, *hclusterref);
2235  // Remove it from the block
2236  const ::math::XYZPointF& chargedPosition =
2237  dynamic_cast<const reco::PFBlockElementTrack*>(&elements[trk.second.first])->positionAtECALEntrance();
2238  ::math::XYZVector chargedDirection(chargedPosition.X(), chargedPosition.Y(), chargedPosition.Z());
2239  chargedDirection = chargedDirection.Unit();
2240  totalChargedMomentum -= trackMomentum;
2241  // Update the calo energies
2242  if (totalEcal > 0.)
2243  calibEcal -= std::min(calibEcal, muonECAL_[0] * calibEcal / totalEcal);
2244  if (totalHcal > 0.)
2245  calibHcal -= std::min(calibHcal, muonHCAL_[0] * calibHcal / totalHcal);
2246  totalEcal -= std::min(totalEcal, muonECAL_[0]);
2247  totalHcal -= std::min(totalHcal, muonHCAL_[0]);
2248  if (totalEcal > muonECAL_[0])
2249  photonAtECAL -= muonECAL_[0] * chargedDirection;
2250  if (totalHcal > muonHCAL_[0])
2251  hadronAtECAL -= muonHCAL_[0] * calibHcal / totalHcal * chargedDirection;
2252  caloEnergy = calibEcal + calibHcal;
2253  muonHCALEnergy += muonHCAL_[0];
2254  muonHCALError += muonHCAL_[1] * muonHCAL_[1];
2255  if (muonHO > 0.) {
2256  muonHCALEnergy += muonHO_[0];
2257  muonHCALError += muonHO_[1] * muonHO_[1];
2258  if (totalHcal > 0.) {
2259  calibHcal -= std::min(calibHcal, muonHO_[0] * calibHcal / totalHcal);
2260  totalHcal -= std::min(totalHcal, muonHO_[0]);
2261  }
2262  }
2263  muonECALEnergy += muonECAL_[0];
2264  muonECALError += muonECAL_[1] * muonECAL_[1];
2265  active[iTrack] = false;
2266  // Stop the loop whenever enough muons are removed
2267  //Commented out: Keep looking for muons since they often come in pairs -Matt
2268  //if ( totalChargedMomentum < caloEnergy ) break;
2269  }
2270  // New calo resolution.
2271  caloResolution = neutralHadronEnergyResolution(totalChargedMomentum, hclusterref->positionREP().Eta());
2272  caloResolution *= totalChargedMomentum;
2273  caloResolution = std::sqrt(caloResolution * caloResolution + muonHCALError + muonECALError);
2274  }
2275  }
2276 
2277 #ifdef EDM_ML_DEBUG
2278  LogTrace("PFAlgo|createCandidatesHCAL") << "\tBefore Cleaning ";
2279  LogTrace("PFAlgo|createCandidatesHCAL") << "\tCompare Calo Energy to total charged momentum ";
2280  LogTrace("PFAlgo|createCandidatesHCAL") << "\t\tsum p = " << totalChargedMomentum << " +- " << sqrt(sumpError2);
2281  LogTrace("PFAlgo|createCandidatesHCAL") << "\t\tsum ecal = " << totalEcal;
2282  LogTrace("PFAlgo|createCandidatesHCAL") << "\t\tsum hcal = " << totalHcal;
2283  LogTrace("PFAlgo|createCandidatesHCAL") << "\t\t => Calo Energy = " << caloEnergy << " +- " << caloResolution;
2284  LogTrace("PFAlgo|createCandidatesHCAL")
2285  << "\t\t => Calo Energy- total charged momentum = " << caloEnergy - totalChargedMomentum << " +- "
2286  << sqrt(sumpError2 + caloResolution * caloResolution);
2287 #endif
2288 
2289  // Second consider bad tracks (if still needed after muon removal)
2290  unsigned corrTrack = 10000000;
2291  double corrFact = 1.;
2292 
2293  if (rejectTracks_Bad_ && totalChargedMomentum - caloEnergy > nSigmaTRACK_ * caloResolution) {
2294  for (auto const& trk : associatedTracks) {
2295  const unsigned iTrack = trk.second.first;
2296  // Only active tracks
2297  if (!active[iTrack])
2298  continue;
2299  const reco::TrackRef& trackref = elements[trk.second.first].trackRef();
2300 
2301  const double dptRel = fabs(trk.first) / trackref->pt() * 100;
2302  const bool isSecondary = isFromSecInt(elements[iTrack], "secondary");
2303  const bool isPrimary = isFromSecInt(elements[iTrack], "primary");
2304 
2305  if (isSecondary && dptRel < dptRel_DispVtx_)
2306  continue;
2307  // Consider only bad tracks
2308  if (fabs(trk.first) < ptError_)
2309  break;
2310  // What would become the block charged momentum if this track were removed
2311  const double wouldBeTotalChargedMomentum = totalChargedMomentum - trackref->p();
2312  // Reject worst tracks, as long as the total charged momentum
2313  // is larger than the calo energy
2314 
2315  if (wouldBeTotalChargedMomentum > caloEnergy) {
2316  if (isSecondary) {
2317  LogTrace("PFAlgo|createCandidatesHCAL")
2318  << "In bad track rejection step dptRel = " << dptRel << " dptRel_DispVtx_ = " << dptRel_DispVtx_;
2319  LogTrace("PFAlgo|createCandidatesHCAL")
2320  << "The calo energy would be still smaller even without this track but it is attached to a NI";
2321  }
2322 
2323  if (isPrimary || (isSecondary && dptRel < dptRel_DispVtx_))
2324  continue;
2325  active[iTrack] = false;
2326  totalChargedMomentum = wouldBeTotalChargedMomentum;
2327  LogTrace("PFAlgo|createCandidatesHCAL")
2328  << "\tElement " << elements[iTrack] << " rejected (dpt = " << -trk.first
2329  << " GeV/c, algo = " << trackref->algo() << ")";
2330  // Just rescale the nth worst track momentum to equalize the calo energy
2331  } else {
2332  if (isPrimary)
2333  break;
2334  corrTrack = iTrack;
2335  corrFact = (caloEnergy - wouldBeTotalChargedMomentum) / elements[trk.second.first].trackRef()->p();
2336  if (trackref->p() * corrFact < 0.05) {
2337  corrFact = 0.;
2338  active[iTrack] = false;
2339  }
2340  totalChargedMomentum -= trackref->p() * (1. - corrFact);
2341  LogTrace("PFAlgo|createCandidatesHCAL")
2342  << "\tElement " << elements[iTrack] << " (dpt = " << -trk.first << " GeV/c, algo = " << trackref->algo()
2343  << ") rescaled by " << corrFact << " Now the total charged momentum is " << totalChargedMomentum;
2344  break;
2345  }
2346  }
2347  }
2348 
2349  // New determination of the calo and track resolution avec track deletion/rescaling.
2350  caloResolution = neutralHadronEnergyResolution(totalChargedMomentum, hclusterref->positionREP().Eta());
2351  caloResolution *= totalChargedMomentum;
2352  caloResolution = std::sqrt(caloResolution * caloResolution + muonHCALError + muonECALError);
2353 
2354  // Check if the charged momentum is still very inconsistent with the calo measurement.
2355  // In this case, just drop all tracks from 4th and 5th iteration linked to this block
2356 
2357  if (rejectTracks_Step45_ && sortedTracks.size() > 1 &&
2358  totalChargedMomentum - caloEnergy > nSigmaTRACK_ * caloResolution) {
2359  for (auto const& trk : associatedTracks) {
2360  unsigned iTrack = trk.second.first;
2361  reco::TrackRef trackref = elements[iTrack].trackRef();
2362  if (!active[iTrack])
2363  continue;
2364 
2365  double dptRel = fabs(trk.first) / trackref->pt() * 100;
2366  bool isPrimaryOrSecondary = isFromSecInt(elements[iTrack], "all");
2367 
2368  if (isPrimaryOrSecondary && dptRel < dptRel_DispVtx_)
2369  continue;
2370 
2371  if (PFTrackAlgoTools::step5(trackref->algo())) {
2372  active[iTrack] = false;
2373  totalChargedMomentum -= trackref->p();
2374 
2375  LogTrace("PFAlgo|createCandidatesHCAL")
2376  << "\tElement " << elements[iTrack] << " rejected (dpt = " << -trk.first
2377  << " GeV/c, algo = " << trackref->algo() << ")";
2378  }
2379  }
2380  }
2381 
2382  // New determination of the calo and track resolution avec track deletion/rescaling.
2383  caloResolution = neutralHadronEnergyResolution(totalChargedMomentum, hclusterref->positionREP().Eta());
2384  caloResolution *= totalChargedMomentum;
2385  caloResolution = std::sqrt(caloResolution * caloResolution + muonHCALError + muonECALError);
2386 
2387  // Make PF candidates with the remaining tracks in the block
2388  sumpError2 = 0.;
2389  for (auto const& trk : associatedTracks) {
2390  unsigned iTrack = trk.second.first;
2391  if (!active[iTrack])
2392  continue;
2393  reco::TrackRef trackRef = elements[iTrack].trackRef();
2394  double trackMomentum = trackRef->p();
2395  double dp = trackRef->qoverpError() * trackMomentum * trackMomentum;
2396  unsigned tmpi = reconstructTrack(elements[iTrack]);
2397 
2398  (*pfCandidates_)[tmpi].addElementInBlock(blockref, iTrack);
2399  (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHcal);
2400  setHcalDepthInfo((*pfCandidates_)[tmpi], *hclusterref);
2401  auto myEcals = associatedEcals.equal_range(iTrack);
2402  for (auto ii = myEcals.first; ii != myEcals.second; ++ii) {
2403  unsigned iEcal = ii->second.second;
2404  if (active[iEcal])
2405  continue;
2406  (*pfCandidates_)[tmpi].addElementInBlock(blockref, iEcal);
2407  }
2408 
2409  if (useHO_) {
2410  auto myHOs = associatedHOs.equal_range(iTrack);
2411  for (auto ii = myHOs.first; ii != myHOs.second; ++ii) {
2412  unsigned iHO = ii->second.second;
2413  if (active[iHO])
2414  continue;
2415  (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHO);
2416  }
2417  }
2418 
2419  if (iTrack == corrTrack) {
2420  if (corrFact < 0.)
2421  corrFact = 0.; // protect against negative scaling
2422  (*pfCandidates_)[tmpi].rescaleMomentum(corrFact);
2423  trackMomentum *= corrFact;
2424  }
2425  chargedHadronsIndices.push_back(tmpi);
2426  chargedHadronsInBlock.push_back(iTrack);
2427  active[iTrack] = false;
2428  hcalP.push_back(trackMomentum);
2429  hcalDP.push_back(dp);
2430  if (dp / trackMomentum > maxDPovP)
2431  maxDPovP = dp / trackMomentum;
2432  sumpError2 += dp * dp;
2433  }
2434 
2435  // The total uncertainty of the difference Calo-Track
2436  double totalError = sqrt(sumpError2 + caloResolution * caloResolution);
2437 
2438 #ifdef EDM_ML_DEBUG
2439  LogTrace("PFAlgo|createCandidatesHCAL")
2440  << "\tCompare Calo Energy to total charged momentum " << endl
2441  << "\t\tsum p = " << totalChargedMomentum << " +- " << sqrt(sumpError2) << endl
2442  << "\t\tsum ecal = " << totalEcal << endl
2443  << "\t\tsum hcal = " << totalHcal << endl
2444  << "\t\t => Calo Energy = " << caloEnergy << " +- " << caloResolution << endl
2445  << "\t\t => Calo Energy- total charged momentum = " << caloEnergy - totalChargedMomentum << " +- "
2446  << totalError;
2447 #endif
2448 
2449  /* */
2450 
2452  double nsigma = nSigmaHCAL(totalChargedMomentum, hclusterref->positionREP().Eta());
2453  //double nsigma = nSigmaHCAL(caloEnergy,hclusterref->positionREP().Eta());
2454  if (abs(totalChargedMomentum - caloEnergy) < nsigma * totalError) {
2455  // deposited caloEnergy compatible with total charged momentum
2456  // if tracking errors are large take weighted average
2457 
2458 #ifdef EDM_ML_DEBUG
2459  LogTrace("PFAlgo|createCandidatesHCAL")
2460  << "\t\tcase 1: COMPATIBLE "
2461  << "|Calo Energy- total charged momentum| = " << abs(caloEnergy - totalChargedMomentum) << " < " << nsigma
2462  << " x " << totalError;
2463  if (maxDPovP < 0.1)
2464  LogTrace("PFAlgo|createCandidatesHCAL") << "\t\t\tmax DP/P = " << maxDPovP << " less than 0.1: do nothing ";
2465  else
2466  LogTrace("PFAlgo|createCandidatesHCAL")
2467  << "\t\t\tmax DP/P = " << maxDPovP << " > 0.1: take weighted averages ";
2468 #endif
2469 
2470  // if max DP/P < 10% do nothing
2471  if (maxDPovP > 0.1) {
2472  // for each track associated to hcal
2473  // int nrows = tkIs.size();
2474  int nrows = chargedHadronsIndices.size();
2475  TMatrixTSym<double> a(nrows);
2476  TVectorD b(nrows);
2477  TVectorD check(nrows);
2478  double sigma2E = caloResolution * caloResolution;
2479  for (int i = 0; i < nrows; i++) {
2480  double sigma2i = hcalDP[i] * hcalDP[i];
2481  LogTrace("PFAlgo|createCandidatesHCAL")
2482  << "\t\t\ttrack associated to hcal " << i << " P = " << hcalP[i] << " +- " << hcalDP[i];
2483  a(i, i) = 1. / sigma2i + 1. / sigma2E;
2484  b(i) = hcalP[i] / sigma2i + caloEnergy / sigma2E;
2485  for (int j = 0; j < nrows; j++) {
2486  if (i == j)
2487  continue;
2488  a(i, j) = 1. / sigma2E;
2489  } // end loop on j
2490  } // end loop on i
2491 
2492  // solve ax = b
2493  TDecompChol decomp(a);
2494  bool ok = false;
2495  TVectorD x = decomp.Solve(b, ok);
2496  // for each track create a PFCandidate track
2497  // with a momentum rescaled to weighted average
2498  if (ok) {
2499  for (int i = 0; i < nrows; i++) {
2500  // unsigned iTrack = trackInfos[i].index;
2501  unsigned ich = chargedHadronsIndices[i];
2502  double rescaleFactor = x(i) / hcalP[i];
2503  if (rescaleFactor < 0.)
2504  rescaleFactor = 0.; // protect against negative scaling
2505  (*pfCandidates_)[ich].rescaleMomentum(rescaleFactor);
2506 
2507  LogTrace("PFAlgo|createCandidatesHCAL")
2508  << "\t\t\told p " << hcalP[i] << " new p " << x(i) << " rescale " << rescaleFactor;
2509  }
2510  } else {
2511  edm::LogError("PFAlgo::createCandidatesHCAL") << "TDecompChol.Solve returned ok=false";
2512  assert(0);
2513  }
2514  }
2515  }
2516 
2518  else if (caloEnergy > totalChargedMomentum) {
2519  //case 2: caloEnergy > totalChargedMomentum + nsigma*totalError
2520  //there is an excess of energy in the calos
2521  //create a neutral hadron or a photon
2522 
2523  double eNeutralHadron = caloEnergy - totalChargedMomentum;
2524  double ePhoton = (caloEnergy - totalChargedMomentum) /
2525  slopeEcal; // KH: this slopeEcal is computed based on ECAL energy under the hadron hypothesis,
2526  // thought we are creating photons.
2527  // This is a fuzzy case, but it should be better than corrected twice under both egamma and hadron hypotheses.
2528 
2529 #ifdef EDM_ML_DEBUG
2530  if (!sortedTracks.empty()) {
2531  LogTrace("PFAlgo|createCandidatesHCAL") << "\t\tcase 2: NEUTRAL DETECTION " << caloEnergy << " > " << nsigma
2532  << "x" << totalError << " + " << totalChargedMomentum;
2533  LogTrace("PFAlgo|createCandidatesHCAL") << "\t\tneutral activity detected: " << endl
2534  << "\t\t\t photon = " << ePhoton << endl
2535  << "\t\t\tor neutral hadron = " << eNeutralHadron;
2536 
2537  LogTrace("PFAlgo|createCandidatesHCAL") << "\t\tphoton or hadron ?";
2538  }
2539 
2540  if (sortedTracks.empty())
2541  LogTrace("PFAlgo|createCandidatesHCAL") << "\t\tno track -> hadron ";
2542  else
2543  LogTrace("PFAlgo|createCandidatesHCAL")
2544  << "\t\t" << sortedTracks.size() << " tracks -> check if the excess is photonic or hadronic";
2545 #endif
2546 
2547  double ratioMax = 0.;
2548  reco::PFClusterRef maxEcalRef;
2549  unsigned maxiEcal = 9999;
2550 
2551  // for each track associated to hcal: iterator IE ie :
2552 
2553  LogTrace("PFAlgo|createCandidatesHCAL") << "loop over sortedTracks.size()=" << sortedTracks.size();
2554  for (auto const& trk : sortedTracks) {
2555  unsigned iTrack = trk.second;
2556 
2557  PFBlockElement::Type type = elements[iTrack].type();
2559 
2560  reco::TrackRef trackRef = elements[iTrack].trackRef();
2561  assert(!trackRef.isNull());
2562 
2563  auto iae = associatedEcals.find(iTrack);
2564 
2565  if (iae == associatedEcals.end())
2566  continue;
2567 
2568  // double distECAL = iae->second.first;
2569  unsigned iEcal = iae->second.second;
2570 
2571  PFBlockElement::Type typeEcal = elements[iEcal].type();
2572  assert(typeEcal == reco::PFBlockElement::ECAL);
2573 
2574  reco::PFClusterRef clusterRef = elements[iEcal].clusterRef();
2575  assert(!clusterRef.isNull());
2576 
2577  double pTrack = trackRef->p();
2578  double eECAL = clusterRef->energy();
2579  double eECALOverpTrack = eECAL / pTrack;
2580 
2581  if (eECALOverpTrack > ratioMax) {
2582  ratioMax = eECALOverpTrack;
2583  maxEcalRef = clusterRef;
2584  maxiEcal = iEcal;
2585  }
2586 
2587  } // end loop on tracks associated to hcal: iterator IE ie
2588 
2589  std::vector<reco::PFClusterRef> pivotalClusterRef;
2590  std::vector<unsigned> iPivotal;
2591  std::vector<double> particleEnergy, ecalEnergy, hcalEnergy, rawecalEnergy, rawhcalEnergy;
2592  std::vector<::math::XYZVector> particleDirection;
2593 
2594  // If the excess is smaller than the ecal energy, assign the whole
2595  // excess to photons
2596  if (ePhoton < totalEcal || eNeutralHadron - calibEcal < 1E-10) {
2597  if (!maxEcalRef.isNull()) {
2598  // So the merged photon energy is,
2599  mergedPhotonEnergy = ePhoton;
2600  }
2601  } else {
2602  // Otherwise assign the whole ECAL energy to the photons
2603  if (!maxEcalRef.isNull()) {
2604  // So the merged photon energy is,
2605  mergedPhotonEnergy = totalEcalEGMCalib; // KH: use calibrated ECAL energy under the egamma hypothesis
2606  }
2607  // ... and assign the remaining excess to neutral hadrons using the direction of ecal clusters
2608  mergedNeutralHadronEnergy = eNeutralHadron - calibEcal;
2609  }
2610 
2611  if (mergedPhotonEnergy > 0) {
2612  // Split merged photon into photons for each energetic ecal cluster (necessary for jet substructure reconstruction)
2613  // make only one merged photon if less than 2 ecal clusters
2614  // KH: this part still needs review, after using non-corrected ECAL energy for PF hadron calibrations
2615  if (ecalClusters.size() <= 1) {
2616  ecalClusters.clear();
2617  ecalClusters.emplace_back(
2618  maxiEcal,
2619  photonAtECAL,
2620  1.); // KH: calibration factor of 1, which should be ok as long as sumEcalClusters is consistent with photonAtECAL in this case
2621  sumEcalClusters = sqrt(photonAtECAL.Mag2());
2622  }
2623  for (auto const& pae : ecalClusters) {
2624  const double clusterEnergyCalibrated =
2625  sqrt(std::get<1>(pae).Mag2()) *
2626  std::get<2>(
2627  pae); // KH: calibrated under the egamma hypothesis. Note: sumEcalClusters is normally calibrated under egamma hypothesis
2628  particleEnergy.push_back(mergedPhotonEnergy * clusterEnergyCalibrated / sumEcalClusters);
2629  particleDirection.push_back(std::get<1>(pae));
2630  ecalEnergy.push_back(mergedPhotonEnergy * clusterEnergyCalibrated / sumEcalClusters);
2631  hcalEnergy.push_back(0.);
2632  rawecalEnergy.push_back(totalEcal);
2633  rawhcalEnergy.push_back(0.);
2634  pivotalClusterRef.push_back(elements[std::get<0>(pae)].clusterRef());
2635  iPivotal.push_back(std::get<0>(pae));
2636  }
2637  } // mergedPhotonEnergy > 0
2638 
2639  if (mergedNeutralHadronEnergy > 1.0) {
2640  // Split merged neutral hadrons according to directions of energetic ecal clusters (necessary for jet substructure reconstruction)
2641  // make only one merged neutral hadron if less than 2 ecal clusters
2642  if (ecalClusters.size() <= 1) {
2643  ecalClusters.clear();
2644  ecalClusters.emplace_back(
2645  iHcal,
2646  hadronAtECAL,
2647  1.); // KH: calibration factor of 1, which should be ok as long as sumEcalClusters is consistent with photonAtECAL
2648  sumEcalClusters = sqrt(hadronAtECAL.Mag2());
2649  }
2650  for (auto const& pae : ecalClusters) {
2651  const double clusterEnergyCalibrated =
2652  sqrt(std::get<1>(pae).Mag2()) *
2653  std::get<2>(
2654  pae); // KH: calibrated under the egamma hypothesis. Note: sumEcalClusters is normally calibrated under egamma hypothesis
2655  particleEnergy.push_back(mergedNeutralHadronEnergy * clusterEnergyCalibrated / sumEcalClusters);
2656  particleDirection.push_back(std::get<1>(pae));
2657  ecalEnergy.push_back(0.);
2658  hcalEnergy.push_back(mergedNeutralHadronEnergy * clusterEnergyCalibrated / sumEcalClusters);
2659  rawecalEnergy.push_back(0.);
2660  rawhcalEnergy.push_back(totalHcal);
2661  pivotalClusterRef.push_back(hclusterref);
2662  iPivotal.push_back(iHcal);
2663  }
2664  } //mergedNeutralHadronEnergy > 1.0
2665 
2666  // reconstructing a merged neutral
2667  // the type of PFCandidate is known from the
2668  // reference to the pivotal cluster.
2669 
2670  for (unsigned iPivot = 0; iPivot < iPivotal.size(); ++iPivot) {
2671  if (particleEnergy[iPivot] < 0.)
2672  edm::LogWarning("PFAlgo|createCandidatesHCAL")
2673  << "ALARM = Negative energy for iPivot=" << iPivot << ", " << particleEnergy[iPivot];
2674 
2675  const bool useDirection = true;
2676  auto& neutral = (*pfCandidates_)[reconstructCluster(*pivotalClusterRef[iPivot],
2677  particleEnergy[iPivot],
2678  useDirection,
2679  particleDirection[iPivot].X(),
2680  particleDirection[iPivot].Y(),
2681  particleDirection[iPivot].Z())];
2682 
2683  neutral.setEcalEnergy(rawecalEnergy[iPivot], ecalEnergy[iPivot]);
2684  if (!useHO_) {
2685  neutral.setHcalEnergy(rawhcalEnergy[iPivot], hcalEnergy[iPivot]);
2686  neutral.setHoEnergy(0., 0.);
2687  } else { // useHO_
2688  if (rawhcalEnergy[iPivot] == 0.) { // photons should be here
2689  neutral.setHcalEnergy(0., 0.);
2690  neutral.setHoEnergy(0., 0.);
2691  } else {
2692  neutral.setHcalEnergy(max(rawhcalEnergy[iPivot] - totalHO, 0.0),
2693  hcalEnergy[iPivot] * max(1. - totalHO / rawhcalEnergy[iPivot], 0.));
2694  neutral.setHoEnergy(totalHO, totalHO * hcalEnergy[iPivot] / rawhcalEnergy[iPivot]);
2695  }
2696  }
2697  neutral.setPs1Energy(0.);
2698  neutral.setPs2Energy(0.);
2699  neutral.set_mva_nothing_gamma(-1.);
2700  // neutral.addElement(&elements[iPivotal]);
2701  // neutral.addElementInBlock(blockref, iPivotal[iPivot]);
2702  neutral.addElementInBlock(blockref, iHcal);
2703  for (unsigned iTrack : chargedHadronsInBlock) {
2704  neutral.addElementInBlock(blockref, iTrack);
2705  // Assign the position of the track at the ECAL entrance
2706  const ::math::XYZPointF& chargedPosition =
2707  dynamic_cast<const reco::PFBlockElementTrack*>(&elements[iTrack])->positionAtECALEntrance();
2708  neutral.setPositionAtECALEntrance(chargedPosition);
2709 
2710  auto myEcals = associatedEcals.equal_range(iTrack);
2711  for (auto ii = myEcals.first; ii != myEcals.second; ++ii) {
2712  unsigned iEcal = ii->second.second;
2713  if (active[iEcal])
2714  continue;
2715  neutral.addElementInBlock(blockref, iEcal);
2716  }
2717  }
2718  }
2719 
2720  } // excess of energy
2721 
2722  // will now share the hcal energy between the various charged hadron
2723  // candidates, taking into account the potential neutral hadrons
2724 
2725  //JB: The question is: we've resolved the merged photons cleanly, but how should
2726  //the remaining hadrons be assigned the remaining ecal energy?
2727  //*Temporary solution*: follow HCAL example with fractions...
2728 
2729  // remove the energy of the potential neutral hadron
2730  double totalHcalEnergyCalibrated = std::max(calibHcal - mergedNeutralHadronEnergy, 0.);
2731  // similarly for the merged photons
2732  double totalEcalEnergyCalibrated = std::max(calibEcal - mergedPhotonEnergy, 0.);
2733  // share between the charged hadrons
2734 
2735  //COLIN can compute this before
2736  // not exactly equal to sum p, this is sum E
2737  double chargedHadronsTotalEnergy = 0;
2738  for (unsigned index : chargedHadronsIndices) {
2739  reco::PFCandidate& chargedHadron = (*pfCandidates_)[index];
2740  chargedHadronsTotalEnergy += chargedHadron.energy();
2741  }
2742 
2743  for (unsigned index : chargedHadronsIndices) {
2744  reco::PFCandidate& chargedHadron = (*pfCandidates_)[index];
2745  float fraction = chargedHadron.energy() / chargedHadronsTotalEnergy;
2746 
2747  if (!useHO_) {
2748  chargedHadron.setHcalEnergy(fraction * totalHcal, fraction * totalHcalEnergyCalibrated);
2749  chargedHadron.setHoEnergy(0., 0.);
2750  } else {
2751  chargedHadron.setHcalEnergy(fraction * max(totalHcal - totalHO, 0.0),
2752  fraction * totalHcalEnergyCalibrated * (1. - totalHO / totalHcal));
2753  chargedHadron.setHoEnergy(fraction * totalHO, fraction * totalHO * totalHcalEnergyCalibrated / totalHcal);
2754  }
2755  //JB: fixing up (previously omitted) setting of ECAL energy gouzevit
2756  chargedHadron.setEcalEnergy(fraction * totalEcal, fraction * totalEcalEnergyCalibrated);
2757  }
2758 
2759  // Finally treat unused ecal satellites as photons.
2760  for (auto const& ecalSatellite : ecalSatellites) {
2761  // Ignore satellites already taken
2762  unsigned iEcal = std::get<0>(ecalSatellite.second);
2763  if (!active[iEcal])
2764  continue;
2765 
2766  // Sanity checks again (well not useful, this time!)
2767  PFBlockElement::Type type = elements[iEcal].type();
2769  PFClusterRef eclusterref = elements[iEcal].clusterRef();
2770  assert(!eclusterref.isNull());
2771 
2772  // Lock the cluster
2773  active[iEcal] = false;
2774 
2775  // Find the associated tracks
2776  std::multimap<double, unsigned> assTracks;
2777  block.associatedElements(iEcal, linkData, assTracks, reco::PFBlockElement::TRACK, reco::PFBlock::LINKTEST_ALL);
2778 
2779  // Create a photon
2780  double ecalClusterEnergyCalibrated =
2781  sqrt(std::get<1>(ecalSatellite.second).Mag2()) *
2782  std::get<2>(
2783  ecalSatellite.second); // KH: calibrated under the egamma hypothesis (rawEcalClusterEnergy * calibration)
2784  auto& cand = (*pfCandidates_)[reconstructCluster(*eclusterref, ecalClusterEnergyCalibrated)];
2785  cand.setEcalEnergy(eclusterref->energy(), ecalClusterEnergyCalibrated);
2786  cand.setHcalEnergy(0., 0.);
2787  cand.setHoEnergy(0., 0.);
2788  cand.setPs1Energy(associatedPSs[iEcal].first);
2789  cand.setPs2Energy(associatedPSs[iEcal].second);
2790  cand.addElementInBlock(blockref, iEcal);
2791  cand.addElementInBlock(blockref, sortedTracks.begin()->second);
2792 
2793  if (fabs(eclusterref->energy() - sqrt(std::get<1>(ecalSatellite.second).Mag2())) > 1e-3 ||
2794  fabs(eclusterref->correctedEnergy() - ecalClusterEnergyCalibrated) > 1e-3)
2795  edm::LogWarning("PFAlgo:processBlock")
2796  << "ecalCluster vs ecalSatellites look inconsistent (eCluster E, calibE, ecalSatellite E, calib E): "
2797  << eclusterref->energy() << " " << eclusterref->correctedEnergy() << " "
2798  << sqrt(std::get<1>(ecalSatellite.second).Mag2()) << " " << ecalClusterEnergyCalibrated;
2799 
2800  } // ecalSatellites
2801 
2802  } // hcalIs
2803  // end loop on hcal element iHcal= hcalIs[i]
2804  LogTrace("PFAlgo|createCandidatesHCAL") << "end of function PFAlgo::createCandidatesHCAL";
2805 }

References a, funct::abs(), cms::cuda::assert(), b, groupFilesInBlocks::block, calibration_, muons2muons_cfi::chargedHadron, RPCNoise_example::check, Calorimetry_cff::dp, dptRel_DispVtx_, MillePedeFileConverter_cfg::e, ECAL, bsc_activity_cfg::ecal, reco::PFBlockElement::ECAL, RecoEcal_cff::ecalClusters, bookConverter::elements, PFEnergyCalibration::energyEmHad(), PFTrackAlgoTools::errorScale(), factors45_, dqmdumpme::first, HLT_2018_cff::fraction, HCAL, ElementIndices::hcalIs, photonIsolationHIProducer_cfi::ho, DigiToRawDM_cff::HO, reco::PFBlockElement::HO, mps_fire::i, cuy::ii, isFromSecInt(), PFMuonAlgo::isIsolatedMuon(), PFMuonAlgo::isLooseMuon(), PFMuonAlgo::isMuon(), edm::Ref< C, T, F >::isNull(), dqmiolumiharvest::j, reco::PFBlock::LINKTEST_ALL, LogTrace, SiStripPI::max, min(), muonECAL_, muonHCAL_, muonHO_, neutralHadronEnergyResolution(), jets_cff::nMuons, nSigmaHCAL(), nSigmaTRACK_, convertSQLiteXML::ok, AlCaHLTBitMon_ParallelJobs::p, pfCandidates_, ptError_, bTagCommon_cff::ratioMax, reconstructCluster(), reconstructTrack(), rejectTracks_Bad_, rejectTracks_Step45_, edm::second(), setHcalDepthInfo(), mathSSE::sqrt(), PFTrackAlgoTools::step5(), reco::PFBlockElement::TRACK, reco::btau::trackMomentum, useHO_, x, X, DOFs::Y, and DOFs::Z.

Referenced by processBlock().

◆ createCandidatesHCALUnlinked()

void PFAlgo::createCandidatesHCALUnlinked ( const reco::PFBlock block,
reco::PFBlock::LinkData linkData,
const edm::OwnVector< reco::PFBlockElement > &  elements,
std::vector< bool > &  active,
const reco::PFBlockRef blockref,
ElementIndices inds,
std::vector< bool > &  deadArea 
)
private

Definition at line 2807 of file PFAlgo.cc.

2813  {
2814  // Processing the remaining HCAL clusters
2815  LogTrace("PFAlgo|createCandidatesHCALUnlinked")
2816  << "start of function PFAlgo::createCandidatesHCALUnlinked, hcalIs.size()=" << inds.hcalIs.size();
2817 
2818  // --------------- loop remaining hcal ------------------
2819 
2820  for (unsigned iHcal : inds.hcalIs) {
2821  // Keep ECAL and HO elements for reference in the PFCandidate
2822  std::vector<unsigned> ecalRefs;
2823  std::vector<unsigned> hoRefs;
2824 
2825  LogTrace("PFAlgo|createCandidatesHCALUnlinked") << elements[iHcal] << " ";
2826 
2827  if (!active[iHcal]) {
2828  LogTrace("PFAlgo|createCandidatesHCALUnlinked") << "not active " << iHcal;
2829  continue;
2830  }
2831 
2832  // Find the ECAL elements linked to it
2833  std::multimap<double, unsigned> ecalElems;
2834  block.associatedElements(iHcal, linkData, ecalElems, reco::PFBlockElement::ECAL, reco::PFBlock::LINKTEST_ALL);
2835 
2836  // Loop on these ECAL elements
2837  float totalEcal = 0.;
2838  float ecalMax = 0.;
2839  reco::PFClusterRef eClusterRef;
2840  for (auto const& ecal : ecalElems) {
2841  unsigned iEcal = ecal.second;
2842  double dist = ecal.first;
2843  PFBlockElement::Type type = elements[iEcal].type();
2845 
2846  // Check if already used
2847  if (!active[iEcal])
2848  continue;
2849 
2850  // Check the distance (one HCALPlusECAL tower, roughly)
2851  // if ( dist > 0.15 ) continue;
2852 
2853  //COLINFEB16
2854  // what could be done is to
2855  // - link by rechit.
2856  // - take in the neutral hadron all the ECAL clusters
2857  // which are within the same CaloTower, according to the distance,
2858  // except the ones which are closer to another HCAL cluster.
2859  // - all the other ECAL linked to this HCAL are photons.
2860  //
2861  // about the closest HCAL cluster.
2862  // it could maybe be easier to loop on the ECAL clusters first
2863  // to cut the links to all HCAL clusters except the closest, as is
2864  // done in the first track loop. But maybe not!
2865  // or add an helper function to the PFAlgo class to ask
2866  // if a given element is the closest of a given type to another one?
2867 
2868  // Check if not closer from another free HCAL
2869  std::multimap<double, unsigned> hcalElems;
2870  block.associatedElements(iEcal, linkData, hcalElems, reco::PFBlockElement::HCAL, reco::PFBlock::LINKTEST_ALL);
2871 
2872  const bool isClosest = std::none_of(hcalElems.begin(), hcalElems.end(), [&](auto const& hcal) {
2873  return active[hcal.second] && hcal.first < dist;
2874  });
2875 
2876  if (!isClosest)
2877  continue;
2878 
2879 #ifdef EDM_ML_DEBUG
2880  LogTrace("PFAlgo|createCandidatesHCALUnlinked")
2881  << "\telement " << elements[iEcal] << " linked with dist " << dist;
2882  LogTrace("PFAlgo|createCandidatesHCALUnlinked") << "Added to HCAL cluster to form a neutral hadron";
2883 #endif
2884 
2885  reco::PFClusterRef eclusterRef = elements[iEcal].clusterRef();
2886  assert(!eclusterRef.isNull());
2887 
2888  // KH: use raw ECAL energy for PF hadron calibration_.
2889  double ecalEnergy = eclusterRef->energy(); // ecalEnergy = eclusterRef->correctedEnergy();
2890 
2891  totalEcal += ecalEnergy;
2892  if (ecalEnergy > ecalMax) {
2893  ecalMax = ecalEnergy;
2894  eClusterRef = eclusterRef;
2895  }
2896 
2897  ecalRefs.push_back(iEcal);
2898  active[iEcal] = false;
2899 
2900  } // End loop ECAL
2901 
2902  // Now find the HO clusters linked to the HCAL cluster
2903  double totalHO = 0.;
2904  double hoMax = 0.;
2905  //unsigned jHO = 0;
2906  if (useHO_) {
2907  std::multimap<double, unsigned> hoElems;
2908  block.associatedElements(iHcal, linkData, hoElems, reco::PFBlockElement::HO, reco::PFBlock::LINKTEST_ALL);
2909 
2910  // Loop on these HO elements
2911  // double totalHO = 0.;
2912  // double hoMax = 0.;
2913  // unsigned jHO = 0;
2914  reco::PFClusterRef hoClusterRef;
2915  for (auto const& ho : hoElems) {
2916  unsigned iHO = ho.second;
2917  double dist = ho.first;
2918  PFBlockElement::Type type = elements[iHO].type();
2920 
2921  // Check if already used
2922  if (!active[iHO])
2923  continue;
2924 
2925  // Check the distance (one HCALPlusHO tower, roughly)
2926  // if ( dist > 0.15 ) continue;
2927 
2928  // Check if not closer from another free HCAL
2929  std::multimap<double, unsigned> hcalElems;
2930  block.associatedElements(iHO, linkData, hcalElems, reco::PFBlockElement::HCAL, reco::PFBlock::LINKTEST_ALL);
2931 
2932  const bool isClosest = std::none_of(hcalElems.begin(), hcalElems.end(), [&](auto const& hcal) {
2933  return active[hcal.second] && hcal.first < dist;
2934  });
2935 
2936  if (!isClosest)
2937  continue;
2938 
2939 #ifdef EDM_ML_DEBUG
2940  if (useHO_) {
2941  LogTrace("PFAlgo|createCandidatesHCALUnlinked")
2942  << "\telement " << elements[iHO] << " linked with dist " << dist;
2943  LogTrace("PFAlgo|createCandidatesHCALUnlinked") << "Added to HCAL cluster to form a neutral hadron";
2944  }
2945 #endif
2946 
2947  reco::PFClusterRef hoclusterRef = elements[iHO].clusterRef();
2948  assert(!hoclusterRef.isNull());
2949 
2950  double hoEnergy =
2951  hoclusterRef->energy(); // calibration_.energyEm(*hoclusterRef,ps1Ene,ps2Ene,crackCorrection);
2952 
2953  totalHO += hoEnergy;
2954  if (hoEnergy > hoMax) {
2955  hoMax = hoEnergy;
2956  hoClusterRef = hoclusterRef;
2957  //jHO = iHO;
2958  }
2959 
2960  hoRefs.push_back(iHO);
2961  active[iHO] = false;
2962 
2963  } // End loop HO
2964  }
2965 
2966  PFClusterRef hclusterRef = elements[iHcal].clusterRef();
2967  assert(!hclusterRef.isNull());
2968 
2969  // HCAL energy
2970  double totalHcal = hclusterRef->energy();
2971  // Include the HO energy
2972  if (useHO_)
2973  totalHcal += totalHO;
2974 
2975  // Calibration
2976  double calibEcal = totalEcal > 0. ? totalEcal : 0.;
2977  double calibHcal = std::max(0., totalHcal);
2978  if (hclusterRef->layer() == PFLayer::HF_HAD || hclusterRef->layer() == PFLayer::HF_EM) {
2979  calibEcal = totalEcal;
2980  } else {
2982  -1., calibEcal, calibHcal, hclusterRef->positionREP().Eta(), hclusterRef->positionREP().Phi());
2983  }
2984 
2985  auto& cand = (*pfCandidates_)[reconstructCluster(*hclusterRef, calibEcal + calibHcal)];
2986 
2987  cand.setEcalEnergy(totalEcal, calibEcal);
2988  if (!useHO_) {
2989  cand.setHcalEnergy(totalHcal, calibHcal);
2990  cand.setHoEnergy(0., 0.);
2991  } else {
2992  cand.setHcalEnergy(max(totalHcal - totalHO, 0.0), calibHcal * (1. - totalHO / totalHcal));
2993  cand.setHoEnergy(totalHO, totalHO * calibHcal / totalHcal);
2994  }
2995  cand.setPs1Energy(0.);
2996  cand.setPs2Energy(0.);
2997  cand.addElementInBlock(blockref, iHcal);
2998  for (auto const& ec : ecalRefs)
2999  cand.addElementInBlock(blockref, ec);
3000  for (auto const& ho : hoRefs)
3001  cand.addElementInBlock(blockref, ho);
3002 
3003  } //loop hcal elements
3004 }

References cms::cuda::assert(), groupFilesInBlocks::block, calibration_, ECAL, bsc_activity_cfg::ecal, reco::PFBlockElement::ECAL, bookConverter::elements, PFEnergyCalibration::energyEmHad(), reco::PFBlockElement::HCAL, patCandidatesForDimuonsSequences_cff::hcal, ElementIndices::hcalIs, PFLayer::HF_EM, PFLayer::HF_HAD, photonIsolationHIProducer_cfi::ho, DigiToRawDM_cff::HO, reco::PFBlockElement::HO, edm::Ref< C, T, F >::isNull(), reco::PFBlock::LINKTEST_ALL, LogTrace, SiStripPI::max, reconstructCluster(), and useHO_.

Referenced by processBlock().

◆ createCandidatesHF()

void PFAlgo::createCandidatesHF ( const reco::PFBlock block,
reco::PFBlock::LinkData linkData,
const edm::OwnVector< reco::PFBlockElement > &  elements,
std::vector< bool > &  active,
const reco::PFBlockRef blockref,
ElementIndices inds 
)
private

Definition at line 1253 of file PFAlgo.cc.

1258  {
1259  LogTrace("PFAlgo|createCandidatesHF") << "starting function PFAlgo::createCandidatesHF";
1260 
1261  bool trackInBlock = !inds.trackIs.empty();
1262  // inds.trackIs can be empty, even if there are tracks in this block,
1263  // but what we want to check is if this block has any track including inactive ones
1264  if (!trackInBlock)
1265  for (unsigned iEle = 0; iEle < elements.size(); iEle++) {
1266  PFBlockElement::Type type = elements[iEle].type();
1267  if (type == PFBlockElement::TRACK) {
1268  trackInBlock = true;
1269  break;
1270  }
1271  }
1272  // there is at least one HF element in this block.
1273  // in case of no track, all elements must be HF
1274  if (!trackInBlock)
1275  assert(inds.hfEmIs.size() + inds.hfHadIs.size() == elements.size());
1276 
1277  //
1278  // Dealing with a block with at least one track
1279  // Occasionally, there are only inactive tracks and multiple HF clusters. Consider such blocks too.
1280  //
1281  if (trackInBlock) { // count any tracks (not only active tracks)
1282  // sorted tracks associated with a HfHad cluster
1283  std::multimap<double, unsigned> sortedTracks;
1284  std::multimap<double, unsigned> sortedTracksActive; // only active ones
1285  // HfEms associated with tracks linked to a HfHad cluster
1286  std::multimap<unsigned, std::pair<double, unsigned>> associatedHfEms;
1287  // Temporary map for HfEm satellite clusters
1288  std::multimap<double, std::pair<unsigned, double>> hfemSatellites;
1289 
1290  //
1291  // Loop over active HfHad clusters
1292  //
1293  for (unsigned iHfHad : inds.hfHadIs) {
1294  PFBlockElement::Type type = elements[iHfHad].type();
1295  assert(type == PFBlockElement::HFHAD);
1296 
1297  PFClusterRef hclusterRef = elements[iHfHad].clusterRef();
1298  assert(!hclusterRef.isNull());
1299 
1300  sortedTracks.clear();
1301  sortedTracksActive.clear();
1302  associatedHfEms.clear();
1303  hfemSatellites.clear();
1304 
1305  // Look for associated tracks
1306  block.associatedElements(
1307  iHfHad, linkData, sortedTracks, reco::PFBlockElement::TRACK, reco::PFBlock::LINKTEST_ALL);
1308 
1309  LogTrace("PFAlgo|createCandidatesHF") << "elements[" << iHfHad << "]=" << elements[iHfHad];
1310 
1311  if (sortedTracks.empty()) {
1312  LogTrace("PFAlgo|createCandidatesHCF") << "\tno associated tracks, keep for later";
1313  continue;
1314  }
1315 
1316  // Lock the HFHAD cluster
1317  active[iHfHad] = false;
1318 
1319  LogTrace("PFAlgo|createCandidatesHF") << sortedTracks.size() << " associated tracks:";
1320 
1321  double totalChargedMomentum = 0.;
1322  double sumpError2 = 0.;
1323 
1324  //
1325  // Loop over all tracks associated to this HFHAD cluster
1326  //
1327  for (auto const& trk : sortedTracks) {
1328  unsigned iTrack = trk.second;
1329 
1330  // Check the track has not already been used
1331  if (!active[iTrack])
1332  continue;
1333  // Sanity check 1
1334  PFBlockElement::Type type = elements[iTrack].type();
1336  // Sanity check 2
1337  reco::TrackRef trackRef = elements[iTrack].trackRef();
1338  assert(!trackRef.isNull());
1339 
1340  // Introduce tracking errors
1341  double trackMomentum = trackRef->p();
1342  totalChargedMomentum += trackMomentum;
1343 
1344  // Also keep the total track momentum error for comparison with the calo energy
1345  double dp = trackRef->qoverpError() * trackMomentum * trackMomentum;
1346  sumpError2 += dp * dp;
1347 
1348  // Store active tracks for 2nd loop to create charged hadrons
1349  sortedTracksActive.emplace(trk);
1350 
1351  // look for HFEM elements associated to iTrack (associated to iHfHad)
1352  std::multimap<double, unsigned> sortedHfEms;
1353  block.associatedElements(
1354  iTrack, linkData, sortedHfEms, reco::PFBlockElement::HFEM, reco::PFBlock::LINKTEST_ALL);
1355 
1356  LogTrace("PFAlgo|createCandidatesHF") << "number of HfEm elements linked to this track: " << sortedHfEms.size();
1357 
1358  bool connectedToHfEm = false; // Will become true if there is at least one HFEM cluster connected
1359 
1360  //
1361  // Loop over all HFEM clusters connected to iTrack
1362  //
1363  for (auto const& hfem : sortedHfEms) {
1364  unsigned iHfEm = hfem.second;
1365  double dist = hfem.first;
1366 
1367  // Ignore HFEM cluters already used
1368  if (!active[iHfEm]) {
1369  LogTrace("PFAlgo|createCandidatesHF") << "cluster locked";
1370  continue;
1371  }
1372 
1373  // Sanity checks
1374  PFBlockElement::Type type = elements[iHfEm].type();
1375  assert(type == PFBlockElement::HFEM);
1376  PFClusterRef eclusterRef = elements[iHfEm].clusterRef();
1377  assert(!eclusterRef.isNull());
1378 
1379  // Check if this HFEM is not closer to another track - ignore it in that case
1380  std::multimap<double, unsigned> sortedTracksHfEm;
1381  block.associatedElements(
1382  iHfEm, linkData, sortedTracksHfEm, reco::PFBlockElement::TRACK, reco::PFBlock::LINKTEST_ALL);
1383  unsigned jTrack = sortedTracksHfEm.begin()->second;
1384  if (jTrack != iTrack)
1385  continue;
1386 
1387  double distHfEm = block.dist(jTrack, iHfEm, linkData, reco::PFBlock::LINKTEST_ALL);
1388  double hfemEnergy = eclusterRef->energy();
1389 
1390  if (!connectedToHfEm) { // This is the closest HFEM cluster - will add its energy later
1391 
1392  LogTrace("PFAlgo|createCandidatesHF") << "closest: " << elements[iHfEm];
1393  connectedToHfEm = true;
1394  std::pair<unsigned, double> satellite(iHfEm, hfemEnergy);
1395  hfemSatellites.emplace(-1., satellite);
1396 
1397  } else { // Keep satellite clusters for later
1398 
1399  // KH: same as above.
1400  std::pair<unsigned, double> satellite(iHfEm, hfemEnergy);
1401  hfemSatellites.emplace(dist, satellite);
1402  }
1403 
1404  std::pair<double, unsigned> associatedHfEm(distHfEm, iHfEm);
1405  associatedHfEms.emplace(iTrack, associatedHfEm);
1406 
1407  } // End loop hfem associated to iTrack
1408  } // sortedTracks
1409 
1410  // HfHad energy
1411  double uncalibratedenergyHfHad = hclusterRef->energy();
1412  double energyHfHad = uncalibratedenergyHfHad;
1414  energyHfHad = thepfEnergyCalibrationHF_.energyHad( // HAD only calibration
1415  uncalibratedenergyHfHad,
1416  hclusterRef->positionREP().Eta(),
1417  hclusterRef->positionREP().Phi());
1418  }
1419  double calibFactorHfHad = (uncalibratedenergyHfHad > 0.) ? energyHfHad / uncalibratedenergyHfHad : 1.;
1420 
1421  // HfEm energy
1422  double energyHfEmTmp = 0.;
1423  double uncalibratedenergyHfEmTmp = 0.;
1424  double energyHfEm = 0.;
1425  double uncalibratedenergyHfEm = 0.;
1426 
1427  // estimated HF resolution and track p error
1428  double caloResolution = hfEnergyResolution(totalChargedMomentum);
1429  caloResolution *= totalChargedMomentum;
1430  double totalError = sqrt(caloResolution * caloResolution + sumpError2);
1431  double nsigmaHFEM = nSigmaHFEM(totalChargedMomentum);
1432  double nsigmaHFHAD = nSigmaHFHAD(totalChargedMomentum);
1433 
1434  // Handle case that no active track gets associated to HfHad cluster
1435  if (sortedTracksActive.empty()) {
1436  // look for HFEM elements associated to iHfHad
1437  std::multimap<double, unsigned> sortedHfEms;
1438  std::multimap<double, unsigned> sortedHfEmsActive;
1439  block.associatedElements(
1440  iHfHad, linkData, sortedHfEms, reco::PFBlockElement::HFEM, reco::PFBlock::LINKTEST_ALL);
1441  //
1442  // If iHfHad is connected to HFEM cluster, Loop over all of them
1443  //
1444  if (!sortedHfEms.empty()) {
1445  for (auto const& hfem : sortedHfEms) {
1446  unsigned iHfEm = hfem.second;
1447  // Ignore HFEM cluters already used
1448  if (!active[iHfEm])
1449  continue;
1450  sortedHfEmsActive.emplace(hfem);
1451  PFClusterRef eclusterRef = elements[iHfEm].clusterRef();
1452  assert(!eclusterRef.isNull());
1453  double hfemEnergy = eclusterRef->energy();
1454  uncalibratedenergyHfEm += hfemEnergy;
1455  energyHfEm = uncalibratedenergyHfEm;
1458  uncalibratedenergyHfEm, 0.0, eclusterRef->positionREP().Eta(), eclusterRef->positionREP().Phi());
1459  energyHfHad = thepfEnergyCalibrationHF_.energyEmHad(
1460  0.0, uncalibratedenergyHfHad, hclusterRef->positionREP().Eta(), hclusterRef->positionREP().Phi());
1461  } // calib true
1462  } // loop over sortedHfEm
1463  } // if !sortedHfEms.empty()
1464  //
1465  // Create HF candidates
1466  unsigned tmpi = reconstructCluster(*hclusterRef, energyHfEm + energyHfHad);
1467  (*pfCandidates_)[tmpi].setHcalEnergy(uncalibratedenergyHfHad, energyHfHad);
1468  (*pfCandidates_)[tmpi].setEcalEnergy(uncalibratedenergyHfEm, energyHfEm);
1469  (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfHad);
1470  for (auto const& hfem : sortedHfEmsActive) {
1471  unsigned iHfEm = hfem.second;
1472  (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfEm);
1473  active[iHfEm] = false;
1474  }
1475 
1476  } // if sortedTracksActive.empty() ends
1477  //
1478  // Active tracks are associated.
1479  // Create HFHAD candidates from excess energy w.r.t. tracks
1480  else if ((energyHfHad - totalChargedMomentum) > nsigmaHFHAD * totalError) { // HfHad is excessive
1481  assert(energyHfEm == 0.);
1482  // HfHad candidate from excess
1483  double energyHfHadExcess = max(energyHfHad - totalChargedMomentum, 0.);
1484  double uncalibratedenergyHfHadExcess = energyHfHadExcess / calibFactorHfHad;
1485  unsigned tmpi = reconstructCluster(*hclusterRef, energyHfHadExcess);
1486  (*pfCandidates_)[tmpi].setHcalEnergy(uncalibratedenergyHfHadExcess, energyHfHadExcess);
1487  (*pfCandidates_)[tmpi].setEcalEnergy(0., 0.);
1488  (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfHad);
1489  energyHfHad = max(energyHfHad - energyHfHadExcess, 0.);
1490  uncalibratedenergyHfHad = max(uncalibratedenergyHfHad - uncalibratedenergyHfHadExcess, 0.);
1491  }
1492  //
1493  // If there is a room for HFEM satellites to get associated,
1494  // loop over all HFEM satellites, starting for the closest to the various tracks
1495  // and adding other satellites until saturation of the total track momentum
1496  //
1497  else {
1498  for (auto const& hfemSatellite : hfemSatellites) {
1499  //
1500  uncalibratedenergyHfEmTmp += std::get<1>(hfemSatellite.second); // KH: raw HFEM energy
1501  energyHfEmTmp = uncalibratedenergyHfEmTmp;
1502  double energyHfHadTmp = uncalibratedenergyHfHad; // now to test hfhad calibration with EM+HAD cases
1503  unsigned iHfEm = std::get<0>(hfemSatellite.second);
1504  PFClusterRef eclusterRef = elements[iHfEm].clusterRef();
1505  assert(!eclusterRef.isNull());
1507  energyHfEmTmp = thepfEnergyCalibrationHF_.energyEmHad(
1508  uncalibratedenergyHfEmTmp, 0.0, eclusterRef->positionREP().Eta(), eclusterRef->positionREP().Phi());
1509  energyHfHadTmp = thepfEnergyCalibrationHF_.energyEmHad(
1510  0.0, uncalibratedenergyHfHad, hclusterRef->positionREP().Eta(), hclusterRef->positionREP().Phi());
1511  }
1512 
1513  double caloEnergyTmp = energyHfEmTmp + energyHfHadTmp;
1514  double calibFactorHfEm = (uncalibratedenergyHfEmTmp > 0.) ? energyHfEmTmp / uncalibratedenergyHfEmTmp : 1.;
1515 
1516  // Continue looping until all closest clusters are exhausted and as long as
1517  // the calorimetric energy does not saturate the total momentum.
1518  if (hfemSatellite.first < 0. || caloEnergyTmp < totalChargedMomentum) {
1519  LogTrace("PFAlgo|createCandidatesHF")
1520  << "\t\t\tactive, adding " << std::get<1>(hfemSatellite.second) << " to HFEM energy, and locking";
1521  active[std::get<0>(hfemSatellite.second)] = false;
1522  // HfEm is excessive (possible for the first hfemSatellite)
1523  if (hfemSatellite.first < 0. && (caloEnergyTmp - totalChargedMomentum) > nsigmaHFEM * totalError) {
1524  // HfEm candidate from excess
1525  double energyHfEmExcess = max(caloEnergyTmp - totalChargedMomentum, 0.);
1526  double uncalibratedenergyHfEmExcess = energyHfEmExcess / calibFactorHfEm;
1527  unsigned tmpi = reconstructCluster(*eclusterRef, energyHfEmExcess);
1528  (*pfCandidates_)[tmpi].setEcalEnergy(uncalibratedenergyHfEmExcess, energyHfEmExcess);
1529  (*pfCandidates_)[tmpi].setHcalEnergy(0, 0.);
1530  (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfEm);
1531  energyHfEmTmp = max(energyHfEmTmp - energyHfEmExcess, 0.);
1532  uncalibratedenergyHfEmTmp = max(uncalibratedenergyHfEmTmp - uncalibratedenergyHfEmExcess, 0.);
1533  }
1534  energyHfEm = energyHfEmTmp;
1535  uncalibratedenergyHfEm = uncalibratedenergyHfEmTmp;
1536  energyHfHad = energyHfHadTmp;
1537  continue;
1538  }
1539  break;
1540  } // loop over hfemsattelites ends
1541  } // if HFHAD is excessive or not
1542 
1543  //
1544  // Loop over all tracks associated to this HFHAD cluster *again* in order to produce charged hadrons
1545  //
1546  for (auto const& trk : sortedTracksActive) {
1547  unsigned iTrack = trk.second;
1548 
1549  // Sanity check
1550  reco::TrackRef trackRef = elements[iTrack].trackRef();
1551  assert(!trackRef.isNull());
1552 
1553  //
1554  // Reconstructing charged hadrons
1555  //
1556  unsigned tmpi = reconstructTrack(elements[iTrack]);
1557  active[iTrack] = false;
1558  (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfHad);
1559  auto myHfEms = associatedHfEms.equal_range(iTrack);
1560  for (auto ii = myHfEms.first; ii != myHfEms.second; ++ii) {
1561  unsigned iHfEm = ii->second.second;
1562  if (active[iHfEm])
1563  continue;
1564  (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfEm);
1565  }
1566  double frac = 0.;
1567  if (totalChargedMomentum)
1568  frac = trackRef->p() / totalChargedMomentum;
1569  (*pfCandidates_)[tmpi].setEcalEnergy(uncalibratedenergyHfEm * frac, energyHfEm * frac);
1570  (*pfCandidates_)[tmpi].setHcalEnergy(uncalibratedenergyHfHad * frac, energyHfHad * frac);
1571 
1572  } // sortedTracks loop ends
1573 
1574  } // iHfHad element loop ends
1575 
1576  //
1577  // Loop over remaining active HfEm clusters
1578  //
1579  for (unsigned iHfEm = 0; iHfEm < elements.size(); iHfEm++) {
1580  PFBlockElement::Type type = elements[iHfEm].type();
1581  if (type == PFBlockElement::HFEM && active[iHfEm]) {
1582  reco::PFClusterRef eclusterRef = elements[iHfEm].clusterRef();
1583  double energyHF = 0.;
1584  double uncalibratedenergyHF = 0.;
1585  unsigned tmpi = 0;
1586  // do EM-only calibration here
1587  energyHF = eclusterRef->energy();
1588  uncalibratedenergyHF = energyHF;
1591  uncalibratedenergyHF, eclusterRef->positionREP().Eta(), eclusterRef->positionREP().Phi());
1592  }
1593  tmpi = reconstructCluster(*eclusterRef, energyHF);
1594  (*pfCandidates_)[tmpi].setEcalEnergy(uncalibratedenergyHF, energyHF);
1595  (*pfCandidates_)[tmpi].setHcalEnergy(0., 0.);
1596  (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfEm);
1597  active[iHfEm] = false;
1598  LogTrace("PFAlgo|createCandidatesHF") << "HF EM alone from blocks with tracks! " << energyHF;
1599  }
1600  } // remaining active HfEm cluster loop ends
1601 
1602  } // if-statement for blocks including tracks ends here
1603  //
1604  // -----------------------------------------------
1605  // From here, traditional PF HF candidate creation
1606  // -----------------------------------------------
1607  //
1608  else if (elements.size() == 1) {
1609  //Auguste: HAD-only calibration here
1610  reco::PFClusterRef clusterRef = elements[0].clusterRef();
1611  double energyHF = 0.;
1612  double uncalibratedenergyHF = 0.;
1613  unsigned tmpi = 0;
1614  switch (clusterRef->layer()) {
1615  case PFLayer::HF_EM:
1616  // do EM-only calibration here
1617  energyHF = clusterRef->energy();
1618  uncalibratedenergyHF = energyHF;
1621  uncalibratedenergyHF, clusterRef->positionREP().Eta(), clusterRef->positionREP().Phi());
1622  }
1623  tmpi = reconstructCluster(*clusterRef, energyHF);
1624  (*pfCandidates_)[tmpi].setEcalEnergy(uncalibratedenergyHF, energyHF);
1625  (*pfCandidates_)[tmpi].setHcalEnergy(0., 0.);
1626  (*pfCandidates_)[tmpi].setHoEnergy(0., 0.);
1627  (*pfCandidates_)[tmpi].setPs1Energy(0.);
1628  (*pfCandidates_)[tmpi].setPs2Energy(0.);
1629  (*pfCandidates_)[tmpi].addElementInBlock(blockref, inds.hfEmIs[0]);
1630  LogTrace("PFAlgo|createCandidatesHF") << "HF EM alone ! " << energyHF;
1631  break;
1632  case PFLayer::HF_HAD:
1633  // do HAD-only calibration here
1634  energyHF = clusterRef->energy();
1635  uncalibratedenergyHF = energyHF;
1638  uncalibratedenergyHF, clusterRef->positionREP().Eta(), clusterRef->positionREP().Phi());
1639  }
1640  tmpi = reconstructCluster(*clusterRef, energyHF);
1641  (*pfCandidates_)[tmpi].setHcalEnergy(uncalibratedenergyHF, energyHF);
1642  (*pfCandidates_)[tmpi].setEcalEnergy(0., 0.);
1643  (*pfCandidates_)[tmpi].setHoEnergy(0., 0.);
1644  (*pfCandidates_)[tmpi].setPs1Energy(0.);
1645  (*pfCandidates_)[tmpi].setPs2Energy(0.);
1646  (*pfCandidates_)[tmpi].addElementInBlock(blockref, inds.hfHadIs[0]);
1647  LogTrace("PFAlgo|createCandidatesHF") << "HF Had alone ! " << energyHF;
1648  break;
1649  default:
1650  assert(0);
1651  }
1652  } else if (elements.size() == 2) {
1653  //Auguste: EM + HAD calibration here
1654  reco::PFClusterRef c0 = elements[0].clusterRef();
1655  reco::PFClusterRef c1 = elements[1].clusterRef();
1656  // 2 HF elements. Must be in each layer.
1657  reco::PFClusterRef cem = (c0->layer() == PFLayer::HF_EM ? c0 : c1);
1658  reco::PFClusterRef chad = (c1->layer() == PFLayer::HF_HAD ? c1 : c0);
1659 
1660  if (cem->layer() != PFLayer::HF_EM || chad->layer() != PFLayer::HF_HAD) {
1661  edm::LogError("PFAlgo::createCandidatesHF") << "Error: 2 elements, but not 1 HFEM and 1 HFHAD";
1662  edm::LogError("PFAlgo::createCandidatesHF") << block;
1663  assert(0);
1664  // assert( c1->layer()== PFLayer::HF_EM &&
1665  // c0->layer()== PFLayer::HF_HAD );
1666  }
1667  // do EM+HAD calibration here
1668  double energyHfEm = cem->energy();
1669  double energyHfHad = chad->energy();
1670  double uncalibratedenergyHfEm = energyHfEm;
1671  double uncalibratedenergyHfHad = energyHfHad;
1674  uncalibratedenergyHfEm, 0.0, c0->positionREP().Eta(), c0->positionREP().Phi());
1675  energyHfHad = thepfEnergyCalibrationHF_.energyEmHad(
1676  0.0, uncalibratedenergyHfHad, c1->positionREP().Eta(), c1->positionREP().Phi());
1677  }
1678  auto& cand = (*pfCandidates_)[reconstructCluster(*chad, energyHfEm + energyHfHad)];
1679  cand.setEcalEnergy(uncalibratedenergyHfEm, energyHfEm);
1680  cand.setHcalEnergy(uncalibratedenergyHfHad, energyHfHad);
1681  cand.setHoEnergy(0., 0.);
1682  cand.setPs1Energy(0.);
1683  cand.setPs2Energy(0.);
1684  cand.addElementInBlock(blockref, inds.hfEmIs[0]);
1685  cand.addElementInBlock(blockref, inds.hfHadIs[0]);
1686  LogTrace("PFAlgo|createCandidatesHF") << "HF EM+HAD found ! " << energyHfEm << " " << energyHfHad;
1687  } else {
1688  // Unusual blocks including HF elements, but do not fit any of the above categories
1689  edm::LogWarning("PFAlgo::createCandidatesHF")
1690  << "Warning: HF, but n elem different from 1 or 2 or >=3 or !trackIs.empty()";
1691  edm::LogWarning("PFAlgo::createCandidatesHF") << block;
1692  }
1693  LogTrace("PFAlgo|createCandidateHF") << "end of function PFAlgo::createCandidateHF";
1694 }

References cms::cuda::assert(), groupFilesInBlocks::block, fftjetpileupestimator_calo_uncalib_cfi::c0, alignmentValidation::c1, Calorimetry_cff::dp, bookConverter::elements, PFEnergyCalibrationHF::energyEm(), PFEnergyCalibrationHF::energyEmHad(), PFEnergyCalibrationHF::energyHad(), HcalResponse_cfi::energyHF, cropTnPTrees::frac, PFEnergyCalibrationHF::getcalibHF_use(), PFLayer::HF_EM, PFLayer::HF_HAD, reco::PFBlockElement::HFEM, ElementIndices::hfEmIs, hfEnergyResolution(), ElementIndices::hfHadIs, cuy::ii, edm::Ref< C, T, F >::isNull(), reco::PFBlock::LINKTEST_ALL, LogTrace, SiStripPI::max, nSigmaHFEM(), nSigmaHFHAD(), reconstructCluster(), reconstructTrack(), mathSSE::sqrt(), thepfEnergyCalibrationHF_, reco::PFBlockElement::TRACK, ElementIndices::trackIs, and reco::btau::trackMomentum.

Referenced by processBlock().

◆ decideType()

int PFAlgo::decideType ( const edm::OwnVector< reco::PFBlockElement > &  elements,
const reco::PFBlockElement::Type  type,
std::vector< bool > &  active,
ElementIndices inds,
std::vector< bool > &  deadArea,
unsigned int  iEle 
)
private

Definition at line 1195 of file PFAlgo.cc.

1200  {
1201  switch (type) {
1202  case PFBlockElement::TRACK:
1203  if (active[iEle]) {
1204  inds.trackIs.push_back(iEle);
1205  LogTrace("PFAlgo|decideType") << "TRACK, stored index, continue";
1206  }
1207  break;
1208  case PFBlockElement::ECAL:
1209  if (active[iEle]) {
1210  inds.ecalIs.push_back(iEle);
1211  LogTrace("PFAlgo|decideType") << "ECAL, stored index, continue";
1212  }
1213  return 1; //continue
1214  case PFBlockElement::HCAL:
1215  if (active[iEle]) {
1216  if (elements[iEle].clusterRef()->flags() & reco::CaloCluster::badHcalMarker) {
1217  LogTrace("PFAlgo|decideType") << "HCAL DEAD AREA: remember and skip.";
1218  active[iEle] = false;
1219  deadArea[iEle] = true;
1220  return 1; //continue
1221  }
1222  inds.hcalIs.push_back(iEle);
1223  LogTrace("PFAlgo|decideType") << "HCAL, stored index, continue";
1224  }
1225  return 1; //continue
1226  case PFBlockElement::HO:
1227  if (useHO_) {
1228  if (active[iEle]) {
1229  inds.hoIs.push_back(iEle);
1230  LogTrace("PFAlgo|decideType") << "HO, stored index, continue";
1231  }
1232  }
1233  return 1; //continue
1234  case PFBlockElement::HFEM:
1235  if (active[iEle]) {
1236  inds.hfEmIs.push_back(iEle);
1237  LogTrace("PFAlgo|decideType") << "HFEM, stored index, continue";
1238  }
1239  return 1; //continue
1240  case PFBlockElement::HFHAD:
1241  if (active[iEle]) {
1242  inds.hfHadIs.push_back(iEle);
1243  LogTrace("PFAlgo|decideType") << "HFHAD, stored index, continue";
1244  }
1245  return 1; //continue
1246  default:
1247  return 1; //continue
1248  }
1249  LogTrace("PFAlgo|decideType") << "Did not match type to anything, return 0";
1250  return 0;
1251 }

References reco::CaloCluster::badHcalMarker, ECAL, ElementIndices::ecalIs, bookConverter::elements, HLT_2018_cff::flags, HCAL, ElementIndices::hcalIs, ElementIndices::hfEmIs, ElementIndices::hfHadIs, DigiToRawDM_cff::HO, ElementIndices::hoIs, LogTrace, ElementIndices::trackIs, and useHO_.

Referenced by elementLoop().

◆ egammaFilters()

void PFAlgo::egammaFilters ( const reco::PFBlockRef blockref,
std::vector< bool > &  active,
PFEGammaFilters const *  pfegamma 
)
private

Definition at line 222 of file PFAlgo.cc.

224  {
225  // const edm::ValueMap<reco::GsfElectronRef> & myGedElectronValMap(*valueMapGedElectrons_);
226 
227  unsigned int negmcandidates = pfEgammaCandidates_->size();
228  LogTrace("PFAlgo|egammaFilters") << "start of function PFAlgo::egammaFilters(), negmcandidates=" << negmcandidates;
229 
230  for (unsigned int ieg = 0; ieg < negmcandidates; ++ieg) {
231  // const reco::PFCandidate & egmcand((*pfEgammaCandidates_)[ieg]);
233 
234  const PFCandidate::ElementsInBlocks& theElements = (*pfEgmRef).elementsInBlocks();
235  PFCandidate::ElementsInBlocks::const_iterator iegfirst = theElements.begin();
236  bool sameBlock = false;
237  bool isGoodElectron = false;
238  bool isGoodPhoton = false;
239  bool isPrimaryElectron = false;
240  if (iegfirst->first == blockref)
241  sameBlock = true;
242  if (sameBlock) {
243  LogTrace("PFAlgo|egammaFilters") << " I am in looping on EGamma Candidates: pt " << (*pfEgmRef).pt()
244  << " eta,phi " << (*pfEgmRef).eta() << ", " << (*pfEgmRef).phi() << " charge "
245  << (*pfEgmRef).charge();
246 
247  if ((*pfEgmRef).gsfTrackRef().isNonnull()) {
248  reco::GsfElectronRef gedEleRef = (*valueMapGedElectrons_)[pfEgmRef];
249  if (gedEleRef.isNonnull()) {
250  isGoodElectron = pfegamma->passElectronSelection(*gedEleRef, *pfEgmRef, nVtx_);
251  isPrimaryElectron = pfegamma->isElectron(*gedEleRef);
252  if (isGoodElectron)
253  LogTrace("PFAlgo|egammaFilters")
254  << "** Good Electron, pt " << gedEleRef->pt() << " eta, phi " << gedEleRef->eta() << ", "
255  << gedEleRef->phi() << " charge " << gedEleRef->charge() << " isPrimary " << isPrimaryElectron
256  << " isoDr03 "
257  << (gedEleRef->dr03TkSumPt() + gedEleRef->dr03EcalRecHitSumEt() + gedEleRef->dr03HcalTowerSumEt())
258  << " mva_isolated " << gedEleRef->mva_Isolated() << " mva_e_pi " << gedEleRef->mva_e_pi();
259  }
260  }
261  if ((*pfEgmRef).superClusterRef().isNonnull()) {
262  reco::PhotonRef gedPhoRef = (*valueMapGedPhotons_)[pfEgmRef];
263  if (gedPhoRef.isNonnull()) {
264  isGoodPhoton = pfegamma->passPhotonSelection(*gedPhoRef);
265  if (isGoodPhoton)
266  LogTrace("PFAlgo|egammaFilters") << "** Good Photon, pt " << gedPhoRef->pt() << " eta, phi "
267  << gedPhoRef->eta() << ", " << gedPhoRef->phi() << endl;
268  }
269  }
270  } // end sameBlock
271 
272  if (isGoodElectron && isGoodPhoton) {
273  if (isPrimaryElectron)
274  isGoodPhoton = false;
275  else
276  isGoodElectron = false;
277  }
278 
279  // isElectron
280  if (isGoodElectron) {
281  reco::GsfElectronRef gedEleRef = (*valueMapGedElectrons_)[pfEgmRef];
282  reco::PFCandidate myPFElectron = *pfEgmRef;
283  // run protections
284  bool lockTracks = false;
285  bool isSafe = true;
287  lockTracks = true;
288  isSafe = pfegamma->isElectronSafeForJetMET(*gedEleRef, myPFElectron, primaryVertex_, lockTracks);
289  }
290 
291  if (isSafe) {
293  myPFElectron.setParticleType(particleType);
294  myPFElectron.setCharge(gedEleRef->charge());
295  myPFElectron.setP4(gedEleRef->p4());
296  myPFElectron.set_mva_e_pi(gedEleRef->mva_e_pi());
297  myPFElectron.set_mva_Isolated(gedEleRef->mva_Isolated());
298 
299  LogTrace("PFAlgo|egammaFilters") << " PFAlgo: found an electron with NEW EGamma code ";
300  LogTrace("PFAlgo|egammaFilters") << " myPFElectron: pt " << myPFElectron.pt() << " eta,phi "
301  << myPFElectron.eta() << ", " << myPFElectron.phi() << " mva "
302  << myPFElectron.mva_e_pi() << " charge " << myPFElectron.charge();
303 
304  LogTrace("PFAlgo|egammaFilters") << " THE BLOCK " << *blockref;
305  for (auto const& eb : theElements) {
306  active[eb.second] = false;
307  LogTrace("PFAlgo|egammaFilters") << " Elements used " << eb.second;
308  }
309 
310  // The electron is considered safe for JetMET and the additional tracks pointing to it are locked
311  if (lockTracks) {
312  const PFCandidate::ElementsInBlocks& extraTracks = myPFElectron.egammaExtraRef()->extraNonConvTracks();
313  for (auto const& trk : extraTracks) {
314  LogTrace("PFAlgo|egammaFilters") << " Extra locked track " << trk.second;
315  active[trk.second] = false;
316  }
317  }
318 
319  LogTrace("PFAlgo|egammaFilters") << "Creating PF electron: pt=" << myPFElectron.pt()
320  << " eta=" << myPFElectron.eta() << " phi=" << myPFElectron.phi();
321  pfCandidates_->push_back(myPFElectron);
322 
323  } else {
324  LogTrace("PFAlgo|egammaFilters") << "PFAlgo: Electron DISCARDED, NOT SAFE FOR JETMET ";
325  }
326  } //isGoodElectron
327 
328  if (isGoodPhoton) {
329  reco::PhotonRef gedPhoRef = (*valueMapGedPhotons_)[pfEgmRef];
330  reco::PFCandidate myPFPhoton = *pfEgmRef;
331  bool isSafe = true;
333  isSafe = pfegamma->isPhotonSafeForJetMET(*gedPhoRef, myPFPhoton);
334  }
335 
336  if (isSafe) {
338  myPFPhoton.setParticleType(particleType);
339  myPFPhoton.setCharge(0);
340  myPFPhoton.set_mva_nothing_gamma(1.);
342  myPFPhoton.setVertex(v);
343  myPFPhoton.setP4(gedPhoRef->p4());
344  LogTrace("PFAlgo|egammaFilters") << " PFAlgo: found a photon with NEW EGamma code ";
345  LogTrace("PFAlgo|egammaFilters") << " myPFPhoton: pt " << myPFPhoton.pt() << " eta,phi " << myPFPhoton.eta()
346  << ", " << myPFPhoton.phi() << " charge " << myPFPhoton.charge();
347 
348  // Lock all the elements
349  LogTrace("PFAlgo|egammaFilters") << " THE BLOCK " << *blockref;
350  for (auto const& eb : theElements) {
351  active[eb.second] = false;
352  LogTrace("PFAlgo|egammaFilters") << " Elements used " << eb.second;
353  }
354  LogTrace("PFAlgo|egammaFilters") << "Creating PF photon: pt=" << myPFPhoton.pt() << " eta=" << myPFPhoton.eta()
355  << " phi=" << myPFPhoton.phi();
356  pfCandidates_->push_back(myPFPhoton);
357 
358  } // end isSafe
359  } // end isGoodPhoton
360  } // end loop on EGM candidates
361  LogTrace("PFAlgo|egammaFilters") << "end of function PFAlgo::egammaFilters";
362 }

References reco::LeafCandidate::charge(), reco::PFCandidate::e, reco::PFCandidate::egammaExtraRef(), reco::LeafCandidate::eta(), reco::PFCandidate::gamma, PFEGammaFilters::isElectron(), PFEGammaFilters::isElectronSafeForJetMET(), edm::Ref< C, T, F >::isNonnull(), PFEGammaFilters::isPhotonSafeForJetMET(), LogTrace, reco::PFCandidate::mva_e_pi(), nVtx_, PbPb_ZMuSkimMuonDPG_cff::particleType, PFEGammaFilters::passElectronSelection(), PFEGammaFilters::passPhotonSelection(), pfCandidates_, pfEgammaCandidates_, reco::LeafCandidate::phi(), primaryVertex_, reco::LeafCandidate::pt(), edm::View< T >::refAt(), reco::PFCandidate::set_mva_e_pi(), reco::PFCandidate::set_mva_Isolated(), reco::PFCandidate::set_mva_nothing_gamma(), reco::LeafCandidate::setCharge(), reco::LeafCandidate::setP4(), reco::PFCandidate::setParticleType(), reco::PFCandidate::setVertex(), edm::View< T >::size(), useProtectionsForJetMET_, findQualityFiles::v, reco::Vertex::x(), reco::Vertex::y(), and reco::Vertex::z().

Referenced by processBlock().

◆ elementLoop()

void PFAlgo::elementLoop ( const reco::PFBlock block,
reco::PFBlock::LinkData linkData,
const edm::OwnVector< reco::PFBlockElement > &  elements,
std::vector< bool > &  active,
const reco::PFBlockRef blockref,
ElementIndices inds,
std::vector< bool > &  deadArea 
)
private

Definition at line 991 of file PFAlgo.cc.

997  {
998  LogTrace("PFAlgo|elementLoop") << "start of function PFAlgo::elementLoop, elements.size()" << elements.size();
999 
1000  for (unsigned iEle = 0; iEle < elements.size(); iEle++) {
1001  PFBlockElement::Type type = elements[iEle].type();
1002 
1003  LogTrace("PFAlgo|elementLoop") << "elements[iEle=" << iEle << "]=" << elements[iEle];
1004  //only process TRACK elements, but fill the ElementIndices vector with indices for all elements.
1005  //Mark the active & deadArea for bad HCAL
1006  auto ret_decideType = decideType(elements, type, active, inds, deadArea, iEle);
1007  if (ret_decideType == 1) {
1008  LogTrace("PFAlgo|elementLoop") << "ret_decideType==1, continuing";
1009  continue;
1010  }
1011  LogTrace("PFAlgo|elementLoop") << "ret_decideType=" << ret_decideType << " type=" << type;
1012 
1013  active[iEle] = checkAndReconstructSecondaryInteraction(blockref, elements, active[iEle], iEle);
1014 
1015  if (!active[iEle]) {
1016  LogTrace("PFAlgo|elementLoop") << "Already used by electrons, muons, conversions";
1017  continue;
1018  }
1019 
1020  reco::TrackRef trackRef = elements[iEle].trackRef();
1021  assert(!trackRef.isNull());
1022 
1023  LogTrace("PFAlgo|elementLoop") << "PFAlgo:processBlock"
1024  << " trackIs.size()=" << inds.trackIs.size()
1025  << " ecalIs.size()=" << inds.ecalIs.size() << " hcalIs.size()=" << inds.hcalIs.size()
1026  << " hoIs.size()=" << inds.hoIs.size() << " hfEmIs.size()=" << inds.hfEmIs.size()
1027  << " hfHadIs.size()=" << inds.hfHadIs.size();
1028 
1029  // look for associated elements of all types
1030  //COLINFEB16
1031  // all types of links are considered.
1032  // the elements are sorted by increasing distance
1033  std::multimap<double, unsigned> ecalElems;
1034  block.associatedElements(iEle, linkData, ecalElems, reco::PFBlockElement::ECAL, reco::PFBlock::LINKTEST_ALL);
1035 
1036  std::multimap<double, unsigned> hcalElems;
1037  block.associatedElements(iEle, linkData, hcalElems, reco::PFBlockElement::HCAL, reco::PFBlock::LINKTEST_ALL);
1038 
1039  std::multimap<double, unsigned> hfEmElems;
1040  std::multimap<double, unsigned> hfHadElems;
1041  block.associatedElements(iEle, linkData, hfEmElems, reco::PFBlockElement::HFEM, reco::PFBlock::LINKTEST_ALL);
1042  block.associatedElements(iEle, linkData, hfHadElems, reco::PFBlockElement::HFHAD, reco::PFBlock::LINKTEST_ALL);
1043 
1044  LogTrace("PFAlgo|elementLoop") << "\tTrack " << iEle << " is linked to " << ecalElems.size() << " ecal and "
1045  << hcalElems.size() << " hcal and " << hfEmElems.size() << " hfEm and "
1046  << hfHadElems.size() << " hfHad elements";
1047 
1048 #ifdef EDM_ML_DEBUG
1049  for (const auto& pair : ecalElems) {
1050  LogTrace("PFAlgo|elementLoop") << "ecal: dist " << pair.first << "\t elem " << pair.second;
1051  }
1052  for (const auto& pair : hcalElems) {
1053  LogTrace("PFAlgo|elementLoop") << "hcal: dist " << pair.first << "\t elem " << pair.second
1054  << (deadArea[pair.second] ? " DEAD AREA MARKER" : "");
1055  }
1056 #endif
1057 
1058  const bool hasDeadHcal = checkHasDeadHcal(hcalElems, deadArea);
1059  if (hasDeadHcal) {
1060  hcalElems.clear();
1061  }
1062  const bool goodTrackDeadHcal = checkGoodTrackDeadHcal(trackRef, hasDeadHcal);
1063 
1064  // When a track has no HCAL cluster linked, but another track is linked to the same
1065  // ECAL cluster and an HCAL cluster, link the track to the HCAL cluster for
1066  // later analysis
1067  if (hcalElems.empty() && !ecalElems.empty() && !hasDeadHcal) {
1068  relinkTrackToHcal(block, ecalElems, hcalElems, active, linkData, iEle);
1069  }
1070 
1071  //MICHELE
1072  //TEMPORARY SOLUTION FOR ELECTRON REJECTION IN PFTAU
1073  //COLINFEB16
1074  // in case particle flow electrons are not reconstructed,
1075  // the mva_e_pi of the charged hadron will be set to 1
1076  // if a GSF element is associated to the current TRACK element
1077  // This information will be used in the electron rejection for tau ID.
1078  std::multimap<double, unsigned> gsfElems;
1079  block.associatedElements(iEle, linkData, gsfElems, reco::PFBlockElement::GSF);
1080 
1081  if (hcalElems.empty()) {
1082  LogTrace("PFAlgo|elementLoop") << "no hcal element connected to track " << iEle;
1083  }
1084 
1085  // will now loop on associated elements ...
1086  bool hcalFound = false;
1087  bool hfhadFound = false;
1088 
1089  LogTrace("PFAlgo|elementLoop") << "now looping on elements associated to the track: ecalElems";
1090 
1091  // ... first on associated ECAL elements
1092  // Check if there is still a free ECAL for this track
1093  for (auto const& ecal : ecalElems) {
1094  unsigned index = ecal.second;
1095  // Sanity checks and optional printout
1097 #ifdef EDM_ML_DEBUG
1098  double dist = ecal.first;
1099  LogTrace("PFAlgo|elementLoop") << "\telement " << elements[index] << " linked with distance = " << dist;
1100  if (!active[index])
1101  LogTrace("PFAlgo|elementLoop") << "This ECAL is already used - skip it";
1102 #endif
1104 
1105  // This ECAL is not free (taken by an electron?) - just skip it
1106  if (!active[index])
1107  continue;
1108 
1109  // Flag ECAL clusters for which the corresponding track is not linked to an HCAL cluster
1110 
1111  //reco::PFClusterRef clusterRef = elements[index].clusterRef();
1112  //assert( !clusterRef.isNull() );
1113  if (!hcalElems.empty())
1114  LogTrace("PFAlgo|elementLoop") << "\t\tat least one hcal element connected to the track."
1115  << " Sparing Ecal cluster for the hcal loop";
1116 
1117  } //loop print ecal elements
1118 
1119  // tracks which are not linked to an HCAL (or HFHAD)
1120  // are reconstructed now.
1121 
1122  if (hcalElems.empty() && hfHadElems.empty()) {
1123  auto ret_continue = recoTracksNotHCAL(
1124  block, linkData, elements, blockref, active, goodTrackDeadHcal, hasDeadHcal, iEle, ecalElems, trackRef);
1125  if (ret_continue) {
1126  continue;
1127  }
1128  } // end if( hcalElems.empty() && hfHadElems.empty() )
1129 
1130  // In case several HCAL elements are linked to this track,
1131  // unlinking all of them except the closest.
1132  for (auto const& hcal : hcalElems) {
1133  unsigned index = hcal.second;
1134 
1136 
1137 #ifdef EDM_ML_DEBUG
1138  double dist = block.dist(iEle, index, linkData, reco::PFBlock::LINKTEST_ALL);
1139  LogTrace("PFAlgo|elementLoop") << "\telement " << elements[index] << " linked with distance " << dist;
1140 #endif
1142 
1143  // all hcal clusters except the closest
1144  // will be unlinked from the track
1145  if (!hcalFound) { // closest hcal
1146  LogTrace("PFAlgo|elementLoop") << "\t\tclosest hcal cluster, doing nothing";
1147 
1148  hcalFound = true;
1149 
1150  // active[index] = false;
1151  // hcalUsed.push_back( index );
1152  } else { // other associated hcal
1153  // unlink from the track
1154  LogTrace("PFAlgo|elementLoop") << "\t\tsecondary hcal cluster. unlinking";
1155  block.setLink(iEle, index, -1., linkData, PFBlock::LINKTEST_RECHIT);
1156  }
1157  } //loop hcal elements
1158 
1159  // ---Same for HFHAD---
1160  // In case several HFHAD elements are linked to this track,
1161  // unlinking all of them except the closest.
1162  for (auto const& hfhad : hfHadElems) {
1163  unsigned index = hfhad.second;
1164 
1166 
1167 #ifdef EDM_ML_DEBUG
1168  double dist = block.dist(iEle, index, linkData, reco::PFBlock::LINKTEST_ALL);
1169  LogTrace("PFAlgo|elementLoop") << "\telement " << elements[index] << " linked with distance " << dist;
1170 #endif
1171  assert(type == PFBlockElement::HFHAD);
1172 
1173  // all hfhad clusters except the closest
1174  // will be unlinked from the track
1175  if (!hfhadFound) { // closest hfhad
1176  LogTrace("PFAlgo|elementLoop") << "\t\tclosest hfhad cluster, doing nothing";
1177 
1178  hfhadFound = true;
1179 
1180  } else { // other associated hfhad
1181  // unlink from the track
1182  LogTrace("PFAlgo|elementLoop") << "\t\tsecondary hfhad cluster. unlinking";
1183  block.setLink(iEle, index, -1., linkData, PFBlock::LINKTEST_RECHIT);
1184  }
1185  } //loop hfhad elements
1186 
1187  LogTrace("PFAlgo|elementLoop") << "end of loop over iEle";
1188  } // end of outer loop on elements iEle of any type
1189  LogTrace("PFAlgo|elementLoop") << "end of function PFAlgo::elementLoop";
1190 }

References cms::cuda::assert(), groupFilesInBlocks::block, checkAndReconstructSecondaryInteraction(), checkGoodTrackDeadHcal(), checkHasDeadHcal(), decideType(), ECAL, bsc_activity_cfg::ecal, reco::PFBlockElement::ECAL, ElementIndices::ecalIs, bookConverter::elements, reco::PFBlockElement::GSF, HCAL, reco::PFBlockElement::HCAL, ElementIndices::hcalIs, reco::PFBlockElement::HFEM, ElementIndices::hfEmIs, reco::PFBlockElement::HFHAD, ElementIndices::hfHadIs, ElementIndices::hoIs, edm::Ref< C, T, F >::isNull(), reco::PFBlock::LINKTEST_ALL, LogTrace, recoTracksNotHCAL(), relinkTrackToHcal(), and ElementIndices::trackIs.

Referenced by processBlock().

◆ getCleanedCandidates()

reco::PFCandidateCollection& PFAlgo::getCleanedCandidates ( )
inline
Returns
collection of cleaned HF candidates

Definition at line 112 of file PFAlgo.h.

112 { return pfCleanedCandidates_; }

References pfCleanedCandidates_.

Referenced by PFProducer::produce().

◆ getPFMuonAlgo()

PFMuonAlgo * PFAlgo::getPFMuonAlgo ( )

Definition at line 66 of file PFAlgo.cc.

66 { return pfmu_.get(); }

References pfmu_.

Referenced by PFProducer::produce().

◆ hfEnergyResolution()

double PFAlgo::hfEnergyResolution ( double  clusterEnergy) const
private

Definition at line 3372 of file PFAlgo.cc.

3372  {
3373  // Add a protection
3374  clusterEnergyHF = std::max(clusterEnergyHF, 1.);
3375 
3376  double resol =
3377  sqrt(resolHF_square_[0] / clusterEnergyHF + resolHF_square_[1] + resolHF_square_[2] / pow(clusterEnergyHF, 2));
3378  // 0: stochastic term, 1: constant term, 2: noise term
3379  // Note: resolHF_square_[0,1,2] should be already squared
3380 
3381  return resol;
3382 }

References SiStripPI::max, funct::pow(), l1ParticleFlow_cff::resol, resolHF_square_, and mathSSE::sqrt().

Referenced by createCandidatesHF().

◆ isFromSecInt()

bool PFAlgo::isFromSecInt ( const reco::PFBlockElement eTrack,
std::string  order 
) const
private

Definition at line 3464 of file PFAlgo.cc.

3464  {
3467  // reco::PFBlockElement::TrackType T_FROM_GAMMACONV = reco::PFBlockElement::T_FROM_GAMMACONV;
3469 
3470  bool bPrimary = (order.find("primary") != string::npos);
3471  bool bSecondary = (order.find("secondary") != string::npos);
3472  bool bAll = (order.find("all") != string::npos);
3473 
3474  bool isToDisp = usePFNuclearInteractions_ && eTrack.trackType(T_TO_DISP);
3475  bool isFromDisp = usePFNuclearInteractions_ && eTrack.trackType(T_FROM_DISP);
3476 
3477  if (bPrimary && isToDisp)
3478  return true;
3479  if (bSecondary && isFromDisp)
3480  return true;
3481  if (bAll && (isToDisp || isFromDisp))
3482  return true;
3483 
3484  // bool isFromConv = usePFConversions_ && eTrack.trackType(T_FROM_GAMMACONV);
3485 
3486  // if ((bAll || bSecondary)&& isFromConv) return true;
3487 
3488  bool isFromDecay = (bAll || bSecondary) && usePFDecays_ && eTrack.trackType(T_FROM_V0);
3489 
3490  return isFromDecay;
3491 }

References eventshapeDQM_cfi::order, reco::PFBlockElement::T_FROM_DISP, reco::PFBlockElement::T_FROM_V0, reco::PFBlockElement::T_TO_DISP, reco::PFBlockElement::trackType(), usePFDecays_, and usePFNuclearInteractions_.

Referenced by checkAndReconstructSecondaryInteraction(), createCandidatesHCAL(), reconstructTrack(), and recoTracksNotHCAL().

◆ makeConnectedCandidates()

reco::PFCandidateCollection PFAlgo::makeConnectedCandidates ( )
inline
Returns
the collection of candidates

Definition at line 115 of file PFAlgo.h.

115 { return connector_.connect(*pfCandidates_); }

References PFCandConnector::connect(), connector_, and pfCandidates_.

Referenced by PFProducer::produce().

◆ neutralHadronEnergyResolution()

double PFAlgo::neutralHadronEnergyResolution ( double  clusterEnergy,
double  clusterEta 
) const
private

todo: use PFClusterTools for this

Definition at line 3355 of file PFAlgo.cc.

3355  {
3356  // Add a protection
3357  clusterEnergyHCAL = std::max(clusterEnergyHCAL, 1.);
3358 
3359  double resol = fabs(eta) < 1.48 ? sqrt(1.02 * 1.02 / clusterEnergyHCAL + 0.065 * 0.065)
3360  : sqrt(1.20 * 1.20 / clusterEnergyHCAL + 0.028 * 0.028);
3361 
3362  return resol;
3363 }

References PVValHelper::eta, SiStripPI::max, l1ParticleFlow_cff::resol, and mathSSE::sqrt().

Referenced by createCandidatesHCAL(), and recoTracksNotHCAL().

◆ nSigmaHCAL()

double PFAlgo::nSigmaHCAL ( double  clusterEnergy,
double  clusterEta 
) const
private

Definition at line 3365 of file PFAlgo.cc.

3365  {
3366  double nS = fabs(eta) < 1.48 ? nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL / nSigmaEConstHCAL))
3367  : nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL / nSigmaEConstHCAL));
3368 
3369  return nS;
3370 }

References PVValHelper::eta, JetChargeProducer_cfi::exp, nSigmaEConstHCAL, and nSigmaHCAL_.

Referenced by createCandidatesHCAL().

◆ nSigmaHFEM()

double PFAlgo::nSigmaHFEM ( double  clusterEnergy) const
private

Definition at line 3384 of file PFAlgo.cc.

3384  {
3385  double nS = nSigmaHFEM_ * (1. + exp(-clusterEnergyHF / nSigmaEConstHFEM));
3386  return nS;
3387 }

References JetChargeProducer_cfi::exp, nSigmaEConstHFEM, and nSigmaHFEM_.

Referenced by createCandidatesHF().

◆ nSigmaHFHAD()

double PFAlgo::nSigmaHFHAD ( double  clusterEnergy) const
private

Definition at line 3389 of file PFAlgo.cc.

3389  {
3390  double nS = nSigmaHFHAD_ * (1. + exp(-clusterEnergyHF / nSigmaEConstHFHAD));
3391  return nS;
3392 }

References JetChargeProducer_cfi::exp, nSigmaEConstHFHAD, and nSigmaHFHAD_.

Referenced by createCandidatesHF().

◆ postCleaning()

void PFAlgo::postCleaning ( )
private

Definition at line 3493 of file PFAlgo.cc.

3493  {
3494  //Compute met and met significance (met/sqrt(SumEt))
3495  double metX = 0.;
3496  double metY = 0.;
3497  double sumet = 0;
3498  std::vector<unsigned int> pfCandidatesToBeRemoved;
3499  for (auto const& pfc : *pfCandidates_) {
3500  metX += pfc.px();
3501  metY += pfc.py();
3502  sumet += pfc.pt();
3503  }
3504  double met2 = metX * metX + metY * metY;
3505  // Select events with large MET significance.
3506  double significance = std::sqrt(met2 / sumet);
3507  double significanceCor = significance;
3509  double metXCor = metX;
3510  double metYCor = metY;
3511  double sumetCor = sumet;
3512  double met2Cor = met2;
3513  double deltaPhi = 3.14159;
3514  double deltaPhiPt = 100.;
3515  bool next = true;
3516  unsigned iCor = 1E9;
3517 
3518  // Find the HF candidate with the largest effect on the MET
3519  while (next) {
3520  double metReduc = -1.;
3521  // Loop on the candidates
3522  for (unsigned i = 0; i < pfCandidates_->size(); ++i) {
3523  const PFCandidate& pfc = (*pfCandidates_)[i];
3524 
3525  // Check that the pfCandidate is in the HF
3527  continue;
3528 
3529  // Check if has meaningful pt
3530  if (pfc.pt() < minHFCleaningPt_)
3531  continue;
3532 
3533  // Check that it is not already scheculed to be cleaned
3534  const bool skip = std::any_of(
3535  pfCandidatesToBeRemoved.begin(), pfCandidatesToBeRemoved.end(), [&](unsigned int j) { return i == j; });
3536  if (skip)
3537  continue;
3538 
3539  // Check that the pt and the MET are aligned
3540  deltaPhi = std::acos((metX * pfc.px() + metY * pfc.py()) / (pfc.pt() * std::sqrt(met2)));
3541  deltaPhiPt = deltaPhi * pfc.pt();
3542  if (deltaPhiPt > maxDeltaPhiPt_)
3543  continue;
3544 
3545  // Now remove the candidate from the MET
3546  double metXInt = metX - pfc.px();
3547  double metYInt = metY - pfc.py();
3548  double sumetInt = sumet - pfc.pt();
3549  double met2Int = metXInt * metXInt + metYInt * metYInt;
3550  if (met2Int < met2Cor) {
3551  metXCor = metXInt;
3552  metYCor = metYInt;
3553  metReduc = (met2 - met2Int) / met2Int;
3554  met2Cor = met2Int;
3555  sumetCor = sumetInt;
3556  significanceCor = std::sqrt(met2Cor / sumetCor);
3557  iCor = i;
3558  }
3559  }
3560  //
3561  // If the MET must be significanly reduced, schedule the candidate to be cleaned
3562  if (metReduc > minDeltaMet_) {
3563  pfCandidatesToBeRemoved.push_back(iCor);
3564  metX = metXCor;
3565  metY = metYCor;
3566  sumet = sumetCor;
3567  met2 = met2Cor;
3568  } else {
3569  // Otherwise just stop the loop
3570  next = false;
3571  }
3572  }
3573  //
3574  // The significance must be significantly reduced to indeed clean the candidates
3575  if (significance - significanceCor > minSignificanceReduction_ && significanceCor < maxSignificance_) {
3576  edm::LogInfo("PFAlgo|postCleaning") << "Significance reduction = " << significance << " -> " << significanceCor
3577  << " = " << significanceCor - significance;
3578  for (unsigned int toRemove : pfCandidatesToBeRemoved) {
3579  edm::LogInfo("PFAlgo|postCleaning") << "Removed : " << (*pfCandidates_)[toRemove];
3580  pfCleanedCandidates_.push_back((*pfCandidates_)[toRemove]);
3581  (*pfCandidates_)[toRemove].rescaleMomentum(1E-6);
3582  //reco::PFCandidate::ParticleType unknown = reco::PFCandidate::X;
3583  //(*pfCandidates_)[toRemove].setParticleType(unknown);
3584  }
3585  }
3586  } //significance
3587 } //postCleaning

References SiPixelRawToDigiRegional_cfi::deltaPhi, reco::PFCandidate::egamma_HF, reco::PFCandidate::h_HF, mps_fire::i, dqmiolumiharvest::j, maxDeltaPhiPt_, maxSignificance_, minDeltaMet_, minHFCleaningPt_, minSignificance_, minSignificanceReduction_, GetRecoTauVFromDQM_MC_cff::next, reco::PFCandidate::particleId(), pfCandidates_, pfCleanedCandidates_, reco::LeafCandidate::pt(), reco::LeafCandidate::px(), reco::LeafCandidate::py(), met_cff::significance, optionsL1T::skip, and mathSSE::sqrt().

Referenced by reconstructParticles().

◆ processBlock()

void PFAlgo::processBlock ( const reco::PFBlockRef blockref,
std::list< reco::PFBlockRef > &  hcalBlockRefs,
std::list< reco::PFBlockRef > &  ecalBlockRefs,
PFEGammaFilters const *  pfegamma 
)
private

process one block. can be reimplemented in more sophisticated algorithms

Definition at line 3055 of file PFAlgo.cc.

3058  {
3059  assert(!blockref.isNull());
3060  const reco::PFBlock& block = *blockref;
3061 
3062  LogTrace("PFAlgo|processBlock") << "start of function PFAlgo::processBlock, block=" << block;
3063 
3065  LogTrace("PFAlgo|processBlock") << "elements.size()=" << elements.size();
3066  // make a copy of the link data, which will be edited.
3067  PFBlock::LinkData linkData = block.linkData();
3068 
3069  // keep track of the elements which are still active.
3070  vector<bool> active(elements.size(), true);
3071 
3072  // //PFElectrons:
3073  // usePFElectrons_ external configurable parameter to set the usage of pf electron
3074  std::vector<reco::PFCandidate> tempElectronCandidates;
3075  tempElectronCandidates.clear();
3076 
3077  // New EGamma Reconstruction 10/10/2013
3078  if (useEGammaFilters_) {
3079  egammaFilters(blockref, active, pfegamma);
3080  } // end if use EGammaFilters
3081 
3082  //Lock extra conversion tracks not used by Photon Algo
3083  if (usePFConversions_) {
3084  conversionAlgo(elements, active);
3085  }
3086 
3087  // In the following elementLoop() function, the primary goal is to deal with tracks that are:
3088  // - not associated to an HCAL cluster
3089  // - not identified as an electron.
3090  // Those tracks should be predominantly relatively low energy charged
3091  // hadrons which are not detected in the ECAL.
3092 
3093  // The secondary goal is to prepare for the next loops
3094  // - The ecal and hcal elements are sorted in separate vectors in `ElementIndices inds`
3095  // which will be used as a base for the corresponding loops.
3096  // - For tracks which are connected to more than one HCAL cluster,
3097  // the links between the track and the cluster are cut for all clusters
3098  // but the closest one.
3099  // - HF only blocks ( HFEM, HFHAD, HFEM+HFAD) are identified
3100 
3101  // obsolete comments?
3102  // loop1:
3103  // - sort ecal and hcal elements in separate vectors
3104  // - for tracks:
3105  // - lock closest ecal cluster
3106  // - cut link to farthest hcal cluster, if more than 1.
3107 
3108  vector<bool> deadArea(elements.size(), false);
3109 
3110  // vectors to store element indices to ho, hcal and ecal elements, will be filled by elementLoop()
3111  ElementIndices inds;
3112 
3113  elementLoop(block, linkData, elements, active, blockref, inds, deadArea);
3114 
3115  // Reconstruct pfCandidate from HF (either EM-only, Had-only or both)
3116  // For phase2, process also pfblocks containing HF clusters and linked tracks
3117  if (!(inds.hfEmIs.empty() && inds.hfHadIs.empty())) {
3118  createCandidatesHF(block, linkData, elements, active, blockref, inds);
3119  if (inds.hcalIs.empty() && inds.ecalIs.empty())
3120  return;
3121  LogDebug("PFAlgo::processBlock")
3122  << "Block contains HF clusters, and also contains ECAL or HCAL clusters. Continue.\n"
3123  << block;
3124  }
3125 
3126  createCandidatesHCAL(block, linkData, elements, active, blockref, inds, deadArea);
3127  // COLINFEB16: now dealing with the HCAL elements that are not linked to any track
3128  createCandidatesHCALUnlinked(block, linkData, elements, active, blockref, inds, deadArea);
3129  createCandidatesECAL(block, linkData, elements, active, blockref, inds, deadArea);
3130 
3131  LogTrace("PFAlgo|processBlock") << "end of function PFAlgo::processBlock";
3132 } // end processBlock

References cms::cuda::assert(), groupFilesInBlocks::block, conversionAlgo(), createCandidatesECAL(), createCandidatesHCAL(), createCandidatesHCALUnlinked(), createCandidatesHF(), egammaFilters(), elementLoop(), bookConverter::elements, edm::Ref< C, T, F >::isNull(), LogDebug, LogTrace, useEGammaFilters_, and usePFConversions_.

Referenced by reconstructParticles().

◆ reconstructCluster()

unsigned PFAlgo::reconstructCluster ( const reco::PFCluster cluster,
double  particleEnergy,
bool  useDirection = false,
double  particleX = 0.,
double  particleY = 0.,
double  particleZ = 0. 
)
private

Reconstruct a neutral particle from a cluster. If chargedEnergy is specified, the neutral particle is created only if the cluster energy is significantly larger than the chargedEnergy. In this case, the energy of the neutral particle is cluster energy - chargedEnergy

Definition at line 3214 of file PFAlgo.cc.

3219  {
3220  LogTrace("PFAlgo|reconstructCluster") << "start of function PFAlgo::reconstructCluster, cluster=" << cluster
3221  << "particleEnergy=" << particleEnergy << "useDirection=" << useDirection
3222  << "particleX=" << particleX << "particleY=" << particleY
3223  << "particleZ=" << particleZ;
3224 
3226 
3227  // need to convert the ::math::XYZPoint data member of the PFCluster class=
3228  // to a displacement vector:
3229 
3230  // Transform particleX,Y,Z to a position at ECAL/HCAL entrance
3231  double factor = 1.;
3232  if (useDirection) {
3233  switch (cluster.layer()) {
3234  case PFLayer::ECAL_BARREL:
3235  case PFLayer::HCAL_BARREL1:
3236  factor = std::sqrt(cluster.position().Perp2() / (particleX * particleX + particleY * particleY));
3237  break;
3238  case PFLayer::ECAL_ENDCAP:
3239  case PFLayer::HCAL_ENDCAP:
3240  case PFLayer::HF_HAD:
3241  case PFLayer::HF_EM:
3242  factor = cluster.position().Z() / particleZ;
3243  break;
3244  default:
3245  assert(0);
3246  }
3247  }
3248  //MIKE First of all let's check if we have vertex.
3249  ::math::XYZPoint vertexPos;
3250  if (useVertices_)
3252  else
3253  vertexPos = ::math::XYZPoint(0.0, 0.0, 0.0);
3254 
3255  ::math::XYZVector clusterPos(cluster.position().X() - vertexPos.X(),
3256  cluster.position().Y() - vertexPos.Y(),
3257  cluster.position().Z() - vertexPos.Z());
3258  ::math::XYZVector particleDirection(
3259  particleX * factor - vertexPos.X(), particleY * factor - vertexPos.Y(), particleZ * factor - vertexPos.Z());
3260 
3261  //::math::XYZVector clusterPos( cluster.position().X(), cluster.position().Y(),cluster.position().Z() );
3262  //::math::XYZVector particleDirection ( particleX, particleY, particleZ );
3263 
3264  clusterPos = useDirection ? particleDirection.Unit() : clusterPos.Unit();
3265  clusterPos *= particleEnergy;
3266 
3267  // clusterPos is now a vector along the cluster direction,
3268  // with a magnitude equal to the cluster energy.
3269 
3270  double mass = 0;
3271  ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double>> momentum(
3272  clusterPos.X(), clusterPos.Y(), clusterPos.Z(), mass);
3273  // mathcore is a piece of #$%
3275  // implicit constructor not allowed
3276  tmp = momentum;
3277 
3278  // Charge
3279  int charge = 0;
3280 
3281  // Type
3282  switch (cluster.layer()) {
3283  case PFLayer::ECAL_BARREL:
3284  case PFLayer::ECAL_ENDCAP:
3286  break;
3287  case PFLayer::HCAL_BARREL1:
3288  case PFLayer::HCAL_ENDCAP:
3289  particleType = PFCandidate::h0;
3290  break;
3291  case PFLayer::HF_HAD:
3292  particleType = PFCandidate::h_HF;
3293  break;
3294  case PFLayer::HF_EM:
3295  particleType = PFCandidate::egamma_HF;
3296  break;
3297  default:
3298  assert(0);
3299  }
3300 
3301  // The pf candidate
3302  LogTrace("PFAlgo|reconstructCluster") << "Creating PFCandidate charge=" << charge << ", type=" << particleType
3303  << ", pt=" << tmp.pt() << ", eta=" << tmp.eta() << ", phi=" << tmp.phi();
3305 
3306  // The position at ECAL entrance (well: watch out, it is not true
3307  // for HCAL clusters... to be fixed)
3308  pfCandidates_->back().setPositionAtECALEntrance(
3309  ::math::XYZPointF(cluster.position().X(), cluster.position().Y(), cluster.position().Z()));
3310 
3311  //Set the cnadidate Vertex
3312  pfCandidates_->back().setVertex(vertexPos);
3313 
3314  // depth info
3315  setHcalDepthInfo(pfCandidates_->back(), cluster);
3316 
3317  //*TODO* cluster time is not reliable at the moment, so only use track timing
3318 
3319  LogTrace("PFAlgo|reconstructCluster") << "** candidate: " << pfCandidates_->back();
3320 
3321  // returns index to the newly created PFCandidate
3322  return pfCandidates_->size() - 1;
3323 }

References cms::cuda::assert(), ALCARECOTkAlJpsiMuMu_cff::charge, PFLayer::ECAL_BARREL, PFLayer::ECAL_ENDCAP, DQMScaleToClient_cfi::factor, CustomPhysics_cfi::gamma, PFLayer::HCAL_BARREL1, PFLayer::HCAL_ENDCAP, PFLayer::HF_EM, PFLayer::HF_HAD, reco::PFCluster::layer(), LogTrace, EgHLTOffHistBins_cfi::mass, PbPb_ZMuSkimMuonDPG_cff::particleType, pfElectronTranslator_cfi::PFCandidate, pfCandidates_, reco::CaloCluster::position(), primaryVertex_, setHcalDepthInfo(), mathSSE::sqrt(), createJobs::tmp, useVertices_, reco::PFCandidate::X, reco::Vertex::x(), reco::Vertex::y(), and reco::Vertex::z().

Referenced by checkCleaning(), createCandidatesECAL(), createCandidatesHCAL(), createCandidatesHCALUnlinked(), createCandidatesHF(), and recoTracksNotHCAL().

◆ reconstructParticles()

void PFAlgo::reconstructParticles ( const reco::PFBlockHandle blockHandle,
PFEGammaFilters const *  pfegamma 
)

reconstruct particles

Definition at line 132 of file PFAlgo.cc.

132  {
133  auto const& blocks = *blockHandle;
134 
135  // reset output collection
136  pfCandidates_->clear();
137 
138  LogTrace("PFAlgo|reconstructParticles")
139  << "start of function PFAlgo::reconstructParticles, blocks.size()=" << blocks.size();
140 
141  // sort elements in three lists:
142  std::list<reco::PFBlockRef> hcalBlockRefs;
143  std::list<reco::PFBlockRef> ecalBlockRefs;
144  std::list<reco::PFBlockRef> hoBlockRefs;
145  std::list<reco::PFBlockRef> otherBlockRefs;
146 
147  for (unsigned i = 0; i < blocks.size(); ++i) {
148  reco::PFBlockRef blockref = reco::PFBlockRef(blockHandle, i);
149 
150  const reco::PFBlock& block = *blockref;
152 
153  bool singleEcalOrHcal = false;
154  if (elements.size() == 1) {
156  ecalBlockRefs.push_back(blockref);
157  singleEcalOrHcal = true;
158  }
160  hcalBlockRefs.push_back(blockref);
161  singleEcalOrHcal = true;
162  }
163  if (elements[0].type() == reco::PFBlockElement::HO) {
164  // Single HO elements are likely to be noise. Not considered for now.
165  hoBlockRefs.push_back(blockref);
166  singleEcalOrHcal = true;
167  }
168  }
169 
170  if (!singleEcalOrHcal) {
171  otherBlockRefs.push_back(blockref);
172  }
173  } //loop blocks
174 
175  LogTrace("PFAlgo|reconstructParticles")
176  << "# Ecal blocks: " << ecalBlockRefs.size() << ", # Hcal blocks: " << hcalBlockRefs.size()
177  << ", # HO blocks: " << hoBlockRefs.size() << ", # Other blocks: " << otherBlockRefs.size();
178 
179  // loop on blocks that are not single ecal,
180  // and not single hcal.
181 
182  unsigned nblcks = 0;
183  for (auto const& other : otherBlockRefs) {
184  LogTrace("PFAlgo|reconstructParticles") << "processBlock, Block number " << nblcks++;
185  processBlock(other, hcalBlockRefs, ecalBlockRefs, pfegamma);
186  }
187 
188  std::list<reco::PFBlockRef> empty;
189 
190  unsigned hblcks = 0;
191  // process remaining single hcal blocks
192  for (auto const& hcal : hcalBlockRefs) {
193  LogTrace("PFAlgo|reconstructParticles") << "processBlock, HCAL block number " << hblcks++;
194  processBlock(hcal, empty, empty, pfegamma);
195  }
196 
197  unsigned eblcks = 0;
198  // process remaining single ecal blocks
199  for (auto const& ecal : ecalBlockRefs) {
200  LogTrace("PFAlgo|reconstructParticles") << "processBlock, ECAL block number " << eblcks++;
201  processBlock(ecal, empty, empty, pfegamma);
202  }
203 
204  // Post HF Cleaning
205  pfCleanedCandidates_.clear();
206  // Check if the post HF Cleaning was requested - if not, do nothing
207  if (postHFCleaning_) {
208  postCleaning();
209  }
210 
211  //Muon post cleaning
212  pfmu_->postClean(pfCandidates_.get());
213 
214  //Add Missing muons
215  if (muonHandle_.isValid())
216  pfmu_->addMissingMuons(muonHandle_, pfCandidates_.get());
217 
218  LogTrace("PFAlgo|reconstructParticles")
219  << "end of function PFAlgo::reconstructParticles, pfCandidates_->size()=" << pfCandidates_->size();
220 }

References groupFilesInBlocks::block, gather_cfg::blocks, bsc_activity_cfg::ecal, reco::PFBlockElement::ECAL, bookConverter::elements, relativeConstraints::empty, reco::PFBlockElement::HCAL, reco::PFBlockElement::HO, mps_fire::i, edm::HandleBase::isValid(), LogTrace, muonHandle_, trackingPlots::other, pfCandidates_, pfCleanedCandidates_, pfmu_, postCleaning(), postHFCleaning_, and processBlock().

Referenced by PFProducer::produce().

◆ reconstructTrack()

unsigned PFAlgo::reconstructTrack ( const reco::PFBlockElement elt,
bool  allowLoose = false 
)
private

Reconstruct a charged particle from a track Returns the index of the newly created candidate in pfCandidates_ Michalis added a flag here to treat muons inside jets

Definition at line 3135 of file PFAlgo.cc.

3135  {
3136  const auto* eltTrack = dynamic_cast<const reco::PFBlockElementTrack*>(&elt);
3137 
3138  const reco::TrackRef& trackRef = eltTrack->trackRef();
3139  const reco::Track& track = *trackRef;
3140  const reco::MuonRef& muonRef = eltTrack->muonRef();
3141  int charge = track.charge() > 0 ? 1 : -1;
3142 
3143  // Assume this particle is a charged Hadron
3144  double px = track.px();
3145  double py = track.py();
3146  double pz = track.pz();
3147  double energy = sqrt(track.p() * track.p() + 0.13957 * 0.13957);
3148 
3149  LogTrace("PFAlgo|reconstructTrack") << "Reconstructing PF candidate from track of pT = " << track.pt()
3150  << " eta = " << track.eta() << " phi = " << track.phi() << " px = " << px
3151  << " py = " << py << " pz = " << pz << " energy = " << energy;
3152 
3153  // Create a PF Candidate
3154  ::math::XYZTLorentzVector momentum(px, py, pz, energy);
3156 
3157  // Add it to the stack
3158  LogTrace("PFAlgo|reconstructTrack") << "Creating PFCandidate charge=" << charge << ", type=" << particleType
3159  << ", pt=" << momentum.pt() << ", eta=" << momentum.eta()
3160  << ", phi=" << momentum.phi();
3161  pfCandidates_->push_back(PFCandidate(charge, momentum, particleType));
3162  //Set vertex and stuff like this
3163  pfCandidates_->back().setVertexSource(PFCandidate::kTrkVertex);
3164  pfCandidates_->back().setTrackRef(trackRef);
3165  pfCandidates_->back().setPositionAtECALEntrance(eltTrack->positionAtECALEntrance());
3166  if (muonRef.isNonnull())
3167  pfCandidates_->back().setMuonRef(muonRef);
3168 
3169  //Set time
3170  if (elt.isTimeValid())
3171  pfCandidates_->back().setTime(elt.time(), elt.timeError());
3172 
3173  //OK Now try to reconstruct the particle as a muon
3174  bool isMuon = pfmu_->reconstructMuon(pfCandidates_->back(), muonRef, allowLoose);
3175  bool isFromDisp = isFromSecInt(elt, "secondary");
3176 
3177  if ((!isMuon) && isFromDisp) {
3178  double dpt = trackRef->ptError();
3179  double dptRel = dpt / trackRef->pt() * 100;
3180  //If the track is ill measured it is better to not refit it, since the track information probably would not be used.
3181  //In the PFAlgo we use the trackref information. If the track error is too big the refitted information might be very different
3182  // from the not refitted one.
3183  if (dptRel < dptRel_DispVtx_) {
3184  LogTrace("PFAlgo|reconstructTrack")
3185  << "Not refitted px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy;
3186  //reco::TrackRef trackRef = eltTrack->trackRef();
3188  eltTrack->displacedVertexRef(reco::PFBlockElement::T_FROM_DISP)->displacedVertexRef();
3189  reco::Track trackRefit = vRef->refittedTrack(trackRef);
3190  //change the momentum with the refitted track
3191  ::math::XYZTLorentzVector momentum(
3192  trackRefit.px(), trackRefit.py(), trackRefit.pz(), sqrt(trackRefit.p() * trackRefit.p() + 0.13957 * 0.13957));
3193  LogTrace("PFAlgo|reconstructTrack")
3194  << "Refitted px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy;
3195  }
3196  pfCandidates_->back().setFlag(reco::PFCandidate::T_FROM_DISP, true);
3197  pfCandidates_->back().setDisplacedVertexRef(
3198  eltTrack->displacedVertexRef(reco::PFBlockElement::T_FROM_DISP)->displacedVertexRef(),
3200  }
3201 
3202  // do not label as primary a track which would be recognised as a muon. A muon cannot produce NI. It is with high probability a fake
3203  if (isFromSecInt(elt, "primary") && !isMuon) {
3204  pfCandidates_->back().setFlag(reco::PFCandidate::T_TO_DISP, true);
3205  pfCandidates_->back().setDisplacedVertexRef(
3206  eltTrack->displacedVertexRef(reco::PFBlockElement::T_TO_DISP)->displacedVertexRef(),
3208  }
3209 
3210  // returns index to the newly created PFCandidate
3211  return pfCandidates_->size() - 1;
3212 }

References ALCARECOTkAlJpsiMuMu_cff::charge, dptRel_DispVtx_, HCALHighEnergyHPDFilter_cfi::energy, reco::PFCandidate::h, isFromSecInt(), reco::isMuon(), edm::Ref< C, T, F >::isNonnull(), reco::PFBlockElement::isTimeValid(), LogTrace, reco::TrackBase::p(), PbPb_ZMuSkimMuonDPG_cff::particleType, pfElectronTranslator_cfi::PFCandidate, pfCandidates_, pfmu_, multPhiCorr_741_25nsDY_cfi::px, reco::TrackBase::px(), multPhiCorr_741_25nsDY_cfi::py, reco::TrackBase::py(), reco::TrackBase::pz(), mathSSE::sqrt(), reco::PFBlockElement::T_FROM_DISP, reco::PFCandidate::T_FROM_DISP, reco::PFBlockElement::T_TO_DISP, reco::PFCandidate::T_TO_DISP, reco::PFBlockElement::time(), reco::PFBlockElement::timeError(), and HLT_2018_cff::track.

Referenced by checkAndReconstructSecondaryInteraction(), createCandidatesHCAL(), createCandidatesHF(), and recoTracksNotHCAL().

◆ recoTracksNotHCAL()

bool PFAlgo::recoTracksNotHCAL ( const reco::PFBlock block,
reco::PFBlock::LinkData linkData,
const edm::OwnVector< reco::PFBlockElement > &  elements,
const reco::PFBlockRef blockref,
std::vector< bool > &  active,
bool  goodTrackDeadHcal,
bool  hasDeadHcal,
unsigned int  iTrack,
std::multimap< double, unsigned > &  ecalElems,
reco::TrackRef trackRef 
)
private

Definition at line 393 of file PFAlgo.cc.

402  {
403  LogTrace("PFAlgo|recoTracksNotHCAL") << "start of function PFAlgo::recoTracksNotHCAL(), now dealing with tracks "
404  "linked to no HCAL clusters. Was HCal active? "
405  << (!hasDeadHcal);
406  // vector<unsigned> elementIndices;
407  // elementIndices.push_back(iTrack);
408 
409  // The track momentum
410  double trackMomentum = elements[iTrack].trackRef()->p();
411  LogTrace("PFAlgo|recoTracksNotHCAL") << elements[iTrack];
412 
413  // Is it a "tight" muon ? In that case assume no
414  //Track momentum corresponds to the calorimeter
415  //energy for now
416  bool thisIsAMuon = PFMuonAlgo::isMuon(elements[iTrack]);
417  if (thisIsAMuon)
418  trackMomentum = 0.;
419 
420  // If it is not a muon check if Is it a fake track ?
421  //Michalis: I wonder if we should convert this to dpt/pt?
422  if (!thisIsAMuon && elements[iTrack].trackRef()->ptError() > ptError_) {
423  double deficit = trackMomentum;
424  double resol = neutralHadronEnergyResolution(trackMomentum, elements[iTrack].trackRef()->eta());
425  resol *= trackMomentum;
426 
427  if (!ecalElems.empty()) {
428  unsigned thisEcal = ecalElems.begin()->second;
429  reco::PFClusterRef clusterRef = elements[thisEcal].clusterRef();
430  bool useCluster = true;
431  if (hasDeadHcal) {
432  std::multimap<double, unsigned> sortedTracks;
433  block.associatedElements(
434  thisEcal, linkData, sortedTracks, reco::PFBlockElement::TRACK, reco::PFBlock::LINKTEST_ALL);
435  useCluster = (sortedTracks.begin()->second == iTrack);
436  }
437  if (useCluster) {
438  deficit -= clusterRef->energy();
439  resol = neutralHadronEnergyResolution(trackMomentum, clusterRef->positionREP().Eta());
440  resol *= trackMomentum;
441  }
442  }
443 
444  bool isPrimary = isFromSecInt(elements[iTrack], "primary");
445 
446  if (deficit > nSigmaTRACK_ * resol && !isPrimary && !goodTrackDeadHcal) {
447  active[iTrack] = false;
448  LogTrace("PFAlgo|recoTracksNotHCAL")
449  << elements[iTrack] << std::endl
450  << " deficit " << deficit << " > " << nSigmaTRACK_ << " x " << resol << " track pt " << trackRef->pt()
451  << " +- " << trackRef->ptError() << " layers valid " << trackRef->hitPattern().trackerLayersWithMeasurement()
452  << ", lost " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS)
453  << ", lost outer " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_OUTER_HITS)
454  << ", lost inner " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_INNER_HITS)
455  << "(valid fraction " << trackRef->validFraction() << ")"
456  << " chi2/ndf " << trackRef->normalizedChi2() << " |dxy| "
457  << std::abs(trackRef->dxy(primaryVertex_.position())) << " +- " << trackRef->dxyError() << " |dz| "
458  << std::abs(trackRef->dz(primaryVertex_.position())) << " +- " << trackRef->dzError()
459  << "is probably a fake (1) --> lock the track";
460  return true;
461  }
462  } // !thisIsaMuon
463 
464  // Create a track candidate
465  // unsigned tmpi = reconstructTrack( elements[iTrack] );
466  //active[iTrack] = false;
467  std::vector<unsigned> tmpi;
468  std::vector<unsigned> kTrack;
469 
470  // Some cleaning : secondary tracks without calo's and large momentum must be fake
471  double dpt = trackRef->ptError();
472 
473  if (rejectTracks_Step45_ && ecalElems.empty() && trackMomentum > 30. && dpt > 0.5 &&
474  (PFTrackAlgoTools::step45(trackRef->algo()) && !goodTrackDeadHcal)) {
475  double dptRel = dpt / trackRef->pt() * 100;
476  bool isPrimaryOrSecondary = isFromSecInt(elements[iTrack], "all");
477 
478  if (isPrimaryOrSecondary && dptRel < dptRel_DispVtx_) {
479  return true;
480  };
481  unsigned nHits = elements[iTrack].trackRef()->hitPattern().trackerLayersWithMeasurement();
482  unsigned int NLostHit = trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS);
483 
484  LogTrace("PFAlgo|recoTracksNotHCAL") << "A track (algo = " << trackRef->algo() << ") with momentum "
485  << trackMomentum << " / " << elements[iTrack].trackRef()->pt() << " +/- "
486  << dpt << " / " << elements[iTrack].trackRef()->eta()
487  << " without any link to ECAL/HCAL and with " << nHits << " (" << NLostHit
488  << ") hits (lost hits) has been cleaned";
489 
490  active[iTrack] = false;
491  return true;
492  } //rejectTracks_Step45_ && ...
493 
494  tmpi.push_back(reconstructTrack(elements[iTrack]));
495 
496  kTrack.push_back(iTrack);
497  active[iTrack] = false;
498 
499  // No ECAL cluster either ... continue...
500  if (ecalElems.empty()) {
501  (*pfCandidates_)[tmpi[0]].setEcalEnergy(0., 0.);
502  (*pfCandidates_)[tmpi[0]].setHcalEnergy(0., 0.);
503  (*pfCandidates_)[tmpi[0]].setHoEnergy(0., 0.);
504  (*pfCandidates_)[tmpi[0]].setPs1Energy(0);
505  (*pfCandidates_)[tmpi[0]].setPs2Energy(0);
506  (*pfCandidates_)[tmpi[0]].addElementInBlock(blockref, kTrack[0]);
507  return true;
508  }
509 
510  // Look for closest ECAL cluster
511  const unsigned int thisEcal = ecalElems.begin()->second;
512  reco::PFClusterRef clusterRef = elements[thisEcal].clusterRef();
513  LogTrace("PFAlgo|recoTracksNotHCAL") << " is associated to " << elements[thisEcal];
514 
515  // Set ECAL energy for muons
516  if (thisIsAMuon) {
517  (*pfCandidates_)[tmpi[0]].setEcalEnergy(clusterRef->energy(), std::min(clusterRef->energy(), muonECAL_[0]));
518  (*pfCandidates_)[tmpi[0]].setHcalEnergy(0., 0.);
519  (*pfCandidates_)[tmpi[0]].setHoEnergy(0., 0.);
520  (*pfCandidates_)[tmpi[0]].setPs1Energy(0);
521  (*pfCandidates_)[tmpi[0]].setPs2Energy(0);
522  (*pfCandidates_)[tmpi[0]].addElementInBlock(blockref, kTrack[0]);
523  }
524 
525  double slopeEcal = 1.;
526  bool connectedToEcal = false;
527  unsigned iEcal = 99999;
528  double calibEcal = 0.;
529  double calibHcal = 0.;
530  double totalEcal = thisIsAMuon ? -muonECAL_[0] : 0.;
531 
532  // Consider charged particles closest to the same ECAL cluster
533  std::multimap<double, unsigned> sortedTracks;
534  block.associatedElements(thisEcal, linkData, sortedTracks, reco::PFBlockElement::TRACK, reco::PFBlock::LINKTEST_ALL);
535  LogTrace("PFAlgo|recoTracksNotHCAL") << "the closest ECAL cluster, id " << thisEcal << ", has " << sortedTracks.size()
536  << " associated tracks, now processing them. ";
537 
538  if (hasDeadHcal && !sortedTracks.empty()) {
539  // GP: only allow the ecal cluster closest to this track to be considered
540  LogTrace("PFAlgo|recoTracksNotHCAL") << " the closest track to ECAL " << thisEcal << " is "
541  << sortedTracks.begin()->second << " (distance " << sortedTracks.begin()->first
542  << ")";
543  if (sortedTracks.begin()->second != iTrack) {
544  LogTrace("PFAlgo|recoTracksNotHCAL")
545  << " the closest track to ECAL " << thisEcal << " is " << sortedTracks.begin()->second
546  << " which is not the one being processed. Will skip ECAL linking for this track";
547  (*pfCandidates_)[tmpi[0]].setEcalEnergy(0., 0.);
548  (*pfCandidates_)[tmpi[0]].setHcalEnergy(0., 0.);
549  (*pfCandidates_)[tmpi[0]].setHoEnergy(0., 0.);
550  (*pfCandidates_)[tmpi[0]].setPs1Energy(0);
551  (*pfCandidates_)[tmpi[0]].setPs2Energy(0);
552  (*pfCandidates_)[tmpi[0]].addElementInBlock(blockref, kTrack[0]);
553  return true;
554  } else {
555  LogTrace("PFAlgo|recoTracksNotHCAL")
556  << " the closest track to ECAL " << thisEcal << " is " << sortedTracks.begin()->second
557  << " which is the one being processed. Will skip ECAL linking for all other track";
558  sortedTracks.clear();
559  }
560  }
561 
562  for (auto const& trk : sortedTracks) {
563  unsigned jTrack = trk.second;
564 
565  // Don't consider already used tracks
566  if (!active[jTrack])
567  continue;
568 
569  // The loop is on the other tracks !
570  if (jTrack == iTrack)
571  continue;
572 
573  // Check if the ECAL cluster closest to this track is
574  // indeed the current ECAL cluster. Only tracks not
575  // linked to an HCAL cluster are considered here
576  // (GP: this is because if there's a jTrack linked
577  // to the same Ecal cluster and that also has an Hcal link
578  // we would have also linked iTrack to that Hcal above)
579  std::multimap<double, unsigned> sortedECAL;
580  block.associatedElements(jTrack, linkData, sortedECAL, reco::PFBlockElement::ECAL, reco::PFBlock::LINKTEST_ALL);
581  if (sortedECAL.begin()->second != thisEcal)
582  continue;
583 
584  // Check if this track is a muon
585  bool thatIsAMuon = PFMuonAlgo::isMuon(elements[jTrack]);
586  LogTrace("PFAlgo|recoTracksNotHCAL") << " found track " << jTrack << (thatIsAMuon ? " (muon) " : " (non-muon)")
587  << ", with distance = " << sortedECAL.begin()->first;
588 
589  // Check if this track is not a fake
590  bool rejectFake = false;
591  reco::TrackRef trackRef = elements[jTrack].trackRef();
592  if (!thatIsAMuon && trackRef->ptError() > ptError_) {
593  // GP: FIXME this selection should be adapted depending on hasDeadHcal
594  // but we don't know if jTrack is linked to a dead Hcal or not
595  double deficit = trackMomentum + trackRef->p() - clusterRef->energy();
596  double resol =
597  nSigmaTRACK_ * neutralHadronEnergyResolution(trackMomentum + trackRef->p(), clusterRef->positionREP().Eta());
598  resol *= (trackMomentum + trackRef->p());
599  if (deficit > nSigmaTRACK_ * resol && !goodTrackDeadHcal) {
600  rejectFake = true;
601  kTrack.push_back(jTrack);
602  active[jTrack] = false;
603  LogTrace("PFAlgo|recoTracksNotHCAL")
604  << elements[jTrack] << std::endl
605  << "is probably a fake (2) --> lock the track"
606  << "(trackMomentum = " << trackMomentum << ", clusterEnergy = " << clusterRef->energy()
607  << ", deficit = " << deficit << " > " << nSigmaTRACK_ << " x " << resol
608  << " assuming neutralHadronEnergyResolution "
609  << neutralHadronEnergyResolution(trackMomentum + trackRef->p(), clusterRef->positionREP().Eta()) << ") ";
610  }
611  }
612  if (rejectFake)
613  continue;
614 
615  // Otherwise, add this track momentum to the total track momentum
616  /* */
617  // reco::TrackRef trackRef = elements[jTrack].trackRef();
618  if (!thatIsAMuon) {
619  LogTrace("PFAlgo|recoTracksNotHCAL") << "Track momentum increased from " << trackMomentum << " GeV ";
620  trackMomentum += trackRef->p();
621  LogTrace("PFAlgo|recoTracksNotHCAL") << "to " << trackMomentum << " GeV.";
622  LogTrace("PFAlgo|recoTracksNotHCAL") << "with " << elements[jTrack];
623  } else {
624  totalEcal -= muonECAL_[0];
625  totalEcal = std::max(totalEcal, 0.);
626  }
627 
628  // And create a charged particle candidate !
629 
630  tmpi.push_back(reconstructTrack(elements[jTrack]));
631 
632  kTrack.push_back(jTrack);
633  active[jTrack] = false;
634 
635  if (thatIsAMuon) {
636  (*pfCandidates_)[tmpi.back()].setEcalEnergy(clusterRef->energy(), std::min(clusterRef->energy(), muonECAL_[0]));
637  (*pfCandidates_)[tmpi.back()].setHcalEnergy(0., 0.);
638  (*pfCandidates_)[tmpi.back()].setHoEnergy(0., 0.);
639  (*pfCandidates_)[tmpi.back()].setPs1Energy(0);
640  (*pfCandidates_)[tmpi.back()].setPs2Energy(0);
641  (*pfCandidates_)[tmpi.back()].addElementInBlock(blockref, kTrack.back());
642  }
643  }
644 
645  LogTrace("PFAlgo|recoTracksNotHCAL") << "Loop over all associated ECAL clusters";
646  // Loop over all ECAL linked clusters ordered by increasing distance.
647  for (auto const& ecal : ecalElems) {
648  const unsigned index = ecal.second;
649  const PFBlockElement::Type type = elements[index].type();
651  LogTrace("PFAlgo|recoTracksNotHCAL") << elements[index];
652 
653  // Just skip clusters already taken
654  if (!active[index]) {
655  LogTrace("PFAlgo|recoTracksNotHCAL") << "is not active - ignore ";
656  continue;
657  }
658 
659  // Just skip this cluster if it's closer to another track
660  block.associatedElements(index, linkData, sortedTracks, reco::PFBlockElement::TRACK, reco::PFBlock::LINKTEST_ALL);
661 
662  const bool skip = std::none_of(
663  kTrack.begin(), kTrack.end(), [&](unsigned iTrack) { return sortedTracks.begin()->second == iTrack; });
664 
665  if (skip) {
666  LogTrace("PFAlgo|recoTracksNotHCAL") << "is closer to another track - ignore ";
667  continue;
668  }
669 
670  // The corresponding PFCluster and energy
671  const reco::PFClusterRef clusterRef = elements[index].clusterRef();
672  assert(!clusterRef.isNull());
673 
674  LogTrace("PFAlgo|recoTracksNotHCAL") << "Ecal cluster with raw energy = " << clusterRef->energy()
675  << " linked with distance = " << ecal.first;
676 
677  // Check the presence of preshower clusters in the vicinity
678  // Preshower cluster closer to another ECAL cluster are ignored.
679  //JOSH: This should use the association map already produced by the cluster corrector for consistency,
680  //but should be ok for now
681  vector<double> ps1Ene{0.};
682  associatePSClusters(index, reco::PFBlockElement::PS1, block, elements, linkData, active, ps1Ene);
683  vector<double> ps2Ene{0.};
684  associatePSClusters(index, reco::PFBlockElement::PS2, block, elements, linkData, active, ps2Ene);
685 
686  // KH: use raw ECAL energy for PF hadron calibration. use calibrated ECAL energy when adding PF photons
687  const double ecalEnergy = clusterRef->energy();
688  const double ecalEnergyCalibrated = clusterRef->correctedEnergy(); // calibrated based on the egamma hypothesis
689  LogTrace("PFAlgo|recoTracksNotHCAL") << "Corrected ECAL(+PS) energy = " << ecalEnergy;
690 
691  // Since the electrons were found beforehand, this track must be a hadron. Calibrate
692  // the energy under the hadron hypothesis.
693  totalEcal += ecalEnergy;
694  const double previousCalibEcal = calibEcal;
695  const double previousSlopeEcal = slopeEcal;
696  calibEcal = std::max(totalEcal, 0.);
697  calibHcal = 0.;
699  trackMomentum, calibEcal, calibHcal, clusterRef->positionREP().Eta(), clusterRef->positionREP().Phi());
700  if (totalEcal > 0.)
701  slopeEcal = calibEcal / totalEcal;
702 
703  LogTrace("PFAlgo|recoTracksNotHCAL") << "The total calibrated energy so far amounts to = " << calibEcal
704  << " (slope = " << slopeEcal << ")";
705 
706  // Stop the loop when adding more ECAL clusters ruins the compatibility
707  if (connectedToEcal && calibEcal - trackMomentum >= 0.) {
708  // if ( connectedToEcal && calibEcal - trackMomentum >=
709  // nSigmaECAL_*neutralHadronEnergyResolution(trackMomentum,clusterRef->positionREP().Eta()) ) {
710  calibEcal = previousCalibEcal;
711  slopeEcal = previousSlopeEcal;
712  totalEcal = calibEcal / slopeEcal;
713 
714  // Turn this last cluster in a photon
715  // (The PS clusters are already locked in "associatePSClusters")
716  active[index] = false;
717 
718  // Find the associated tracks
719  std::multimap<double, unsigned> assTracks;
720  block.associatedElements(index, linkData, assTracks, reco::PFBlockElement::TRACK, reco::PFBlock::LINKTEST_ALL);
721 
722  auto& ecalCand = (*pfCandidates_)[reconstructCluster(
723  *clusterRef, ecalEnergyCalibrated)]; // KH: use the PF ECAL cluster calibrated energy
724  ecalCand.setEcalEnergy(clusterRef->energy(), ecalEnergyCalibrated);
725  ecalCand.setHcalEnergy(0., 0.);
726  ecalCand.setHoEnergy(0., 0.);
727  ecalCand.setPs1Energy(ps1Ene[0]);
728  ecalCand.setPs2Energy(ps2Ene[0]);
729  ecalCand.addElementInBlock(blockref, index);
730  // Check that there is at least one track
731  if (!assTracks.empty()) {
732  ecalCand.addElementInBlock(blockref, assTracks.begin()->second);
733 
734  // Assign the position of the track at the ECAL entrance
735  const ::math::XYZPointF& chargedPosition =
736  dynamic_cast<const reco::PFBlockElementTrack*>(&elements[assTracks.begin()->second])
737  ->positionAtECALEntrance();
738  ecalCand.setPositionAtECALEntrance(chargedPosition);
739  }
740  break;
741  }
742 
743  // Lock used clusters.
744  connectedToEcal = true;
745  iEcal = index;
746  active[index] = false;
747  for (unsigned ic : tmpi)
748  (*pfCandidates_)[ic].addElementInBlock(blockref, iEcal);
749 
750  } // Loop ecal elements
751 
752  bool bNeutralProduced = false;
753 
754  // Create a photon if the ecal energy is too large
755  if (connectedToEcal) {
756  reco::PFClusterRef pivotalRef = elements[iEcal].clusterRef();
757 
758  double neutralEnergy = calibEcal - trackMomentum;
759 
760  /*
761  // Check if there are other tracks linked to that ECAL
762  for(IE ie = sortedTracks.begin(); ie != sortedTracks.end() && neutralEnergy > 0; ++ie ) {
763  unsigned jTrack = ie->second;
764 
765  // The loop is on the other tracks !
766  if ( jTrack == iTrack ) continue;
767 
768  // Check if the ECAL closest to this track is the current ECAL
769  // Otherwise ignore this track in the neutral energy determination
770  std::multimap<double, unsigned> sortedECAL;
771  block.associatedElements( jTrack, linkData,
772  sortedECAL,
773  reco::PFBlockElement::ECAL,
774  reco::PFBlock::LINKTEST_ALL );
775  if ( sortedECAL.begin()->second != iEcal ) continue;
776 
777  // Check if this track is also linked to an HCAL
778  // (in which case it goes to the next loop and is ignored here)
779  std::multimap<double, unsigned> sortedHCAL;
780  block.associatedElements( jTrack, linkData,
781  sortedHCAL,
782  reco::PFBlockElement::HCAL,
783  reco::PFBlock::LINKTEST_ALL );
784  if ( sortedHCAL.size() ) continue;
785 
786  // Otherwise, subtract this track momentum from the ECAL energy
787  reco::TrackRef trackRef = elements[jTrack].trackRef();
788  neutralEnergy -= trackRef->p();
789 
790  } // End other tracks
791  */
792 
793  // Add a photon if the energy excess is large enough
794  double resol = neutralHadronEnergyResolution(trackMomentum, pivotalRef->positionREP().Eta());
795  resol *= trackMomentum;
796  if (neutralEnergy > std::max(0.5, nSigmaECAL_ * resol)) {
797  neutralEnergy /= slopeEcal;
798  unsigned tmpj = reconstructCluster(*pivotalRef, neutralEnergy);
799  (*pfCandidates_)[tmpj].setEcalEnergy(pivotalRef->energy(), neutralEnergy);
800  (*pfCandidates_)[tmpj].setHcalEnergy(0., 0.);
801  (*pfCandidates_)[tmpj].setHoEnergy(0., 0.);
802  (*pfCandidates_)[tmpj].setPs1Energy(0.);
803  (*pfCandidates_)[tmpj].setPs2Energy(0.);
804  (*pfCandidates_)[tmpj].addElementInBlock(blockref, iEcal);
805  bNeutralProduced = true;
806  for (unsigned ic = 0; ic < kTrack.size(); ++ic)
807  (*pfCandidates_)[tmpj].addElementInBlock(blockref, kTrack[ic]);
808  } // End neutral energy
809 
810  // Set elements in blocks and ECAL energies to all tracks
811  for (unsigned ic = 0; ic < tmpi.size(); ++ic) {
812  // Skip muons
813  if ((*pfCandidates_)[tmpi[ic]].particleId() == reco::PFCandidate::mu)
814  continue;
815 
816  double fraction = trackMomentum > 0 ? (*pfCandidates_)[tmpi[ic]].trackRef()->p() / trackMomentum : 0;
817  double ecalCal = bNeutralProduced ? (calibEcal - neutralEnergy * slopeEcal) * fraction : calibEcal * fraction;
818  double ecalRaw = totalEcal * fraction;
819 
820  LogTrace("PFAlgo|recoTracksNotHCAL")
821  << "The fraction after photon supression is " << fraction << " calibrated ecal = " << ecalCal;
822 
823  (*pfCandidates_)[tmpi[ic]].setEcalEnergy(ecalRaw, ecalCal);
824  (*pfCandidates_)[tmpi[ic]].setHcalEnergy(0., 0.);
825  (*pfCandidates_)[tmpi[ic]].setHoEnergy(0., 0.);
826  (*pfCandidates_)[tmpi[ic]].setPs1Energy(0);
827  (*pfCandidates_)[tmpi[ic]].setPs2Energy(0);
828  (*pfCandidates_)[tmpi[ic]].addElementInBlock(blockref, kTrack[ic]);
829  }
830 
831  } // End connected ECAL
832 
833  // Fill the element_in_block for tracks that are eventually linked to no ECAL clusters at all.
834  for (unsigned ic = 0; ic < tmpi.size(); ++ic) {
835  const PFCandidate& pfc = (*pfCandidates_)[tmpi[ic]];
836  const PFCandidate::ElementsInBlocks& eleInBlocks = pfc.elementsInBlocks();
837  if (eleInBlocks.empty()) {
838  LogTrace("PFAlgo|recoTracksNotHCAL") << "Single track / Fill element in block! ";
839  (*pfCandidates_)[tmpi[ic]].addElementInBlock(blockref, kTrack[ic]);
840  }
841  }
842  LogTrace("PFAlgo|recoTracksNotHCAL") << "end of function PFAlgo::recoTracksNotHCAL";
843  return false;
844 }

References funct::abs(), cms::cuda::assert(), associatePSClusters(), groupFilesInBlocks::block, calibration_, dptRel_DispVtx_, ECAL, bsc_activity_cfg::ecal, reco::PFBlockElement::ECAL, bookConverter::elements, reco::PFCandidate::elementsInBlocks(), PFEnergyCalibration::energyEmHad(), PVValHelper::eta, HLT_2018_cff::fraction, isFromSecInt(), PFMuonAlgo::isMuon(), edm::Ref< C, T, F >::isNull(), reco::PFBlock::LINKTEST_ALL, LogTrace, SiStripPI::max, min(), reco::PFCandidate::mu, muonECAL_, neutralHadronEnergyResolution(), nSigmaECAL_, nSigmaTRACK_, pfCandidates_, reco::Vertex::position(), primaryVertex_, reco::PFBlockElement::PS1, reco::PFBlockElement::PS2, ptError_, reconstructCluster(), reconstructTrack(), rejectTracks_Step45_, l1ParticleFlow_cff::resol, optionsL1T::skip, PFTrackAlgoTools::step45(), reco::PFBlockElement::TRACK, and reco::btau::trackMomentum.

Referenced by elementLoop().

◆ relinkTrackToHcal()

void PFAlgo::relinkTrackToHcal ( const reco::PFBlock block,
std::multimap< double, unsigned > &  ecalElems,
std::multimap< double, unsigned > &  hcalElems,
const std::vector< bool > &  active,
reco::PFBlock::LinkData linkData,
unsigned int  iTrack 
)
private

Definition at line 935 of file PFAlgo.cc.

940  {
941  unsigned ntt = 1;
942  unsigned index = ecalElems.begin()->second;
943  std::multimap<double, unsigned> sortedTracks;
944  block.associatedElements(index, linkData, sortedTracks, reco::PFBlockElement::TRACK, reco::PFBlock::LINKTEST_ALL);
945  LogTrace("PFAlgo|elementLoop") << "The closest ECAL cluster is linked to " << sortedTracks.size()
946  << " tracks, with distance = " << ecalElems.begin()->first;
947 
948  LogTrace("PFAlgo|elementLoop") << "Looping over sortedTracks";
949  // Loop over all tracks
950  for (auto const& trk : sortedTracks) {
951  unsigned jTrack = trk.second;
952  LogTrace("PFAlgo|elementLoop") << "jTrack=" << jTrack;
953  // Track must be active
954  if (!active[jTrack])
955  continue;
956  LogTrace("PFAlgo|elementLoop") << "active[jTrack]=" << active[jTrack];
957 
958  // The loop is on the other tracks !
959  if (jTrack == iTrack)
960  continue;
961  LogTrace("PFAlgo|elementLoop") << "skipping jTrack=" << jTrack << " for same iTrack";
962 
963  // Check if the ECAL closest to this track is the current ECAL
964  // Otherwise ignore this track in the neutral energy determination
965  std::multimap<double, unsigned> sortedECAL;
966  block.associatedElements(jTrack, linkData, sortedECAL, reco::PFBlockElement::ECAL, reco::PFBlock::LINKTEST_ALL);
967  if (sortedECAL.begin()->second != index)
968  continue;
969  LogTrace("PFAlgo|elementLoop") << " track " << jTrack << " with closest ECAL identical ";
970 
971  // Check if this track is also linked to an HCAL
972  std::multimap<double, unsigned> sortedHCAL;
973  block.associatedElements(jTrack, linkData, sortedHCAL, reco::PFBlockElement::HCAL, reco::PFBlock::LINKTEST_ALL);
974  if (sortedHCAL.empty())
975  continue;
976  LogTrace("PFAlgo|elementLoop") << " and with an HCAL cluster " << sortedHCAL.begin()->second;
977  ntt++;
978 
979  // In that case establish a link with the first track
980  block.setLink(iTrack, sortedHCAL.begin()->second, sortedECAL.begin()->first, linkData, PFBlock::LINKTEST_RECHIT);
981 
982  } // End other tracks
983 
984  // Redefine HCAL elements
985  block.associatedElements(iTrack, linkData, hcalElems, reco::PFBlockElement::HCAL, reco::PFBlock::LINKTEST_ALL);
986 
987  if (!hcalElems.empty())
988  LogTrace("PFAlgo|elementLoop") << "Track linked back to HCAL due to ECAL sharing with other tracks";
989 }

References groupFilesInBlocks::block, reco::PFBlockElement::ECAL, reco::PFBlockElement::HCAL, reco::PFBlock::LINKTEST_ALL, LogTrace, and reco::PFBlockElement::TRACK.

Referenced by elementLoop().

◆ setCandConnectorParameters() [1/2]

void PFAlgo::setCandConnectorParameters ( bool  bCorrect,
bool  bCalibPrimary,
double  dptRel_PrimaryTrack,
double  dptRel_MergedTrack,
double  ptErrorSecondary,
const std::vector< double > &  nuclCalibFactors 
)
inline

Definition at line 72 of file PFAlgo.h.

77  {
79  bCorrect, bCalibPrimary, dptRel_PrimaryTrack, dptRel_MergedTrack, ptErrorSecondary, nuclCalibFactors);
80  }

References HLT_2018_cff::bCalibPrimary, HLT_2018_cff::bCorrect, connector_, HLT_2018_cff::nuclCalibFactors, and PFCandConnector::setParameters().

◆ setCandConnectorParameters() [2/2]

void PFAlgo::setCandConnectorParameters ( const edm::ParameterSet iCfgCandConnector)
inline

◆ setDisplacedVerticesParameters()

void PFAlgo::setDisplacedVerticesParameters ( bool  rejectTracks_Bad,
bool  rejectTracks_Step45,
bool  usePFNuclearInteractions,
bool  usePFConversions,
bool  usePFDecays,
double  dptRel_DispVtx 
)

◆ setEGammaCollections()

void PFAlgo::setEGammaCollections ( const edm::View< reco::PFCandidate > &  pfEgammaCandidates,
const edm::ValueMap< reco::GsfElectronRef > &  valueMapGedElectrons,
const edm::ValueMap< reco::PhotonRef > &  valueMapGedPhotons 
)

Definition at line 76 of file PFAlgo.cc.

78  {
79  if (useEGammaFilters_) {
81  valueMapGedElectrons_ = &valueMapGedElectrons;
82  valueMapGedPhotons_ = &valueMapGedPhotons;
83  }
84 }

References particleBasedIsoProducer_cfi::pfEgammaCandidates, pfEgammaCandidates_, useEGammaFilters_, valueMapGedElectrons_, and valueMapGedPhotons_.

Referenced by PFProducer::produce().

◆ setEGammaParameters()

void PFAlgo::setEGammaParameters ( bool  use_EGammaFilters,
bool  useProtectionsForJetMET 
)

Definition at line 68 of file PFAlgo.cc.

68  {
69  useEGammaFilters_ = use_EGammaFilters;
70 
71  if (!useEGammaFilters_)
72  return;
73 
75 }

References useEGammaFilters_, HLT_2018_cff::useProtectionsForJetMET, and useProtectionsForJetMET_.

◆ setEGElectronCollection()

void PFAlgo::setEGElectronCollection ( const reco::GsfElectronCollection egelectrons)

◆ setHcalDepthInfo()

void PFAlgo::setHcalDepthInfo ( reco::PFCandidate cand,
const reco::PFCluster cluster 
) const
private

Definition at line 3325 of file PFAlgo.cc.

3325  {
3326  std::array<double, 7> energyPerDepth;
3327  std::fill(energyPerDepth.begin(), energyPerDepth.end(), 0.0);
3328  for (auto& hitRefAndFrac : cluster.recHitFractions()) {
3329  const auto& hit = *hitRefAndFrac.recHitRef();
3330  if (DetId(hit.detId()).det() == DetId::Hcal) {
3331  if (hit.depth() == 0) {
3332  edm::LogWarning("setHcalDepthInfo") << "Depth zero found";
3333  continue;
3334  }
3335  if (hit.depth() < 1 || hit.depth() > 7) {
3336  throw cms::Exception("CorruptData") << "Bogus depth " << hit.depth() << " at detid " << hit.detId() << "\n";
3337  }
3338  energyPerDepth[hit.depth() - 1] += hitRefAndFrac.fraction() * hit.energy();
3339  }
3340  }
3341  double sum = std::accumulate(energyPerDepth.begin(), energyPerDepth.end(), 0.);
3342  std::array<float, 7> depthFractions;
3343  if (sum > 0) {
3344  for (unsigned int i = 0; i < depthFractions.size(); ++i) {
3345  depthFractions[i] = energyPerDepth[i] / sum;
3346  }
3347  } else {
3348  std::fill(depthFractions.begin(), depthFractions.end(), 0.f);
3349  }
3350  cand.setHcalDepthEnergyFractions(depthFractions);
3351 }

References Exception, ntuplemaker::fill, DetId::Hcal, mps_fire::i, and reco::PFCluster::recHitFractions().

Referenced by createCandidatesHCAL(), and reconstructCluster().

◆ setHOTag()

void PFAlgo::setHOTag ( bool  ho)
inline

Definition at line 65 of file PFAlgo.h.

65 { useHO_ = ho; }

References photonIsolationHIProducer_cfi::ho, and useHO_.

◆ setMuonHandle()

void PFAlgo::setMuonHandle ( const edm::Handle< reco::MuonCollection > &  muons)

Definition at line 86 of file PFAlgo.cc.

86 { muonHandle_ = muons; }

References muonHandle_, and PDWG_BPHSkim_cff::muons.

Referenced by PFProducer::produce().

◆ setPFVertexParameters()

void PFAlgo::setPFVertexParameters ( bool  useVertex,
reco::VertexCollection const &  primaryVertices 
)

Definition at line 112 of file PFAlgo.cc.

112  {
114 
115  //Set the vertices for muon cleaning
116  pfmu_->setInputsForCleaning(primaryVertices);
117 
118  //Now find the primary vertex!
119  bool primaryVertexFound = false;
120  nVtx_ = primaryVertices.size();
121  for (auto const& vertex : primaryVertices) {
122  if (vertex.isValid() && (!vertex.isFake())) {
124  primaryVertexFound = true;
125  break;
126  }
127  }
128  //Use vertices if the user wants to but only if it exists a good vertex
129  useVertices_ = useVertex && primaryVertexFound;
130 }

References nVtx_, pfmu_, primaryVertex_, zMuMuMuonUserData::primaryVertices, HLT_2018_cff::useVertex, useVertices_, and bphysicsOniaDQM_cfi::vertex.

Referenced by PFProducer::produce().

◆ setPostHFCleaningParameters()

void PFAlgo::setPostHFCleaningParameters ( bool  postHFCleaning,
const edm::ParameterSet pfHFCleaningParams 
)

Definition at line 88 of file PFAlgo.cc.

88  {
90  minHFCleaningPt_ = pfHFCleaningParams.getParameter<double>("minHFCleaningPt");
91  minSignificance_ = pfHFCleaningParams.getParameter<double>("minSignificance");
92  maxSignificance_ = pfHFCleaningParams.getParameter<double>("maxSignificance");
93  minSignificanceReduction_ = pfHFCleaningParams.getParameter<double>("minSignificanceReduction");
94  maxDeltaPhiPt_ = pfHFCleaningParams.getParameter<double>("maxDeltaPhiPt");
95  minDeltaMet_ = pfHFCleaningParams.getParameter<double>("minDeltaMet");
96 }

References edm::ParameterSet::getParameter(), maxDeltaPhiPt_, maxSignificance_, minDeltaMet_, minHFCleaningPt_, minSignificance_, minSignificanceReduction_, HLT_2018_cff::postHFCleaning, and postHFCleaning_.

Friends And Related Function Documentation

◆ operator<<

std::ostream& operator<< ( std::ostream &  out,
const PFAlgo algo 
)
friend

Member Data Documentation

◆ calibration_

PFEnergyCalibration& PFAlgo::calibration_
private

Definition at line 257 of file PFAlgo.h.

Referenced by createCandidatesHCAL(), createCandidatesHCALUnlinked(), and recoTracksNotHCAL().

◆ connector_

PFCandConnector PFAlgo::connector_
private

A tool used for a postprocessing of displaced vertices based on reconstructed PFCandidates

Definition at line 290 of file PFAlgo.h.

Referenced by makeConnectedCandidates(), and setCandConnectorParameters().

◆ dptRel_DispVtx_

double PFAlgo::dptRel_DispVtx_
private

Maximal relative uncertainty on the tracks going to or incoming from the displcaed vertex to be used in the PFAlgo

Definition at line 285 of file PFAlgo.h.

Referenced by createCandidatesHCAL(), reconstructTrack(), recoTracksNotHCAL(), and setDisplacedVerticesParameters().

◆ factors45_

std::vector<double> PFAlgo::factors45_
private

Definition at line 298 of file PFAlgo.h.

Referenced by createCandidatesHCAL(), and PFAlgo().

◆ goodPixelTrackDeadHcal_chi2n_

float PFAlgo::goodPixelTrackDeadHcal_chi2n_
private

Definition at line 310 of file PFAlgo.h.

Referenced by checkGoodTrackDeadHcal(), and PFAlgo().

◆ goodPixelTrackDeadHcal_dxy_

float PFAlgo::goodPixelTrackDeadHcal_dxy_
private

Definition at line 313 of file PFAlgo.h.

Referenced by checkGoodTrackDeadHcal(), and PFAlgo().

◆ goodPixelTrackDeadHcal_dz_

float PFAlgo::goodPixelTrackDeadHcal_dz_
private

Definition at line 314 of file PFAlgo.h.

Referenced by checkGoodTrackDeadHcal(), and PFAlgo().

◆ goodPixelTrackDeadHcal_maxLost3Hit_

int PFAlgo::goodPixelTrackDeadHcal_maxLost3Hit_
private

Definition at line 311 of file PFAlgo.h.

Referenced by checkGoodTrackDeadHcal(), and PFAlgo().

◆ goodPixelTrackDeadHcal_maxLost4Hit_

int PFAlgo::goodPixelTrackDeadHcal_maxLost4Hit_
private

Definition at line 312 of file PFAlgo.h.

Referenced by checkGoodTrackDeadHcal(), and PFAlgo().

◆ goodPixelTrackDeadHcal_maxPt_

float PFAlgo::goodPixelTrackDeadHcal_maxPt_
private

Definition at line 308 of file PFAlgo.h.

Referenced by checkGoodTrackDeadHcal(), and PFAlgo().

◆ goodPixelTrackDeadHcal_minEta_

float PFAlgo::goodPixelTrackDeadHcal_minEta_
private

Definition at line 307 of file PFAlgo.h.

Referenced by checkGoodTrackDeadHcal(), and PFAlgo().

◆ goodPixelTrackDeadHcal_ptErrRel_

float PFAlgo::goodPixelTrackDeadHcal_ptErrRel_
private

Definition at line 309 of file PFAlgo.h.

Referenced by checkGoodTrackDeadHcal(), and PFAlgo().

◆ goodTrackDeadHcal_chi2n_

float PFAlgo::goodTrackDeadHcal_chi2n_
private

Definition at line 302 of file PFAlgo.h.

Referenced by checkGoodTrackDeadHcal(), and PFAlgo().

◆ goodTrackDeadHcal_dxy_

float PFAlgo::goodTrackDeadHcal_dxy_
private

Definition at line 305 of file PFAlgo.h.

Referenced by checkGoodTrackDeadHcal(), and PFAlgo().

◆ goodTrackDeadHcal_layers_

int PFAlgo::goodTrackDeadHcal_layers_
private

Definition at line 303 of file PFAlgo.h.

Referenced by checkGoodTrackDeadHcal(), and PFAlgo().

◆ goodTrackDeadHcal_ptErrRel_

float PFAlgo::goodTrackDeadHcal_ptErrRel_
private

Variables for track cleaning in bad HCal areas.

Definition at line 301 of file PFAlgo.h.

Referenced by checkGoodTrackDeadHcal(), and PFAlgo().

◆ goodTrackDeadHcal_validFr_

float PFAlgo::goodTrackDeadHcal_validFr_
private

Definition at line 304 of file PFAlgo.h.

Referenced by checkGoodTrackDeadHcal(), and PFAlgo().

◆ maxDeltaPhiPt_

double PFAlgo::maxDeltaPhiPt_
private

Definition at line 323 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

◆ maxSignificance_

double PFAlgo::maxSignificance_
private

Definition at line 321 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

◆ minDeltaMet_

double PFAlgo::minDeltaMet_
private

Definition at line 324 of file PFAlgo.h.

Referenced by checkCleaning(), postCleaning(), and setPostHFCleaningParameters().

◆ minHFCleaningPt_

double PFAlgo::minHFCleaningPt_
private

Definition at line 319 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

◆ minSignificance_

double PFAlgo::minSignificance_
private

Definition at line 320 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

◆ minSignificanceReduction_

double PFAlgo::minSignificanceReduction_
private

Definition at line 322 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

◆ muonECAL_

std::vector<double> PFAlgo::muonECAL_
private

Definition at line 294 of file PFAlgo.h.

Referenced by createCandidatesHCAL(), PFAlgo(), and recoTracksNotHCAL().

◆ muonHandle_

edm::Handle<reco::MuonCollection> PFAlgo::muonHandle_
private

Definition at line 331 of file PFAlgo.h.

Referenced by reconstructParticles(), and setMuonHandle().

◆ muonHCAL_

std::vector<double> PFAlgo::muonHCAL_
private

Variables for muons and fakes.

Definition at line 293 of file PFAlgo.h.

Referenced by createCandidatesHCAL(), and PFAlgo().

◆ muonHO_

std::vector<double> PFAlgo::muonHO_
private

Definition at line 295 of file PFAlgo.h.

Referenced by createCandidatesHCAL(), and PFAlgo().

◆ nSigmaECAL_

const double PFAlgo::nSigmaECAL_
private

number of sigma to judge energy excess in ECAL

Definition at line 245 of file PFAlgo.h.

Referenced by recoTracksNotHCAL().

◆ nSigmaEConstHCAL

const double PFAlgo::nSigmaEConstHCAL = 100.
private

Definition at line 334 of file PFAlgo.h.

Referenced by nSigmaHCAL().

◆ nSigmaEConstHFEM

const double PFAlgo::nSigmaEConstHFEM = 100.
private

Definition at line 335 of file PFAlgo.h.

Referenced by nSigmaHFEM().

◆ nSigmaEConstHFHAD

const double PFAlgo::nSigmaEConstHFHAD = 100.
private

Definition at line 336 of file PFAlgo.h.

Referenced by nSigmaHFHAD().

◆ nSigmaHCAL_

const double PFAlgo::nSigmaHCAL_
private

number of sigma to judge energy excess in HCAL

Definition at line 248 of file PFAlgo.h.

Referenced by nSigmaHCAL().

◆ nSigmaHFEM_

const double PFAlgo::nSigmaHFEM_
private

number of sigma to judge energy excess in HF

Definition at line 251 of file PFAlgo.h.

Referenced by nSigmaHFEM().

◆ nSigmaHFHAD_

const double PFAlgo::nSigmaHFHAD_
private

Definition at line 252 of file PFAlgo.h.

Referenced by nSigmaHFHAD().

◆ nSigmaTRACK_

double PFAlgo::nSigmaTRACK_
private

Definition at line 296 of file PFAlgo.h.

Referenced by createCandidatesHCAL(), PFAlgo(), and recoTracksNotHCAL().

◆ nVtx_

int PFAlgo::nVtx_
private

Definition at line 286 of file PFAlgo.h.

Referenced by egammaFilters(), and setPFVertexParameters().

◆ pfCandidates_

std::unique_ptr<reco::PFCandidateCollection> PFAlgo::pfCandidates_
private

◆ pfCleanedCandidates_

reco::PFCandidateCollection PFAlgo::pfCleanedCandidates_
private

Definition at line 228 of file PFAlgo.h.

Referenced by getCleanedCandidates(), postCleaning(), and reconstructParticles().

◆ pfEgammaCandidates_

const edm::View<reco::PFCandidate>* PFAlgo::pfEgammaCandidates_
private

Definition at line 267 of file PFAlgo.h.

Referenced by egammaFilters(), and setEGammaCollections().

◆ pfmu_

std::unique_ptr<PFMuonAlgo> PFAlgo::pfmu_
private

◆ postHFCleaning_

bool PFAlgo::postHFCleaning_
private

Definition at line 317 of file PFAlgo.h.

Referenced by reconstructParticles(), and setPostHFCleaningParameters().

◆ postMuonCleaning_

bool PFAlgo::postMuonCleaning_
private

Definition at line 318 of file PFAlgo.h.

◆ primaryVertex_

reco::Vertex PFAlgo::primaryVertex_
private

◆ ptError_

double PFAlgo::ptError_
private

Definition at line 297 of file PFAlgo.h.

Referenced by createCandidatesHCAL(), PFAlgo(), and recoTracksNotHCAL().

◆ rejectTracks_Bad_

bool PFAlgo::rejectTracks_Bad_
private

Flags to use the protection against fakes and not reconstructed displaced vertices

Definition at line 276 of file PFAlgo.h.

Referenced by createCandidatesHCAL(), and setDisplacedVerticesParameters().

◆ rejectTracks_Step45_

bool PFAlgo::rejectTracks_Step45_
private

◆ resolHF_square_

const std::vector<double> PFAlgo::resolHF_square_
private

Definition at line 255 of file PFAlgo.h.

Referenced by hfEnergyResolution(), and PFAlgo().

◆ thepfEnergyCalibrationHF_

PFEnergyCalibrationHF& PFAlgo::thepfEnergyCalibrationHF_
private

Definition at line 258 of file PFAlgo.h.

Referenced by createCandidatesHF().

◆ useBestMuonTrack_

double PFAlgo::useBestMuonTrack_
private

Definition at line 325 of file PFAlgo.h.

◆ useEGammaFilters_

bool PFAlgo::useEGammaFilters_
private

Variables for NEW EGAMMA selection.

Definition at line 265 of file PFAlgo.h.

Referenced by processBlock(), setEGammaCollections(), and setEGammaParameters().

◆ useHO_

bool PFAlgo::useHO_
private

Definition at line 260 of file PFAlgo.h.

Referenced by createCandidatesHCAL(), createCandidatesHCALUnlinked(), decideType(), and setHOTag().

◆ usePFConversions_

bool PFAlgo::usePFConversions_
private

Definition at line 280 of file PFAlgo.h.

Referenced by processBlock(), and setDisplacedVerticesParameters().

◆ usePFDecays_

bool PFAlgo::usePFDecays_
private

Definition at line 281 of file PFAlgo.h.

Referenced by isFromSecInt(), and setDisplacedVerticesParameters().

◆ usePFMuonMomAssign_

bool PFAlgo::usePFMuonMomAssign_
private

Definition at line 272 of file PFAlgo.h.

◆ usePFNuclearInteractions_

bool PFAlgo::usePFNuclearInteractions_
private

Definition at line 279 of file PFAlgo.h.

Referenced by isFromSecInt(), and setDisplacedVerticesParameters().

◆ useProtectionsForJetMET_

bool PFAlgo::useProtectionsForJetMET_
private

Definition at line 266 of file PFAlgo.h.

Referenced by egammaFilters(), and setEGammaParameters().

◆ useVertices_

bool PFAlgo::useVertices_ = false
private

Definition at line 329 of file PFAlgo.h.

Referenced by reconstructCluster(), and setPFVertexParameters().

◆ valueMapGedElectrons_

const edm::ValueMap<reco::GsfElectronRef>* PFAlgo::valueMapGedElectrons_
private

Definition at line 268 of file PFAlgo.h.

Referenced by setEGammaCollections().

◆ valueMapGedPhotons_

const edm::ValueMap<reco::PhotonRef>* PFAlgo::valueMapGedPhotons_
private

Definition at line 269 of file PFAlgo.h.

Referenced by setEGammaCollections().

runTheMatrix.ret
ret
prodAgent to be discontinued
Definition: runTheMatrix.py:355
PDWG_BPHSkim_cff.muons
muons
Definition: PDWG_BPHSkim_cff.py:47
reco::PFBlockElement::isTimeValid
bool isTimeValid() const
do we have a valid time information
Definition: PFBlockElement.h:123
PFAlgo::goodPixelTrackDeadHcal_maxLost3Hit_
int goodPixelTrackDeadHcal_maxLost3Hit_
Definition: PFAlgo.h:311
reco::PFBlockElement::trackType
virtual bool trackType(TrackType trType) const
Definition: PFBlockElement.h:72
reco::PFBlockElement::HO
Definition: PFBlockElement.h:42
PFAlgo::nSigmaEConstHFHAD
const double nSigmaEConstHFHAD
Definition: PFAlgo.h:336
PFAlgo::muonECAL_
std::vector< double > muonECAL_
Definition: PFAlgo.h:294
mps_fire.i
i
Definition: mps_fire.py:355
PFAlgo::calibration_
PFEnergyCalibration & calibration_
Definition: PFAlgo.h:257
PFMuonAlgo::isIsolatedMuon
static bool isIsolatedMuon(const reco::PFBlockElement &elt)
Definition: PFMuonAlgo.cc:102
PFAlgo::useEGammaFilters_
bool useEGammaFilters_
Variables for NEW EGAMMA selection.
Definition: PFAlgo.h:265
PFAlgo::nSigmaHFEM
double nSigmaHFEM(double clusterEnergy) const
Definition: PFAlgo.cc:3384
l1ParticleFlow_cff.resol
resol
Definition: l1ParticleFlow_cff.py:17
HLT_2018_cff.useVertex
useVertex
Definition: HLT_2018_cff.py:25062
PFAlgo::pfmu_
std::unique_ptr< PFMuonAlgo > pfmu_
Definition: PFAlgo.h:262
PFAlgo::goodTrackDeadHcal_validFr_
float goodTrackDeadHcal_validFr_
Definition: PFAlgo.h:304
HLT_2018_cff.nuclCalibFactors
nuclCalibFactors
Definition: HLT_2018_cff.py:12317
PFAlgo::goodPixelTrackDeadHcal_maxLost4Hit_
int goodPixelTrackDeadHcal_maxLost4Hit_
Definition: PFAlgo.h:312
hit::y
double y
Definition: SiStripHitEffFromCalibTree.cc:90
PFAlgo::decideType
int decideType(const edm::OwnVector< reco::PFBlockElement > &elements, const reco::PFBlockElement::Type type, std::vector< bool > &active, ElementIndices &inds, std::vector< bool > &deadArea, unsigned int iEle)
Definition: PFAlgo.cc:1195
PFAlgo::goodPixelTrackDeadHcal_chi2n_
float goodPixelTrackDeadHcal_chi2n_
Definition: PFAlgo.h:310
reco::PFCandidate::e
Definition: PFCandidate.h:46
PFAlgo::nVtx_
int nVtx_
Definition: PFAlgo.h:286
PFAlgo::goodTrackDeadHcal_chi2n_
float goodTrackDeadHcal_chi2n_
Definition: PFAlgo.h:302
PFAlgo::useVertices_
bool useVertices_
Definition: PFAlgo.h:329
muon
Definition: MuonCocktails.h:17
PFAlgo::goodPixelTrackDeadHcal_dz_
float goodPixelTrackDeadHcal_dz_
Definition: PFAlgo.h:314
PFAlgo::postCleaning
void postCleaning()
Definition: PFAlgo.cc:3493
reco::PFCandidate::setVertex
void setVertex(const math::XYZPoint &p) override
Definition: PFCandidate.h:403
DiDispStaMuonMonitor_cfi.pt
pt
Definition: DiDispStaMuonMonitor_cfi.py:39
reco::TrackBase::p
double p() const
momentum vector magnitude
Definition: TrackBase.h:605
muons2muons_cfi.chargedHadron
chargedHadron
Definition: muons2muons_cfi.py:26
reco::PFCluster::layer
PFLayer::Layer layer() const
cluster layer, see PFLayer.h in this directory
Definition: PFCluster.cc:100
X
#define X(str)
Definition: MuonsGrabber.cc:38
PFTrackAlgoTools::step45
bool step45(const reco::TrackBase::TrackAlgorithm &)
Definition: PFTrackAlgoTools.cc:221
PFAlgo::isFromSecInt
bool isFromSecInt(const reco::PFBlockElement &eTrack, std::string order) const
Definition: PFAlgo.cc:3464
min
T min(T a, T b)
Definition: MathUtil.h:58
reco::Vertex::z
double z() const
z coordinate
Definition: Vertex.h:120
reco::PFCandidate::mva_e_pi
float mva_e_pi() const
mva for electron-pion discrimination
Definition: PFCandidate.h:316
HLT_2018_cff.postHFCleaning
postHFCleaning
Definition: HLT_2018_cff.py:12313
edm::View::refAt
RefToBase< value_type > refAt(size_type i) const
PFTrackAlgoTools::step5
bool step5(const reco::TrackBase::TrackAlgorithm &)
Definition: PFTrackAlgoTools.cc:232
reco::PFBlockElement::time
float time() const
Definition: PFBlockElement.h:125
PFAlgo::valueMapGedElectrons_
const edm::ValueMap< reco::GsfElectronRef > * valueMapGedElectrons_
Definition: PFAlgo.h:268
hcal
Definition: ConfigurationDatabase.cc:13
edm::Ref::isNull
bool isNull() const
Checks for null.
Definition: Ref.h:235
multPhiCorr_741_25nsDY_cfi.py
py
Definition: multPhiCorr_741_25nsDY_cfi.py:12
AlCaHLTBitMon_ParallelJobs.p
p
Definition: AlCaHLTBitMon_ParallelJobs.py:153
cropTnPTrees.frac
frac
Definition: cropTnPTrees.py:18
reco::PFBlock
Block of elements.
Definition: PFBlock.h:26
reco::PFBlockElement::T_TO_DISP
Definition: PFBlockElement.h:47
ElementIndices::hfHadIs
std::vector< unsigned > hfHadIs
Definition: PFAlgo.h:50
PFAlgo::rejectTracks_Step45_
bool rejectTracks_Step45_
Definition: PFAlgo.h:277
ElementIndices::ecalIs
std::vector< unsigned > ecalIs
Definition: PFAlgo.h:44
PFEnergyCalibration::energyEmHad
void energyEmHad(double t, double &e, double &h, double eta, double phi) const
Definition: PFEnergyCalibration.cc:195
DetId::Hcal
Definition: DetId.h:28
PFAlgo::createCandidatesHCAL
void createCandidatesHCAL(const reco::PFBlock &block, reco::PFBlock::LinkData &linkData, const edm::OwnVector< reco::PFBlockElement > &elements, std::vector< bool > &active, const reco::PFBlockRef &blockref, ElementIndices &inds, std::vector< bool > &deadArea)
Definition: PFAlgo.cc:1696
edm::LogInfo
Definition: MessageLogger.h:254
PFLayer::HCAL_ENDCAP
Definition: PFLayer.h:37
reco::PFCluster::recHitFractions
const std::vector< reco::PFRecHitFraction > & recHitFractions() const
vector of rechit fractions
Definition: PFCluster.h:69
reco::PFCandidate::h
Definition: PFCandidate.h:45
PFAlgo::nSigmaEConstHFEM
const double nSigmaEConstHFEM
Definition: PFAlgo.h:335
reco::PFCandidate::h_HF
Definition: PFCandidate.h:50
XYZVector
math::XYZVector XYZVector
Definition: RawParticle.h:26
cms::cuda::assert
assert(be >=bs)
particleBasedIsoProducer_cfi.pfEgammaCandidates
pfEgammaCandidates
Definition: particleBasedIsoProducer_cfi.py:12
CustomPhysics_cfi.gamma
gamma
Definition: CustomPhysics_cfi.py:17
HLT_2018_cff.useProtectionsForJetMET
useProtectionsForJetMET
Definition: HLT_2018_cff.py:12406
edm::second
U second(std::pair< T, U > const &p)
Definition: ParameterSet.cc:215
PFAlgo::dptRel_DispVtx_
double dptRel_DispVtx_
Definition: PFAlgo.h:285
reco::TrackBase::px
double px() const
x coordinate of momentum vector
Definition: TrackBase.h:611
reco::Vertex::position
const Point & position() const
position
Definition: Vertex.h:114
reco::PFBlockElement::HCAL
Definition: PFBlockElement.h:36
DDAxes::x
PFAlgo::pfEgammaCandidates_
const edm::View< reco::PFCandidate > * pfEgammaCandidates_
Definition: PFAlgo.h:267
reco::LeafCandidate::pt
double pt() const final
transverse momentum
Definition: LeafCandidate.h:146
PFAlgo::muonHO_
std::vector< double > muonHO_
Definition: PFAlgo.h:295
findQualityFiles.v
v
Definition: findQualityFiles.py:179
PFAlgo::goodPixelTrackDeadHcal_ptErrRel_
float goodPixelTrackDeadHcal_ptErrRel_
Definition: PFAlgo.h:309
reco::PFCandidate::elementsInBlocks
const ElementsInBlocks & elementsInBlocks() const
Definition: PFCandidate.cc:636
createJobs.tmp
tmp
align.sh
Definition: createJobs.py:716
HLT_2018_cff.postMuonCleaning
postMuonCleaning
Definition: HLT_2018_cff.py:12310
convertSQLiteXML.ok
bool ok
Definition: convertSQLiteXML.py:98
PFAlgo::minHFCleaningPt_
double minHFCleaningPt_
Definition: PFAlgo.h:319
HLT_2018_cff.resolHF_square
resolHF_square
Definition: HLT_2018_cff.py:12307
dqmdumpme.first
first
Definition: dqmdumpme.py:55
reco::PFBlockRef
edm::Ref< PFBlockCollection > PFBlockRef
persistent reference to PFCluster objects
Definition: PFBlockFwd.h:19
PFAlgo::createCandidatesHCALUnlinked
void createCandidatesHCALUnlinked(const reco::PFBlock &block, reco::PFBlock::LinkData &linkData, const edm::OwnVector< reco::PFBlockElement > &elements, std::vector< bool > &active, const reco::PFBlockRef &blockref, ElementIndices &inds, std::vector< bool > &deadArea)
Definition: PFAlgo.cc:2807
PFAlgo::nSigmaECAL_
const double nSigmaECAL_
number of sigma to judge energy excess in ECAL
Definition: PFAlgo.h:245
reco::PFCandidate::X
Definition: PFCandidate.h:44
edm::Ref< PFClusterCollection >
PFLayer::ECAL_BARREL
Definition: PFLayer.h:33
reco::PFBlockElement::Type
Type
Definition: PFBlockElement.h:30
hit::x
double x
Definition: SiStripHitEffFromCalibTree.cc:89
patCandidatesForDimuonsSequences_cff.hcal
hcal
Definition: patCandidatesForDimuonsSequences_cff.py:37
PFAlgo::nSigmaHCAL
double nSigmaHCAL(double clusterEnergy, double clusterEta) const
Definition: PFAlgo.cc:3365
HLT_2018_cff.bCorrect
bCorrect
Definition: HLT_2018_cff.py:12318
reco::PFCandidate::egammaExtraRef
reco::PFCandidateEGammaExtraRef egammaExtraRef() const
return a reference to the EGamma extra
Definition: PFCandidate.cc:554
PFAlgo::minDeltaMet_
double minDeltaMet_
Definition: PFAlgo.h:324
DetId
Definition: DetId.h:17
cmsdt::algo
algo
Definition: constants.h:164
optionsL1T.skip
skip
Definition: optionsL1T.py:30
pfElectronTranslator_cfi.PFCandidate
PFCandidate
Definition: pfElectronTranslator_cfi.py:6
PFAlgo::usePFDecays_
bool usePFDecays_
Definition: PFAlgo.h:281
ECAL
Definition: HCALResponse.h:21
RPCNoise_example.check
check
Definition: RPCNoise_example.py:71
PFAlgo::elementLoop
void elementLoop(const reco::PFBlock &block, reco::PFBlock::LinkData &linkData, const edm::OwnVector< reco::PFBlockElement > &elements, std::vector< bool > &active, const reco::PFBlockRef &blockref, ElementIndices &inds, std::vector< bool > &deadArea)
Definition: PFAlgo.cc:991
reco::PFCandidate::mu
Definition: PFCandidate.h:47
HLT_2018_cff.bCalibPrimary
bCalibPrimary
Definition: HLT_2018_cff.py:12319
reco::TrackBase::py
double py() const
y coordinate of momentum vector
Definition: TrackBase.h:614
PFLayer::HF_EM
Definition: PFLayer.h:38
SiPixelRawToDigiRegional_cfi.deltaPhi
deltaPhi
Definition: SiPixelRawToDigiRegional_cfi.py:9
PFAlgo::conversionAlgo
void conversionAlgo(const edm::OwnVector< reco::PFBlockElement > &elements, std::vector< bool > &active)
Definition: PFAlgo.cc:364
Calorimetry_cff.dp
dp
Definition: Calorimetry_cff.py:157
reco::LeafCandidate::py
double py() const final
y coordinate of momentum vector
Definition: LeafCandidate.h:142
HLT_2018_cff.dptRel_DispVtx
dptRel_DispVtx
Definition: HLT_2018_cff.py:12325
PFAlgo::createCandidatesHF
void createCandidatesHF(const reco::PFBlock &block, reco::PFBlock::LinkData &linkData, const edm::OwnVector< reco::PFBlockElement > &elements, std::vector< bool > &active, const reco::PFBlockRef &blockref, ElementIndices &inds)
Definition: PFAlgo.cc:1253
reco::PFBlockElement::TRACK
Definition: PFBlockElement.h:32
jets_cff.nMuons
nMuons
Definition: jets_cff.py:209
PVValHelper::eta
Definition: PVValidationHelpers.h:69
mathSSE::sqrt
T sqrt(T t)
Definition: SSEVec.h:19
PFLayer::HCAL_BARREL1
Definition: PFLayer.h:35
PFEnergyCalibrationHF::energyHad
double energyHad(double uncalibratedEnergyHCAL, double eta, double phi)
Definition: PFEnergyCalibrationHF.cc:63
reco::Track
Definition: Track.h:27
reco::btau::trackMomentum
Definition: TaggingVariable.h:41
PFEnergyCalibrationHF::energyEmHad
double energyEmHad(double uncalibratedEnergyECAL, double uncalibratedEnergyHCAL, double eta, double phi)
Definition: PFEnergyCalibrationHF.cc:76
reco::CaloCluster::badHcalMarker
Definition: CaloCluster.h:50
PFAlgo::checkAndReconstructSecondaryInteraction
bool checkAndReconstructSecondaryInteraction(const reco::PFBlockRef &blockref, const edm::OwnVector< reco::PFBlockElement > &elements, bool isActive, int iElement)
Definition: PFAlgo.cc:849
DQMScaleToClient_cfi.factor
factor
Definition: DQMScaleToClient_cfi.py:8
trackingPlots.other
other
Definition: trackingPlots.py:1465
HCALHighEnergyHPDFilter_cfi.energy
energy
Definition: HCALHighEnergyHPDFilter_cfi.py:5
PFAlgo::reconstructTrack
unsigned reconstructTrack(const reco::PFBlockElement &elt, bool allowLoose=false)
Definition: PFAlgo.cc:3135
HCAL
Definition: HCALResponse.h:21
DigiToRawDM_cff.HO
HO
Definition: DigiToRawDM_cff.py:23
b
double b
Definition: hdecay.h:118
PFAlgo::muonHCAL_
std::vector< double > muonHCAL_
Variables for muons and fakes.
Definition: PFAlgo.h:293
PFAlgo::minSignificanceReduction_
double minSignificanceReduction_
Definition: PFAlgo.h:322
hit::z
double z
Definition: SiStripHitEffFromCalibTree.cc:91
reco::PFCandidate::ElementsInBlocks
std::vector< ElementInBlock > ElementsInBlocks
Definition: PFCandidate.h:378
reco::PFBlockElement::T_FROM_V0
Definition: PFBlockElement.h:47
edm::View::size
size_type size() const
reco::PFCandidate::set_mva_Isolated
void set_mva_Isolated(float mvaI)
Definition: PFCandidate.h:310
PFAlgo::nSigmaHFHAD
double nSigmaHFHAD(double clusterEnergy) const
Definition: PFAlgo.cc:3389
reco::PFBlockElement::TrackType
TrackType
Definition: PFBlockElement.h:47
PFAlgo::maxDeltaPhiPt_
double maxDeltaPhiPt_
Definition: PFAlgo.h:323
edm::LogWarning
Definition: MessageLogger.h:141
PFAlgo::goodTrackDeadHcal_layers_
int goodTrackDeadHcal_layers_
Definition: PFAlgo.h:303
ALCARECOTkAlJpsiMuMu_cff.charge
charge
Definition: ALCARECOTkAlJpsiMuMu_cff.py:47
PFLayer::HF_HAD
Definition: PFLayer.h:39
reco::PFBlockElement::T_FROM_DISP
Definition: PFBlockElement.h:47
HLT_2018_cff.usePFDecays
usePFDecays
Definition: HLT_2018_cff.py:12392
ntuplemaker.fill
fill
Definition: ntuplemaker.py:304
reco::PFCandidate::set_mva_e_pi
void set_mva_e_pi(float mvaNI)
Definition: PFCandidate.h:314
PFAlgo::nSigmaHFEM_
const double nSigmaHFEM_
number of sigma to judge energy excess in HF
Definition: PFAlgo.h:251
bphysicsOniaDQM_cfi.vertex
vertex
Definition: bphysicsOniaDQM_cfi.py:7
LogDebug
#define LogDebug(id)
Definition: MessageLogger.h:670
edm::ParameterSet
Definition: ParameterSet.h:36
math::XYZPoint
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
reco::PFBlockElement::HFEM
Definition: PFBlockElement.h:39
edm::LogError
Definition: MessageLogger.h:183
a
double a
Definition: hdecay.h:119
RecoEcal_cff.ecalClusters
ecalClusters
Definition: RecoEcal_cff.py:26
Phase1L1TJetCalibrator_cfi.calibration
calibration
Definition: Phase1L1TJetCalibrator_cfi.py:2
reco::PFBlockElement::GSF
Definition: PFBlockElement.h:37
zMuMuMuonUserData.primaryVertices
primaryVertices
Definition: zMuMuMuonUserData.py:12
PFCandConnector::setParameters
void setParameters(const edm::ParameterSet &iCfgCandConnector)
Definition: PFCandConnector.h:30
reco::LeafCandidate::eta
double eta() const final
momentum pseudorapidity
Definition: LeafCandidate.h:152
SiStripPI::max
Definition: SiStripPayloadInspectorHelper.h:169
PFAlgo::nSigmaHCAL_
const double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:248
reco::PFCandidate::particleId
virtual ParticleType particleId() const
Definition: PFCandidate.h:366
reco::Vertex::x
double x() const
x coordinate
Definition: Vertex.h:116
edm::Ref::isNonnull
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:238
reco::PFCandidate::T_FROM_DISP
Definition: PFCandidate.h:68
PFAlgo::checkHasDeadHcal
bool checkHasDeadHcal(const std::multimap< double, unsigned > &hcalElems, const std::vector< bool > &deadArea)
Definition: PFAlgo.cc:869
reco::PFCandidate::egamma_HF
Definition: PFCandidate.h:51
math::XYZVector
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:31
PFAlgo::ptError_
double ptError_
Definition: PFAlgo.h:297
reco::PFBlockElement::ECAL
Definition: PFBlockElement.h:35
PFAlgo::usePFNuclearInteractions_
bool usePFNuclearInteractions_
Definition: PFAlgo.h:279
cand
Definition: decayParser.h:34
eventshapeDQM_cfi.order
order
Definition: eventshapeDQM_cfi.py:8
PFAlgo::goodPixelTrackDeadHcal_minEta_
float goodPixelTrackDeadHcal_minEta_
Definition: PFAlgo.h:307
PFAlgo::goodTrackDeadHcal_dxy_
float goodTrackDeadHcal_dxy_
Definition: PFAlgo.h:305
HLT_2018_cff.usePFNuclearInteractions
usePFNuclearInteractions
Definition: HLT_2018_cff.py:12399
PFAlgo::checkGoodTrackDeadHcal
bool checkGoodTrackDeadHcal(const reco::TrackRef &trackRef, bool hasDeadHcal)
Definition: PFAlgo.cc:896
alignmentValidation.c1
c1
do drawing
Definition: alignmentValidation.py:1025
PFAlgo::rejectTracks_Bad_
bool rejectTracks_Bad_
Definition: PFAlgo.h:276
reco::PFBlockElement::timeError
float timeError() const
Definition: PFBlockElement.h:127
DOFs::Z
Definition: AlignPCLThresholdsWriter.cc:37
reco::PFBlockElement::T_FROM_GAMMACONV
Definition: PFBlockElement.h:47
PFAlgo::setHcalDepthInfo
void setHcalDepthInfo(reco::PFCandidate &cand, const reco::PFCluster &cluster) const
Definition: PFAlgo.cc:3325
reco::PFCandidate::gamma
Definition: PFCandidate.h:48
photonIsolationHIProducer_cfi.ho
ho
Definition: photonIsolationHIProducer_cfi.py:10
reco::LeafCandidate::charge
int charge() const final
electric charge
Definition: LeafCandidate.h:106
HcalResponse_cfi.energyHF
energyHF
Definition: HcalResponse_cfi.py:1084
groupFilesInBlocks.block
block
Definition: groupFilesInBlocks.py:150
PFAlgo::goodTrackDeadHcal_ptErrRel_
float goodTrackDeadHcal_ptErrRel_
Variables for track cleaning in bad HCal areas.
Definition: PFAlgo.h:301
PFAlgo::createCandidatesECAL
void createCandidatesECAL(const reco::PFBlock &block, reco::PFBlock::LinkData &linkData, const edm::OwnVector< reco::PFBlockElement > &elements, std::vector< bool > &active, const reco::PFBlockRef &blockref, ElementIndices &inds, std::vector< bool > &deadArea)
Definition: PFAlgo.cc:3006
PFAlgo::maxSignificance_
double maxSignificance_
Definition: PFAlgo.h:321
reco::PFBlockElement::HFHAD
Definition: PFBlockElement.h:40
PFAlgo::primaryVertex_
reco::Vertex primaryVertex_
Definition: PFAlgo.h:328
PFAlgo::reconstructCluster
unsigned reconstructCluster(const reco::PFCluster &cluster, double particleEnergy, bool useDirection=false, double particleX=0., double particleY=0., double particleZ=0.)
Definition: PFAlgo.cc:3214
reco::PFBlock::LinkData
std::map< unsigned int, Link > LinkData
Definition: PFBlock.h:39
PFAlgo::nSigmaHFHAD_
const double nSigmaHFHAD_
Definition: PFAlgo.h:252
PFAlgo::valueMapGedPhotons_
const edm::ValueMap< reco::PhotonRef > * valueMapGedPhotons_
Definition: PFAlgo.h:269
PFAlgo::muonHandle_
edm::Handle< reco::MuonCollection > muonHandle_
Definition: PFAlgo.h:331
reco::PFBlock::LINKTEST_ALL
Definition: PFBlock.h:41
PFAlgo::useProtectionsForJetMET_
bool useProtectionsForJetMET_
Definition: PFAlgo.h:266
reco::TrackBase::conversionStep
Definition: TrackBase.h:102
XYZPoint
math::XYZVector XYZPoint
Definition: CalorimetryManager.cc:66
PFAlgo::recoTracksNotHCAL
bool recoTracksNotHCAL(const reco::PFBlock &block, reco::PFBlock::LinkData &linkData, const edm::OwnVector< reco::PFBlockElement > &elements, const reco::PFBlockRef &blockref, std::vector< bool > &active, bool goodTrackDeadHcal, bool hasDeadHcal, unsigned int iTrack, std::multimap< double, unsigned > &ecalElems, reco::TrackRef &trackRef)
Definition: PFAlgo.cc:393
reco::CaloCluster::position
const math::XYZPoint & position() const
cluster centroid position
Definition: CaloCluster.h:154
ElementIndices
Definition: PFAlgo.h:40
PFAlgo::pfCandidates_
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:226
PFEnergyCalibrationHF::energyEm
double energyEm(double uncalibratedEnergyECAL, double eta, double phi)
Definition: PFEnergyCalibrationHF.cc:48
edm::ParameterSet::getParameter
T getParameter(std::string const &) const
multPhiCorr_741_25nsDY_cfi.px
px
Definition: multPhiCorr_741_25nsDY_cfi.py:10
PFAlgo::nSigmaTRACK_
double nSigmaTRACK_
Definition: PFAlgo.h:296
reco::LeafCandidate::setP4
void setP4(const LorentzVector &p4) final
set 4-momentum
Definition: LeafCandidate.h:158
bookConverter.elements
elements
Definition: bookConverter.py:147
type
type
Definition: HCALResponse.h:21
reco::Vertex::y
double y() const
y coordinate
Definition: Vertex.h:118
DOFs::Y
Definition: AlignPCLThresholdsWriter.cc:37
reco::LeafCandidate::phi
double phi() const final
momentum azimuthal angle
Definition: LeafCandidate.h:148
PFAlgo::factors45_
std::vector< double > factors45_
Definition: PFAlgo.h:298
qcdUeDQM_cfi.quality
quality
Definition: qcdUeDQM_cfi.py:31
PFMuonAlgo::isMuon
static bool isMuon(const reco::PFBlockElement &elt)
Definition: PFMuonAlgo.cc:56
PFAlgo::nSigmaEConstHCAL
const double nSigmaEConstHCAL
Definition: PFAlgo.h:334
PFAlgo::connector_
PFCandConnector connector_
Definition: PFAlgo.h:290
PFAlgo::goodPixelTrackDeadHcal_dxy_
float goodPixelTrackDeadHcal_dxy_
Definition: PFAlgo.h:313
math::XYZTLorentzVector
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
reco::PFCandidate::T_TO_DISP
Definition: PFCandidate.h:67
relativeConstraints.empty
bool empty
Definition: relativeConstraints.py:46
PFAlgo::egammaFilters
void egammaFilters(const reco::PFBlockRef &blockref, std::vector< bool > &active, PFEGammaFilters const *pfegamma)
Definition: PFAlgo.cc:222
PFAlgo::processBlock
void processBlock(const reco::PFBlockRef &blockref, std::list< reco::PFBlockRef > &hcalBlockRefs, std::list< reco::PFBlockRef > &ecalBlockRefs, PFEGammaFilters const *pfegamma)
Definition: PFAlgo.cc:3055
Exception
Definition: hltDiff.cc:246
reco::PFCandidateCollection
std::vector< reco::PFCandidate > PFCandidateCollection
collection of PFCandidates
Definition: PFCandidateFwd.h:12
reco::PFCluster
Particle flow cluster, see clustering algorithm in PFClusterAlgo.
Definition: PFCluster.h:46
reco::LeafCandidate::setCharge
void setCharge(Charge q) final
set electric charge
Definition: LeafCandidate.h:108
EgHLTOffHistBins_cfi.mass
mass
Definition: EgHLTOffHistBins_cfi.py:34
PFAlgo::usePFConversions_
bool usePFConversions_
Definition: PFAlgo.h:280
HLT_2018_cff.usePFConversions
usePFConversions
Definition: HLT_2018_cff.py:12304
PFAlgo::pfCleanedCandidates_
reco::PFCandidateCollection pfCleanedCandidates_
Definition: PFAlgo.h:228
fftjetpileupestimator_calo_uncalib_cfi.c0
c0
Definition: fftjetpileupestimator_calo_uncalib_cfi.py:8
bsc_activity_cfg.ecal
ecal
Definition: bsc_activity_cfg.py:25
AlignmentPI::index
index
Definition: AlignmentPayloadInspectorHelper.h:46
PFAlgo::goodPixelTrackDeadHcal_maxPt_
float goodPixelTrackDeadHcal_maxPt_
Definition: PFAlgo.h:308
PFAlgo::hfEnergyResolution
double hfEnergyResolution(double clusterEnergy) const
Definition: PFAlgo.cc:3372
reco::PFRecHit
Particle flow rechit (rechit + geometry and topology information). See clustering algorithm in PFClus...
Definition: PFRecHit.h:31
reco::PFCandidate
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:40
HLT_2018_cff.track
track
Definition: HLT_2018_cff.py:10352
funct::pow
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:30
PFTrackAlgoTools::errorScale
double errorScale(const reco::TrackBase::TrackAlgorithm &, const std::vector< double > &)
Definition: PFTrackAlgoTools.cc:86
reco::TrackBase::pz
double pz() const
z coordinate of momentum vector
Definition: TrackBase.h:617
HLT_2018_cff.rejectTracks_Step45
rejectTracks_Step45
Definition: HLT_2018_cff.py:12394
PFEnergyCalibrationHF::getcalibHF_use
const bool & getcalibHF_use() const
Definition: PFEnergyCalibrationHF.h:47
HLT_2018_cff.iCfgCandConnector
iCfgCandConnector
Definition: HLT_2018_cff.py:12316
ElementIndices::hoIs
std::vector< unsigned > hoIs
Definition: PFAlgo.h:43
funct::abs
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
reco::PFBlockElement::PS1
Definition: PFBlockElement.h:33
LogTrace
#define LogTrace(id)
Definition: MessageLogger.h:671
ElementIndices::hfEmIs
std::vector< unsigned > hfEmIs
Definition: PFAlgo.h:49
PFCandConnector::connect
reco::PFCandidateCollection connect(reco::PFCandidateCollection &pfCand) const
Definition: PFCandConnector.cc:63
HLT_2018_cff.rejectTracks_Bad
rejectTracks_Bad
Definition: HLT_2018_cff.py:12321
PbPb_ZMuSkimMuonDPG_cff.particleType
particleType
Definition: PbPb_ZMuSkimMuonDPG_cff.py:27
reco::PFCandidate::ParticleType
ParticleType
particle types
Definition: PFCandidate.h:43
dqmiolumiharvest.j
j
Definition: dqmiolumiharvest.py:66
JetChargeProducer_cfi.exp
exp
Definition: JetChargeProducer_cfi.py:6
edm::HandleBase::isValid
bool isValid() const
Definition: HandleBase.h:70
PFAlgo::useHO_
bool useHO_
Definition: PFAlgo.h:260
math::XYZPointF
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< float > > XYZPointF
point in space with cartesian internal representation
Definition: Point3D.h:10
PFLayer::ECAL_ENDCAP
Definition: PFLayer.h:32
bTagCommon_cff.ratioMax
ratioMax
Definition: bTagCommon_cff.py:34
PFAlgo::neutralHadronEnergyResolution
double neutralHadronEnergyResolution(double clusterEnergy, double clusterEta) const
todo: use PFClusterTools for this
Definition: PFAlgo.cc:3355
PFAlgo::minSignificance_
double minSignificance_
Definition: PFAlgo.h:320
ElementIndices::hcalIs
std::vector< unsigned > hcalIs
Definition: PFAlgo.h:42
reco::LeafCandidate::px
double px() const final
x coordinate of momentum vector
Definition: LeafCandidate.h:140
PFAlgo::postHFCleaning_
bool postHFCleaning_
Definition: PFAlgo.h:317
gather_cfg.blocks
blocks
Definition: gather_cfg.py:90
HLT_2018_cff.flags
flags
Definition: HLT_2018_cff.py:11758
HLT_2018_cff.fraction
fraction
Definition: HLT_2018_cff.py:51317
cuy.ii
ii
Definition: cuy.py:590
ElementIndices::trackIs
std::vector< unsigned > trackIs
Definition: PFAlgo.h:45
PFAlgo::relinkTrackToHcal
void relinkTrackToHcal(const reco::PFBlock &block, std::multimap< double, unsigned > &ecalElems, std::multimap< double, unsigned > &hcalElems, const std::vector< bool > &active, reco::PFBlock::LinkData &linkData, unsigned int iTrack)
Definition: PFAlgo.cc:935
reco::PFCandidate::setParticleType
void setParticleType(ParticleType type)
set Particle Type
Definition: PFCandidate.cc:256
PFMuonAlgo::isLooseMuon
static bool isLooseMuon(const reco::PFBlockElement &elt)
Definition: PFMuonAlgo.cc:65
PFAlgo::resolHF_square_
const std::vector< double > resolHF_square_
Definition: PFAlgo.h:255
hit
Definition: SiStripHitEffFromCalibTree.cc:88
muonDTDigis_cfi.pset
pset
Definition: muonDTDigis_cfi.py:27
reco::PFBlockElement::PS2
Definition: PFBlockElement.h:34
edm::OwnVector< reco::PFBlockElement >
met_cff.significance
significance
Definition: met_cff.py:19
PFAlgo::associatePSClusters
void associatePSClusters(unsigned iEcal, reco::PFBlockElement::Type psElementType, const reco::PFBlock &block, const edm::OwnVector< reco::PFBlockElement > &elements, const reco::PFBlock::LinkData &linkData, std::vector< bool > &active, std::vector< double > &psEne)
Associate PS clusters to a given ECAL cluster, and return their energy.
Definition: PFAlgo.cc:3419
reco::PFCandidate::set_mva_nothing_gamma
void set_mva_nothing_gamma(float mva)
set mva for gamma detection
Definition: PFCandidate.h:331
GetRecoTauVFromDQM_MC_cff.next
next
Definition: GetRecoTauVFromDQM_MC_cff.py:31
MillePedeFileConverter_cfg.e
e
Definition: MillePedeFileConverter_cfg.py:37
PFAlgo::thepfEnergyCalibrationHF_
PFEnergyCalibrationHF & thepfEnergyCalibrationHF_
Definition: PFAlgo.h:258
reco::isMuon
bool isMuon(const Candidate &part)
Definition: pdgIdUtils.h:9
reco::TrackBase::highPurity
Definition: TrackBase.h:154