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...
 
PFMuonAlgogetPFMuonAlgo ()
 
 PFAlgo ()
 constructor More...
 
const std::unique_ptr< reco::PFCandidateCollection > & pfCandidates () const
 
void reconstructParticles (const reco::PFBlockHandle &blockHandle)
 
void reconstructParticles (const reco::PFBlockCollection &blocks)
 reconstruct particles More...
 
void setAlgo (int algo)
 
void setBadHcalTrackParams (const edm::ParameterSet &pset)
 
void setCandConnectorParameters (const edm::ParameterSet &iCfgCandConnector)
 
void setCandConnectorParameters (bool bCorrect, bool bCalibPrimary, double dptRel_PrimaryTrack, double dptRel_MergedTrack, double ptErrorSecondary, const std::vector< double > &nuclCalibFactors)
 
void setDebug (bool debug)
 
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, std::string ele_iso_path_mvaWeightFile, double ele_iso_pt, double ele_iso_mva_barrel, double ele_iso_mva_endcap, double ele_iso_combIso_barrel, double ele_iso_combIso_endcap, double ele_noniso_mva, unsigned int ele_missinghits, bool useProtectionsForJetMET, const edm::ParameterSet &ele_protectionsForJetMET, const edm::ParameterSet &ele_protectionsForBadHcal, double ph_MinEt, double ph_combIso, double ph_HoE, double ph_sietaieta_eb, double ph_sietaieta_ee, const edm::ParameterSet &ph_protectionsForJetMET, const edm::ParameterSet &ph_protectionsForBadHcal)
 
void setEGElectronCollection (const reco::GsfElectronCollection &egelectrons)
 
void setElectronExtraRef (const edm::OrphanHandle< reco::PFCandidateElectronExtraCollection > &extrah)
 
void setHOTag (bool ho)
 
void setMuonHandle (const edm::Handle< reco::MuonCollection > &)
 
void setParameters (double nSigmaECAL, double nSigmaHCAL, const std::shared_ptr< PFEnergyCalibration > &calibration, const std::shared_ptr< PFEnergyCalibrationHF > &thepfEnergyCalibrationHF)
 
void setPFEleParameters (double mvaEleCut, std::string mvaWeightFileEleID, bool usePFElectrons, const std::shared_ptr< PFSCEnergyCalibration > &thePFSCEnergyCalibration, const std::shared_ptr< PFEnergyCalibration > &thePFEnergyCalibration, double sumEtEcalIsoForEgammaSC_barrel, double sumEtEcalIsoForEgammaSC_endcap, double coneEcalIsoForEgammaSC, double sumPtTrackIsoForEgammaSC_barrel, double sumPtTrackIsoForEgammaSC_endcap, unsigned int nTrackIsoForEgammaSC, double coneTrackIsoForEgammaSC, bool applyCrackCorrections=false, bool usePFSCEleCalib=true, bool useEGElectrons=false, bool useEGammaSupercluster=true)
 
void setPFMuonAlgo (PFMuonAlgo *algo)
 
void setPFMuonAndFakeParameters (const edm::ParameterSet &pset)
 
void setPFPhotonParameters (bool usePFPhoton, std::string mvaWeightFileConvID, double mvaConvCut, bool useReg, std::string X0_Map, const std::shared_ptr< PFEnergyCalibration > &thePFEnergyCalibration, double sumPtTrackIsoForPhoton, double sumPtTrackIsoSlopeForPhoton)
 
void setPFPhotonRegWeights (const GBRForest *LCorrForestEB, const GBRForest *LCorrForestEE, const GBRForest *GCorrForestBarrel, const GBRForest *GCorrForestEndcapHr9, const GBRForest *GCorrForestEndcapLr9, const GBRForest *PFEcalResolution)
 
void setPFVertexParameters (bool useVertex, const reco::VertexCollection *primaryVertices)
 
void setPhotonExtraRef (const edm::OrphanHandle< reco::PFCandidatePhotonExtraCollection > &pf_extrah)
 
void setPostHFCleaningParameters (bool postHFCleaning, double minHFCleaningPt, double minSignificance, double maxSignificance, double minSignificanceReduction, double maxDeltaPhiPt, double minDeltaMet)
 
std::shared_ptr< PFEnergyCalibrationthePFEnergyCalibration ()
 return the pointer to the calibration function More...
 
std::unique_ptr< reco::PFCandidateCollectiontransferCandidates ()
 
std::unique_ptr< reco::PFCandidateCollectiontransferCleanedCandidates ()
 
std::unique_ptr< reco::PFCandidateCollectiontransferElectronCandidates ()
 
std::unique_ptr< reco::PFCandidateElectronExtraCollectiontransferElectronExtra ()
 
std::unique_ptr< reco::PFCandidatePhotonExtraCollectiontransferPhotonExtra ()
 
 ~PFAlgo ()
 destructor More...
 

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...
 
reco::PFBlockRef createBlockRef (const reco::PFBlockCollection &blocks, unsigned bi)
 
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
 
void postCleaning ()
 
void processBlock (const reco::PFBlockRef &blockref, std::list< reco::PFBlockRef > &hcalBlockRefs, std::list< reco::PFBlockRef > &ecalBlockRefs)
 
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)
 
void setHcalDepthInfo (reco::PFCandidate &cand, const reco::PFCluster &cluster) const
 

Private Attributes

int algo_
 
bool applyCrackCorrectionsElectrons_
 
reco::PFBlockHandle blockHandle_
 input block handle (full framework case) More...
 
std::shared_ptr< PFEnergyCalibrationcalibration_
 
double coneEcalIsoForEgammaSC_
 
double coneTrackIsoForEgammaSC_
 
PFCandConnector connector_
 
bool debug_
 
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_
 
double mvaEleCut_
 
std::string mvaWeightFileEleID_
 Variables for PFElectrons. More...
 
double nSigmaECAL_
 number of sigma to judge energy excess in ECAL More...
 
double nSigmaHCAL_
 number of sigma to judge energy excess in HCAL More...
 
double nSigmaTRACK_
 
unsigned int nTrackIsoForEgammaSC_
 
int nVtx_
 
std::unique_ptr< reco::PFCandidateCollectionpfCandidates_
 
std::unique_ptr< reco::PFCandidateCollectionpfCleanedCandidates_
 
PFEGammaFilterspfegamma_
 
const edm::View< reco::PFCandidate > * pfEgammaCandidates_
 
PFElectronAlgopfele_
 
std::unique_ptr< reco::PFCandidateCollectionpfElectronCandidates_
 the unfiltered electron collection More...
 
reco::PFCandidateElectronExtraCollection pfElectronExtra_
 the unfiltered electron collection More...
 
PFMuonAlgopfmu_
 
PFPhotonAlgopfpho_
 
std::unique_ptr< reco::PFCandidateCollectionpfPhotonCandidates_
 the unfiltered photon collection More...
 
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
 the extra photon collection More...
 
bool postHFCleaning_
 
bool postMuonCleaning_
 
reco::Vertex primaryVertex_
 
double ptError_
 
bool rejectTracks_Bad_
 
bool rejectTracks_Step45_
 
std::vector< double > setchi2Values_
 
double sumEtEcalIsoForEgammaSC_barrel_
 
double sumEtEcalIsoForEgammaSC_endcap_
 
double sumPtTrackIsoForEgammaSC_barrel_
 
double sumPtTrackIsoForEgammaSC_endcap_
 
std::shared_ptr< PFEnergyCalibrationHFthepfEnergyCalibrationHF_
 
std::shared_ptr< PFSCEnergyCalibrationthePFSCEnergyCalibration_
 
double useBestMuonTrack_
 
bool useEGammaFilters_
 Variables for NEW EGAMMA selection. More...
 
bool useEGammaSupercluster_
 
bool useEGElectrons_
 
bool useHO_
 
bool usePFConversions_
 
bool usePFDecays_
 
bool usePFElectrons_
 
bool usePFMuonMomAssign_
 
bool usePFNuclearInteractions_
 
bool usePFPhotons_
 
bool usePFSCEleCalib_
 
bool useProtectionsForJetMET_
 
bool useVertices_
 
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 49 of file PFAlgo.h.

Constructor & Destructor Documentation

PFAlgo::PFAlgo ( )

constructor

Definition at line 51 of file PFAlgo.cc.

53  nSigmaECAL_(0),
54  nSigmaHCAL_(1),
55  algo_(1),
56  debug_(false),
57  pfele_(nullptr),
58  pfpho_(nullptr),
59  pfegamma_(nullptr),
60  useVertices_(false)
61 {}
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:286
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:326
PFElectronAlgo * pfele_
Definition: PFAlgo.h:353
int algo_
Definition: PFAlgo.h:333
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:354
PFEGammaFilters * pfegamma_
Definition: PFAlgo.h:360
std::vector< reco::PFCandidate > PFCandidateCollection
collection of PFCandidates
bool useVertices_
Definition: PFAlgo.h:426
bool debug_
Definition: PFAlgo.h:334
double nSigmaECAL_
number of sigma to judge energy excess in ECAL
Definition: PFAlgo.h:323
PFAlgo::~PFAlgo ( )

destructor

Definition at line 63 of file PFAlgo.cc.

References pfegamma_, pfele_, pfpho_, useEGammaFilters_, usePFElectrons_, and usePFPhotons_.

63  {
64  if (usePFElectrons_) delete pfele_;
65  if (usePFPhotons_) delete pfpho_;
66  if (useEGammaFilters_) delete pfegamma_;
67 }
PFElectronAlgo * pfele_
Definition: PFAlgo.h:353
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:354
PFEGammaFilters * pfegamma_
Definition: PFAlgo.h:360
bool useEGammaFilters_
Variables for NEW EGAMMA selection.
Definition: PFAlgo.h:359
bool usePFPhotons_
Definition: PFAlgo.h:341
bool usePFElectrons_
Definition: PFAlgo.h:340

Member Function Documentation

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 3467 of file PFAlgo.cc.

References reco::PFBlock::associatedElements(), reco::PFBlockElement::ECAL, edm::Ref< C, T, F >::isNull(), and reco::PFBlock::LINKTEST_ALL.

Referenced by processBlock().

3473  {
3474 
3475  // Find all PS clusters with type psElement associated to ECAL cluster iEcal,
3476  // within all PFBlockElement "elements" of a given PFBlock "block"
3477  // psElement can be reco::PFBlockElement::PS1 or reco::PFBlockElement::PS2
3478  // Returns a vector of PS cluster energies, and updates the "active" vector.
3479 
3480  // Find all PS clusters linked to the iEcal cluster
3481  std::multimap<double, unsigned> sortedPS;
3482  block.associatedElements( iEcal, linkData,
3483  sortedPS, psElementType,
3485 
3486  // Loop over these PS clusters
3487  double totalPS = 0.;
3488  for(auto const& ps : sortedPS) {
3489 
3490  // CLuster index and distance to iEcal
3491  unsigned iPS = ps.second;
3492  // double distPS = ps.first;
3493 
3494  // Ignore clusters already in use
3495  if (!active[iPS]) continue;
3496 
3497  // Check that this cluster is not closer to another ECAL cluster
3498  std::multimap<double, unsigned> sortedECAL;
3499  block.associatedElements( iPS, linkData,
3500  sortedECAL,
3503  unsigned jEcal = sortedECAL.begin()->second;
3504  if ( jEcal != iEcal ) continue;
3505 
3506  // Update PS energy
3507  PFBlockElement::Type pstype = elements[ iPS ].type();
3508  assert( pstype == psElementType );
3509  PFClusterRef psclusterref = elements[iPS].clusterRef();
3510  assert(!psclusterref.isNull() );
3511  totalPS += psclusterref->energy();
3512  psEne[0] += psclusterref->energy();
3513  active[iPS] = false;
3514  }
3515 
3516 
3517 }
bool isNull() const
Checks for null.
Definition: Ref.h:248
void associatedElements(unsigned i, const LinkData &linkData, std::multimap< double, unsigned > &sortedAssociates, reco::PFBlockElement::Type type=PFBlockElement::NONE, LinkTest test=LINKTEST_RECHIT) const
Definition: PFBlock.cc:75
void PFAlgo::checkCleaning ( const reco::PFRecHitCollection cleanedHF)

Check HF Cleaning.

Definition at line 3660 of file PFAlgo.cc.

References gather_cfg::cout, debug_, reco::PFRecHit::energy(), mps_fire::i, reco::PFRecHit::layer(), Basic3DVector< T >::mag2(), minDeltaMet_, GetRecoTauVFromDQM_MC_cff::next, pfCandidates_, reco::PFRecHit::position(), EnergyCorrector::pt, reconstructCluster(), createPayload::skip, mathSSE::sqrt(), reco::PFRecHit::time(), Basic3DVector< T >::x(), Basic3DVector< T >::y(), and Basic3DVector< T >::z().

Referenced by setCandConnectorParameters().

3660  {
3661 
3662 
3663  // No hits to recover, leave.
3664  if ( cleanedHits.empty() ) return;
3665 
3666  //Compute met and met significance (met/sqrt(SumEt))
3667  double metX = 0.;
3668  double metY = 0.;
3669  double sumet = 0;
3670  std::vector<unsigned int> hitsToBeAdded;
3671  for(auto const& pfc : *pfCandidates_) {
3672  metX += pfc.px();
3673  metY += pfc.py();
3674  sumet += pfc.pt();
3675  }
3676  double met2 = metX*metX+metY*metY;
3677  double met2_Original = met2;
3678  // Select events with large MET significance.
3679  // double significance = std::sqrt(met2/sumet);
3680  // double significanceCor = significance;
3681  double metXCor = metX;
3682  double metYCor = metY;
3683  double sumetCor = sumet;
3684  double met2Cor = met2;
3685  bool next = true;
3686  unsigned iCor = 1E9;
3687 
3688  // Find the cleaned hit with the largest effect on the MET
3689  while ( next ) {
3690 
3691  double metReduc = -1.;
3692  // Loop on the candidates
3693  for(unsigned i=0; i<cleanedHits.size(); ++i) {
3694  const PFRecHit& hit = cleanedHits[i];
3695  double length = std::sqrt(hit.position().mag2());
3696  double px = hit.energy() * hit.position().x()/length;
3697  double py = hit.energy() * hit.position().y()/length;
3698  double pt = std::sqrt(px*px + py*py);
3699 
3700  // Check that it is not already scheculed to be cleaned
3701  bool skip = false;
3702  for(unsigned int hitIdx : hitsToBeAdded) {
3703  if ( i == hitIdx ) skip = true;
3704  if ( skip ) break;
3705  }
3706  if ( skip ) continue;
3707 
3708  // Now add the candidate to the MET
3709  double metXInt = metX + px;
3710  double metYInt = metY + py;
3711  double sumetInt = sumet + pt;
3712  double met2Int = metXInt*metXInt+metYInt*metYInt;
3713 
3714  // And check if it could contribute to a MET reduction
3715  if ( met2Int < met2Cor ) {
3716  metXCor = metXInt;
3717  metYCor = metYInt;
3718  metReduc = (met2-met2Int)/met2Int;
3719  met2Cor = met2Int;
3720  sumetCor = sumetInt;
3721  // significanceCor = std::sqrt(met2Cor/sumetCor);
3722  iCor = i;
3723  }
3724  }
3725  //
3726  // If the MET must be significanly reduced, schedule the candidate to be added
3727  //
3728  if ( metReduc > minDeltaMet_ ) {
3729  hitsToBeAdded.push_back(iCor);
3730  metX = metXCor;
3731  metY = metYCor;
3732  sumet = sumetCor;
3733  met2 = met2Cor;
3734  } else {
3735  // Otherwise just stop the loop
3736  next = false;
3737  }
3738  }
3739  //
3740  // At least 10 GeV MET reduction
3741  if ( std::sqrt(met2_Original) - std::sqrt(met2) > 5. ) {
3742  if ( debug_ ) {
3743  std::cout << hitsToBeAdded.size() << " hits were re-added " << std::endl;
3744  std::cout << "MET reduction = " << std::sqrt(met2_Original) << " -> "
3745  << std::sqrt(met2Cor) << " = " << std::sqrt(met2Cor) - std::sqrt(met2_Original)
3746  << std::endl;
3747  std::cout << "Added after cleaning check : " << std::endl;
3748  }
3749  for(unsigned int hitIdx : hitsToBeAdded) {
3750  const PFRecHit& hit = cleanedHits[hitIdx];
3751  PFCluster cluster(hit.layer(), hit.energy(),
3752  hit.position().x(), hit.position().y(), hit.position().z() );
3753  reconstructCluster(cluster,hit.energy());
3754  if ( debug_ ) {
3755  std::cout << pfCandidates_->back() << ". time = " << hit.time() << std::endl;
3756  }
3757  }
3758  }
3759 
3760 }
T y() const
Cartesian y coordinate.
T x() const
Cartesian x coordinate.
Particle flow cluster, see clustering algorithm in PFClusterAlgo.
Definition: PFCluster.h:47
double minDeltaMet_
Definition: PFAlgo.h:421
float time() const
timing for cleaned hits
Definition: PFRecHit.h:118
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:286
unsigned reconstructCluster(const reco::PFCluster &cluster, double particleEnergy, bool useDirection=false, double particleX=0., double particleY=0., double particleZ=0.)
Definition: PFAlgo.cc:3261
PositionType const & position() const
rechit cell centre x, y, z
Definition: PFRecHit.h:129
PFLayer::Layer layer() const
rechit layer
Definition: PFRecHit.h:111
Particle flow rechit (rechit + geometry and topology information). See clustering algorithm in PFClus...
Definition: PFRecHit.h:32
T z() const
Cartesian z coordinate.
T sqrt(T t)
Definition: SSEVec.h:18
float energy() const
rechit energy
Definition: PFRecHit.h:114
bool debug_
Definition: PFAlgo.h:334
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
reco::PFBlockRef PFAlgo::createBlockRef ( const reco::PFBlockCollection blocks,
unsigned  bi 
)
private

create a reference to a block, transient or persistent depending on the needs

Definition at line 3455 of file PFAlgo.cc.

References blockHandle_, and edm::HandleBase::isValid().

Referenced by reconstructParticles().

3456  {
3457 
3458  if( blockHandle_.isValid() ) {
3459  return reco::PFBlockRef( blockHandle_, bi );
3460  }
3461  else {
3462  return reco::PFBlockRef( &blocks, bi );
3463  }
3464 }
edm::Ref< PFBlockCollection > PFBlockRef
persistent reference to PFCluster objects
Definition: PFBlockFwd.h:20
bool isValid() const
Definition: HandleBase.h:74
reco::PFBlockHandle blockHandle_
input block handle (full framework case)
Definition: PFAlgo.h:320
PFMuonAlgo * PFAlgo::getPFMuonAlgo ( )

Definition at line 85 of file PFAlgo.cc.

References pfmu_.

Referenced by setCandConnectorParameters().

85  {
86  return pfmu_;
87 }
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:355
bool PFAlgo::isFromSecInt ( const reco::PFBlockElement eTrack,
std::string  order 
) const
private

Definition at line 3521 of file PFAlgo.cc.

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

Referenced by processBlock(), and reconstructTrack().

3521  {
3522 
3525  // reco::PFBlockElement::TrackType T_FROM_GAMMACONV = reco::PFBlockElement::T_FROM_GAMMACONV;
3527 
3528  bool bPrimary = (order.find("primary") != string::npos);
3529  bool bSecondary = (order.find("secondary") != string::npos);
3530  bool bAll = (order.find("all") != string::npos);
3531 
3532  bool isToDisp = usePFNuclearInteractions_ && eTrack.trackType(T_TO_DISP);
3533  bool isFromDisp = usePFNuclearInteractions_ && eTrack.trackType(T_FROM_DISP);
3534 
3535  if (bPrimary && isToDisp) return true;
3536  if (bSecondary && isFromDisp ) return true;
3537  if (bAll && ( isToDisp || isFromDisp ) ) return true;
3538 
3539 // bool isFromConv = usePFConversions_ && eTrack.trackType(T_FROM_GAMMACONV);
3540 
3541 // if ((bAll || bSecondary)&& isFromConv) return true;
3542 
3543  bool isFromDecay = (bAll || bSecondary) && usePFDecays_ && eTrack.trackType(T_FROM_V0);
3544 
3545  return isFromDecay;
3546 
3547 
3548 }
bool usePFNuclearInteractions_
Definition: PFAlgo.h:375
virtual bool trackType(TrackType trType) const
bool usePFDecays_
Definition: PFAlgo.h:377
double PFAlgo::neutralHadronEnergyResolution ( double  clusterEnergy,
double  clusterEta 
) const
private

todo: use PFClusterTools for this

Returns
calibrated energy of a photon
calibrated energy of a neutral hadron, which can leave some energy in the ECAL ( energyECAL>0 )

Definition at line 3406 of file PFAlgo.cc.

References mathSSE::sqrt().

Referenced by processBlock(), and thePFEnergyCalibration().

3406  {
3407 
3408  // Add a protection
3409  if ( clusterEnergyHCAL < 1. ) clusterEnergyHCAL = 1.;
3410 
3411  double resol = fabs(eta) < 1.48 ?
3412  sqrt (1.02*1.02/clusterEnergyHCAL + 0.065*0.065)
3413  :
3414  sqrt (1.20*1.20/clusterEnergyHCAL + 0.028*0.028);
3415 
3416  return resol;
3417 
3418 }
T sqrt(T t)
Definition: SSEVec.h:18
double PFAlgo::nSigmaHCAL ( double  clusterEnergy,
double  clusterEta 
) const
private

Definition at line 3421 of file PFAlgo.cc.

References JetChargeProducer_cfi::exp, and nSigmaHCAL_.

Referenced by processBlock(), setDebug(), setParameters(), and thePFEnergyCalibration().

3421  {
3422  double nS = fabs(eta) < 1.48 ?
3423  nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL/100.))
3424  :
3425  nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL/100.));
3426 
3427  return nS;
3428 }
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:326
const std::unique_ptr<reco::PFCandidateCollection>& PFAlgo::pfCandidates ( ) const
inline
Returns
collection of candidates

Definition at line 197 of file PFAlgo.h.

References pfCandidates_.

Referenced by operator<<().

197  {
198  return pfCandidates_;
199  }
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:286
void PFAlgo::postCleaning ( )
private

Definition at line 3557 of file PFAlgo.cc.

References gather_cfg::cout, hiPixelPairStep_cff::deltaPhi, reco::PFCandidate::egamma_HF, reco::PFCandidate::h_HF, mps_fire::i, maxDeltaPhiPt_, maxSignificance_, minDeltaMet_, minHFCleaningPt_, minSignificance_, minSignificanceReduction_, GetRecoTauVFromDQM_MC_cff::next, reco::PFCandidate::particleId(), pfCandidates_, pfCleanedCandidates_, postHFCleaning_, reco::LeafCandidate::pt(), reco::LeafCandidate::px(), reco::LeafCandidate::py(), createPayload::skip, and mathSSE::sqrt().

Referenced by reconstructParticles().

3557  {
3558 
3559  // Check if the post HF Cleaning was requested - if not, do nothing
3560  if ( !postHFCleaning_ ) return;
3561 
3562  //Compute met and met significance (met/sqrt(SumEt))
3563  double metX = 0.;
3564  double metY = 0.;
3565  double sumet = 0;
3566  std::vector<unsigned int> pfCandidatesToBeRemoved;
3567  for(auto const& pfc : *pfCandidates_) {
3568  metX += pfc.px();
3569  metY += pfc.py();
3570  sumet += pfc.pt();
3571  }
3572  double met2 = metX*metX+metY*metY;
3573  // Select events with large MET significance.
3574  double significance = std::sqrt(met2/sumet);
3575  double significanceCor = significance;
3576  if ( significance > minSignificance_ ) {
3577 
3578  double metXCor = metX;
3579  double metYCor = metY;
3580  double sumetCor = sumet;
3581  double met2Cor = met2;
3582  double deltaPhi = 3.14159;
3583  double deltaPhiPt = 100.;
3584  bool next = true;
3585  unsigned iCor = 1E9;
3586 
3587  // Find the HF candidate with the largest effect on the MET
3588  while ( next ) {
3589 
3590  double metReduc = -1.;
3591  // Loop on the candidates
3592  for(unsigned i=0; i<pfCandidates_->size(); ++i) {
3593  const PFCandidate& pfc = (*pfCandidates_)[i];
3594 
3595  // Check that the pfCandidate is in the HF
3596  if ( pfc.particleId() != reco::PFCandidate::h_HF &&
3597  pfc.particleId() != reco::PFCandidate::egamma_HF ) continue;
3598 
3599  // Check if has meaningful pt
3600  if ( pfc.pt() < minHFCleaningPt_ ) continue;
3601 
3602  // Check that it is not already scheculed to be cleaned
3603  const bool skip = std::any_of(pfCandidatesToBeRemoved.begin(), pfCandidatesToBeRemoved.end(),
3604  [&](unsigned int j){ return i == j; });
3605  if ( skip ) continue;
3606 
3607  // Check that the pt and the MET are aligned
3608  deltaPhi = std::acos((metX*pfc.px()+metY*pfc.py())/(pfc.pt()*std::sqrt(met2)));
3609  deltaPhiPt = deltaPhi*pfc.pt();
3610  if ( deltaPhiPt > maxDeltaPhiPt_ ) continue;
3611 
3612  // Now remove the candidate from the MET
3613  double metXInt = metX - pfc.px();
3614  double metYInt = metY - pfc.py();
3615  double sumetInt = sumet - pfc.pt();
3616  double met2Int = metXInt*metXInt+metYInt*metYInt;
3617  if ( met2Int < met2Cor ) {
3618  metXCor = metXInt;
3619  metYCor = metYInt;
3620  metReduc = (met2-met2Int)/met2Int;
3621  met2Cor = met2Int;
3622  sumetCor = sumetInt;
3623  significanceCor = std::sqrt(met2Cor/sumetCor);
3624  iCor = i;
3625  }
3626  }
3627  //
3628  // If the MET must be significanly reduced, schedule the candidate to be cleaned
3629  if ( metReduc > minDeltaMet_ ) {
3630  pfCandidatesToBeRemoved.push_back(iCor);
3631  metX = metXCor;
3632  metY = metYCor;
3633  sumet = sumetCor;
3634  met2 = met2Cor;
3635  } else {
3636  // Otherwise just stop the loop
3637  next = false;
3638  }
3639  }
3640  //
3641  // The significance must be significantly reduced to indeed clean the candidates
3642  if ( significance - significanceCor > minSignificanceReduction_ &&
3643  significanceCor < maxSignificance_ ) {
3644  std::cout << "Significance reduction = " << significance << " -> "
3645  << significanceCor << " = " << significanceCor - significance
3646  << std::endl;
3647  for(unsigned int toRemove : pfCandidatesToBeRemoved) {
3648  std::cout << "Removed : " << (*pfCandidates_)[toRemove] << std::endl;
3649  pfCleanedCandidates_->push_back( (*pfCandidates_)[toRemove] );
3650  (*pfCandidates_)[toRemove].rescaleMomentum(1E-6);
3651  //reco::PFCandidate::ParticleType unknown = reco::PFCandidate::X;
3652  //(*pfCandidates_)[toRemove].setParticleType(unknown);
3653  }
3654  }
3655  }
3656 
3657 }
double maxDeltaPhiPt_
Definition: PFAlgo.h:420
double maxSignificance_
Definition: PFAlgo.h:418
double minHFCleaningPt_
Definition: PFAlgo.h:416
double minDeltaMet_
Definition: PFAlgo.h:421
double minSignificance_
Definition: PFAlgo.h:417
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:286
double px() const final
x coordinate of momentum vector
double pt() const final
transverse momentum
double minSignificanceReduction_
Definition: PFAlgo.h:419
std::unique_ptr< reco::PFCandidateCollection > pfCleanedCandidates_
Definition: PFAlgo.h:292
bool postHFCleaning_
Definition: PFAlgo.h:414
T sqrt(T t)
Definition: SSEVec.h:18
double py() const final
y coordinate of momentum vector
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:40
virtual ParticleType particleId() const
Definition: PFCandidate.h:374
void PFAlgo::processBlock ( const reco::PFBlockRef blockref,
std::list< reco::PFBlockRef > &  hcalBlockRefs,
std::list< reco::PFBlockRef > &  ecalBlockRefs 
)
private

process one block. can be reimplemented in more sophisticated algorithms

Definition at line 530 of file PFAlgo.cc.

References a, funct::abs(), patPFMETCorrections_cff::algo, associatePSClusters(), b, reco::CaloCluster::badHcalMarker, edm::OwnVector< T, P >::begin(), groupFilesInBlocks::block, fftjetpileupestimator_calo_uncalib_cfi::c0, alignmentValidation::c1, calibration_, MessageLogger_cfi::cerr, reco::LeafCandidate::charge(), muons2muons_cfi::chargedHadron, trackerTree::check(), reco::TrackBase::conversionStep, gather_cfg::cout, debug_, dptRel_DispVtx_, reco::PFCandidate::e, RecoEcal_EventContent_cff::ec, ECAL, digitizers_cfi::ecal, reco::PFBlockElement::ECAL, RecoEcal_cff::ecalClusters, reco::PFCandidate::egammaExtraRef(), allElectronIsolations_cfi::elements, reco::PFCandidate::elementsInBlocks(), edm::OwnVector< T, P >::empty(), reco::LeafCandidate::energy(), PFTrackAlgoTools::errorScale(), PVValHelper::eta, reco::LeafCandidate::eta(), factors45_, plotBeamSpotDB::first, flags, dedxEstimators_cff::fraction, reco::PFCandidate::gamma, PFElectronAlgo::getAllElectronCandidates(), PFElectronAlgo::getElectronCandidates(), PFElectronAlgo::getElectronExtra(), 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_, reco::PFBlockElement::GSF, HCAL, digitizers_cfi::hcal, reco::PFBlockElement::HCAL, PFLayer::HF_EM, PFLayer::HF_HAD, reco::TrackBase::highPurity, photonIsolationHIProducer_cfi::ho, reco::PFBlockElement::HO, hcaldqm::constants::HO, mps_fire::i, cuy::ii, PFEGammaFilters::isElectron(), PFEGammaFilters::isElectronSafeForJetMET(), PFElectronAlgo::isElectronValidCandidate(), isFromSecInt(), PFMuonAlgo::isGlobalTightMuon(), PFMuonAlgo::isIsolatedMuon(), PFMuonAlgo::isLooseMuon(), PFMuonAlgo::isMuon(), edm::Ref< C, T, F >::isNonnull(), edm::Ref< C, T, F >::isNull(), PFEGammaFilters::isPhotonSafeForJetMET(), PFPhotonAlgo::isPhotonValidCandidate(), PFMuonAlgo::isTrackerTightMuon(), reco::PFBlock::LINKTEST_ALL, SiStripPI::max, min(), reco::PFCandidate::mu, muonECAL_, muonHCAL_, muonHO_, reco::PFCandidate::mva_e_pi(), neutralHadronEnergyResolution(), jets_cff::nMuons, nSigmaECAL_, nSigmaHCAL(), nSigmaTRACK_, nVtx_, convertSQLiteXML::ok, AlCaHLTBitMon_ParallelJobs::p, objects.autophobj::particleType, PFEGammaFilters::passElectronSelection(), PFEGammaFilters::passPhotonSelection(), pfCandidates_, pfegamma_, pfEgammaCandidates_, pfele_, pfElectronCandidates_, pfElectronExtra_, pfpho_, pfPhotonCandidates_, pfPhotonExtra_, reco::LeafCandidate::phi(), reco::Vertex::position(), primaryVertex_, reco::PFBlockElement::PS1, reco::PFBlockElement::PS2, reco::LeafCandidate::pt(), ptError_, edm::OwnVector< T, P >::push_back(), jets_cff::quality, reconstructCluster(), reconstructTrack(), edm::View< T >::refAt(), rejectTracks_Bad_, rejectTracks_Step45_, edm::second(), reco::PFCandidate::set_mva_e_pi(), reco::PFCandidate::set_mva_Isolated(), reco::PFCandidate::set_mva_nothing_gamma(), reco::LeafCandidate::setCharge(), reco::PFCandidate::setEcalEnergy(), setHcalDepthInfo(), reco::PFCandidate::setHcalEnergy(), reco::PFCandidate::setHoEnergy(), reco::LeafCandidate::setP4(), reco::PFCandidate::setParticleType(), reco::PFBlockElementTrack::setPositionAtECALEntrance(), reco::PFCandidate::setVertex(), edm::OwnVector< T, P >::size(), edm::View< T >::size(), createPayload::skip, mathSSE::sqrt(), PFTrackAlgoTools::step45(), PFTrackAlgoTools::step5(), reco::PFBlockElement::T_FROM_GAMMACONV, thepfEnergyCalibrationHF_, reco::PFBlockElement::TRACK, reco::btau::trackMomentum, funct::true, useEGammaFilters_, useHO_, usePFConversions_, usePFElectrons_, usePFPhotons_, useProtectionsForJetMET_, findQualityFiles::v, x, X, reco::Vertex::x(), DOFs::Y, reco::Vertex::y(), DOFs::Z, and reco::Vertex::z().

Referenced by reconstructParticles(), and thePFEnergyCalibration().

532  {
533 
534  // debug_ = false;
535  assert(!blockref.isNull() );
536  const reco::PFBlock& block = *blockref;
537 
538  if(debug_) {
539  cout<<"#########################################################"<<endl;
540  cout<<"##### Process Block: #####"<<endl;
541  cout<<"#########################################################"<<endl;
542  cout<<block<<endl;
543  }
544 
545 
546  const edm::OwnVector< reco::PFBlockElement >& elements = block.elements();
547  // make a copy of the link data, which will be edited.
548  PFBlock::LinkData linkData = block.linkData();
549 
550  // keep track of the elements which are still active.
551  vector<bool> active( elements.size(), true );
552 
553 
554  // //PFElectrons:
555  // usePFElectrons_ external configurable parameter to set the usage of pf electron
556  std::vector<reco::PFCandidate> tempElectronCandidates;
557  tempElectronCandidates.clear();
558  if (usePFElectrons_) {
559  if (pfele_->isElectronValidCandidate(blockref,active, primaryVertex_ )){
560  // if there is at least a valid candidate is get the vector of pfcandidates
561  const std::vector<reco::PFCandidate> PFElectCandidates_(pfele_->getElectronCandidates());
562  for(auto const& ec : PFElectCandidates_) tempElectronCandidates.push_back(ec);
563 
564  // (***) We're filling the ElectronCandidates into the PFCandiate collection
565  // ..... Once we let PFPhotonAlgo over-write electron-decision, we need to move this to
566  // ..... after the PhotonAlgo has run (Fabian)
567  }
568  // The vector active is automatically changed (it is passed by ref) in PFElectronAlgo
569  // for all the electron candidate
571  pfele_->getAllElectronCandidates().begin(),
573 
574  pfElectronExtra_.insert(pfElectronExtra_.end(),
575  pfele_->getElectronExtra().begin(),
576  pfele_->getElectronExtra().end());
577 
578  }
579  if( /* --- */ usePFPhotons_ /* --- */ ) {
580 
581  if(debug_)
582  cout<<endl<<"--------------- entering PFPhotonAlgo ----------------"<<endl;
583  vector<PFCandidatePhotonExtra> pfPhotonExtraCand;
584  if ( pfpho_->isPhotonValidCandidate(blockref, // passing the reference to the PFBlock
585  active, // std::vector<bool> containing information about acitivity
586  pfPhotonCandidates_, // pointer to candidate vector, to be filled by the routine
587  pfPhotonExtraCand, // candidate extra vector, to be filled by the routine
588  tempElectronCandidates
589  //pfElectronCandidates_ // pointer to some auziliary UNTOUCHED FOR NOW
590  ) ) {
591  if(debug_)
592  std::cout<< " In this PFBlock we found "<<pfPhotonCandidates_->size()<<" Photon Candidates."<<std::endl;
593 
594  // CAUTION: In case we want to allow the PhotonAlgo to 'over-write' what the ElectronAlgo did above
595  // ........ we should NOT fill the PFCandidate-vector with the electrons above (***)
596 
597  // Here we need to add all the photon cands to the pfCandidate list
598  unsigned int extracand =0;
599  for(auto const& cand : *pfPhotonCandidates_) {
600  pfCandidates_->push_back(cand);
601  pfPhotonExtra_.push_back(pfPhotonExtraCand[extracand]);
602  ++extracand;
603  }
604 
605  } // end of 'if' in case photons are found
606  pfPhotonExtraCand.clear();
607  pfPhotonCandidates_->clear();
608  } // end of Photon algo
609 
610  if (usePFElectrons_) {
611  for(auto const& ec : tempElectronCandidates) {
612  pfCandidates_->push_back(ec);
613  }
614  tempElectronCandidates.clear();
615  }
616 
617 
618  // New EGamma Reconstruction 10/10/2013
619  if(useEGammaFilters_) {
620 
621  // const edm::ValueMap<reco::GsfElectronRef> & myGedElectronValMap(*valueMapGedElectrons_);
622  bool egmLocalDebug = debug_;
623  bool egmLocalBlockDebug = false;
624 
625  unsigned int negmcandidates = pfEgammaCandidates_->size();
626  for(unsigned int ieg=0 ; ieg < negmcandidates; ++ieg) {
627  // const reco::PFCandidate & egmcand((*pfEgammaCandidates_)[ieg]);
629 
630  const PFCandidate::ElementsInBlocks& theElements = (*pfEgmRef).elementsInBlocks();
631  PFCandidate::ElementsInBlocks::const_iterator iegfirst = theElements.begin();
632  bool sameBlock = false;
633  bool isGoodElectron = false;
634  bool isGoodPhoton = false;
635  bool isPrimaryElectron = false;
636  if(iegfirst->first == blockref)
637  sameBlock = true;
638  if(sameBlock) {
639 
640  if(egmLocalDebug)
641  cout << " I am in looping on EGamma Candidates: pt " << (*pfEgmRef).pt()
642  << " eta,phi " << (*pfEgmRef).eta() << ", " << (*pfEgmRef).phi()
643  << " charge " << (*pfEgmRef).charge() << endl;
644 
645  if((*pfEgmRef).gsfTrackRef().isNonnull()) {
646 
647  reco::GsfElectronRef gedEleRef = (*valueMapGedElectrons_)[pfEgmRef];
648  if(gedEleRef.isNonnull()) {
649  isGoodElectron = pfegamma_->passElectronSelection(*gedEleRef,*pfEgmRef,nVtx_);
650  isPrimaryElectron = pfegamma_->isElectron(*gedEleRef);
651  if(egmLocalDebug){
652  if(isGoodElectron)
653  cout << "** Good Electron, pt " << gedEleRef->pt()
654  << " eta, phi " << gedEleRef->eta() << ", " << gedEleRef->phi()
655  << " charge " << gedEleRef->charge()
656  << " isPrimary " << isPrimaryElectron
657  << " isoDr03 " << (gedEleRef->dr03TkSumPt() + gedEleRef->dr03EcalRecHitSumEt() + gedEleRef->dr03HcalTowerSumEt())
658  << " mva_isolated " << gedEleRef->mva_Isolated()
659  << " mva_e_pi " << gedEleRef->mva_e_pi()
660  << endl;
661  }
662 
663 
664  }
665  }
666  if((*pfEgmRef).superClusterRef().isNonnull()) {
667 
668  reco::PhotonRef gedPhoRef = (*valueMapGedPhotons_)[pfEgmRef];
669  if(gedPhoRef.isNonnull()) {
670  isGoodPhoton = pfegamma_->passPhotonSelection(*gedPhoRef);
671  if(egmLocalDebug) {
672  if(isGoodPhoton)
673  cout << "** Good Photon, pt " << gedPhoRef->pt()
674  << " eta, phi " << gedPhoRef->eta() << ", " << gedPhoRef->phi() << endl;
675  }
676  }
677  }
678  } // end same block
679 
680  if(isGoodElectron && isGoodPhoton) {
681  if(isPrimaryElectron)
682  isGoodPhoton = false;
683  else
684  isGoodElectron = false;
685  }
686 
687  // isElectron
688  if(isGoodElectron) {
689  reco::GsfElectronRef gedEleRef = (*valueMapGedElectrons_)[pfEgmRef];
690  reco::PFCandidate myPFElectron = *pfEgmRef;
691  // run protections
692  bool lockTracks = false;
693  bool isSafe = true;
695  lockTracks = true;
696  isSafe = pfegamma_->isElectronSafeForJetMET(*gedEleRef,myPFElectron,primaryVertex_,lockTracks);
697  }
698 
699  if(isSafe) {
701  myPFElectron.setParticleType(particleType);
702  myPFElectron.setCharge(gedEleRef->charge());
703  myPFElectron.setP4(gedEleRef->p4());
704  myPFElectron.set_mva_e_pi(gedEleRef->mva_e_pi());
705  myPFElectron.set_mva_Isolated(gedEleRef->mva_Isolated());
706 
707  if(egmLocalDebug) {
708  cout << " PFAlgo: found an electron with NEW EGamma code " << endl;
709  cout << " myPFElectron: pt " << myPFElectron.pt()
710  << " eta,phi " << myPFElectron.eta() << ", " <<myPFElectron.phi()
711  << " mva " << myPFElectron.mva_e_pi()
712  << " charge " << myPFElectron.charge() << endl;
713  }
714 
715 
716  // Lock all the elements
717  if(egmLocalBlockDebug)
718  cout << " THE BLOCK " << *blockref << endl;
719  for (auto const& eb : theElements) {
720  active[eb.second] = false;
721  if(egmLocalBlockDebug||(debug_&&egmLocalDebug))
722  cout << " Elements used " << eb.second << endl;
723  }
724 
725  // The electron is considered safe for JetMET and the additional tracks pointing to it are locked
726  if(lockTracks) {
727  const PFCandidate::ElementsInBlocks& extraTracks = myPFElectron.egammaExtraRef()->extraNonConvTracks();
728  for (auto const& trk : extraTracks) {
729  if(egmLocalBlockDebug||(debug_&&egmLocalDebug)) {
730  cout << " Extra locked track " << trk.second << endl;
731  }
732  active[trk.second] = false;
733  }
734  }
735 
736  pfCandidates_->push_back(myPFElectron);
737 
738  }
739  else {
740  if(egmLocalDebug)
741  cout << "PFAlgo: Electron DISCARDED, NOT SAFE FOR JETMET " << endl;
742  }
743  }
744  if(isGoodPhoton) {
745  reco::PhotonRef gedPhoRef = (*valueMapGedPhotons_)[pfEgmRef];
746  reco::PFCandidate myPFPhoton = *pfEgmRef;
747  bool isSafe = true;
749  isSafe = pfegamma_->isPhotonSafeForJetMET(*gedPhoRef,myPFPhoton);
750  }
751 
752 
753 
754  if(isSafe) {
756  myPFPhoton.setParticleType(particleType);
757  myPFPhoton.setCharge(0);
758  myPFPhoton.set_mva_nothing_gamma(1.);
760  myPFPhoton.setVertex( v );
761  myPFPhoton.setP4(gedPhoRef->p4());
762  if(egmLocalDebug) {
763  cout << " PFAlgo: found a photon with NEW EGamma code " << endl;
764  cout << " myPFPhoton: pt " << myPFPhoton.pt()
765  << " eta,phi " << myPFPhoton.eta() << ", " <<myPFPhoton.phi()
766  << " charge " << myPFPhoton.charge() << endl;
767  }
768 
769  // Lock all the elements
770  if(egmLocalBlockDebug)
771  cout << " THE BLOCK " << *blockref << endl;
772  for (auto const& eb : theElements) {
773  active[eb.second] = false;
774  if(egmLocalBlockDebug||(debug_&&egmLocalDebug))
775  cout << " Elements used " << eb.second << endl;
776  }
777  pfCandidates_->push_back(myPFPhoton);
778 
779  } // end isSafe
780  } // end isGoodPhoton
781  } // end loop on EGM candidates
782  } // end if use EGammaFilters
783 
784 
785 
786  //Lock extra conversion tracks not used by Photon Algo
787  if (usePFConversions_ )
788  {
789  for(unsigned iEle=0; iEle<elements.size(); iEle++) {
790  PFBlockElement::Type type = elements[iEle].type();
791  if(type==PFBlockElement::TRACK)
792  {
793  if(elements[iEle].trackRef()->algo() == reco::TrackBase::conversionStep)
794  active[iEle]=false;
795  if(elements[iEle].trackRef()->quality(reco::TrackBase::highPurity))continue;
796  const auto* trackRef = dynamic_cast<const reco::PFBlockElementTrack*>((&elements[iEle]));
797  if(!(trackRef->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)))continue;
798  if(!elements[iEle].convRefs().empty())active[iEle]=false;
799  }
800  }
801  }
802 
803 
804 
805 
806 
807  if(debug_)
808  cout<<endl<<"--------------- loop 1 ------------------"<<endl;
809 
810  //COLINFEB16
811  // In loop 1, we loop on all elements.
812 
813  // The primary goal is to deal with tracks that are:
814  // - not associated to an HCAL cluster
815  // - not identified as an electron.
816  // Those tracks should be predominantly relatively low energy charged
817  // hadrons which are not detected in the ECAL.
818 
819  // The secondary goal is to prepare for the next loops
820  // - The ecal and hcal elements are sorted in separate vectors
821  // which will be used as a base for the corresponding loops.
822  // - For tracks which are connected to more than one HCAL cluster,
823  // the links between the track and the cluster are cut for all clusters
824  // but the closest one.
825  // - HF only blocks ( HFEM, HFHAD, HFEM+HFAD) are identified
826 
827  // obsolete comments?
828  // loop1:
829  // - sort ecal and hcal elements in separate vectors
830  // - for tracks:
831  // - lock closest ecal cluster
832  // - cut link to farthest hcal cluster, if more than 1.
833 
834  // vectors to store indices to ho, hcal and ecal elements
835  vector<unsigned> hcalIs;
836  vector<unsigned> hoIs;
837  vector<unsigned> ecalIs;
838  vector<unsigned> trackIs;
839  vector<unsigned> ps1Is;
840  vector<unsigned> ps2Is;
841 
842  vector<unsigned> hfEmIs;
843  vector<unsigned> hfHadIs;
844 
845  vector<bool> deadArea(elements.size(), false);
846 
847  for(unsigned iEle=0; iEle<elements.size(); iEle++) {
848  PFBlockElement::Type type = elements[iEle].type();
849 
850  if(debug_ && type != PFBlockElement::BREM ) cout<<endl<<elements[iEle];
851 
852  switch( type ) {
853  case PFBlockElement::TRACK:
854  if ( active[iEle] ) {
855  trackIs.push_back( iEle );
856  if(debug_) cout<<"TRACK, stored index, continue"<<endl;
857  }
858  break;
860  if ( active[iEle] ) {
861  ecalIs.push_back( iEle );
862  if(debug_) cout<<"ECAL, stored index, continue"<<endl;
863  }
864  continue;
866  if ( active[iEle] ) {
867  if (elements[iEle].clusterRef()->flags() & reco::CaloCluster::badHcalMarker) {
868  if(debug_) cout<<"HCAL DEAD AREA: remember and skip."<<endl;
869  active[iEle] = false;
870  deadArea[iEle] = true;
871  continue;
872  }
873  hcalIs.push_back( iEle );
874  if(debug_) cout<<"HCAL, stored index, continue"<<endl;
875  }
876  continue;
877  case PFBlockElement::HO:
878  if (useHO_) {
879  if ( active[iEle] ) {
880  hoIs.push_back( iEle );
881  if(debug_) cout<<"HO, stored index, continue"<<endl;
882  }
883  }
884  continue;
885  case PFBlockElement::HFEM:
886  if ( active[iEle] ) {
887  hfEmIs.push_back( iEle );
888  if(debug_) cout<<"HFEM, stored index, continue"<<endl;
889  }
890  continue;
891  case PFBlockElement::HFHAD:
892  if ( active[iEle] ) {
893  hfHadIs.push_back( iEle );
894  if(debug_) cout<<"HFHAD, stored index, continue"<<endl;
895  }
896  continue;
897  default:
898  continue;
899  }
900 
901  // we're now dealing with a track
902  unsigned iTrack = iEle;
903  reco::MuonRef muonRef = elements[iTrack].muonRef();
904  if (debug_ && muonRef.isNonnull()) {
905  cout << "track " << iTrack << " has a valid muon reference. " << std::endl;
906  cout << " - isMuon: " << PFMuonAlgo::isMuon(muonRef) << endl;
907  cout << " - isGlobalTightMuon: " << PFMuonAlgo::isGlobalTightMuon(muonRef) << endl;
908  cout << " - isTrackerTightMuon: " << PFMuonAlgo::isTrackerTightMuon(muonRef) << endl;
909  cout << " - isIsolatedMuon: " << PFMuonAlgo::isIsolatedMuon(muonRef) << endl;
910  }
911 
912  //Check if the track is a primary track of a secondary interaction
913  //If that is the case reconstruct a charged hadron noly using that
914  //track
915  if (active[iTrack] && isFromSecInt(elements[iEle], "primary")){
916  bool isPrimaryTrack = elements[iEle].displacedVertexRef(PFBlockElement::T_TO_DISP)->displacedVertexRef()->isTherePrimaryTracks();
917  if (isPrimaryTrack) {
918  if (debug_) cout << "Primary Track reconstructed alone" << endl;
919 
920  unsigned tmpi = reconstructTrack(elements[iEle]);
921  (*pfCandidates_)[tmpi].addElementInBlock( blockref, iEle );
922  active[iTrack] = false;
923  }
924  }
925 
926 
927  if(debug_) {
928  if ( !active[iTrack] )
929  cout << "Already used by electrons, muons, conversions" << endl;
930  }
931 
932  // Track already used as electron, muon, conversion?
933  // Added a check on the activated element
934  if ( ! active[iTrack] ) continue;
935 
936  reco::TrackRef trackRef = elements[iTrack].trackRef();
937  assert( !trackRef.isNull() );
938 
939  if (debug_ ) {
940  cout <<"PFAlgo:processBlock "<<" "<<trackIs.size()<<" "<<ecalIs.size()<<" "<<hcalIs.size()<<" "<<hoIs.size()<<endl;
941  }
942 
943  // look for associated elements of all types
944  //COLINFEB16
945  // all types of links are considered.
946  // the elements are sorted by increasing distance
947  std::multimap<double, unsigned> ecalElems;
948  block.associatedElements( iTrack, linkData,
949  ecalElems ,
952 
953  std::multimap<double, unsigned> hcalElems;
954  block.associatedElements( iTrack, linkData,
955  hcalElems,
958 
959  if (debug_ ) {
960  std::cout << "\tTrack " << iTrack << " is linked to " << ecalElems.size() << " ecal and " << hcalElems.size() << " hcal elements" << std::endl;
961  for (const auto & pair : ecalElems) {
962  std::cout << "ecal: dist " << pair.first << "\t elem " << pair.second << std::endl;
963  }
964  for (const auto & pair : hcalElems) {
965  std::cout << "hcal: dist " << pair.first << "\t elem " << pair.second << (deadArea[pair.second] ? " DEAD AREA MARKER" : "") << std::endl;
966  }
967  }
968  // there's 3 possible options possible here, in principle:
969  // 1) flag everything that may be associated to a dead hcal marker
970  // 2) flag everything whose closest hcal link is a dead hcal marker
971  // 3) flag only things that are linked only to dead hcal marker
972  // in our first test we go for (2)
973  //--- option (1) --
974  //bool hasDeadHcal = false;
975  //for (auto it = hcalElems.begin(), ed = hcalElems.end(); it != ed; /*NOTE NO ++it HERE */ ) {
976  // if (deadArea[it->second]) { hasDeadHcal = true; it = hcalElems.erase(it); } // std::multimap::erase returns iterator to next
977  // else ++it;
978  //}
979  //--- option (2) --
980  bool hasDeadHcal = false;
981  if (!hcalElems.empty() && deadArea[hcalElems.begin()->second]) {
982  hasDeadHcal = true;
983  hcalElems.clear();
984  }
985  //--- option (3) --
986  //bool hasDeadHcal = true;
987  //for (auto it = hcalElems.begin(), ed = hcalElems.end(); it != ed; /*NOTE NO ++it HERE */ ) {
988  // if (deadArea[it->second]) { it = hcalElems.erase(it); } // std::multimap::erase returns iterator to next
989  // else { hasDeadHcal = false; }
990  //}
991 
992  // for tracks with bad Hcal, check the quality
993  bool goodTrackDeadHcal = false;
994  if (hasDeadHcal) {
995  goodTrackDeadHcal = ( trackRef->ptError() < goodTrackDeadHcal_ptErrRel_ * trackRef->pt() &&
996  trackRef->normalizedChi2() < goodTrackDeadHcal_chi2n_ &&
997  trackRef->hitPattern().trackerLayersWithMeasurement() >= goodTrackDeadHcal_layers_ &&
998  trackRef->validFraction() > goodTrackDeadHcal_validFr_ &&
1000  // now we add an extra block for tracks at high |eta|
1001  if (!goodTrackDeadHcal &&
1002  std::abs(trackRef->eta()) > goodPixelTrackDeadHcal_minEta_ && // high eta
1003  trackRef->hitPattern().pixelLayersWithMeasurement() >= 3 && // pixel track
1004  trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS) == 0 &&
1005  trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_INNER_HITS) == 0 &&
1006  trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_OUTER_HITS) <= (
1007  trackRef->hitPattern().pixelLayersWithMeasurement() > 3 ?
1009  trackRef->normalizedChi2() < goodPixelTrackDeadHcal_chi2n_ && // tighter cut
1012  trackRef->ptError() < goodPixelTrackDeadHcal_ptErrRel_*trackRef->pt() && // sanity
1013  trackRef->pt() < goodPixelTrackDeadHcal_maxPt_) { // sanity
1014  goodTrackDeadHcal = true;
1015  // FIXME: may decide to do something to the track pT
1016  }
1017  //if (!goodTrackDeadHcal && trackRef->hitPattern().trackerLayersWithMeasurement() == 4 && trackRef->validFraction() == 1
1018  if (debug_) cout << " track pt " << trackRef->pt() << " +- " << trackRef->ptError()
1019  << " layers valid " << trackRef->hitPattern().trackerLayersWithMeasurement()
1020  << ", lost " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS)
1021  << ", lost outer " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_OUTER_HITS)
1022  << ", lost inner " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_INNER_HITS)
1023  << "(valid fraction " << trackRef->validFraction() << ")"
1024  << " chi2/ndf " << trackRef->normalizedChi2()
1025  << " |dxy| " << std::abs(trackRef->dxy(primaryVertex_.position())) << " +- " << trackRef->dxyError()
1026  << " |dz| " << std::abs(trackRef->dz(primaryVertex_.position())) << " +- " << trackRef->dzError()
1027  << (goodTrackDeadHcal ? " passes " : " fails ") << "quality cuts" << std::endl;
1028  }
1029 
1030  // When a track has no HCAL cluster linked, but another track is linked to the same
1031  // ECAL cluster and an HCAL cluster, link the track to the HCAL cluster for
1032  // later analysis
1033  if ( hcalElems.empty() && !ecalElems.empty() && !hasDeadHcal) {
1034  // debug_ = true;
1035  unsigned ntt = 1;
1036  unsigned index = ecalElems.begin()->second;
1037  std::multimap<double, unsigned> sortedTracks;
1038  block.associatedElements( index, linkData,
1039  sortedTracks,
1042  if (debug_ ) std::cout << "The closest ECAL cluster is linked to " << sortedTracks.size() << " tracks, with distance = " << ecalElems.begin()->first << std::endl;
1043 
1044  // Loop over all tracks
1045  for(auto const& trk : sortedTracks) {
1046  unsigned jTrack = trk.second;
1047  //std::cout << "Track " << jTrack << std::endl;
1048  // Track must be active
1049  if ( !active[jTrack] ) continue;
1050  //std::cout << "Active " << std::endl;
1051 
1052  // The loop is on the other tracks !
1053  if ( jTrack == iTrack ) continue;
1054  //std::cout << "A different track ! " << std::endl;
1055 
1056  // Check if the ECAL closest to this track is the current ECAL
1057  // Otherwise ignore this track in the neutral energy determination
1058  std::multimap<double, unsigned> sortedECAL;
1059  block.associatedElements( jTrack, linkData,
1060  sortedECAL,
1063  if ( sortedECAL.begin()->second != index ) continue;
1064  if (debug_ ) std::cout << " track " << jTrack << " with closest ECAL identical " << std::endl;
1065 
1066 
1067  // Check if this track is also linked to an HCAL
1068  std::multimap<double, unsigned> sortedHCAL;
1069  block.associatedElements( jTrack, linkData,
1070  sortedHCAL,
1073  if ( sortedHCAL.empty() ) continue;
1074  if (debug_ ) std::cout << " and with an HCAL cluster " << sortedHCAL.begin()->second << std::endl;
1075  ntt++;
1076 
1077  // In that case establish a link with the first track
1078  block.setLink( iTrack,
1079  sortedHCAL.begin()->second,
1080  sortedECAL.begin()->first,
1081  linkData,
1082  PFBlock::LINKTEST_RECHIT );
1083 
1084  } // End other tracks
1085 
1086  // Redefine HCAL elements
1087  block.associatedElements( iTrack, linkData,
1088  hcalElems,
1091 
1092  if ( debug_ && !hcalElems.empty() )
1093  std::cout << "Track linked back to HCAL due to ECAL sharing with other tracks" << std::endl;
1094  }
1095 
1096  //MICHELE
1097  //TEMPORARY SOLUTION FOR ELECTRON REJECTION IN PFTAU
1098  //COLINFEB16
1099  // in case particle flow electrons are not reconstructed,
1100  // the mva_e_pi of the charged hadron will be set to 1
1101  // if a GSF element is associated to the current TRACK element
1102  // This information will be used in the electron rejection for tau ID.
1103  std::multimap<double,unsigned> gsfElems;
1104  if (usePFElectrons_ == false) {
1105  block.associatedElements( iTrack, linkData,
1106  gsfElems ,
1108  }
1109  //
1110 
1111  if(hcalElems.empty() && debug_) {
1112  cout<<"no hcal element connected to track "<<iTrack<<endl;
1113  }
1114 
1115  // will now loop on associated elements ...
1116  // typedef std::multimap<double, unsigned>::iterator IE;
1117 
1118  bool hcalFound = false;
1119 
1120  if(debug_)
1121  cout<<"now looping on elements associated to the track"<<endl;
1122 
1123  // ... first on associated ECAL elements
1124  // Check if there is still a free ECAL for this track
1125  for(auto const& ecal : ecalElems) {
1126 
1127  unsigned index = ecal.second;
1128  // Sanity checks and optional printout
1129  PFBlockElement::Type type = elements[index].type();
1130  if(debug_) {
1131  double dist = ecal.first;
1132  cout<<"\telement "<<elements[index]<<" linked with distance = "<< dist <<endl;
1133  if ( ! active[index] ) cout << "This ECAL is already used - skip it" << endl;
1134  }
1135  assert( type == PFBlockElement::ECAL );
1136 
1137  // This ECAL is not free (taken by an electron?) - just skip it
1138  if ( ! active[index] ) continue;
1139 
1140  // Flag ECAL clusters for which the corresponding track is not linked to an HCAL cluster
1141 
1142  //reco::PFClusterRef clusterRef = elements[index].clusterRef();
1143  //assert( !clusterRef.isNull() );
1144  if( !hcalElems.empty() && debug_)
1145  cout<<"\t\tat least one hcal element connected to the track."
1146  <<" Sparing Ecal cluster for the hcal loop"<<endl;
1147 
1148  } //loop print ecal elements
1149 
1150 
1151  // tracks which are not linked to an HCAL
1152  // are reconstructed now.
1153 
1154  if( hcalElems.empty() ) {
1155 
1156  if ( debug_ )
1157  std::cout << "Now deals with tracks linked to no HCAL clusters. Was HCal active? " << (!hasDeadHcal) << std::endl;
1158  // vector<unsigned> elementIndices;
1159  // elementIndices.push_back(iTrack);
1160 
1161  // The track momentum
1162  double trackMomentum = elements[iTrack].trackRef()->p();
1163  if ( debug_ )
1164  std::cout << elements[iTrack] << std::endl;
1165 
1166  // Is it a "tight" muon ? In that case assume no
1167  //Track momentum corresponds to the calorimeter
1168  //energy for now
1169  bool thisIsAMuon = PFMuonAlgo::isMuon(elements[iTrack]);
1170  if ( thisIsAMuon ) trackMomentum = 0.;
1171 
1172  // If it is not a muon check if Is it a fake track ?
1173  //Michalis: I wonder if we should convert this to dpt/pt?
1174  bool rejectFake = false;
1175  if ( !thisIsAMuon && elements[iTrack].trackRef()->ptError() > ptError_ ) {
1176 
1177  double deficit = trackMomentum;
1178  double resol = neutralHadronEnergyResolution(trackMomentum,
1179  elements[iTrack].trackRef()->eta());
1180  resol *= trackMomentum;
1181 
1182  if ( !ecalElems.empty() ) {
1183  unsigned thisEcal = ecalElems.begin()->second;
1184  reco::PFClusterRef clusterRef = elements[thisEcal].clusterRef();
1185  bool useCluster = true;
1186  if (hasDeadHcal) {
1187  std::multimap<double, unsigned> sortedTracks;
1188  block.associatedElements( thisEcal, linkData,
1189  sortedTracks,
1192  useCluster = (sortedTracks.begin()->second == iTrack);
1193  }
1194  if (useCluster) {
1195  deficit -= clusterRef->energy();
1196  resol = neutralHadronEnergyResolution(trackMomentum,
1197  clusterRef->positionREP().Eta());
1198  resol *= trackMomentum;
1199  }
1200  }
1201 
1202  bool isPrimary = isFromSecInt(elements[iTrack], "primary");
1203 
1204  if ( deficit > nSigmaTRACK_*resol && !isPrimary && !goodTrackDeadHcal) {
1205  rejectFake = true;
1206  active[iTrack] = false;
1207  if ( debug_ )
1208  std::cout << elements[iTrack] << std::endl
1209  << " deficit " << deficit << " > " << nSigmaTRACK_ << " x " << resol
1210  << " track pt " << trackRef->pt() << " +- " << trackRef->ptError()
1211  << " layers valid " << trackRef->hitPattern().trackerLayersWithMeasurement()
1212  << ", lost " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS)
1213  << ", lost outer " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_OUTER_HITS)
1214  << ", lost inner " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_INNER_HITS)
1215  << "(valid fraction " << trackRef->validFraction() <<")"
1216  << " chi2/ndf " << trackRef->normalizedChi2()
1217  << " |dxy| " << std::abs(trackRef->dxy(primaryVertex_.position())) << " +- " << trackRef->dxyError()
1218  << " |dz| " << std::abs(trackRef->dz(primaryVertex_.position())) << " +- " << trackRef->dzError()
1219  << "is probably a fake (1) --> lock the track"
1220  << std::endl;
1221  }
1222  }
1223 
1224  if ( rejectFake ) continue;
1225 
1226  // Create a track candidate
1227  // unsigned tmpi = reconstructTrack( elements[iTrack] );
1228  //active[iTrack] = false;
1229  std::vector<unsigned> tmpi;
1230  std::vector<unsigned> kTrack;
1231 
1232  // Some cleaning : secondary tracks without calo's and large momentum must be fake
1233  double Dpt = trackRef->ptError();
1234 
1235  if ( rejectTracks_Step45_ && ecalElems.empty() &&
1236  trackMomentum > 30. && Dpt > 0.5 &&
1237  ( PFTrackAlgoTools::step45(trackRef->algo())
1238  && !goodTrackDeadHcal) ) {
1239 
1240  double dptRel = Dpt/trackRef->pt()*100;
1241  bool isPrimaryOrSecondary = isFromSecInt(elements[iTrack], "all");
1242 
1243  if ( isPrimaryOrSecondary && dptRel < dptRel_DispVtx_) continue;
1244  unsigned nHits = elements[iTrack].trackRef()->hitPattern().trackerLayersWithMeasurement();
1245  unsigned int NLostHit = trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS);
1246 
1247  if ( debug_ )
1248  std::cout << "A track (algo = " << trackRef->algo() << ") with momentum " << trackMomentum
1249  << " / " << elements[iTrack].trackRef()->pt() << " +/- " << Dpt
1250  << " / " << elements[iTrack].trackRef()->eta()
1251  << " without any link to ECAL/HCAL and with " << nHits << " (" << NLostHit
1252  << ") hits (lost hits) has been cleaned" << std::endl;
1253  active[iTrack] = false;
1254  continue;
1255  }
1256 
1257 
1258  tmpi.push_back(reconstructTrack( elements[iTrack]));
1259 
1260  kTrack.push_back(iTrack);
1261  active[iTrack] = false;
1262 
1263  // No ECAL cluster either ... continue...
1264  if ( ecalElems.empty() ) {
1265  (*pfCandidates_)[tmpi[0]].setEcalEnergy( 0., 0. );
1266  (*pfCandidates_)[tmpi[0]].setHcalEnergy( 0., 0. );
1267  (*pfCandidates_)[tmpi[0]].setHoEnergy( 0., 0. );
1268  (*pfCandidates_)[tmpi[0]].setPs1Energy( 0 );
1269  (*pfCandidates_)[tmpi[0]].setPs2Energy( 0 );
1270  (*pfCandidates_)[tmpi[0]].addElementInBlock( blockref, kTrack[0] );
1271  continue;
1272  }
1273 
1274  // Look for closest ECAL cluster
1275  const unsigned int thisEcal = ecalElems.begin()->second;
1276  reco::PFClusterRef clusterRef = elements[thisEcal].clusterRef();
1277  if ( debug_ ) std::cout << " is associated to " << elements[thisEcal] << std::endl;
1278 
1279 
1280  // Set ECAL energy for muons
1281  if ( thisIsAMuon ) {
1282  (*pfCandidates_)[tmpi[0]].setEcalEnergy( clusterRef->energy(),
1283  std::min(clusterRef->energy(), muonECAL_[0]) );
1284  (*pfCandidates_)[tmpi[0]].setHcalEnergy( 0., 0. );
1285  (*pfCandidates_)[tmpi[0]].setHoEnergy( 0., 0. );
1286  (*pfCandidates_)[tmpi[0]].setPs1Energy( 0 );
1287  (*pfCandidates_)[tmpi[0]].setPs2Energy( 0 );
1288  (*pfCandidates_)[tmpi[0]].addElementInBlock( blockref, kTrack[0] );
1289  }
1290 
1291  double slopeEcal = 1.;
1292  bool connectedToEcal = false;
1293  unsigned iEcal = 99999;
1294  double calibEcal = 0.;
1295  double calibHcal = 0.;
1296  double totalEcal = thisIsAMuon ? -muonECAL_[0] : 0.;
1297 
1298  // Consider charged particles closest to the same ECAL cluster
1299  std::multimap<double, unsigned> sortedTracks;
1300  block.associatedElements( thisEcal, linkData,
1301  sortedTracks,
1304  if (debug_) cout << "the closest ECAL cluster, id " << thisEcal << ", has " << sortedTracks.size() << " associated tracks, now processing them. " << endl;
1305 
1306  if (hasDeadHcal && !sortedTracks.empty()) {
1307  // GP: only allow the ecal cluster closest to this track to be considered
1308  if (debug_) cout << " the closest track to ECAL " << thisEcal << " is " << sortedTracks.begin()->second << " (distance " << sortedTracks.begin()->first << ")" << endl;
1309  if (sortedTracks.begin()->second != iTrack) {
1310  if (debug_) cout << " the closest track to ECAL " << thisEcal << " is " << sortedTracks.begin()->second << " which is not the one being processed. Will skip ECAL linking for this track" << endl;
1311  (*pfCandidates_)[tmpi[0]].setEcalEnergy( 0., 0. );
1312  (*pfCandidates_)[tmpi[0]].setHcalEnergy( 0., 0. );
1313  (*pfCandidates_)[tmpi[0]].setHoEnergy( 0., 0. );
1314  (*pfCandidates_)[tmpi[0]].setPs1Energy( 0 );
1315  (*pfCandidates_)[tmpi[0]].setPs2Energy( 0 );
1316  (*pfCandidates_)[tmpi[0]].addElementInBlock( blockref, kTrack[0] );
1317  continue;
1318  } else {
1319  if (debug_) cout << " the closest track to ECAL " << thisEcal << " is " << sortedTracks.begin()->second << " which is the one being processed. Will skip ECAL linking for all other track" << endl;
1320  sortedTracks.clear();
1321  }
1322  }
1323 
1324  for(auto const& trk : sortedTracks) {
1325  unsigned jTrack = trk.second;
1326 
1327  // Don't consider already used tracks
1328  if ( !active[jTrack] ) continue;
1329 
1330  // The loop is on the other tracks !
1331  if ( jTrack == iTrack ) continue;
1332 
1333  // Check if the ECAL cluster closest to this track is
1334  // indeed the current ECAL cluster. Only tracks not
1335  // linked to an HCAL cluster are considered here
1336  // (GP: this is because if there's a jTrack linked
1337  // to the same Ecal cluster and that also has an Hcal link
1338  // we would have also linked iTrack to that Hcal above)
1339  std::multimap<double, unsigned> sortedECAL;
1340  block.associatedElements( jTrack, linkData,
1341  sortedECAL,
1344  if ( sortedECAL.begin()->second != thisEcal ) continue;
1345 
1346  // Check if this track is a muon
1347  bool thatIsAMuon = PFMuonAlgo::isMuon(elements[jTrack]);
1348  if (debug_) {
1349  cout << " found track " << jTrack << (thatIsAMuon ? " (muon) " : " (non-muon)") << ", with distance = " << sortedECAL.begin()->first << std::endl;
1350  }
1351 
1352 
1353  // Check if this track is not a fake
1354  bool rejectFake = false;
1355  reco::TrackRef trackRef = elements[jTrack].trackRef();
1356  if ( !thatIsAMuon && trackRef->ptError() > ptError_) {
1357  // GP: FIXME this selection should be adapted depending on hasDeadHcal
1358  // but we don't know if jTrack is linked to a dead Hcal or not
1359  double deficit = trackMomentum + trackRef->p() - clusterRef->energy();
1360  double resol = nSigmaTRACK_*neutralHadronEnergyResolution(trackMomentum+trackRef->p(),
1361  clusterRef->positionREP().Eta());
1362  resol *= (trackMomentum+trackRef->p());
1363  if ( deficit > nSigmaTRACK_*resol && !goodTrackDeadHcal) {
1364  rejectFake = true;
1365  kTrack.push_back(jTrack);
1366  active[jTrack] = false;
1367  if ( debug_ )
1368  std::cout << elements[jTrack] << std::endl
1369  << "is probably a fake (2) --> lock the track"
1370  << "(trackMomentum = " << trackMomentum << ", clusterEnergy = " << clusterRef->energy() <<
1371  ", deficit = " << deficit << " > " << nSigmaTRACK_ << " x " << resol <<
1372  " assuming neutralHadronEnergyResolution " << neutralHadronEnergyResolution(trackMomentum+trackRef->p(), clusterRef->positionREP().Eta()) << ") "
1373  << std::endl;
1374  }
1375  }
1376  if ( rejectFake ) continue;
1377 
1378 
1379  // Otherwise, add this track momentum to the total track momentum
1380  /* */
1381  // reco::TrackRef trackRef = elements[jTrack].trackRef();
1382  if ( !thatIsAMuon ) {
1383  if ( debug_ )
1384  std::cout << "Track momentum increased from " << trackMomentum << " GeV ";
1385  trackMomentum += trackRef->p();
1386  if ( debug_ ) {
1387  std::cout << "to " << trackMomentum << " GeV." << std::endl;
1388  std::cout << "with " << elements[jTrack] << std::endl;
1389  }
1390  } else {
1391  totalEcal -= muonECAL_[0];
1392  totalEcal = std::max(totalEcal, 0.);
1393  }
1394 
1395  // And create a charged particle candidate !
1396 
1397  tmpi.push_back(reconstructTrack( elements[jTrack] ));
1398 
1399 
1400  kTrack.push_back(jTrack);
1401  active[jTrack] = false;
1402 
1403  if ( thatIsAMuon ) {
1404  (*pfCandidates_)[tmpi.back()].setEcalEnergy(clusterRef->energy(),
1405  std::min(clusterRef->energy(),muonECAL_[0]));
1406  (*pfCandidates_)[tmpi.back()].setHcalEnergy( 0., 0. );
1407  (*pfCandidates_)[tmpi.back()].setHoEnergy( 0., 0. );
1408  (*pfCandidates_)[tmpi.back()].setPs1Energy( 0 );
1409  (*pfCandidates_)[tmpi.back()].setPs2Energy( 0 );
1410  (*pfCandidates_)[tmpi.back()].addElementInBlock( blockref, kTrack.back() );
1411  }
1412  }
1413 
1414 
1415  if ( debug_ ) std::cout << "Loop over all associated ECAL clusters" << std::endl;
1416  // Loop over all ECAL linked clusters ordered by increasing distance.
1417  for(auto const& ecal : ecalElems)
1418  {
1419  const unsigned index = ecal.second;
1420  const PFBlockElement::Type type = elements[index].type();
1421  assert( type == PFBlockElement::ECAL );
1422  if ( debug_ ) std::cout << elements[index] << std::endl;
1423 
1424  // Just skip clusters already taken
1425  if ( debug_ && ! active[index] ) std::cout << "is not active - ignore " << std::endl;
1426  if ( ! active[index] ) continue;
1427 
1428  // Just skip this cluster if it's closer to another track
1429  block.associatedElements( index, linkData, sortedTracks,
1431 
1432  const bool skip = std::none_of(kTrack.begin(), kTrack.end(), [&](unsigned iTrack){
1433  return sortedTracks.begin()->second == iTrack;
1434  });
1435 
1436  if ( debug_ && skip ) std::cout << "is closer to another track - ignore " << std::endl;
1437  if ( skip ) continue;
1438 
1439  // The corresponding PFCluster and energy
1440  const reco::PFClusterRef clusterRef = elements[index].clusterRef();
1441  assert( !clusterRef.isNull() );
1442 
1443  if ( debug_ ) {
1444  std::cout <<"Ecal cluster with raw energy = " << clusterRef->energy()
1445  <<" linked with distance = " << ecal.first << std::endl;
1446  }
1447  //double dist = ie->first;
1448  //if ( !connectedToEcal && dist > 0.1 ) {
1449  //std::cout << "Warning - first ECAL cluster at a distance of " << dist << "from the closest track!" << std::endl;
1450  //cout<<"\telement "<<elements[index]<<" linked with distance = "<< dist <<endl;
1451  //cout<<"\telement "<<elements[iTrack]<<" linked with distance = "<< dist <<endl;
1452  //}
1453 
1454  // Check the presence of preshower clusters in the vicinity
1455  // Preshower cluster closer to another ECAL cluster are ignored.
1456  //JOSH: This should use the association map already produced by the cluster corrector for consistency,
1457  //but should be ok for now
1458  vector<double> ps1Ene{0.};
1459  associatePSClusters(index, reco::PFBlockElement::PS1, block, elements, linkData, active, ps1Ene);
1460  vector<double> ps2Ene{0.};
1461  associatePSClusters(index, reco::PFBlockElement::PS2, block, elements, linkData, active, ps2Ene);
1462 
1463  const double ecalEnergy = clusterRef->correctedEnergy();
1464  if ( debug_ ) std::cout << "Corrected ECAL(+PS) energy = " << ecalEnergy << std::endl;
1465 
1466  // Since the electrons were found beforehand, this track must be a hadron. Calibrate
1467  // the energy under the hadron hypothesis.
1468  totalEcal += ecalEnergy;
1469  const double previousCalibEcal = calibEcal;
1470  const double previousSlopeEcal = slopeEcal;
1471  calibEcal = std::max(totalEcal,0.);
1472  calibHcal = 0.;
1473  calibration_->energyEmHad( trackMomentum,calibEcal,calibHcal,
1474  clusterRef->positionREP().Eta(),
1475  clusterRef->positionREP().Phi() );
1476  if ( totalEcal > 0.) slopeEcal = calibEcal/totalEcal;
1477 
1478  if ( debug_ )
1479  std::cout << "The total calibrated energy so far amounts to = " << calibEcal << " (slope = " << slopeEcal << ")" << std::endl;
1480 
1481 
1482  // Stop the loop when adding more ECAL clusters ruins the compatibility
1483  if ( connectedToEcal && calibEcal - trackMomentum >= 0. ) {
1484  // if ( connectedToEcal && calibEcal - trackMomentum >=
1485  // nSigmaECAL_*neutralHadronEnergyResolution(trackMomentum,clusterRef->positionREP().Eta()) ) {
1486  calibEcal = previousCalibEcal;
1487  slopeEcal = previousSlopeEcal;
1488  totalEcal = calibEcal/slopeEcal;
1489 
1490  // Turn this last cluster in a photon
1491  // (The PS clusters are already locked in "associatePSClusters")
1492  active[index] = false;
1493 
1494  // Find the associated tracks
1495  std::multimap<double, unsigned> assTracks;
1496  block.associatedElements( index, linkData,
1497  assTracks,
1500 
1501  auto& ecalCand = (*pfCandidates_)[reconstructCluster( *clusterRef, ecalEnergy )];
1502  ecalCand.setEcalEnergy( clusterRef->energy(), ecalEnergy );
1503  ecalCand.setHcalEnergy( 0., 0. );
1504  ecalCand.setHoEnergy( 0., 0. );
1505  ecalCand.setPs1Energy( ps1Ene[0] );
1506  ecalCand.setPs2Energy( ps2Ene[0] );
1507  ecalCand.addElementInBlock( blockref, index );
1508  // Check that there is at least one track
1509  if(!assTracks.empty()) {
1510  ecalCand.addElementInBlock( blockref, assTracks.begin()->second );
1511 
1512  // Assign the position of the track at the ECAL entrance
1513  const ::math::XYZPointF& chargedPosition =
1514  dynamic_cast<const reco::PFBlockElementTrack*>(&elements[assTracks.begin()->second])->positionAtECALEntrance();
1515  ecalCand.setPositionAtECALEntrance(chargedPosition);
1516  }
1517  break;
1518  }
1519 
1520  // Lock used clusters.
1521  connectedToEcal = true;
1522  iEcal = index;
1523  active[index] = false;
1524  for (unsigned ic : tmpi) (*pfCandidates_)[ic].addElementInBlock( blockref, iEcal );
1525 
1526  } // Loop ecal elements
1527 
1528  bool bNeutralProduced = false;
1529 
1530  // Create a photon if the ecal energy is too large
1531  if( connectedToEcal ) {
1532  reco::PFClusterRef pivotalRef = elements[iEcal].clusterRef();
1533 
1534  double neutralEnergy = calibEcal - trackMomentum;
1535 
1536  /*
1537  // Check if there are other tracks linked to that ECAL
1538  for(IE ie = sortedTracks.begin(); ie != sortedTracks.end() && neutralEnergy > 0; ++ie ) {
1539  unsigned jTrack = ie->second;
1540 
1541  // The loop is on the other tracks !
1542  if ( jTrack == iTrack ) continue;
1543 
1544  // Check if the ECAL closest to this track is the current ECAL
1545  // Otherwise ignore this track in the neutral energy determination
1546  std::multimap<double, unsigned> sortedECAL;
1547  block.associatedElements( jTrack, linkData,
1548  sortedECAL,
1549  reco::PFBlockElement::ECAL,
1550  reco::PFBlock::LINKTEST_ALL );
1551  if ( sortedECAL.begin()->second != iEcal ) continue;
1552 
1553  // Check if this track is also linked to an HCAL
1554  // (in which case it goes to the next loop and is ignored here)
1555  std::multimap<double, unsigned> sortedHCAL;
1556  block.associatedElements( jTrack, linkData,
1557  sortedHCAL,
1558  reco::PFBlockElement::HCAL,
1559  reco::PFBlock::LINKTEST_ALL );
1560  if ( sortedHCAL.size() ) continue;
1561 
1562  // Otherwise, subtract this track momentum from the ECAL energy
1563  reco::TrackRef trackRef = elements[jTrack].trackRef();
1564  neutralEnergy -= trackRef->p();
1565 
1566  } // End other tracks
1567  */
1568 
1569  // Add a photon is the energy excess is large enough
1570  double resol = neutralHadronEnergyResolution(trackMomentum,pivotalRef->positionREP().Eta());
1571  resol *= trackMomentum;
1572  if ( neutralEnergy > std::max(0.5,nSigmaECAL_*resol) ) {
1573  neutralEnergy /= slopeEcal;
1574  unsigned tmpj = reconstructCluster( *pivotalRef, neutralEnergy );
1575  (*pfCandidates_)[tmpj].setEcalEnergy( pivotalRef->energy(), neutralEnergy );
1576  (*pfCandidates_)[tmpj].setHcalEnergy( 0., 0. );
1577  (*pfCandidates_)[tmpj].setHoEnergy( 0., 0. );
1578  (*pfCandidates_)[tmpj].setPs1Energy( 0. );
1579  (*pfCandidates_)[tmpj].setPs2Energy( 0. );
1580  (*pfCandidates_)[tmpj].addElementInBlock(blockref, iEcal);
1581  bNeutralProduced = true;
1582  for (unsigned ic=0; ic<kTrack.size();++ic)
1583  (*pfCandidates_)[tmpj].addElementInBlock( blockref, kTrack[ic] );
1584  } // End neutral energy
1585 
1586  // Set elements in blocks and ECAL energies to all tracks
1587  for (unsigned ic=0; ic<tmpi.size();++ic) {
1588 
1589  // Skip muons
1590  if ( (*pfCandidates_)[tmpi[ic]].particleId() == reco::PFCandidate::mu ) continue;
1591 
1592  double fraction = trackMomentum > 0 ? (*pfCandidates_)[tmpi[ic]].trackRef()->p()/trackMomentum : 0;
1593  double ecalCal = bNeutralProduced ?
1594  (calibEcal-neutralEnergy*slopeEcal)*fraction : calibEcal*fraction;
1595  double ecalRaw = totalEcal*fraction;
1596 
1597  if (debug_) cout << "The fraction after photon supression is " << fraction << " calibrated ecal = " << ecalCal << endl;
1598 
1599  (*pfCandidates_)[tmpi[ic]].setEcalEnergy( ecalRaw, ecalCal );
1600  (*pfCandidates_)[tmpi[ic]].setHcalEnergy( 0., 0. );
1601  (*pfCandidates_)[tmpi[ic]].setHoEnergy( 0., 0. );
1602  (*pfCandidates_)[tmpi[ic]].setPs1Energy( 0 );
1603  (*pfCandidates_)[tmpi[ic]].setPs2Energy( 0 );
1604  (*pfCandidates_)[tmpi[ic]].addElementInBlock( blockref, kTrack[ic] );
1605  }
1606 
1607  } // End connected ECAL
1608 
1609  // Fill the element_in_block for tracks that are eventually linked to no ECAL clusters at all.
1610  for (unsigned ic=0; ic<tmpi.size();++ic) {
1611  const PFCandidate& pfc = (*pfCandidates_)[tmpi[ic]];
1612  const PFCandidate::ElementsInBlocks& eleInBlocks = pfc.elementsInBlocks();
1613  if ( eleInBlocks.empty() ) {
1614  if ( debug_ )std::cout << "Single track / Fill element in block! " << std::endl;
1615  (*pfCandidates_)[tmpi[ic]].addElementInBlock( blockref, kTrack[ic] );
1616  }
1617  }
1618 
1619  } // end if( hcalElems.empty() )
1620 
1621 
1622  // In case several HCAL elements are linked to this track,
1623  // unlinking all of them except the closest.
1624  for(auto const& hcal : hcalElems) {
1625 
1626  unsigned index = hcal.second;
1627 
1628  PFBlockElement::Type type = elements[index].type();
1629 
1630  if(debug_) {
1631  double dist = block.dist(iTrack,index,linkData,reco::PFBlock::LINKTEST_ALL);
1632  cout<<"\telement "<<elements[index]<<" linked with distance "<< dist <<endl;
1633  }
1634 
1635  assert( type == PFBlockElement::HCAL );
1636 
1637  // all hcal clusters except the closest
1638  // will be unlinked from the track
1639  if( !hcalFound ) { // closest hcal
1640  if(debug_)
1641  cout<<"\t\tclosest hcal cluster, doing nothing"<<endl;
1642 
1643  hcalFound = true;
1644 
1645  // active[index] = false;
1646  // hcalUsed.push_back( index );
1647  }
1648  else { // other associated hcal
1649  // unlink from the track
1650  if(debug_)
1651  cout<<"\t\tsecondary hcal cluster. unlinking"<<endl;
1652  block.setLink( iTrack, index, -1., linkData,
1653  PFBlock::LINKTEST_RECHIT );
1654  }
1655  } //loop hcal elements
1656  } // end of loop 1 on elements iEle of any type
1657 
1658 
1659 
1660  // deal with HF.
1661  if( !(hfEmIs.empty() && hfHadIs.empty() ) ) {
1662  // there is at least one HF element in this block.
1663  // so all elements must be HF.
1664  assert( hfEmIs.size() + hfHadIs.size() == elements.size() );
1665 
1666  if( elements.size() == 1 ) {
1667  //Auguste: HAD-only calibration here
1668  reco::PFClusterRef clusterRef = elements[0].clusterRef();
1669  double energyHF = 0.;
1670  double uncalibratedenergyHF = 0.;
1671  unsigned tmpi = 0;
1672  switch( clusterRef->layer() ) {
1673  case PFLayer::HF_EM:
1674  // do EM-only calibration here
1675  energyHF = clusterRef->energy();
1676  uncalibratedenergyHF = energyHF;
1677  if(thepfEnergyCalibrationHF_->getcalibHF_use()==true){
1678  energyHF = thepfEnergyCalibrationHF_->energyEm(uncalibratedenergyHF,
1679  clusterRef->positionREP().Eta(),
1680  clusterRef->positionREP().Phi());
1681  }
1682  tmpi = reconstructCluster( *clusterRef, energyHF );
1683  (*pfCandidates_)[tmpi].setEcalEnergy( uncalibratedenergyHF, energyHF );
1684  (*pfCandidates_)[tmpi].setHcalEnergy( 0., 0.);
1685  (*pfCandidates_)[tmpi].setHoEnergy( 0., 0.);
1686  (*pfCandidates_)[tmpi].setPs1Energy( 0. );
1687  (*pfCandidates_)[tmpi].setPs2Energy( 0. );
1688  (*pfCandidates_)[tmpi].addElementInBlock( blockref, hfEmIs[0] );
1689  //std::cout << "HF EM alone ! " << energyHF << std::endl;
1690  break;
1691  case PFLayer::HF_HAD:
1692  // do HAD-only calibration here
1693  energyHF = clusterRef->energy();
1694  uncalibratedenergyHF = energyHF;
1695  if(thepfEnergyCalibrationHF_->getcalibHF_use()==true){
1696  energyHF = thepfEnergyCalibrationHF_->energyHad(uncalibratedenergyHF,
1697  clusterRef->positionREP().Eta(),
1698  clusterRef->positionREP().Phi());
1699  }
1700  tmpi = reconstructCluster( *clusterRef, energyHF );
1701  (*pfCandidates_)[tmpi].setHcalEnergy( uncalibratedenergyHF, energyHF );
1702  (*pfCandidates_)[tmpi].setEcalEnergy( 0., 0.);
1703  (*pfCandidates_)[tmpi].setHoEnergy( 0., 0.);
1704  (*pfCandidates_)[tmpi].setPs1Energy( 0. );
1705  (*pfCandidates_)[tmpi].setPs2Energy( 0. );
1706  (*pfCandidates_)[tmpi].addElementInBlock( blockref, hfHadIs[0] );
1707  //std::cout << "HF Had alone ! " << energyHF << std::endl;
1708  break;
1709  default:
1710  assert(0);
1711  }
1712  }
1713  else if( elements.size() == 2 ) {
1714  //Auguste: EM + HAD calibration here
1715  reco::PFClusterRef c0 = elements[0].clusterRef();
1716  reco::PFClusterRef c1 = elements[1].clusterRef();
1717  // 2 HF elements. Must be in each layer.
1718  reco::PFClusterRef cem = ( c0->layer() == PFLayer::HF_EM ? c0 : c1 );
1719  reco::PFClusterRef chad = ( c1->layer() == PFLayer::HF_HAD ? c1 : c0 );
1720 
1721  if( cem->layer() != PFLayer::HF_EM || chad->layer() != PFLayer::HF_HAD ) {
1722  cerr<<"Error: 2 elements, but not 1 HFEM and 1 HFHAD"<<endl;
1723  cerr<<block<<endl;
1724  assert(0);
1725 // assert( c1->layer()== PFLayer::HF_EM &&
1726 // c0->layer()== PFLayer::HF_HAD );
1727  }
1728  // do EM+HAD calibration here
1729  double energyHfEm = cem->energy();
1730  double energyHfHad = chad->energy();
1731  double uncalibratedenergyHFEm = energyHfEm;
1732  double uncalibratedenergyHFHad = energyHfHad;
1733  if(thepfEnergyCalibrationHF_->getcalibHF_use()==true){
1734 
1735  energyHfEm = thepfEnergyCalibrationHF_->energyEmHad(uncalibratedenergyHFEm,
1736  0.0,
1737  c0->positionREP().Eta(),
1738  c0->positionREP().Phi());
1739  energyHfHad = thepfEnergyCalibrationHF_->energyEmHad(0.0,
1740  uncalibratedenergyHFHad,
1741  c1->positionREP().Eta(),
1742  c1->positionREP().Phi());
1743  }
1744  auto& cand = (*pfCandidates_)[reconstructCluster( *chad, energyHfEm+energyHfHad )];
1745  cand.setEcalEnergy( uncalibratedenergyHFEm, energyHfEm );
1746  cand.setHcalEnergy( uncalibratedenergyHFHad, energyHfHad);
1747  cand.setHoEnergy( 0., 0.);
1748  cand.setPs1Energy( 0. );
1749  cand.setPs2Energy( 0. );
1750  cand.addElementInBlock( blockref, hfEmIs[0] );
1751  cand.addElementInBlock( blockref, hfHadIs[0] );
1752  //std::cout << "HF EM+HAD found ! " << energyHfEm << " " << energyHfHad << std::endl;
1753  }
1754  else {
1755  // 1 HF element in the block,
1756  // but number of elements not equal to 1 or 2
1757  cerr<<"Warning: HF, but n elem different from 1 or 2"<<endl;
1758  cerr<<block<<endl;
1759 // assert(0);
1760 // cerr<<"not ready for navigation in the HF!"<<endl;
1761  }
1762  }
1763 
1764 
1765 
1766  if(debug_) {
1767  cout<<endl;
1768  cout<<endl<<"--------------- loop hcal ---------------------"<<endl;
1769  }
1770 
1771  // track information:
1772  // trackRef
1773  // ecal energy
1774  // hcal energy
1775  // rescale
1776 
1777  for(unsigned iHcal : hcalIs) {
1778  PFBlockElement::Type type = elements[iHcal].type();
1779 
1780  assert( type == PFBlockElement::HCAL );
1781 
1782  if(debug_) cout<<endl<<elements[iHcal]<<endl;
1783 
1784  // vector<unsigned> elementIndices;
1785  // elementIndices.push_back(iHcal);
1786 
1787  // associated tracks
1788  std::multimap<double, unsigned> sortedTracks;
1789  block.associatedElements( iHcal, linkData,
1790  sortedTracks,
1793 
1794  std::multimap< unsigned, std::pair<double, unsigned> > associatedEcals;
1795 
1796  std::map< unsigned, std::pair<double, double> > associatedPSs;
1797 
1798  std::multimap<double, std::pair<unsigned,bool> > associatedTracks;
1799 
1800  // A temporary maps for ECAL satellite clusters
1801  std::multimap<double,std::pair<unsigned,::math::XYZVector> > ecalSatellites;
1802  std::pair<unsigned,::math::XYZVector> fakeSatellite(iHcal,::math::XYZVector(0.,0.,0.));
1803  ecalSatellites.emplace(-1., fakeSatellite);
1804 
1805  std::multimap< unsigned, std::pair<double, unsigned> > associatedHOs;
1806 
1807  PFClusterRef hclusterref = elements[iHcal].clusterRef();
1808  assert(!hclusterref.isNull() );
1809 
1810 
1811  //if there is no track attached to that HCAL, then do not
1812  //reconstruct an HCAL alone, check if it can be recovered
1813  //first
1814 
1815  // if no associated tracks, create a neutral hadron
1816  //if(sortedTracks.empty() ) {
1817 
1818  if( sortedTracks.empty() ) {
1819  if(debug_)
1820  cout<<"\tno associated tracks, keep for later"<<endl;
1821  continue;
1822  }
1823 
1824  // Lock the HCAL cluster
1825  active[iHcal] = false;
1826 
1827 
1828  // in the following, tracks are associated to this hcal cluster.
1829  // will look for an excess of energy in the calorimeters w/r to
1830  // the charged energy, and turn this excess into a neutral hadron or
1831  // a photon.
1832 
1833  if(debug_) cout<<"\t"<<sortedTracks.size()<<" associated tracks:"<<endl;
1834 
1835  double totalChargedMomentum = 0;
1836  double sumpError2 = 0.;
1837  double totalHO = 0.;
1838  double totalEcal = 0.;
1839  double totalHcal = hclusterref->energy();
1840  vector<double> hcalP;
1841  vector<double> hcalDP;
1842  vector<unsigned> tkIs;
1843  double maxDPovP = -9999.;
1844 
1845  //Keep track of how much energy is assigned to calorimeter-vs-track energy/momentum excess
1846  vector< unsigned > chargedHadronsIndices;
1847  vector< unsigned > chargedHadronsInBlock;
1848  double mergedNeutralHadronEnergy = 0;
1849  double mergedPhotonEnergy = 0;
1850  double muonHCALEnergy = 0.;
1851  double muonECALEnergy = 0.;
1852  double muonHCALError = 0.;
1853  double muonECALError = 0.;
1854  unsigned nMuons = 0;
1855 
1856 
1857  ::math::XYZVector photonAtECAL(0.,0.,0.);
1858  std::vector<std::pair<unsigned,::math::XYZVector> > ecalClusters;
1859  double sumEcalClusters=0;
1860  ::math::XYZVector hadronDirection(hclusterref->position().X(),
1861  hclusterref->position().Y(),
1862  hclusterref->position().Z());
1863  hadronDirection = hadronDirection.Unit();
1864  ::math::XYZVector hadronAtECAL = totalHcal * hadronDirection;
1865 
1866  // Loop over all tracks associated to this HCAL cluster
1867  for(auto const& trk : sortedTracks) {
1868 
1869  unsigned iTrack = trk.second;
1870 
1871  // Check the track has not already been used (e.g., in electrons, conversions...)
1872  if ( !active[iTrack] ) continue;
1873  // Sanity check 1
1874  PFBlockElement::Type type = elements[iTrack].type();
1875  assert( type == reco::PFBlockElement::TRACK );
1876  // Sanity check 2
1877  reco::TrackRef trackRef = elements[iTrack].trackRef();
1878  assert( !trackRef.isNull() );
1879 
1880  // The direction at ECAL entrance
1881  const ::math::XYZPointF& chargedPosition =
1882  dynamic_cast<const reco::PFBlockElementTrack*>(&elements[iTrack])->positionAtECALEntrance();
1883  ::math::XYZVector chargedDirection(chargedPosition.X(),chargedPosition.Y(),chargedPosition.Z());
1884  chargedDirection = chargedDirection.Unit();
1885 
1886  // look for ECAL elements associated to iTrack (associated to iHcal)
1887  std::multimap<double, unsigned> sortedEcals;
1888  block.associatedElements( iTrack, linkData,
1889  sortedEcals,
1892 
1893  if(debug_) cout<<"\t\t\tnumber of Ecal elements linked to this track: "
1894  <<sortedEcals.size()<<endl;
1895 
1896  // look for HO elements associated to iTrack (associated to iHcal)
1897  std::multimap<double, unsigned> sortedHOs;
1898  if (useHO_) {
1899  block.associatedElements( iTrack, linkData,
1900  sortedHOs,
1903 
1904  }
1905  if(debug_)
1906  cout<<"PFAlgo : number of HO elements linked to this track: "
1907  <<sortedHOs.size()<<endl;
1908 
1909  // Create a PF Candidate right away if the track is a tight muon
1910  reco::MuonRef muonRef = elements[iTrack].muonRef();
1911 
1912 
1913  bool thisIsAMuon = PFMuonAlgo::isMuon(elements[iTrack]);
1914  bool thisIsAnIsolatedMuon = PFMuonAlgo::isIsolatedMuon(elements[iTrack]);
1915  bool thisIsALooseMuon = false;
1916 
1917 
1918  if(!thisIsAMuon ) {
1919  thisIsALooseMuon = PFMuonAlgo::isLooseMuon(elements[iTrack]);
1920  }
1921 
1922 
1923  if ( thisIsAMuon ) {
1924  if ( debug_ ) {
1925  std::cout << "\t\tThis track is identified as a muon - remove it from the stack" << std::endl;
1926  std::cout << "\t\t" << elements[iTrack] << std::endl;
1927  }
1928 
1929  // Create a muon.
1930 
1931  unsigned tmpi = reconstructTrack( elements[iTrack] );
1932 
1933 
1934  (*pfCandidates_)[tmpi].addElementInBlock( blockref, iTrack );
1935  (*pfCandidates_)[tmpi].addElementInBlock( blockref, iHcal );
1936  double muonHcal = std::min(muonHCAL_[0]+muonHCAL_[1],totalHcal);
1937 
1938  // if muon is isolated and muon momentum exceeds the calo energy, absorb the calo energy
1939  // rationale : there has been a EM showering by the muon in the calorimeter - or the coil -
1940  // and we don't want to double count the energy
1941  bool letMuonEatCaloEnergy = false;
1942 
1943  if(thisIsAnIsolatedMuon){
1944  // The factor 1.3 is the e/pi factor in HCAL...
1945  double totalCaloEnergy = totalHcal / 1.30;
1946  unsigned iEcal = 0;
1947  if( !sortedEcals.empty() ) {
1948  iEcal = sortedEcals.begin()->second;
1949  PFClusterRef eclusterref = elements[iEcal].clusterRef();
1950  totalCaloEnergy += eclusterref->energy();
1951  }
1952 
1953  if (useHO_) {
1954  // The factor 1.3 is assumed to be the e/pi factor in HO, too.
1955  unsigned iHO = 0;
1956  if( !sortedHOs.empty() ) {
1957  iHO = sortedHOs.begin()->second;
1958  PFClusterRef eclusterref = elements[iHO].clusterRef();
1959  totalCaloEnergy += eclusterref->energy() / 1.30;
1960  }
1961  }
1962 
1963  // std::cout << "muon p / total calo = " << muonRef->p() << " " << (pfCandidates_->back()).p() << " " << totalCaloEnergy << std::endl;
1964  //if(muonRef->p() > totalCaloEnergy ) letMuonEatCaloEnergy = true;
1965  if( (pfCandidates_->back()).p() > totalCaloEnergy ) letMuonEatCaloEnergy = true;
1966  }
1967 
1968  if(letMuonEatCaloEnergy) muonHcal = totalHcal;
1969  double muonEcal =0.;
1970  unsigned iEcal = 0;
1971  if( !sortedEcals.empty() ) {
1972  iEcal = sortedEcals.begin()->second;
1973  PFClusterRef eclusterref = elements[iEcal].clusterRef();
1974  (*pfCandidates_)[tmpi].addElementInBlock( blockref, iEcal);
1975  muonEcal = std::min(muonECAL_[0]+muonECAL_[1],eclusterref->energy());
1976  if(letMuonEatCaloEnergy) muonEcal = eclusterref->energy();
1977  // If the muon expected energy accounts for the whole ecal cluster energy, lock the ecal cluster
1978  if ( eclusterref->energy() - muonEcal < 0.2 ) active[iEcal] = false;
1979  (*pfCandidates_)[tmpi].setEcalEnergy(eclusterref->energy(), muonEcal);
1980  }
1981  unsigned iHO = 0;
1982  double muonHO =0.;
1983  if (useHO_) {
1984  if( !sortedHOs.empty() ) {
1985  iHO = sortedHOs.begin()->second;
1986  PFClusterRef hoclusterref = elements[iHO].clusterRef();
1987  (*pfCandidates_)[tmpi].addElementInBlock( blockref, iHO);
1988  muonHO = std::min(muonHO_[0]+muonHO_[1],hoclusterref->energy());
1989  if(letMuonEatCaloEnergy) muonHO = hoclusterref->energy();
1990  // If the muon expected energy accounts for the whole HO cluster energy, lock the HO cluster
1991  if ( hoclusterref->energy() - muonHO < 0.2 ) active[iHO] = false;
1992  (*pfCandidates_)[tmpi].setHcalEnergy(totalHcal, muonHcal);
1993  (*pfCandidates_)[tmpi].setHoEnergy(hoclusterref->energy(), muonHO);
1994  }
1995  } else {
1996  (*pfCandidates_)[tmpi].setHcalEnergy(totalHcal, muonHcal);
1997  }
1998  setHcalDepthInfo((*pfCandidates_)[tmpi], *hclusterref);
1999 
2000  if(letMuonEatCaloEnergy){
2001  muonHCALEnergy += totalHcal;
2002  if (useHO_) muonHCALEnergy +=muonHO;
2003  muonHCALError += 0.;
2004  muonECALEnergy += muonEcal;
2005  muonECALError += 0.;
2006  photonAtECAL -= muonEcal*chargedDirection;
2007  hadronAtECAL -= totalHcal*chargedDirection;
2008  if ( !sortedEcals.empty() ) active[iEcal] = false;
2009  active[iHcal] = false;
2010  if (useHO_ && !sortedHOs.empty() ) active[iHO] = false;
2011  }
2012  else{
2013  // Estimate of the energy deposit & resolution in the calorimeters
2014  muonHCALEnergy += muonHCAL_[0];
2015  muonHCALError += muonHCAL_[1]*muonHCAL_[1];
2016  if ( muonHO > 0. ) {
2017  muonHCALEnergy += muonHO_[0];
2018  muonHCALError += muonHO_[1]*muonHO_[1];
2019  }
2020  muonECALEnergy += muonECAL_[0];
2021  muonECALError += muonECAL_[1]*muonECAL_[1];
2022  // ... as well as the equivalent "momentum" at ECAL entrance
2023  photonAtECAL -= muonECAL_[0]*chargedDirection;
2024  hadronAtECAL -= muonHCAL_[0]*chargedDirection;
2025  }
2026 
2027  // Remove it from the stack
2028  active[iTrack] = false;
2029  // Go to next track
2030  continue;
2031  }
2032 
2033  //
2034 
2035  if(debug_) cout<<"\t\t"<<elements[iTrack]<<endl;
2036 
2037  // introduce tracking errors
2038  double trackMomentum = trackRef->p();
2039  totalChargedMomentum += trackMomentum;
2040 
2041  // If the track is not a tight muon, but still resembles a muon
2042  // keep it for later for blocks with too large a charged energy
2043  if ( thisIsALooseMuon && !thisIsAMuon ) nMuons += 1;
2044 
2045  // ... and keep anyway the pt error for possible fake rejection
2046  // ... blow up errors of 5th anf 4th iteration, to reject those
2047  // ... tracks first (in case it's needed)
2048  double Dpt = trackRef->ptError();
2049  double blowError = PFTrackAlgoTools::errorScale(trackRef->algo(),factors45_);
2050  // except if it is from an interaction
2051  bool isPrimaryOrSecondary = isFromSecInt(elements[iTrack], "all");
2052 
2053  if ( isPrimaryOrSecondary ) blowError = 1.;
2054 
2055  std::pair<unsigned,bool> tkmuon(iTrack,thisIsALooseMuon);
2056  associatedTracks.emplace(-Dpt*blowError, tkmuon);
2057 
2058  // Also keep the total track momentum error for comparison with the calo energy
2059  double Dp = trackRef->qoverpError()*trackMomentum*trackMomentum;
2060  sumpError2 += Dp*Dp;
2061 
2062  bool connectedToEcal = false; // Will become true if there is at least one ECAL cluster connected
2063  if( !sortedEcals.empty() )
2064  { // start case: at least one ecal element associated to iTrack
2065 
2066  // Loop over all connected ECAL clusters
2067  for (auto const& ecal : sortedEcals) {
2068 
2069  unsigned iEcal = ecal.second;
2070  double dist = ecal.first;
2071 
2072  // Ignore ECAL cluters already used
2073  if( !active[iEcal] ) {
2074  if(debug_) cout<<"\t\tcluster locked"<<endl;
2075  continue;
2076  }
2077 
2078  // Sanity checks
2079  PFBlockElement::Type type = elements[ iEcal ].type();
2080  assert( type == PFBlockElement::ECAL );
2081  PFClusterRef eclusterref = elements[iEcal].clusterRef();
2082  assert(!eclusterref.isNull() );
2083 
2084  // Check if this ECAL is not closer to another track - ignore it in that case
2085  std::multimap<double, unsigned> sortedTracksEcal;
2086  block.associatedElements( iEcal, linkData,
2087  sortedTracksEcal,
2090  unsigned jTrack = sortedTracksEcal.begin()->second;
2091  if ( jTrack != iTrack ) continue;
2092 
2093  // double chi2Ecal = block.chi2(jTrack,iEcal,linkData,
2094  // reco::PFBlock::LINKTEST_ALL);
2095  double distEcal = block.dist(jTrack,iEcal,linkData,
2097 
2098  // totalEcal += eclusterref->energy();
2099  // float ecalEnergyUnCalibrated = eclusterref->energy();
2100  //std::cout << "Ecal Uncalibrated " << ecalEnergyUnCalibrated << std::endl;
2101 
2102  float ecalEnergyCalibrated = eclusterref->correctedEnergy();
2103  ::math::XYZVector photonDirection(eclusterref->position().X(),
2104  eclusterref->position().Y(),
2105  eclusterref->position().Z());
2106  photonDirection = photonDirection.Unit();
2107 
2108  if ( !connectedToEcal ) { // This is the closest ECAL cluster - will add its energy later
2109 
2110  if(debug_) cout<<"\t\t\tclosest: "
2111  <<elements[iEcal]<<endl;
2112 
2113  connectedToEcal = true;
2114  // PJ 1st-April-09 : To be done somewhere !!! (Had to comment it, but it is needed)
2115  // currentChargedHadron.addElementInBlock( blockref, iEcal );
2116 
2117  std::pair<unsigned,::math::XYZVector> satellite(iEcal,ecalEnergyCalibrated*photonDirection);
2118  ecalSatellites.emplace(-1., satellite);
2119 
2120  } else { // Keep satellite clusters for later
2121 
2122  std::pair<unsigned,::math::XYZVector> satellite(iEcal,ecalEnergyCalibrated*photonDirection);
2123  ecalSatellites.emplace(dist, satellite);
2124 
2125  }
2126 
2127  std::pair<double, unsigned> associatedEcal( distEcal, iEcal );
2128  associatedEcals.emplace(iTrack, associatedEcal);
2129 
2130  } // End loop ecal associated to iTrack
2131  } // end case: at least one ecal element associated to iTrack
2132 
2133  if( useHO_ && !sortedHOs.empty() )
2134  { // start case: at least one ho element associated to iTrack
2135 
2136  // Loop over all connected HO clusters
2137  for (auto const& ho : sortedHOs) {
2138 
2139  unsigned iHO = ho.second;
2140  double distHO = ho.first;
2141 
2142  // Ignore HO cluters already used
2143  if( !active[iHO] ) {
2144  if(debug_) cout<<"\t\tcluster locked"<<endl;
2145  continue;
2146  }
2147 
2148  // Sanity checks
2149  PFBlockElement::Type type = elements[ iHO ].type();
2150  assert( type == PFBlockElement::HO );
2151  PFClusterRef hoclusterref = elements[iHO].clusterRef();
2152  assert(!hoclusterref.isNull() );
2153 
2154  // Check if this HO is not closer to another track - ignore it in that case
2155  std::multimap<double, unsigned> sortedTracksHO;
2156  block.associatedElements( iHO, linkData,
2157  sortedTracksHO,
2160  unsigned jTrack = sortedTracksHO.begin()->second;
2161  if ( jTrack != iTrack ) continue;
2162 
2163  // double chi2HO = block.chi2(jTrack,iHO,linkData,
2164  // reco::PFBlock::LINKTEST_ALL);
2165  //double distHO = block.dist(jTrack,iHO,linkData,
2166  // reco::PFBlock::LINKTEST_ALL);
2167 
2168  // Increment the total energy by the energy of this HO cluster
2169  totalHO += hoclusterref->energy();
2170  active[iHO] = false;
2171  // Keep track for later reference in the PFCandidate.
2172  std::pair<double, unsigned> associatedHO( distHO, iHO );
2173  associatedHOs.emplace(iTrack, associatedHO);
2174 
2175  } // End loop ho associated to iTrack
2176  } // end case: at least one ho element associated to iTrack
2177 
2178 
2179  } // end loop on tracks associated to hcal element iHcal
2180 
2181  // Include totalHO in totalHCAL for the time being (it will be calibrated as HCAL energy)
2182  totalHcal += totalHO;
2183 
2184  // test compatibility between calo and tracker. //////////////
2185 
2186  double caloEnergy = 0.;
2187  double slopeEcal = 1.0;
2188  double calibEcal = 0.;
2189  double calibHcal = 0.;
2190  hadronDirection = hadronAtECAL.Unit();
2191 
2192  // Determine the expected calo resolution from the total charged momentum
2193  double Caloresolution = neutralHadronEnergyResolution( totalChargedMomentum, hclusterref->positionREP().Eta());
2194  Caloresolution *= totalChargedMomentum;
2195  // Account for muons
2196  Caloresolution = std::sqrt(Caloresolution*Caloresolution + muonHCALError + muonECALError);
2197  totalEcal -= std::min(totalEcal,muonECALEnergy);
2198  totalHcal -= std::min(totalHcal,muonHCALEnergy);
2199  if ( totalEcal < 1E-9 ) photonAtECAL = ::math::XYZVector(0.,0.,0.);
2200  if ( totalHcal < 1E-9 ) hadronAtECAL = ::math::XYZVector(0.,0.,0.);
2201 
2202  // Loop over all ECAL satellites, starting for the closest to the various tracks
2203  // and adding other satellites until saturation of the total track momentum
2204  // Note : for code simplicity, the first element of the loop is the HCAL cluster
2205  // with 0 energy in the ECAL
2206  for(auto const& ecalSatellite : ecalSatellites) {
2207 
2208  // Add the energy of this ECAL cluster
2209  double previousCalibEcal = calibEcal;
2210  double previousCalibHcal = calibHcal;
2211  double previousCaloEnergy = caloEnergy;
2212  double previousSlopeEcal = slopeEcal;
2213  ::math::XYZVector previousHadronAtECAL = hadronAtECAL;
2214  //
2215  totalEcal += sqrt(ecalSatellite.second.second.Mag2());
2216  photonAtECAL += ecalSatellite.second.second;
2217  calibEcal = std::max(0.,totalEcal);
2218  calibHcal = std::max(0.,totalHcal);
2219  hadronAtECAL = calibHcal * hadronDirection;
2220  // Calibrate ECAL and HCAL energy under the hadron hypothesis.
2221  calibration_->energyEmHad( totalChargedMomentum,calibEcal,calibHcal,
2222  hclusterref->positionREP().Eta(),
2223  hclusterref->positionREP().Phi() );
2224  caloEnergy = calibEcal+calibHcal;
2225  if ( totalEcal > 0.) slopeEcal = calibEcal/totalEcal;
2226 
2227  hadronAtECAL = calibHcal * hadronDirection;
2228 
2229  // Continue looping until all closest clusters are exhausted and as long as
2230  // the calorimetric energy does not saturate the total momentum.
2231  if ( ecalSatellite.first < 0. || caloEnergy - totalChargedMomentum <= 0. ) {
2232  if(debug_) std::cout << "\t\t\tactive, adding " << ecalSatellite.second.second
2233  << " to ECAL energy, and locking" << endl;
2234  active[ecalSatellite.second.first] = false;
2235  double clusterEnergy=sqrt(ecalSatellite.second.second.Mag2());
2236  if(clusterEnergy>50) {
2237  ecalClusters.push_back(ecalSatellite.second);
2238  sumEcalClusters+=clusterEnergy;
2239  }
2240  continue;
2241  }
2242 
2243  // Otherwise, do not consider the last cluster examined and exit.
2244  // active[ecalSatellite.second.first] = true;
2245  totalEcal -= sqrt(ecalSatellite.second.second.Mag2());
2246  photonAtECAL -= ecalSatellite.second.second;
2247  calibEcal = previousCalibEcal;
2248  calibHcal = previousCalibHcal;
2249  hadronAtECAL = previousHadronAtECAL;
2250  slopeEcal = previousSlopeEcal;
2251  caloEnergy = previousCaloEnergy;
2252 
2253  break;
2254 
2255  }
2256 
2257  // Sanity check !
2258  assert(caloEnergy>=0);
2259 
2260 
2261  // And now check for hadronic energy excess...
2262 
2263  //colin: resolution should be measured on the ecal+hcal case.
2264  // however, the result will be close.
2265  // double Caloresolution = neutralHadronEnergyResolution( caloEnergy );
2266  // Caloresolution *= caloEnergy;
2267  // PJ The resolution is on the expected charged calo energy !
2268  //double Caloresolution = neutralHadronEnergyResolution( totalChargedMomentum, hclusterref->positionREP().Eta());
2269  //Caloresolution *= totalChargedMomentum;
2270  // that of the charged particles linked to the cluster!
2271 
2272  /* */
2274  if ( totalChargedMomentum - caloEnergy > nSigmaTRACK_*Caloresolution ) {
2275 
2276  /*
2277  cout<<"\tCompare Calo Energy to total charged momentum "<<endl;
2278  cout<<"\t\tsum p = "<<totalChargedMomentum<<" +- "<<sqrt(sumpError2)<<endl;
2279  cout<<"\t\tsum ecal = "<<totalEcal<<endl;
2280  cout<<"\t\tsum hcal = "<<totalHcal<<endl;
2281  cout<<"\t\t => Calo Energy = "<<caloEnergy<<" +- "<<Caloresolution<<endl;
2282  cout<<"\t\t => Calo Energy- total charged momentum = "
2283  <<caloEnergy-totalChargedMomentum<<" +- "<<TotalError<<endl;
2284  cout<<endl;
2285  cout << "\t\tNumber/momentum of muons found in the block : " << nMuons << std::endl;
2286  */
2287  // First consider loose muons
2288  if ( nMuons > 0 ) {
2289  for(auto const& trk : associatedTracks) {
2290 
2291  // Only muons
2292  if ( !trk.second.second ) continue;
2293 
2294  const unsigned int iTrack = trk.second.first;
2295  // Only active tracks
2296  if ( !active[iTrack] ) continue;
2297 
2298  const double trackMomentum = elements[trk.second.first].trackRef()->p();
2299 
2300  // look for ECAL elements associated to iTrack (associated to iHcal)
2301  std::multimap<double, unsigned> sortedEcals;
2302  block.associatedElements( iTrack, linkData,
2303  sortedEcals,
2306  std::multimap<double, unsigned> sortedHOs;
2307  block.associatedElements( iTrack, linkData,
2308  sortedHOs,
2311 
2312  //Here allow for loose muons!
2313  auto& muon = (*pfCandidates_)[reconstructTrack( elements[iTrack],true)];
2314 
2315  muon.addElementInBlock( blockref, iTrack );
2316  muon.addElementInBlock( blockref, iHcal );
2317  const double muonHcal = std::min(muonHCAL_[0]+muonHCAL_[1],totalHcal-totalHO);
2318  double muonHO = 0.;
2319  muon.setHcalEnergy(totalHcal,muonHcal);
2320  if( !sortedEcals.empty() ) {
2321  const unsigned int iEcal = sortedEcals.begin()->second;
2322  PFClusterRef eclusterref = elements[iEcal].clusterRef();
2323  muon.addElementInBlock( blockref, iEcal);
2324  const double muonEcal = std::min(muonECAL_[0]+muonECAL_[1],eclusterref->energy());
2325  muon.setEcalEnergy(eclusterref->energy(),muonEcal);
2326  }
2327  if( useHO_ && !sortedHOs.empty() ) {
2328  const unsigned int iHO = sortedHOs.begin()->second;
2329  PFClusterRef hoclusterref = elements[iHO].clusterRef();
2330  muon.addElementInBlock( blockref, iHO);
2331  muonHO = std::min(muonHO_[0]+muonHO_[1],hoclusterref->energy());
2332  muon.setHcalEnergy(max(totalHcal-totalHO,0.0),muonHcal);
2333  muon.setHoEnergy(hoclusterref->energy(),muonHO);
2334  }
2335  setHcalDepthInfo(muon, *hclusterref);
2336  // Remove it from the block
2337  const ::math::XYZPointF& chargedPosition =
2338  dynamic_cast<const reco::PFBlockElementTrack*>(&elements[trk.second.first])->positionAtECALEntrance();
2339  ::math::XYZVector chargedDirection(chargedPosition.X(), chargedPosition.Y(), chargedPosition.Z());
2340  chargedDirection = chargedDirection.Unit();
2341  totalChargedMomentum -= trackMomentum;
2342  // Update the calo energies
2343  if ( totalEcal > 0. ) calibEcal -= std::min(calibEcal,muonECAL_[0]*calibEcal/totalEcal);
2344  if ( totalHcal > 0. ) calibHcal -= std::min(calibHcal,muonHCAL_[0]*calibHcal/totalHcal);
2345  totalEcal -= std::min(totalEcal,muonECAL_[0]);
2346  totalHcal -= std::min(totalHcal,muonHCAL_[0]);
2347  if ( totalEcal > muonECAL_[0] ) photonAtECAL -= muonECAL_[0] * chargedDirection;
2348  if ( totalHcal > muonHCAL_[0] ) hadronAtECAL -= muonHCAL_[0]*calibHcal/totalHcal * chargedDirection;
2349  caloEnergy = calibEcal + calibHcal;
2350  muonHCALEnergy += muonHCAL_[0];
2351  muonHCALError += muonHCAL_[1] * muonHCAL_[1];
2352  if ( muonHO > 0. ) {
2353  muonHCALEnergy += muonHO_[0];
2354  muonHCALError += muonHO_[1] * muonHO_[1];
2355  if ( totalHcal > 0. ) {
2356  calibHcal -= std::min(calibHcal,muonHO_[0] * calibHcal/totalHcal);
2357  totalHcal -= std::min(totalHcal,muonHO_[0]);
2358  }
2359  }
2360  muonECALEnergy += muonECAL_[0];
2361  muonECALError += muonECAL_[1] * muonECAL_[1];
2362  active[iTrack] = false;
2363  // Stop the loop whenever enough muons are removed
2364  //Commented out: Keep looking for muons since they often come in pairs -Matt
2365  //if ( totalChargedMomentum < caloEnergy ) break;
2366  }
2367  // New calo resolution.
2368  Caloresolution = neutralHadronEnergyResolution( totalChargedMomentum, hclusterref->positionREP().Eta());
2369  Caloresolution *= totalChargedMomentum;
2370  Caloresolution = std::sqrt(Caloresolution*Caloresolution + muonHCALError + muonECALError);
2371  }
2372  }
2373 
2374  if(debug_){
2375  cout<<"\tBefore Cleaning "<<endl;
2376  cout<<"\tCompare Calo Energy to total charged momentum "<<endl;
2377  cout<<"\t\tsum p = "<<totalChargedMomentum<<" +- "<<sqrt(sumpError2)<<endl;
2378  cout<<"\t\tsum ecal = "<<totalEcal<<endl;
2379  cout<<"\t\tsum hcal = "<<totalHcal<<endl;
2380  cout<<"\t\t => Calo Energy = "<<caloEnergy<<" +- "<<Caloresolution<<endl;
2381  cout<<"\t\t => Calo Energy- total charged momentum = "
2382  <<caloEnergy-totalChargedMomentum<<" +- "<<sqrt(sumpError2 + Caloresolution*Caloresolution)<<endl;
2383  cout<<endl;
2384  }
2385 
2386 
2387  // Second consider bad tracks (if still needed after muon removal)
2388  unsigned corrTrack = 10000000;
2389  double corrFact = 1.;
2390 
2391  if (rejectTracks_Bad_ && totalChargedMomentum - caloEnergy > nSigmaTRACK_*Caloresolution)
2392  {
2393  for(auto const& trk : associatedTracks)
2394  {
2395  const unsigned iTrack = trk.second.first;
2396  // Only active tracks
2397  if ( !active[iTrack] ) continue;
2398  const reco::TrackRef& trackref = elements[trk.second.first].trackRef();
2399 
2400  const double dptRel = fabs(trk.first)/trackref->pt()*100;
2401  const bool isSecondary = isFromSecInt(elements[iTrack], "secondary");
2402  const bool isPrimary = isFromSecInt(elements[iTrack], "primary");
2403 
2404  if ( isSecondary && dptRel < dptRel_DispVtx_ ) continue;
2405  // Consider only bad tracks
2406  if ( fabs(trk.first) < ptError_ ) break;
2407  // What would become the block charged momentum if this track were removed
2408  const double wouldBeTotalChargedMomentum = totalChargedMomentum - trackref->p();
2409  // Reject worst tracks, as long as the total charged momentum
2410  // is larger than the calo energy
2411 
2412  if ( wouldBeTotalChargedMomentum > caloEnergy ) {
2413  if (debug_ && isSecondary) {
2414  cout << "In bad track rejection step dptRel = " << dptRel << " dptRel_DispVtx_ = " << dptRel_DispVtx_ << endl;
2415  cout << "The calo energy would be still smaller even without this track but it is attached to a NI"<< endl;
2416  }
2417 
2418  if(isPrimary || (isSecondary && dptRel < dptRel_DispVtx_)) continue;
2419  active[iTrack] = false;
2420  totalChargedMomentum = wouldBeTotalChargedMomentum;
2421  if ( debug_ )
2422  std::cout << "\tElement " << elements[iTrack]
2423  << " rejected (Dpt = " << -trk.first
2424  << " GeV/c, algo = " << trackref->algo() << ")" << std::endl;
2425  // Just rescale the nth worst track momentum to equalize the calo energy
2426  } else {
2427  if(isPrimary) break;
2428  corrTrack = iTrack;
2429  corrFact = (caloEnergy - wouldBeTotalChargedMomentum)/elements[trk.second.first].trackRef()->p();
2430  if ( trackref->p()*corrFact < 0.05 ) {
2431  corrFact = 0.;
2432  active[iTrack] = false;
2433  }
2434  totalChargedMomentum -= trackref->p()*(1.-corrFact);
2435  if ( debug_ )
2436  std::cout << "\tElement " << elements[iTrack]
2437  << " (Dpt = " << -trk.first
2438  << " GeV/c, algo = " << trackref->algo()
2439  << ") rescaled by " << corrFact
2440  << " Now the total charged momentum is " << totalChargedMomentum << endl;
2441  break;
2442  }
2443  }
2444  }
2445 
2446  // New determination of the calo and track resolution avec track deletion/rescaling.
2447  Caloresolution = neutralHadronEnergyResolution( totalChargedMomentum, hclusterref->positionREP().Eta());
2448  Caloresolution *= totalChargedMomentum;
2449  Caloresolution = std::sqrt(Caloresolution*Caloresolution + muonHCALError + muonECALError);
2450 
2451  // Check if the charged momentum is still very inconsistent with the calo measurement.
2452  // In this case, just drop all tracks from 4th and 5th iteration linked to this block
2453 
2454  if ( rejectTracks_Step45_ &&
2455  sortedTracks.size() > 1 &&
2456  totalChargedMomentum - caloEnergy > nSigmaTRACK_*Caloresolution ) {
2457  for(auto const& trk : associatedTracks) {
2458  unsigned iTrack = trk.second.first;
2459  reco::TrackRef trackref = elements[iTrack].trackRef();
2460  if ( !active[iTrack] ) continue;
2461 
2462  double dptRel = fabs(trk.first)/trackref->pt()*100;
2463  bool isPrimaryOrSecondary = isFromSecInt(elements[iTrack], "all");
2464 
2465 
2466 
2467 
2468  if (isPrimaryOrSecondary && dptRel < dptRel_DispVtx_) continue;
2469 
2470  if (PFTrackAlgoTools::step5(trackref->algo())) {
2471  active[iTrack] = false;
2472  totalChargedMomentum -= trackref->p();
2473 
2474  if ( debug_ )
2475  std::cout << "\tElement " << elements[iTrack]
2476  << " rejected (Dpt = " << -trk.first
2477  << " GeV/c, algo = " << trackref->algo() << ")" << std::endl;
2478 
2479  }
2480  }
2481 
2482  }
2483 
2484  // New determination of the calo and track resolution avec track deletion/rescaling.
2485  Caloresolution = neutralHadronEnergyResolution( totalChargedMomentum, hclusterref->positionREP().Eta());
2486  Caloresolution *= totalChargedMomentum;
2487  Caloresolution = std::sqrt(Caloresolution*Caloresolution + muonHCALError + muonECALError);
2488 
2489  // Make PF candidates with the remaining tracks in the block
2490  sumpError2 = 0.;
2491  for(auto const& trk : associatedTracks) {
2492  unsigned iTrack = trk.second.first;
2493  if ( !active[iTrack] ) continue;
2494  reco::TrackRef trackRef = elements[iTrack].trackRef();
2495  double trackMomentum = trackRef->p();
2496  double Dp = trackRef->qoverpError()*trackMomentum*trackMomentum;
2497  unsigned tmpi = reconstructTrack( elements[iTrack] );
2498 
2499 
2500  (*pfCandidates_)[tmpi].addElementInBlock( blockref, iTrack );
2501  (*pfCandidates_)[tmpi].addElementInBlock( blockref, iHcal );
2502  setHcalDepthInfo((*pfCandidates_)[tmpi], *hclusterref);
2503  auto myEcals = associatedEcals.equal_range(iTrack);
2504  for (auto ii=myEcals.first; ii!=myEcals.second; ++ii ) {
2505  unsigned iEcal = ii->second.second;
2506  if ( active[iEcal] ) continue;
2507  (*pfCandidates_)[tmpi].addElementInBlock( blockref, iEcal );
2508  }
2509 
2510  if (useHO_) {
2511  auto myHOs = associatedHOs.equal_range(iTrack);
2512  for (auto ii=myHOs.first; ii!=myHOs.second; ++ii ) {
2513  unsigned iHO = ii->second.second;
2514  if ( active[iHO] ) continue;
2515  (*pfCandidates_)[tmpi].addElementInBlock( blockref, iHO );
2516  }
2517  }
2518 
2519  if ( iTrack == corrTrack ) {
2520  (*pfCandidates_)[tmpi].rescaleMomentum(corrFact);
2521  trackMomentum *= corrFact;
2522  }
2523  chargedHadronsIndices.push_back( tmpi );
2524  chargedHadronsInBlock.push_back( iTrack );
2525  active[iTrack] = false;
2526  hcalP.push_back(trackMomentum);
2527  hcalDP.push_back(Dp);
2528  if (Dp/trackMomentum > maxDPovP) maxDPovP = Dp/trackMomentum;
2529  sumpError2 += Dp*Dp;
2530  }
2531 
2532  // The total uncertainty of the difference Calo-Track
2533  double TotalError = sqrt(sumpError2 + Caloresolution*Caloresolution);
2534 
2535  if ( debug_ ) {
2536  cout<<"\tCompare Calo Energy to total charged momentum "<<endl;
2537  cout<<"\t\tsum p = "<<totalChargedMomentum<<" +- "<<sqrt(sumpError2)<<endl;
2538  cout<<"\t\tsum ecal = "<<totalEcal<<endl;
2539  cout<<"\t\tsum hcal = "<<totalHcal<<endl;
2540  cout<<"\t\t => Calo Energy = "<<caloEnergy<<" +- "<<Caloresolution<<endl;
2541  cout<<"\t\t => Calo Energy- total charged momentum = "
2542  <<caloEnergy-totalChargedMomentum<<" +- "<<TotalError<<endl;
2543  cout<<endl;
2544  }
2545 
2546  /* */
2547 
2549  double nsigma = nSigmaHCAL(totalChargedMomentum,hclusterref->positionREP().Eta());
2550  //double nsigma = nSigmaHCAL(caloEnergy,hclusterref->positionREP().Eta());
2551  if ( abs(totalChargedMomentum-caloEnergy)<nsigma*TotalError ) {
2552 
2553  // deposited caloEnergy compatible with total charged momentum
2554  // if tracking errors are large take weighted average
2555 
2556  if(debug_) {
2557  cout<<"\t\tcase 1: COMPATIBLE "
2558  <<"|Calo Energy- total charged momentum| = "
2559  <<abs(caloEnergy-totalChargedMomentum)
2560  <<" < "<<nsigma<<" x "<<TotalError<<endl;
2561  if (maxDPovP < 0.1 )
2562  cout<<"\t\t\tmax DP/P = "<< maxDPovP
2563  <<" less than 0.1: do nothing "<<endl;
2564  else
2565  cout<<"\t\t\tmax DP/P = "<< maxDPovP
2566  <<" > 0.1: take weighted averages "<<endl;
2567  }
2568 
2569  // if max DP/P < 10% do nothing
2570  if (maxDPovP > 0.1) {
2571 
2572  // for each track associated to hcal
2573  // int nrows = tkIs.size();
2574  int nrows = chargedHadronsIndices.size();
2575  TMatrixTSym<double> a (nrows);
2576  TVectorD b (nrows);
2577  TVectorD check(nrows);
2578  double sigma2E = Caloresolution*Caloresolution;
2579  for(int i=0; i<nrows; i++) {
2580  double sigma2i = hcalDP[i]*hcalDP[i];
2581  if (debug_){
2582  cout<<"\t\t\ttrack associated to hcal "<<i
2583  <<" P = "<<hcalP[i]<<" +- "
2584  <<hcalDP[i]<<endl;
2585  }
2586  a(i,i) = 1./sigma2i + 1./sigma2E;
2587  b(i) = hcalP[i]/sigma2i + caloEnergy/sigma2E;
2588  for(int j=0; j<nrows; j++) {
2589  if (i==j) continue;
2590  a(i,j) = 1./sigma2E;
2591  } // end loop on j
2592  } // end loop on i
2593 
2594  // solve ax = b
2595  //if (debug_){// debug1
2596  //cout<<" matrix a(i,j) "<<endl;
2597  //a.Print();
2598  //cout<<" vector b(i) "<<endl;
2599  //b.Print();
2600  //} // debug1
2601  TDecompChol decomp(a);
2602  bool ok = false;
2603  TVectorD x = decomp.Solve(b, ok);
2604  // for each track create a PFCandidate track
2605  // with a momentum rescaled to weighted average
2606  if (ok) {
2607  for (int i=0; i<nrows; i++){
2608  // unsigned iTrack = trackInfos[i].index;
2609  unsigned ich = chargedHadronsIndices[i];
2610  double rescaleFactor = x(i)/hcalP[i];
2611  (*pfCandidates_)[ich].rescaleMomentum( rescaleFactor );
2612 
2613  if(debug_){
2614  cout<<"\t\t\told p "<<hcalP[i]
2615  <<" new p "<<x(i)
2616  <<" rescale "<<rescaleFactor<<endl;
2617  }
2618  }
2619  }
2620  else {
2621  cerr<<"not ok!"<<endl;
2622  assert(0);
2623  }
2624  }
2625  }
2626 
2628  else if( caloEnergy > totalChargedMomentum ) {
2629 
2630  //case 2: caloEnergy > totalChargedMomentum + nsigma*TotalError
2631  //there is an excess of energy in the calos
2632  //create a neutral hadron or a photon
2633 
2634  /*
2635  //If it's isolated don't create neutrals since the energy deposit is always coming from a showering muon
2636  bool thisIsAnIsolatedMuon = false;
2637  for(IE ie = sortedTracks.begin(); ie != sortedTracks.end(); ++ie ) {
2638  unsigned iTrack = ie->second;
2639  if(PFMuonAlgo::isIsolatedMuon(elements[iTrack].muonRef())) thisIsAnIsolatedMuon = true;
2640  }
2641 
2642  if(thisIsAnIsolatedMuon){
2643  if(debug_)cout<<" Not looking for neutral b/c this is an isolated muon "<<endl;
2644  break;
2645  }
2646  */
2647  double eNeutralHadron = caloEnergy - totalChargedMomentum;
2648  double ePhoton = (caloEnergy - totalChargedMomentum) / slopeEcal;
2649 
2650  if(debug_) {
2651  if(!sortedTracks.empty() ){
2652  cout<<"\t\tcase 2: NEUTRAL DETECTION "
2653  <<caloEnergy<<" > "<<nsigma<<"x"<<TotalError
2654  <<" + "<<totalChargedMomentum<<endl;
2655  cout<<"\t\tneutral activity detected: "<<endl
2656  <<"\t\t\t photon = "<<ePhoton<<endl
2657  <<"\t\t\tor neutral hadron = "<<eNeutralHadron<<endl;
2658 
2659  cout<<"\t\tphoton or hadron ?"<<endl;}
2660 
2661  if(sortedTracks.empty() )
2662  cout<<"\t\tno track -> hadron "<<endl;
2663  else
2664  cout<<"\t\t"<<sortedTracks.size()
2665  <<" tracks -> check if the excess is photonic or hadronic"<<endl;
2666  }
2667 
2668 
2669  double ratioMax = 0.;
2670  reco::PFClusterRef maxEcalRef;
2671  unsigned maxiEcal= 9999;
2672 
2673  // for each track associated to hcal: iterator IE ie :
2674 
2675  for(auto const& trk : sortedTracks) {
2676 
2677  unsigned iTrack = trk.second;
2678 
2679  PFBlockElement::Type type = elements[iTrack].type();
2680  assert( type == reco::PFBlockElement::TRACK );
2681 
2682  reco::TrackRef trackRef = elements[iTrack].trackRef();
2683  assert( !trackRef.isNull() );
2684 
2685  auto iae = associatedEcals.find(iTrack);
2686 
2687  if( iae == associatedEcals.end() ) continue;
2688 
2689  // double distECAL = iae->second.first;
2690  unsigned iEcal = iae->second.second;
2691 
2692  PFBlockElement::Type typeEcal = elements[iEcal].type();
2693  assert(typeEcal == reco::PFBlockElement::ECAL);
2694 
2695  reco::PFClusterRef clusterRef = elements[iEcal].clusterRef();
2696  assert( !clusterRef.isNull() );
2697 
2698  double pTrack = trackRef->p();
2699  double eECAL = clusterRef->energy();
2700  double eECALOverpTrack = eECAL / pTrack;
2701 
2702  if ( eECALOverpTrack > ratioMax ) {
2703  ratioMax = eECALOverpTrack;
2704  maxEcalRef = clusterRef;
2705  maxiEcal = iEcal;
2706  }
2707 
2708  } // end loop on tracks associated to hcal: iterator IE ie
2709 
2710  std::vector<reco::PFClusterRef> pivotalClusterRef;
2711  std::vector<unsigned> iPivotal;
2712  std::vector<double> particleEnergy, ecalEnergy, hcalEnergy, rawecalEnergy, rawhcalEnergy;
2713  std::vector<::math::XYZVector> particleDirection;
2714 
2715  // If the excess is smaller than the ecal energy, assign the whole
2716  // excess to photons
2717  if ( ePhoton < totalEcal || eNeutralHadron-calibEcal < 1E-10 ) {
2718  if ( !maxEcalRef.isNull() ) {
2719  // So the merged photon energy is,
2720  mergedPhotonEnergy = ePhoton;
2721  }
2722  } else {
2723  // Otherwise assign the whole ECAL energy to the photons
2724  if ( !maxEcalRef.isNull() ) {
2725  // So the merged photon energy is,
2726  mergedPhotonEnergy = totalEcal;
2727  }
2728  // ... and assign the remaining excess to neutral hadrons using the direction of ecal clusters
2729  mergedNeutralHadronEnergy = eNeutralHadron-calibEcal;
2730  }
2731 
2732  if ( mergedPhotonEnergy > 0 ) {
2733  // Split merged photon into photons for each energetic ecal cluster (necessary for jet substructure reconstruction)
2734  // make only one merged photon if less than 2 ecal clusters
2735  if ( ecalClusters.size()<=1 ) {
2736  ecalClusters.clear();
2737  ecalClusters.emplace_back(maxiEcal, photonAtECAL);
2738  sumEcalClusters=sqrt(photonAtECAL.Mag2());
2739  }
2740  for(auto const& pae : ecalClusters) {
2741  const double clusterEnergy=sqrt(pae.second.Mag2());
2742  particleEnergy.push_back(mergedPhotonEnergy*clusterEnergy/sumEcalClusters);
2743  particleDirection.push_back(pae.second);
2744  ecalEnergy.push_back(mergedPhotonEnergy*clusterEnergy/sumEcalClusters);
2745  hcalEnergy.push_back(0.);
2746  rawecalEnergy.push_back(totalEcal);
2747  rawhcalEnergy.push_back(totalHcal);
2748  pivotalClusterRef.push_back(elements[pae.first].clusterRef());
2749  iPivotal.push_back(pae.first);
2750  }
2751  }
2752 
2753  if ( mergedNeutralHadronEnergy > 1.0 ) {
2754  // Split merged neutral hadrons according to directions of energetic ecal clusters (necessary for jet substructure reconstruction)
2755  // make only one merged neutral hadron if less than 2 ecal clusters
2756  if ( ecalClusters.size()<=1 ) {
2757  ecalClusters.clear();
2758  ecalClusters.emplace_back(iHcal, hadronAtECAL);
2759  sumEcalClusters=sqrt(hadronAtECAL.Mag2());
2760  }
2761  for(auto const& pae : ecalClusters) {
2762  const double clusterEnergy=sqrt(pae.second.Mag2());
2763  particleEnergy.push_back(mergedNeutralHadronEnergy*clusterEnergy/sumEcalClusters);
2764  particleDirection.push_back(pae.second);
2765  ecalEnergy.push_back(0.);
2766  hcalEnergy.push_back(mergedNeutralHadronEnergy*clusterEnergy/sumEcalClusters);
2767  rawecalEnergy.push_back(totalEcal);
2768  rawhcalEnergy.push_back(totalHcal);
2769  pivotalClusterRef.push_back(hclusterref);
2770  iPivotal.push_back(iHcal);
2771  }
2772  }
2773 
2774  // reconstructing a merged neutral
2775  // the type of PFCandidate is known from the
2776  // reference to the pivotal cluster.
2777 
2778  for ( unsigned iPivot=0; iPivot<iPivotal.size(); ++iPivot ) {
2779 
2780  if ( particleEnergy[iPivot] < 0. )
2781  std::cout << "ALARM = Negative energy ! "
2782  << particleEnergy[iPivot] << std::endl;
2783 
2784  const bool useDirection = true;
2785  auto& neutral = (*pfCandidates_)[reconstructCluster( *pivotalClusterRef[iPivot],
2786  particleEnergy[iPivot],
2787  useDirection,
2788  particleDirection[iPivot].X(),
2789  particleDirection[iPivot].Y(),
2790  particleDirection[iPivot].Z() )];
2791 
2792 
2793  neutral.setEcalEnergy( rawecalEnergy[iPivot],ecalEnergy[iPivot] );
2794  if ( !useHO_ ) {
2795  neutral.setHcalEnergy( rawhcalEnergy[iPivot],hcalEnergy[iPivot] );
2796  neutral.setHoEnergy(0., 0.);
2797  } else {
2798  neutral.setHcalEnergy( max(rawhcalEnergy[iPivot]-totalHO,0.0),hcalEnergy[iPivot]*(1.-totalHO/rawhcalEnergy[iPivot]));
2799  neutral.setHoEnergy(totalHO, totalHO * hcalEnergy[iPivot]/rawhcalEnergy[iPivot]);
2800  }
2801  neutral.setPs1Energy( 0. );
2802  neutral.setPs2Energy( 0. );
2803  neutral.set_mva_nothing_gamma( -1. );
2804  // neutral.addElement(&elements[iPivotal]);
2805  // neutral.addElementInBlock(blockref, iPivotal[iPivot]);
2806  neutral.addElementInBlock( blockref, iHcal );
2807  for (unsigned iTrack : chargedHadronsInBlock) {
2808  neutral.addElementInBlock( blockref, iTrack );
2809  // Assign the position of the track at the ECAL entrance
2810  const ::math::XYZPointF& chargedPosition =
2811  dynamic_cast<const reco::PFBlockElementTrack*>(&elements[iTrack])->positionAtECALEntrance();
2812  neutral.setPositionAtECALEntrance(chargedPosition);
2813 
2814  auto myEcals = associatedEcals.equal_range(iTrack);
2815  for (auto ii=myEcals.first; ii!=myEcals.second; ++ii ) {
2816  unsigned iEcal = ii->second.second;
2817  if ( active[iEcal] ) continue;
2818  neutral.addElementInBlock( blockref, iEcal );
2819  }
2820  }
2821 
2822  }
2823 
2824  } // excess of energy
2825 
2826 
2827  // will now share the hcal energy between the various charged hadron
2828  // candidates, taking into account the potential neutral hadrons
2829 
2830  double totalHcalEnergyCalibrated = calibHcal;
2831  double totalEcalEnergyCalibrated = calibEcal;
2832  //JB: The question is: we've resolved the merged photons cleanly, but how should
2833  //the remaining hadrons be assigned the remaining ecal energy?
2834  //*Temporary solution*: follow HCAL example with fractions...
2835 
2836  /*
2837  if(totalEcal>0) {
2838  // removing ecal energy from abc calibration
2839  totalHcalEnergyCalibrated -= calibEcal;
2840  // totalHcalEnergyCalibrated -= calibration_->paramECALplusHCAL_slopeECAL() * totalEcal;
2841  }
2842  */
2843  // else caloEnergy = hcal only calibrated energy -> ok.
2844 
2845  // remove the energy of the potential neutral hadron
2846  totalHcalEnergyCalibrated -= mergedNeutralHadronEnergy;
2847  // similarly for the merged photons
2848  totalEcalEnergyCalibrated -= mergedPhotonEnergy;
2849  // share between the charged hadrons
2850 
2851  //COLIN can compute this before
2852  // not exactly equal to sum p, this is sum E
2853  double chargedHadronsTotalEnergy = 0;
2854  for(unsigned index : chargedHadronsIndices) {
2855  reco::PFCandidate& chargedHadron = (*pfCandidates_)[index];
2856  chargedHadronsTotalEnergy += chargedHadron.energy();
2857  }
2858 
2859  for(unsigned index : chargedHadronsIndices) {
2860  reco::PFCandidate& chargedHadron = (*pfCandidates_)[index];
2861  float fraction = chargedHadron.energy()/chargedHadronsTotalEnergy;
2862 
2863  if ( !useHO_ ) {
2864  chargedHadron.setHcalEnergy( fraction * totalHcal, fraction * totalHcalEnergyCalibrated );
2865  chargedHadron.setHoEnergy( 0., 0. );
2866  } else {
2867  chargedHadron.setHcalEnergy( fraction * max(totalHcal-totalHO,0.0), fraction * totalHcalEnergyCalibrated * (1.-totalHO/totalHcal) );
2868  chargedHadron.setHoEnergy( fraction * totalHO, fraction * totalHO * totalHcalEnergyCalibrated / totalHcal );
2869  }
2870  //JB: fixing up (previously omitted) setting of ECAL energy gouzevit
2871  chargedHadron.setEcalEnergy( fraction * totalEcal, fraction * totalEcalEnergyCalibrated );
2872  }
2873 
2874  // Finally treat unused ecal satellites as photons.
2875  for(auto const& ecalSatellite : ecalSatellites) {
2876 
2877  // Ignore satellites already taken
2878  unsigned iEcal = ecalSatellite.second.first;
2879  if ( !active[iEcal] ) continue;
2880 
2881  // Sanity checks again (well not useful, this time!)
2882  PFBlockElement::Type type = elements[ iEcal ].type();
2883  assert( type == PFBlockElement::ECAL );
2884  PFClusterRef eclusterref = elements[iEcal].clusterRef();
2885  assert(!eclusterref.isNull() );
2886 
2887  // Lock the cluster
2888  active[iEcal] = false;
2889 
2890  // Find the associated tracks
2891  std::multimap<double, unsigned> assTracks;
2892  block.associatedElements( iEcal, linkData,
2893  assTracks,
2896 
2897  // Create a photon
2898  auto& cand = (*pfCandidates_)[reconstructCluster( *eclusterref, sqrt(ecalSatellite.second.second.Mag2()) )];
2899  cand.setEcalEnergy( eclusterref->energy(),sqrt(ecalSatellite.second.second.Mag2()) );
2900  cand.setHcalEnergy( 0., 0. );
2901  cand.setHoEnergy( 0., 0. );
2902  cand.setPs1Energy( associatedPSs[iEcal].first );
2903  cand.setPs2Energy( associatedPSs[iEcal].second );
2904  cand.addElementInBlock( blockref, iEcal );
2905  cand.addElementInBlock( blockref, sortedTracks.begin()->second) ;
2906  }
2907 
2908 
2909  }
2910 
2911  // end loop on hcal element iHcal= hcalIs[i]
2912 
2913 
2914  // Processing the remaining HCAL clusters
2915  if(debug_) {
2916  cout<<endl;
2917  if(debug_)
2918  cout<<endl
2919  <<"---- loop remaining hcal ------- "<<endl;
2920  }
2921 
2922 
2923  //COLINFEB16
2924  // now dealing with the HCAL elements that are not linked to any track
2925  for(unsigned iHcal : hcalIs) {
2926 
2927  // Keep ECAL and HO elements for reference in the PFCandidate
2928  std::vector<unsigned> ecalRefs;
2929  std::vector<unsigned> hoRefs;
2930 
2931  if(debug_)
2932  cout<<endl<<elements[iHcal]<<" ";
2933 
2934 
2935  if( !active[iHcal] ) {
2936  if(debug_)
2937  cout<<"not active"<<endl;
2938  continue;
2939  }
2940 
2941  // Find the ECAL elements linked to it
2942  std::multimap<double, unsigned> ecalElems;
2943  block.associatedElements( iHcal, linkData,
2944  ecalElems ,
2947 
2948  // Loop on these ECAL elements
2949  float totalEcal = 0.;
2950  float ecalMax = 0.;
2951  reco::PFClusterRef eClusterRef;
2952  for(auto const& ecal : ecalElems) {
2953 
2954  unsigned iEcal = ecal.second;
2955  double dist = ecal.first;
2956  PFBlockElement::Type type = elements[iEcal].type();
2957  assert( type == PFBlockElement::ECAL );
2958 
2959  // Check if already used
2960  if( !active[iEcal] ) continue;
2961 
2962  // Check the distance (one HCALPlusECAL tower, roughly)
2963  // if ( dist > 0.15 ) continue;
2964 
2965  //COLINFEB16
2966  // what could be done is to
2967  // - link by rechit.
2968  // - take in the neutral hadron all the ECAL clusters
2969  // which are within the same CaloTower, according to the distance,
2970  // except the ones which are closer to another HCAL cluster.
2971  // - all the other ECAL linked to this HCAL are photons.
2972  //
2973  // about the closest HCAL cluster.
2974  // it could maybe be easier to loop on the ECAL clusters first
2975  // to cut the links to all HCAL clusters except the closest, as is
2976  // done in the first track loop. But maybe not!
2977  // or add an helper function to the PFAlgo class to ask
2978  // if a given element is the closest of a given type to another one?
2979 
2980  // Check if not closer from another free HCAL
2981  std::multimap<double, unsigned> hcalElems;
2982  block.associatedElements( iEcal, linkData,
2983  hcalElems ,
2986 
2987  const bool isClosest = std::none_of(hcalElems.begin(), hcalElems.end(), [&](auto const& hcal){
2988  return active[hcal.second] && hcal.first < dist;
2989  });
2990 
2991  if (!isClosest) continue;
2992 
2993 
2994  if(debug_) {
2995  cout<<"\telement "<<elements[iEcal]<<" linked with dist "<< dist<<endl;
2996  cout<<"Added to HCAL cluster to form a neutral hadron"<<endl;
2997  }
2998 
2999  reco::PFClusterRef eclusterRef = elements[iEcal].clusterRef();
3000  assert( !eclusterRef.isNull() );
3001 
3002  double ecalEnergy = eclusterRef->correctedEnergy();
3003 
3004  //std::cout << "EcalEnergy, ps1, ps2 = " << ecalEnergy
3005  // << ", " << ps1Ene[0] << ", " << ps2Ene[0] << std::endl;
3006  totalEcal += ecalEnergy;
3007  if ( ecalEnergy > ecalMax ) {
3008  ecalMax = ecalEnergy;
3009  eClusterRef = eclusterRef;
3010  }
3011 
3012  ecalRefs.push_back(iEcal);
3013  active[iEcal] = false;
3014 
3015 
3016  }// End loop ECAL
3017 
3018  // Now find the HO clusters linked to the HCAL cluster
3019  double totalHO = 0.;
3020  double hoMax = 0.;
3021  //unsigned jHO = 0;
3022  if (useHO_) {
3023  std::multimap<double, unsigned> hoElems;
3024  block.associatedElements( iHcal, linkData,
3025  hoElems ,
3028 
3029  // Loop on these HO elements
3030  // double totalHO = 0.;
3031  // double hoMax = 0.;
3032  // unsigned jHO = 0;
3033  reco::PFClusterRef hoClusterRef;
3034  for(auto const& ho : hoElems) {
3035 
3036  unsigned iHO = ho.second;
3037  double dist = ho.first;
3038  PFBlockElement::Type type = elements[iHO].type();
3039  assert( type == PFBlockElement::HO );
3040 
3041  // Check if already used
3042  if( !active[iHO] ) continue;
3043 
3044  // Check the distance (one HCALPlusHO tower, roughly)
3045  // if ( dist > 0.15 ) continue;
3046 
3047  // Check if not closer from another free HCAL
3048  std::multimap<double, unsigned> hcalElems;
3049  block.associatedElements( iHO, linkData,
3050  hcalElems ,
3053 
3054  const bool isClosest = std::none_of(hcalElems.begin(), hcalElems.end(), [&](auto const& hcal){
3055  return active[hcal.second] && hcal.first < dist;
3056  });
3057 
3058  if (!isClosest) continue;
3059 
3060  if(debug_ && useHO_) {
3061  cout<<"\telement "<<elements[iHO]<<" linked with dist "<< dist<<endl;
3062  cout<<"Added to HCAL cluster to form a neutral hadron"<<endl;
3063  }
3064 
3065  reco::PFClusterRef hoclusterRef = elements[iHO].clusterRef();
3066  assert( !hoclusterRef.isNull() );
3067 
3068  double hoEnergy = hoclusterRef->energy(); // calibration_->energyEm(*hoclusterRef,ps1Ene,ps2Ene,crackCorrection);
3069 
3070  totalHO += hoEnergy;
3071  if ( hoEnergy > hoMax ) {
3072  hoMax = hoEnergy;
3073  hoClusterRef = hoclusterRef;
3074  //jHO = iHO;
3075  }
3076 
3077  hoRefs.push_back(iHO);
3078  active[iHO] = false;
3079 
3080  }// End loop HO
3081  }
3082 
3083  PFClusterRef hclusterRef
3084  = elements[iHcal].clusterRef();
3085  assert( !hclusterRef.isNull() );
3086 
3087  // HCAL energy
3088  double totalHcal = hclusterRef->energy();
3089  // Include the HO energy
3090  if ( useHO_ ) totalHcal += totalHO;
3091 
3092  // std::cout << "Hcal Energy,eta : " << totalHcal
3093  // << ", " << hclusterRef->positionREP().Eta()
3094  // << std::endl;
3095  // Calibration
3096  //double caloEnergy = totalHcal;
3097  // double slopeEcal = 1.0;
3098  double calibEcal = totalEcal > 0. ? totalEcal : 0.;
3099  double calibHcal = std::max(0.,totalHcal);
3100  if ( hclusterRef->layer() == PFLayer::HF_HAD ||
3101  hclusterRef->layer() == PFLayer::HF_EM ) {
3102  //caloEnergy = totalHcal/0.7;
3103  calibEcal = totalEcal;
3104  } else {
3105  calibration_->energyEmHad(-1.,calibEcal,calibHcal,
3106  hclusterRef->positionREP().Eta(),
3107  hclusterRef->positionREP().Phi());
3108  //caloEnergy = calibEcal+calibHcal;
3109  }
3110 
3111  // std::cout << "CalibEcal,HCal = " << calibEcal << ", " << calibHcal << std::endl;
3112  // std::cout << "-------------------------------------------------------------------" << std::endl;
3113  // ECAL energy : calibration
3114 
3115  // double particleEnergy = caloEnergy;
3116  // double particleEnergy = totalEcal + calibHcal;
3117  // particleEnergy /= (1.-0.724/sqrt(particleEnergy)-0.0226/particleEnergy);
3118 
3119  auto& cand = (*pfCandidates_)[reconstructCluster( *hclusterRef, calibEcal+calibHcal )];
3120 
3121  cand.setEcalEnergy( totalEcal, calibEcal );
3122  if ( !useHO_ ) {
3123  cand.setHcalEnergy( totalHcal, calibHcal );
3124  cand.setHoEnergy(0.,0.);
3125  } else {
3126  cand.setHcalEnergy( max(totalHcal-totalHO,0.0), calibHcal*(1.-totalHO/totalHcal));
3127  cand.setHoEnergy(totalHO,totalHO*calibHcal/totalHcal);
3128  }
3129  cand.setPs1Energy( 0. );
3130  cand.setPs2Energy( 0. );
3131  cand.addElementInBlock( blockref, iHcal );
3132  for (auto const& ec : ecalRefs) cand.addElementInBlock( blockref, ec );
3133  for (auto const& ho : hoRefs) cand.addElementInBlock( blockref, ho );
3134 
3135  }//loop hcal elements
3136 
3137 
3138 
3139 
3140  if(debug_) std::cout << std::endl << std::endl << "---- loop ecal------- " << std::endl;
3141 
3142  // for each ecal element iEcal = ecalIs[i] in turn:
3143 
3144  for(unsigned i=0; i<ecalIs.size(); i++) {
3145  unsigned iEcal = ecalIs[i];
3146 
3147  if(debug_)
3148  cout<<endl<<elements[iEcal]<<" ";
3149 
3150  if( ! active[iEcal] ) {
3151  if(debug_)
3152  cout<<"not active"<<endl;
3153  continue;
3154  }
3155 
3156  PFBlockElement::Type type = elements[ iEcal ].type();
3157  assert( type == PFBlockElement::ECAL );
3158 
3159  PFClusterRef clusterref = elements[iEcal].clusterRef();
3160  assert(!clusterref.isNull() );
3161 
3162  active[iEcal] = false;
3163 
3164  float ecalEnergy = clusterref->correctedEnergy();
3165  // float ecalEnergy = calibration_->energyEm( clusterref->energy() );
3166  double particleEnergy = ecalEnergy;
3167 
3168  auto& cand = (*pfCandidates_)[reconstructCluster( *clusterref, particleEnergy )];
3169 
3170  cand.setEcalEnergy( clusterref->energy(),ecalEnergy );
3171  cand.setHcalEnergy( 0., 0. );
3172  cand.setHoEnergy( 0., 0. );
3173  cand.setPs1Energy( 0. );
3174  cand.setPs2Energy( 0. );
3175  cand.addElementInBlock( blockref, iEcal );
3176 
3177  } // end loop on ecal elements iEcal = ecalIs[i]
3178 
3179 } // end processBlock
type
Definition: HCALResponse.h:21
static bool isIsolatedMuon(const reco::PFBlockElement &elt)
Definition: PFMuonAlgo.cc:227
double ptError_
Definition: PFAlgo.h:393
bool isFromSecInt(const reco::PFBlockElement &eTrack, std::string order) const
Definition: PFAlgo.cc:3521
bool usePFConversions_
Definition: PFAlgo.h:376
float goodTrackDeadHcal_dxy_
Definition: PFAlgo.h:401
std::vector< double > muonHCAL_
Variables for muons and fakes.
Definition: PFAlgo.h:389
ParticleType
particle types
Definition: PFCandidate.h:45
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:251
double eta() const final
momentum pseudorapidity
bool isElectronSafeForJetMET(const reco::GsfElectron &, const reco::PFCandidate &, const reco::Vertex &, bool &lockTracks)
void set_mva_nothing_gamma(float mva)
set mva for gamma detection
Definition: PFCandidate.h:330
bool isPhotonValidCandidate(const reco::PFBlockRef &blockRef, std::vector< bool > &active, std::unique_ptr< reco::PFCandidateCollection > &pfPhotonCandidates, std::vector< reco::PFCandidatePhotonExtra > &pfPhotonExtraCandidates, std::vector< reco::PFCandidate > &tempElectronCandidates)
Definition: PFPhotonAlgo.h:82
static bool isMuon(const reco::PFBlockElement &elt)
Definition: PFMuonAlgo.cc:155
const std::vector< reco::PFCandidate > & getAllElectronCandidates()
double errorScale(const reco::TrackBase::TrackAlgorithm &, const std::vector< double > &)
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:286
unsigned reconstructCluster(const reco::PFCluster &cluster, double particleEnergy, bool useDirection=false, double particleX=0., double particleY=0., double particleZ=0.)
Definition: PFAlgo.cc:3261
double y() const
y coordinate
Definition: Vertex.h:113
bool useProtectionsForJetMET_
Definition: PFAlgo.h:361
float goodPixelTrackDeadHcal_minEta_
Definition: PFAlgo.h:403
std::map< unsigned int, Link > LinkData
Definition: PFBlock.h:46
size_type size() const
Definition: OwnVector.h:264
#define X(str)
Definition: MuonsGrabber.cc:48
void setVertex(const math::XYZPoint &p) override
set vertex
Definition: PFCandidate.h:409
size_type size() const
std::vector< Variable::Flags > flags
Definition: MVATrainer.cc:135
double pt() const final
transverse momentum
std::shared_ptr< PFEnergyCalibrationHF > thepfEnergyCalibrationHF_
Definition: PFAlgo.h:329
int charge() const final
electric charge
Definition: LeafCandidate.h:91
bool passElectronSelection(const reco::GsfElectron &, const reco::PFCandidate &, const int &)
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< float > > XYZPointF
point in space with cartesian internal representation
Definition: Point3D.h:10
std::shared_ptr< PFEnergyCalibration > calibration_
Definition: PFAlgo.h:328
PFElectronAlgo * pfele_
Definition: PFAlgo.h:353
float goodPixelTrackDeadHcal_dxy_
Definition: PFAlgo.h:409
const Point & position() const
position
Definition: Vertex.h:109
static bool isGlobalTightMuon(const reco::PFBlockElement &elt)
Definition: PFMuonAlgo.cc:188
int nVtx_
Definition: PFAlgo.h:382
bool rejectTracks_Step45_
Definition: PFAlgo.h:373
std::vector< ElementInBlock > ElementsInBlocks
Definition: PFCandidate.h:387
std::vector< double > factors45_
Definition: PFAlgo.h:394
bool useHO_
Definition: PFAlgo.h:332
RefToBase< value_type > refAt(size_type i) const
U second(std::pair< T, U > const &p)
void setCharge(Charge q) final
set electric charge
Definition: LeafCandidate.h:93
bool isElectron(const reco::GsfElectron &)
void set_mva_e_pi(float mvaNI)
Definition: PFCandidate.h:312
void push_back(D *&d)
Definition: OwnVector.h:290
void set_mva_Isolated(float mvaI)
Definition: PFCandidate.h:308
const edm::View< reco::PFCandidate > * pfEgammaCandidates_
Definition: PFAlgo.h:362
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:3467
void setParticleType(ParticleType type)
set Particle Type
Definition: PFCandidate.cc:265
bool passPhotonSelection(const reco::Photon &)
T sqrt(T t)
Definition: SSEVec.h:18
bool empty() const
Definition: OwnVector.h:269
const std::vector< reco::PFCandidateElectronExtra > & getElectronExtra()
bool step45(const reco::TrackBase::TrackAlgorithm &)
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:354
float goodTrackDeadHcal_validFr_
Definition: PFAlgo.h:400
double energy() const final
energy
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double z() const
z coordinate
Definition: Vertex.h:115
reco::Vertex primaryVertex_
Definition: PFAlgo.h:425
double nSigmaHCAL(double clusterEnergy, double clusterEta) const
Definition: PFAlgo.cc:3421
std::vector< double > muonECAL_
Definition: PFAlgo.h:390
void setPositionAtECALEntrance(float x, float y, float z)
set position at ECAL entrance
T min(T a, T b)
Definition: MathUtil.h:58
PFEGammaFilters * pfegamma_
Definition: PFAlgo.h:360
bool isNull() const
Checks for null.
Definition: Ref.h:248
int goodPixelTrackDeadHcal_maxLost3Hit_
Definition: PFAlgo.h:407
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
Definition: PFAlgo.h:297
ii
Definition: cuy.py:590
void setEcalEnergy(float eeRaw, float eeCorr)
set corrected Ecal energy
Definition: PFCandidate.h:218
float mva_e_pi() const
mva for electron-pion discrimination
Definition: PFCandidate.h:314
std::unique_ptr< reco::PFCandidateCollection > pfPhotonCandidates_
the unfiltered photon collection
Definition: PFAlgo.h:290
const std::vector< reco::PFCandidate > & getElectronCandidates()
float goodPixelTrackDeadHcal_maxPt_
Definition: PFAlgo.h:404
double x() const
x coordinate
Definition: Vertex.h:111
unsigned reconstructTrack(const reco::PFBlockElement &elt, bool allowLoose=false)
Definition: PFAlgo.cc:3182
int goodTrackDeadHcal_layers_
Definition: PFAlgo.h:399
std::vector< double > muonHO_
Definition: PFAlgo.h:391
float goodPixelTrackDeadHcal_ptErrRel_
Definition: PFAlgo.h:405
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:30
double dptRel_DispVtx_
Definition: PFAlgo.h:381
static bool isLooseMuon(const reco::PFBlockElement &elt)
Definition: PFMuonAlgo.cc:168
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
double b
Definition: hdecay.h:120
void setHoEnergy(float eoRaw, float eoCorr)
set corrected Hcal energy
Definition: PFCandidate.h:238
bool isElectronValidCandidate(const reco::PFBlockRef &blockRef, std::vector< bool > &active, const reco::Vertex &primaryVertex)
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:40
double a
Definition: hdecay.h:121
reco::PFCandidateEGammaExtraRef egammaExtraRef() const
return a reference to the EGamma extra
Definition: PFCandidate.cc:605
bool rejectTracks_Bad_
Definition: PFAlgo.h:372
bool useEGammaFilters_
Variables for NEW EGAMMA selection.
Definition: PFAlgo.h:359
bool debug_
Definition: PFAlgo.h:334
float goodTrackDeadHcal_ptErrRel_
Variables for track cleaning in bad HCal areas.
Definition: PFAlgo.h:397
bool step5(const reco::TrackBase::TrackAlgorithm &)
std::unique_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
Definition: PFAlgo.h:288
int goodPixelTrackDeadHcal_maxLost4Hit_
Definition: PFAlgo.h:408
float goodPixelTrackDeadHcal_chi2n_
Definition: PFAlgo.h:406
double nSigmaTRACK_
Definition: PFAlgo.h:392
double neutralHadronEnergyResolution(double clusterEnergy, double clusterEta) const
todo: use PFClusterTools for this
Definition: PFAlgo.cc:3406
def check(config)
Definition: trackerTree.py:14
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
Definition: PFAlgo.h:295
bool usePFPhotons_
Definition: PFAlgo.h:341
const ElementsInBlocks & elementsInBlocks() const
Definition: PFCandidate.cc:691
double phi() const final
momentum azimuthal angle
bool isPhotonSafeForJetMET(const reco::Photon &, const reco::PFCandidate &)
void setP4(const LorentzVector &p4) final
set 4-momentum
float goodTrackDeadHcal_chi2n_
Definition: PFAlgo.h:398
float goodPixelTrackDeadHcal_dz_
Definition: PFAlgo.h:410
void setHcalEnergy(float ehRaw, float ehCorr)
set corrected Hcal energy
Definition: PFCandidate.h:228
void setHcalDepthInfo(reco::PFCandidate &cand, const reco::PFCluster &cluster) const
Definition: PFAlgo.cc:3375
static bool isTrackerTightMuon(const reco::PFBlockElement &elt)
Definition: PFMuonAlgo.cc:214
double nSigmaECAL_
number of sigma to judge energy excess in ECAL
Definition: PFAlgo.h:323
Block of elements.
Definition: PFBlock.h:30
bool usePFElectrons_
Definition: PFAlgo.h:340
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 3261 of file PFAlgo.cc.

References ALCARECOTkAlJpsiMuMu_cff::charge, gather_cfg::cout, debug_, PFLayer::ECAL_BARREL, PFLayer::ECAL_ENDCAP, CustomPhysics_cfi::gamma, PFLayer::HCAL_BARREL1, PFLayer::HCAL_ENDCAP, PFLayer::HF_EM, PFLayer::HF_HAD, reco::PFCluster::layer(), ResonanceBuilder::mass, objects.autophobj::particleType, pfElectronTranslator_cfi::PFCandidate, pfCandidates_, reco::CaloCluster::position(), primaryVertex_, setHcalDepthInfo(), mathSSE::sqrt(), tmp, useVertices_, reco::PFCandidate::X, reco::Vertex::x(), reco::Vertex::y(), and reco::Vertex::z().

Referenced by checkCleaning(), processBlock(), and thePFEnergyCalibration().

3266  {
3267 
3269 
3270  // need to convert the ::math::XYZPoint data member of the PFCluster class=
3271  // to a displacement vector:
3272 
3273  // Transform particleX,Y,Z to a position at ECAL/HCAL entrance
3274  double factor = 1.;
3275  if ( useDirection ) {
3276  switch( cluster.layer() ) {
3277  case PFLayer::ECAL_BARREL:
3278  case PFLayer::HCAL_BARREL1:
3279  factor = std::sqrt(cluster.position().Perp2()/(particleX*particleX+particleY*particleY));
3280  break;
3281  case PFLayer::ECAL_ENDCAP:
3282  case PFLayer::HCAL_ENDCAP:
3283  case PFLayer::HF_HAD:
3284  case PFLayer::HF_EM:
3285  factor = cluster.position().Z()/particleZ;
3286  break;
3287  default:
3288  assert(0);
3289  }
3290  }
3291  //MIKE First of all let's check if we have vertex.
3292  ::math::XYZPoint vertexPos;
3293  if(useVertices_)
3295  else
3296  vertexPos = ::math::XYZPoint(0.0,0.0,0.0);
3297 
3298 
3299  ::math::XYZVector clusterPos( cluster.position().X()-vertexPos.X(),
3300  cluster.position().Y()-vertexPos.Y(),
3301  cluster.position().Z()-vertexPos.Z());
3302  ::math::XYZVector particleDirection ( particleX*factor-vertexPos.X(),
3303  particleY*factor-vertexPos.Y(),
3304  particleZ*factor-vertexPos.Z() );
3305 
3306  //::math::XYZVector clusterPos( cluster.position().X(), cluster.position().Y(),cluster.position().Z() );
3307  //::math::XYZVector particleDirection ( particleX, particleY, particleZ );
3308 
3309  clusterPos = useDirection ? particleDirection.Unit() : clusterPos.Unit();
3310  clusterPos *= particleEnergy;
3311 
3312  // clusterPos is now a vector along the cluster direction,
3313  // with a magnitude equal to the cluster energy.
3314 
3315  double mass = 0;
3316  ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double> >
3317  momentum( clusterPos.X(), clusterPos.Y(), clusterPos.Z(), mass);
3318  // mathcore is a piece of #$%
3320  // implicit constructor not allowed
3321  tmp = momentum;
3322 
3323  // Charge
3324  int charge = 0;
3325 
3326  // Type
3327  switch( cluster.layer() ) {
3328  case PFLayer::ECAL_BARREL:
3329  case PFLayer::ECAL_ENDCAP:
3330  particleType = PFCandidate::gamma;
3331  break;
3332  case PFLayer::HCAL_BARREL1:
3333  case PFLayer::HCAL_ENDCAP:
3334  particleType = PFCandidate::h0;
3335  break;
3336  case PFLayer::HF_HAD:
3337  particleType = PFCandidate::h_HF;
3338  break;
3339  case PFLayer::HF_EM:
3340  particleType = PFCandidate::egamma_HF;
3341  break;
3342  default:
3343  assert(0);
3344  }
3345 
3346  // The pf candidate
3347  pfCandidates_->push_back( PFCandidate( charge,
3348  tmp,
3349  particleType ) );
3350 
3351  // The position at ECAL entrance (well: watch out, it is not true
3352  // for HCAL clusters... to be fixed)
3353  pfCandidates_->back().
3354  setPositionAtECALEntrance(::math::XYZPointF(cluster.position().X(),
3355  cluster.position().Y(),
3356  cluster.position().Z()));
3357 
3358  //Set the cnadidate Vertex
3359  pfCandidates_->back().setVertex(vertexPos);
3360 
3361  // depth info
3362  setHcalDepthInfo(pfCandidates_->back(), cluster);
3363 
3364  //*TODO* cluster time is not reliable at the moment, so only use track timing
3365 
3366  if(debug_)
3367  cout<<"** candidate: "<<pfCandidates_->back()<<endl;
3368 
3369  // returns index to the newly created PFCandidate
3370  return pfCandidates_->size()-1;
3371 
3372 }
PFLayer::Layer layer() const
cluster layer, see PFLayer.h in this directory
Definition: PFCluster.cc:120
const math::XYZPoint & position() const
cluster centroid position
Definition: CaloCluster.h:131
ParticleType
particle types
Definition: PFCandidate.h:45
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:286
double y() const
y coordinate
Definition: Vertex.h:113
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< float > > XYZPointF
point in space with cartesian internal representation
Definition: Point3D.h:10
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
T sqrt(T t)
Definition: SSEVec.h:18
double z() const
z coordinate
Definition: Vertex.h:115
reco::Vertex primaryVertex_
Definition: PFAlgo.h:425
double x() const
x coordinate
Definition: Vertex.h:111
bool useVertices_
Definition: PFAlgo.h:426
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:30
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
math::XYZVector XYZPoint
bool debug_
Definition: PFAlgo.h:334
void setHcalDepthInfo(reco::PFCandidate &cand, const reco::PFCluster &cluster) const
Definition: PFAlgo.cc:3375
void PFAlgo::reconstructParticles ( const reco::PFBlockHandle blockHandle)

reconstruct particles (full framework case) will keep track of the block handle to build persistent references, and call reconstructParticles( const reco::PFBlockCollection& blocks )

Definition at line 407 of file PFAlgo.cc.

References blockHandle_.

Referenced by setCandConnectorParameters().

407  {
408 
409  blockHandle_ = blockHandle;
411 }
void reconstructParticles(const reco::PFBlockHandle &blockHandle)
Definition: PFAlgo.cc:407
reco::PFBlockHandle blockHandle_
input block handle (full framework case)
Definition: PFAlgo.h:320
void PFAlgo::reconstructParticles ( const reco::PFBlockCollection blocks)

reconstruct particles

Definition at line 415 of file PFAlgo.cc.

References PFMuonAlgo::addMissingMuons(), groupFilesInBlocks::block, gather_cfg::cout, createBlockRef(), debug_, digitizers_cfi::ecal, reco::PFBlockElement::ECAL, allElectronIsolations_cfi::elements, reco::PFBlock::elements(), relativeConstraints::empty, reco::PFBlockElement::HCAL, reco::PFBlockElement::HO, mps_fire::i, edm::HandleBase::isValid(), muonHandle_, trackingPlots::other, pfCandidates_, pfCleanedCandidates_, pfElectronCandidates_, pfElectronExtra_, pfmu_, pfPhotonCandidates_, pfPhotonExtra_, PFMuonAlgo::postClean(), postCleaning(), processBlock(), and edm::OwnVector< T, P >::size().

415  {
416 
417  // reset output collection
418  if(pfCandidates_.get() )
419  pfCandidates_->clear();
420  else
422 
423  if(pfElectronCandidates_.get() )
424  pfElectronCandidates_->clear();
425  else
427 
428  // Clearing pfPhotonCandidates
429  if( pfPhotonCandidates_.get() )
430  pfPhotonCandidates_->clear();
431  else
433 
434  if(pfCleanedCandidates_.get() )
435  pfCleanedCandidates_->clear();
436  else
438 
439  // not a unique_ptr; should not be deleted after transfer
440  pfElectronExtra_.clear();
441  pfPhotonExtra_.clear();
442 
443  if( debug_ ) {
444  cout<<"*********************************************************"<<endl;
445  cout<<"***** Particle flow algorithm *****"<<endl;
446  cout<<"*********************************************************"<<endl;
447  }
448 
449  // sort elements in three lists:
450  std::list< reco::PFBlockRef > hcalBlockRefs;
451  std::list< reco::PFBlockRef > ecalBlockRefs;
452  std::list< reco::PFBlockRef > hoBlockRefs;
453  std::list< reco::PFBlockRef > otherBlockRefs;
454 
455  for( unsigned i=0; i<blocks.size(); ++i ) {
456  // reco::PFBlockRef blockref( blockh,i );
457  reco::PFBlockRef blockref = createBlockRef( blocks, i);
458 
459  const reco::PFBlock& block = *blockref;
461  elements = block.elements();
462 
463  bool singleEcalOrHcal = false;
464  if( elements.size() == 1 ){
465  if( elements[0].type() == reco::PFBlockElement::ECAL ){
466  ecalBlockRefs.push_back( blockref );
467  singleEcalOrHcal = true;
468  }
469  if( elements[0].type() == reco::PFBlockElement::HCAL ){
470  hcalBlockRefs.push_back( blockref );
471  singleEcalOrHcal = true;
472  }
473  if( elements[0].type() == reco::PFBlockElement::HO ){
474  // Single HO elements are likely to be noise. Not considered for now.
475  hoBlockRefs.push_back( blockref );
476  singleEcalOrHcal = true;
477  }
478  }
479 
480  if(!singleEcalOrHcal) {
481  otherBlockRefs.push_back( blockref );
482  }
483  }//loop blocks
484 
485  if( debug_ ){
486  cout<<"# Ecal blocks: "<<ecalBlockRefs.size()
487  <<", # Hcal blocks: "<<hcalBlockRefs.size()
488  <<", # HO blocks: "<<hoBlockRefs.size()
489  <<", # Other blocks: "<<otherBlockRefs.size()<<endl;
490  }
491 
492 
493  // loop on blocks that are not single ecal,
494  // and not single hcal.
495 
496  unsigned nblcks = 0;
497  for(auto const& other : otherBlockRefs) {
498  if ( debug_ ) std::cout << "Block number " << nblcks++ << std::endl;
499  processBlock( other, hcalBlockRefs, ecalBlockRefs );
500  }
501 
502  std::list< reco::PFBlockRef > empty;
503 
504  unsigned hblcks = 0;
505  // process remaining single hcal blocks
506  for(auto const& hcal : hcalBlockRefs) {
507  if ( debug_ ) std::cout << "HCAL block number " << hblcks++ << std::endl;
508  processBlock( hcal, empty, empty );
509  }
510 
511  unsigned eblcks = 0;
512  // process remaining single ecal blocks
513  for(auto const& ecal : ecalBlockRefs) {
514  if ( debug_ ) std::cout << "ECAL block number " << eblcks++ << std::endl;
515  processBlock( ecal, empty, empty );
516  }
517 
518  // Post HF Cleaning
519  postCleaning();
520 
521  //Muon post cleaning
522  pfmu_->postClean(pfCandidates_.get());
523 
524  //Add Missing muons
525  if( muonHandle_.isValid())
527 }
type
Definition: HCALResponse.h:21
void addMissingMuons(edm::Handle< reco::MuonCollection >, reco::PFCandidateCollection *cands)
Definition: PFMuonAlgo.cc:953
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:286
size_type size() const
Definition: OwnVector.h:264
void processBlock(const reco::PFBlockRef &blockref, std::list< reco::PFBlockRef > &hcalBlockRefs, std::list< reco::PFBlockRef > &ecalBlockRefs)
Definition: PFAlgo.cc:530
const edm::OwnVector< reco::PFBlockElement > & elements() const
Definition: PFBlock.h:107
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:355
std::unique_ptr< reco::PFCandidateCollection > pfCleanedCandidates_
Definition: PFAlgo.h:292
edm::Handle< reco::MuonCollection > muonHandle_
Definition: PFAlgo.h:428
bool isValid() const
Definition: HandleBase.h:74
reco::PFBlockRef createBlockRef(const reco::PFBlockCollection &blocks, unsigned bi)
Definition: PFAlgo.cc:3455
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
Definition: PFAlgo.h:297
std::unique_ptr< reco::PFCandidateCollection > pfPhotonCandidates_
the unfiltered photon collection
Definition: PFAlgo.h:290
std::vector< reco::PFCandidate > PFCandidateCollection
collection of PFCandidates
bool debug_
Definition: PFAlgo.h:334
std::unique_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
Definition: PFAlgo.h:288
void postCleaning()
Definition: PFAlgo.cc:3557
void postClean(reco::PFCandidateCollection *)
Definition: PFMuonAlgo.cc:849
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
Definition: PFAlgo.h:295
Block of elements.
Definition: PFBlock.h:30
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 3182 of file PFAlgo.cc.

References ALCARECOTkAlJpsiMuMu_cff::charge, reco::TrackBase::charge(), gather_cfg::cout, debug_, dptRel_DispVtx_, reco::TrackBase::eta(), reco::PFCandidate::h, isFromSecInt(), reco::isMuon(), edm::Ref< C, T, F >::isNonnull(), reco::PFBlockElement::isTimeValid(), reco::TrackBase::p(), objects.autophobj::particleType, pfElectronTranslator_cfi::PFCandidate, pfCandidates_, pfmu_, reco::TrackBase::phi(), reco::TrackBase::pt(), reco::TrackBase::px(), reco::TrackBase::py(), reco::TrackBase::pz(), PFMuonAlgo::reconstructMuon(), 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 HiIsolationCommonParameters_cff::track.

Referenced by processBlock(), and thePFEnergyCalibration().

3182  {
3183 
3184  const auto* eltTrack = dynamic_cast<const reco::PFBlockElementTrack*>(&elt);
3185 
3186  const reco::TrackRef& trackRef = eltTrack->trackRef();
3187  const reco::Track& track = *trackRef;
3188  const reco::MuonRef& muonRef = eltTrack->muonRef();
3189  int charge = track.charge()>0 ? 1 : -1;
3190 
3191  // Assume this particle is a charged Hadron
3192  double px = track.px();
3193  double py = track.py();
3194  double pz = track.pz();
3195  double energy = sqrt(track.p()*track.p() + 0.13957*0.13957);
3196 
3197  if (debug_) cout << "Reconstructing PF candidate from track of pT = " << track.pt() << " eta = " << track.eta() << " phi = " << track.phi() << " px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
3198 
3199 
3200  // Create a PF Candidate
3201  ::math::XYZTLorentzVector momentum(px,py,pz,energy);
3204 
3205  // Add it to the stack
3206  pfCandidates_->push_back( PFCandidate( charge,
3207  momentum,
3208  particleType ) );
3209  //Set vertex and stuff like this
3210  pfCandidates_->back().setVertexSource( PFCandidate::kTrkVertex );
3211  pfCandidates_->back().setTrackRef( trackRef );
3212  pfCandidates_->back().setPositionAtECALEntrance( eltTrack->positionAtECALEntrance());
3213  if( muonRef.isNonnull())
3214  pfCandidates_->back().setMuonRef( muonRef );
3215 
3216 
3217  //Set time
3218  if (elt.isTimeValid()) pfCandidates_->back().setTime( elt.time(), elt.timeError() );
3219 
3220  //OK Now try to reconstruct the particle as a muon
3221  bool isMuon=pfmu_->reconstructMuon(pfCandidates_->back(),muonRef,allowLoose);
3222  bool isFromDisp = isFromSecInt(elt, "secondary");
3223 
3224 
3225  if ((!isMuon) && isFromDisp) {
3226  double Dpt = trackRef->ptError();
3227  double dptRel = Dpt/trackRef->pt()*100;
3228  //If the track is ill measured it is better to not refit it, since the track information probably would not be used.
3229  //In the PFAlgo we use the trackref information. If the track error is too big the refitted information might be very different
3230  // from the not refitted one.
3231  if (dptRel < dptRel_DispVtx_){
3232  if (debug_)
3233  cout << "Not refitted px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
3234  //reco::TrackRef trackRef = eltTrack->trackRef();
3235  reco::PFDisplacedVertexRef vRef = eltTrack->displacedVertexRef(reco::PFBlockElement::T_FROM_DISP)->displacedVertexRef();
3236  reco::Track trackRefit = vRef->refittedTrack(trackRef);
3237  //change the momentum with the refitted track
3238  ::math::XYZTLorentzVector momentum(trackRefit.px(),
3239  trackRefit.py(),
3240  trackRefit.pz(),
3241  sqrt(trackRefit.p()*trackRefit.p() + 0.13957*0.13957));
3242  if (debug_)
3243  cout << "Refitted px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
3244  }
3245  pfCandidates_->back().setFlag( reco::PFCandidate::T_FROM_DISP, true);
3246  pfCandidates_->back().setDisplacedVertexRef( eltTrack->displacedVertexRef(reco::PFBlockElement::T_FROM_DISP)->displacedVertexRef(), reco::PFCandidate::T_FROM_DISP);
3247  }
3248 
3249  // 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
3250  if(isFromSecInt(elt, "primary") && !isMuon) {
3251  pfCandidates_->back().setFlag( reco::PFCandidate::T_TO_DISP, true);
3252  pfCandidates_->back().setDisplacedVertexRef( eltTrack->displacedVertexRef(reco::PFBlockElement::T_TO_DISP)->displacedVertexRef(), reco::PFCandidate::T_TO_DISP);
3253  }
3254 
3255  // returns index to the newly created PFCandidate
3256  return pfCandidates_->size()-1;
3257 }
double p() const
momentum vector magnitude
Definition: TrackBase.h:648
bool isFromSecInt(const reco::PFBlockElement &eTrack, std::string order) const
Definition: PFAlgo.cc:3521
ParticleType
particle types
Definition: PFCandidate.h:45
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:251
bool isMuon(const Candidate &part)
Definition: pdgIdUtils.h:11
float time() const
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:286
double phi() const
azimuthal angle of momentum vector
Definition: TrackBase.h:678
double px() const
x coordinate of momentum vector
Definition: TrackBase.h:660
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:355
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
bool isTimeValid() const
do we have a valid time information
double eta() const
pseudorapidity of momentum vector
Definition: TrackBase.h:684
T sqrt(T t)
Definition: SSEVec.h:18
double pt() const
track transverse momentum
Definition: TrackBase.h:654
double pz() const
z coordinate of momentum vector
Definition: TrackBase.h:672
double dptRel_DispVtx_
Definition: PFAlgo.h:381
bool debug_
Definition: PFAlgo.h:334
int charge() const
track electric charge
Definition: TrackBase.h:600
double py() const
y coordinate of momentum vector
Definition: TrackBase.h:666
float timeError() const
bool reconstructMuon(reco::PFCandidate &, const reco::MuonRef &, bool allowLoose=false)
Definition: PFMuonAlgo.cc:717
void PFAlgo::setAlgo ( int  algo)
inline

Definition at line 60 of file PFAlgo.h.

References patPFMETCorrections_cff::algo, and algo_.

void PFAlgo::setBadHcalTrackParams ( const edm::ParameterSet pset)

Definition at line 304 of file PFAlgo.cc.

References edm::ParameterSet::getParameter(), goodPixelTrackDeadHcal_chi2n_, goodPixelTrackDeadHcal_dxy_, goodPixelTrackDeadHcal_dz_, goodPixelTrackDeadHcal_maxLost3Hit_, goodPixelTrackDeadHcal_maxLost4Hit_, goodPixelTrackDeadHcal_maxPt_, goodPixelTrackDeadHcal_minEta_, goodPixelTrackDeadHcal_ptErrRel_, goodTrackDeadHcal_chi2n_, goodTrackDeadHcal_dxy_, goodTrackDeadHcal_layers_, goodTrackDeadHcal_ptErrRel_, and goodTrackDeadHcal_validFr_.

Referenced by setCandConnectorParameters().

305 {
306  goodTrackDeadHcal_ptErrRel_ = pset.getParameter<double>("goodTrackDeadHcal_ptErrRel");
307  goodTrackDeadHcal_chi2n_ = pset.getParameter<double>("goodTrackDeadHcal_chi2n");
308  goodTrackDeadHcal_layers_ = pset.getParameter<uint32_t>("goodTrackDeadHcal_layers");
309  goodTrackDeadHcal_validFr_ = pset.getParameter<double>("goodTrackDeadHcal_validFr");
310  goodTrackDeadHcal_dxy_ = pset.getParameter<double>("goodTrackDeadHcal_dxy");
311 
312  goodPixelTrackDeadHcal_minEta_ = pset.getParameter<double>("goodPixelTrackDeadHcal_minEta");
313  goodPixelTrackDeadHcal_maxPt_ = pset.getParameter<double>("goodPixelTrackDeadHcal_maxPt");
314  goodPixelTrackDeadHcal_ptErrRel_ = pset.getParameter<double>("goodPixelTrackDeadHcal_ptErrRel");
315  goodPixelTrackDeadHcal_chi2n_ = pset.getParameter<double>("goodPixelTrackDeadHcal_chi2n");
316  goodPixelTrackDeadHcal_maxLost3Hit_ = pset.getParameter<int32_t>("goodPixelTrackDeadHcal_maxLost3Hit");
317  goodPixelTrackDeadHcal_maxLost4Hit_ = pset.getParameter<int32_t>("goodPixelTrackDeadHcal_maxLost4Hit");
318  goodPixelTrackDeadHcal_dxy_ = pset.getParameter<double>("goodPixelTrackDeadHcal_dxy");
319  goodPixelTrackDeadHcal_dz_ = pset.getParameter<double>("goodPixelTrackDeadHcal_dz");
320 }
T getParameter(std::string const &) const
float goodTrackDeadHcal_dxy_
Definition: PFAlgo.h:401
float goodPixelTrackDeadHcal_minEta_
Definition: PFAlgo.h:403
float goodPixelTrackDeadHcal_dxy_
Definition: PFAlgo.h:409
float goodTrackDeadHcal_validFr_
Definition: PFAlgo.h:400
int goodPixelTrackDeadHcal_maxLost3Hit_
Definition: PFAlgo.h:407
float goodPixelTrackDeadHcal_maxPt_
Definition: PFAlgo.h:404
int goodTrackDeadHcal_layers_
Definition: PFAlgo.h:399
float goodPixelTrackDeadHcal_ptErrRel_
Definition: PFAlgo.h:405
float goodTrackDeadHcal_ptErrRel_
Variables for track cleaning in bad HCal areas.
Definition: PFAlgo.h:397
int goodPixelTrackDeadHcal_maxLost4Hit_
Definition: PFAlgo.h:408
float goodPixelTrackDeadHcal_chi2n_
Definition: PFAlgo.h:406
float goodTrackDeadHcal_chi2n_
Definition: PFAlgo.h:398
float goodPixelTrackDeadHcal_dz_
Definition: PFAlgo.h:410
void PFAlgo::setCandConnectorParameters ( const edm::ParameterSet iCfgCandConnector)
inline

Definition at line 70 of file PFAlgo.h.

References connector_, and PFCandConnector::setParameters().

70  {
71  connector_.setParameters(iCfgCandConnector);
72  }
PFCandConnector connector_
Definition: PFAlgo.h:386
void setParameters(const edm::ParameterSet &iCfgCandConnector)
void PFAlgo::setCandConnectorParameters ( bool  bCorrect,
bool  bCalibPrimary,
double  dptRel_PrimaryTrack,
double  dptRel_MergedTrack,
double  ptErrorSecondary,
const std::vector< double > &  nuclCalibFactors 
)
inline

Definition at line 74 of file PFAlgo.h.

References particleFlowSuperClusterECAL_cfi::applyCrackCorrections, gather_cfg::blocks, checkCleaning(), particleFlow_cfi::cleanedHF, particleFlow_cfi::coneEcalIsoForEgammaSC, particleFlow_cfi::coneTrackIsoForEgammaSC, connector_, particleFlow_cfi::dptRel_DispVtx, getPFMuonAlgo(), particleFlow_cfi::maxDeltaPhiPt, particleFlow_cfi::maxSignificance, particleFlow_cfi::minDeltaMet, particleFlow_cfi::minHFCleaningPt, particleFlow_cfi::minSignificance, particleFlow_cfi::minSignificanceReduction, particleFlow_cfi::nTrackIsoForEgammaSC, particleBasedIsoProducer_cfi::pfEgammaCandidates, particleFlow_cfi::postHFCleaning, jets_cff::primaryVertices, muonDTDigis_cfi::pset, reconstructParticles(), hltParticleFlowForJets_cfi::rejectTracks_Bad, hltParticleFlowForJets_cfi::rejectTracks_Step45, setBadHcalTrackParams(), setDisplacedVerticesParameters(), setEGammaCollections(), setEGammaParameters(), setEGElectronCollection(), setElectronExtraRef(), PFCandConnector::setParameters(), setPFEleParameters(), setPFMuonAndFakeParameters(), setPFPhotonParameters(), setPFPhotonRegWeights(), setPFVertexParameters(), setPhotonExtraRef(), setPostHFCleaningParameters(), AlCaHLTBitMon_QueryRunRegistry::string, particleFlow_cfi::sumEtEcalIsoForEgammaSC_barrel, particleFlow_cfi::sumEtEcalIsoForEgammaSC_endcap, particleFlow_cfi::sumPtTrackIsoForEgammaSC_barrel, particleFlow_cfi::sumPtTrackIsoForEgammaSC_endcap, particleFlow_cfi::sumPtTrackIsoForPhoton, particleFlow_cfi::sumPtTrackIsoSlopeForPhoton, thePFEnergyCalibration(), hltParticleFlowForJets_cfi::useEGammaSupercluster, Reconstruction_hiPF_cff::usePFConversions, particleFlow_cfi::usePFDecays, Reconstruction_hiPF_cff::usePFElectrons, hltParticleFlowForJets_cfi::usePFNuclearInteractions, hltParticleFlowForJets_cfi::usePFSCEleCalib, hltParticleFlowForJets_cfi::useProtectionsForJetMET, VerticesFromLeptons_cfi::useVertex, and particleFlow_cfi::X0_Map.

void PFAlgo::setDebug ( bool  debug)
inline

Definition at line 63 of file PFAlgo.h.

References connector_, debug, debug_, nSigmaHCAL(), pfegamma_, PFEGammaFilters::setDebug(), PFCandConnector::setDebug(), and setParameters().

PFCandConnector connector_
Definition: PFAlgo.h:386
PFEGammaFilters * pfegamma_
Definition: PFAlgo.h:360
#define debug
Definition: HDRShower.cc:19
void setDebug(bool debug)
bool debug_
Definition: PFAlgo.h:334
void setDebug(bool debug)
void PFAlgo::setDisplacedVerticesParameters ( bool  rejectTracks_Bad,
bool  rejectTracks_Step45,
bool  usePFNuclearInteractions,
bool  usePFConversions,
bool  usePFDecays,
double  dptRel_DispVtx 
)

Definition at line 346 of file PFAlgo.cc.

References particleFlow_cfi::dptRel_DispVtx, dptRel_DispVtx_, hltParticleFlowForJets_cfi::rejectTracks_Bad, rejectTracks_Bad_, hltParticleFlowForJets_cfi::rejectTracks_Step45, rejectTracks_Step45_, Reconstruction_hiPF_cff::usePFConversions, usePFConversions_, particleFlow_cfi::usePFDecays, usePFDecays_, hltParticleFlowForJets_cfi::usePFNuclearInteractions, and usePFNuclearInteractions_.

Referenced by setCandConnectorParameters().

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

Definition at line 263 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

265  {
266  if(useEGammaFilters_) {
268  valueMapGedElectrons_ = & valueMapGedElectrons;
269  valueMapGedPhotons_ = & valueMapGedPhotons;
270  }
271 }
const edm::ValueMap< reco::PhotonRef > * valueMapGedPhotons_
Definition: PFAlgo.h:364
const edm::View< reco::PFCandidate > * pfEgammaCandidates_
Definition: PFAlgo.h:362
bool useEGammaFilters_
Variables for NEW EGAMMA selection.
Definition: PFAlgo.h:359
const edm::ValueMap< reco::GsfElectronRef > * valueMapGedElectrons_
Definition: PFAlgo.h:363
void PFAlgo::setEGammaParameters ( bool  use_EGammaFilters,
std::string  ele_iso_path_mvaWeightFile,
double  ele_iso_pt,
double  ele_iso_mva_barrel,
double  ele_iso_mva_endcap,
double  ele_iso_combIso_barrel,
double  ele_iso_combIso_endcap,
double  ele_noniso_mva,
unsigned int  ele_missinghits,
bool  useProtectionsForJetMET,
const edm::ParameterSet ele_protectionsForJetMET,
const edm::ParameterSet ele_protectionsForBadHcal,
double  ph_MinEt,
double  ph_combIso,
double  ph_HoE,
double  ph_sietaieta_eb,
double  ph_sietaieta_ee,
const edm::ParameterSet ph_protectionsForJetMET,
const edm::ParameterSet ph_protectionsForBadHcal 
)

Definition at line 204 of file PFAlgo.cc.

References pfegamma_, useEGammaFilters_, hltParticleFlowForJets_cfi::useProtectionsForJetMET, and useProtectionsForJetMET_.

Referenced by setCandConnectorParameters().

224 {
225 
226  useEGammaFilters_ = use_EGammaFilters;
227 
228  if(!useEGammaFilters_ ) return;
229  FILE * fileEGamma_ele_iso_ID = fopen(ele_iso_path_mvaWeightFile.c_str(), "r");
230  if (fileEGamma_ele_iso_ID) {
231  fclose(fileEGamma_ele_iso_ID);
232  }
233  else {
234  string err = "PFAlgo: cannot open weight file '";
235  err += ele_iso_path_mvaWeightFile;
236  err += "'";
237  throw invalid_argument( err );
238  }
239 
240  // ele_iso_mvaID_ = new ElectronMVAEstimator(ele_iso_path_mvaWeightFile_);
242 
243  pfegamma_ = new PFEGammaFilters(ph_MinEt,
244  ph_combIso,
245  ph_HoE,
246  ph_sietaieta_eb,
247  ph_sietaieta_ee,
248  ph_protectionsForJetMET,
249  ph_protectionsForBadHcal,
250  ele_iso_pt,
251  ele_iso_mva_barrel,
252  ele_iso_mva_endcap,
253  ele_iso_combIso_barrel,
254  ele_iso_combIso_endcap,
255  ele_noniso_mva,
256  ele_missinghits,
257  ele_iso_path_mvaWeightFile,
258  ele_protectionsForJetMET,
259  ele_protectionsForBadHcal);
260 
261  return;
262 }
bool useProtectionsForJetMET_
Definition: PFAlgo.h:361
PFEGammaFilters * pfegamma_
Definition: PFAlgo.h:360
bool useEGammaFilters_
Variables for NEW EGAMMA selection.
Definition: PFAlgo.h:359
void PFAlgo::setEGElectronCollection ( const reco::GsfElectronCollection egelectrons)

Definition at line 3552 of file PFAlgo.cc.

References pfele_, PFElectronAlgo::setEGElectronCollection(), and useEGElectrons_.

Referenced by setCandConnectorParameters().

3552  {
3554 }
PFElectronAlgo * pfele_
Definition: PFAlgo.h:353
bool useEGElectrons_
Definition: PFAlgo.h:344
void setEGElectronCollection(const reco::GsfElectronCollection &egelectrons)
void PFAlgo::setElectronExtraRef ( const edm::OrphanHandle< reco::PFCandidateElectronExtraCollection > &  extrah)

Definition at line 3764 of file PFAlgo.cc.

References MillePedeFileConverter_cfg::e, pfCandidates_, pfElectronCandidates_, pfElectronExtra_, and usePFElectrons_.

Referenced by setCandConnectorParameters().

3764  {
3765  if(!usePFElectrons_) return;
3766  // std::cout << " setElectronExtraRef " << std::endl;
3767  for(auto& cand : *pfCandidates_) {
3768  // select the electrons and add the extra
3769  if(cand.particleId()==PFCandidate::e) {
3770 
3771  PFElectronExtraEqual myExtraEqual(cand.gsfTrackRef());
3772  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
3773  if(it!=pfElectronExtra_.end()) {
3774  // std::cout << " Index " << it-pfElectronExtra_.begin() << std::endl;
3775  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
3776  cand.setPFElectronExtraRef(theRef);
3777  }
3778  else {
3779  cand.setPFElectronExtraRef(PFCandidateElectronExtraRef());
3780  }
3781  }
3782  else // else save the mva and the extra as well !
3783  {
3784  if(cand.trackRef().isNonnull()) {
3785  PFElectronExtraKfEqual myExtraEqual(cand.trackRef());
3786  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
3787  if(it!=pfElectronExtra_.end()) {
3788  cand.set_mva_e_pi(it->mvaVariable(PFCandidateElectronExtra::MVA_MVA));
3789  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
3790  cand.setPFElectronExtraRef(theRef);
3791  cand.setGsfTrackRef(it->gsfTrackRef());
3792  }
3793  }
3794  }
3795 
3796  }
3797 
3798  for(auto& ele : *pfElectronCandidates_) {
3799  // select the electrons - this test is actually not needed for this collection
3800  if(ele.particleId()==PFCandidate::e) {
3801  // find the corresponding extra
3802  PFElectronExtraEqual myExtraEqual(ele.gsfTrackRef());
3803  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
3804  if(it!=pfElectronExtra_.end()) {
3805  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
3806  ele.setPFElectronExtraRef(theRef);
3807 
3808  }
3809  }
3810  }
3811 
3812 }
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:286
edm::Ref< PFCandidateElectronExtraCollection > PFCandidateElectronExtraRef
persistent reference to a PFCandidateElectronExtra
std::unique_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
Definition: PFAlgo.h:288
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
Definition: PFAlgo.h:295
bool usePFElectrons_
Definition: PFAlgo.h:340
void PFAlgo::setHcalDepthInfo ( reco::PFCandidate cand,
const reco::PFCluster cluster 
) const
private

Definition at line 3375 of file PFAlgo.cc.

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

Referenced by processBlock(), reconstructCluster(), and thePFEnergyCalibration().

3375  {
3376  std::array<double,7> energyPerDepth;
3377  std::fill(energyPerDepth.begin(), energyPerDepth.end(), 0.0);
3378  for (auto & hitRefAndFrac : cluster.recHitFractions()) {
3379  const auto & hit = *hitRefAndFrac.recHitRef();
3380  if (DetId(hit.detId()).det() == DetId::Hcal) {
3381  if (hit.depth() == 0) {
3382  edm::LogWarning("setHcalDepthInfo") << "Depth zero found";
3383  continue;
3384  }
3385  if (hit.depth() < 1 || hit.depth() > 7) {
3386  throw cms::Exception("CorruptData") << "Bogus depth " << hit.depth() << " at detid " << hit.detId() << "\n";
3387  }
3388  energyPerDepth[hit.depth()-1] += hitRefAndFrac.fraction()*hit.energy();
3389  }
3390  }
3391  double sum = std::accumulate(energyPerDepth.begin(), energyPerDepth.end(), 0.);
3392  std::array<float,7> depthFractions;
3393  if (sum > 0) {
3394  for (unsigned int i = 0; i < depthFractions.size(); ++i) {
3395  depthFractions[i] = energyPerDepth[i]/sum;
3396  }
3397  } else {
3398  std::fill(depthFractions.begin(), depthFractions.end(), 0.f);
3399  }
3400  cand.setHcalDepthEnergyFractions(depthFractions);
3401 }
void setHcalDepthEnergyFractions(const std::array< float, 7 > &fracs)
set the fraction of hcal energy as function of depth (index 0..6 for depth 1..7)
Definition: PFCandidate.h:432
Definition: DetId.h:18
const std::vector< reco::PFRecHitFraction > & recHitFractions() const
vector of rechit fractions
Definition: PFCluster.h:72
void PFAlgo::setHOTag ( bool  ho)
inline

Definition at line 59 of file PFAlgo.h.

References photonIsolationHIProducer_cfi::ho, and useHO_.

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

Definition at line 323 of file PFAlgo.cc.

References muonHandle_, and extraflags_cff::muons.

Referenced by setPFMuonAlgo().

323  {
324  muonHandle_ = muons;
325 }
edm::Handle< reco::MuonCollection > muonHandle_
Definition: PFAlgo.h:428
void PFAlgo::setParameters ( double  nSigmaECAL,
double  nSigmaHCAL,
const std::shared_ptr< PFEnergyCalibration > &  calibration,
const std::shared_ptr< PFEnergyCalibrationHF > &  thepfEnergyCalibrationHF 
)

Definition at line 71 of file PFAlgo.cc.

References calibration_, nSigmaECAL_, nSigmaHCAL(), nSigmaHCAL_, and thepfEnergyCalibrationHF_.

Referenced by setDebug().

74  {
75 
76  nSigmaECAL_ = nSigmaECAL;
78 
79  calibration_ = calibration;
80  thepfEnergyCalibrationHF_ = thepfEnergyCalibrationHF;
81 
82 }
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:326
std::shared_ptr< PFEnergyCalibrationHF > thepfEnergyCalibrationHF_
Definition: PFAlgo.h:329
std::shared_ptr< PFEnergyCalibration > calibration_
Definition: PFAlgo.h:328
double nSigmaHCAL(double clusterEnergy, double clusterEta) const
Definition: PFAlgo.cc:3421
double nSigmaECAL_
number of sigma to judge energy excess in ECAL
Definition: PFAlgo.h:323
void PFAlgo::setPFEleParameters ( double  mvaEleCut,
std::string  mvaWeightFileEleID,
bool  usePFElectrons,
const std::shared_ptr< PFSCEnergyCalibration > &  thePFSCEnergyCalibration,
const std::shared_ptr< PFEnergyCalibration > &  thePFEnergyCalibration,
double  sumEtEcalIsoForEgammaSC_barrel,
double  sumEtEcalIsoForEgammaSC_endcap,
double  coneEcalIsoForEgammaSC,
double  sumPtTrackIsoForEgammaSC_barrel,
double  sumPtTrackIsoForEgammaSC_endcap,
unsigned int  nTrackIsoForEgammaSC,
double  coneTrackIsoForEgammaSC,
bool  applyCrackCorrections = false,
bool  usePFSCEleCalib = true,
bool  useEGElectrons = false,
bool  useEGammaSupercluster = true 
)

Definition at line 91 of file PFAlgo.cc.

References particleFlowSuperClusterECAL_cfi::applyCrackCorrections, applyCrackCorrectionsElectrons_, particleFlow_cfi::coneEcalIsoForEgammaSC, coneEcalIsoForEgammaSC_, particleFlow_cfi::coneTrackIsoForEgammaSC, coneTrackIsoForEgammaSC_, mvaEleCut_, mvaWeightFileEleID_, particleFlow_cfi::nTrackIsoForEgammaSC, nTrackIsoForEgammaSC_, pfele_, particleFlow_cfi::sumEtEcalIsoForEgammaSC_barrel, sumEtEcalIsoForEgammaSC_barrel_, particleFlow_cfi::sumEtEcalIsoForEgammaSC_endcap, sumEtEcalIsoForEgammaSC_endcap_, particleFlow_cfi::sumPtTrackIsoForEgammaSC_barrel, sumPtTrackIsoForEgammaSC_barrel_, particleFlow_cfi::sumPtTrackIsoForEgammaSC_endcap, sumPtTrackIsoForEgammaSC_endcap_, thePFSCEnergyCalibration_, hltParticleFlowForJets_cfi::useEGammaSupercluster, useEGammaSupercluster_, useEGElectrons_, Reconstruction_hiPF_cff::usePFElectrons, usePFElectrons_, hltParticleFlowForJets_cfi::usePFSCEleCalib, and usePFSCEleCalib_.

Referenced by setCandConnectorParameters().

106  {
107 
108  mvaEleCut_ = mvaEleCut;
112  thePFSCEnergyCalibration_ = thePFSCEnergyCalibration;
113  useEGElectrons_ = useEGElectrons;
122 
123 
124  if(!usePFElectrons_) return;
125  mvaWeightFileEleID_ = mvaWeightFileEleID;
126  FILE * fileEleID = fopen(mvaWeightFileEleID_.c_str(), "r");
127  if (fileEleID) {
128  fclose(fileEleID);
129  }
130  else {
131  string err = "PFAlgo: cannot open weight file '";
132  err += mvaWeightFileEleID;
133  err += "'";
134  throw invalid_argument( err );
135  }
150 }
unsigned int nTrackIsoForEgammaSC_
Definition: PFAlgo.h:352
double sumEtEcalIsoForEgammaSC_endcap_
Definition: PFAlgo.h:347
double mvaEleCut_
Definition: PFAlgo.h:339
double coneEcalIsoForEgammaSC_
Definition: PFAlgo.h:348
double coneTrackIsoForEgammaSC_
Definition: PFAlgo.h:351
double sumEtEcalIsoForEgammaSC_barrel_
Definition: PFAlgo.h:346
PFElectronAlgo * pfele_
Definition: PFAlgo.h:353
bool useEGammaSupercluster_
Definition: PFAlgo.h:345
bool useEGElectrons_
Definition: PFAlgo.h:344
std::string mvaWeightFileEleID_
Variables for PFElectrons.
Definition: PFAlgo.h:337
bool usePFSCEleCalib_
Definition: PFAlgo.h:343
std::shared_ptr< PFEnergyCalibration > thePFEnergyCalibration()
return the pointer to the calibration function
Definition: PFAlgo.h:235
std::shared_ptr< PFSCEnergyCalibration > thePFSCEnergyCalibration_
Definition: PFAlgo.h:330
bool applyCrackCorrectionsElectrons_
Definition: PFAlgo.h:342
double sumPtTrackIsoForEgammaSC_endcap_
Definition: PFAlgo.h:350
double sumPtTrackIsoForEgammaSC_barrel_
Definition: PFAlgo.h:349
bool usePFElectrons_
Definition: PFAlgo.h:340
void PFAlgo::setPFMuonAlgo ( PFMuonAlgo algo)
inline

Definition at line 61 of file PFAlgo.h.

References patPFMETCorrections_cff::algo, pfmu_, and setMuonHandle().

void PFAlgo::setPFMuonAndFakeParameters ( const edm::ParameterSet pset)

Definition at line 287 of file PFAlgo.cc.

References factors45_, edm::ParameterSet::getParameter(), muonECAL_, muonHCAL_, muonHO_, nSigmaTRACK_, pfmu_, ptError_, and PFMuonAlgo::setParameters().

Referenced by setCandConnectorParameters().

288 {
289  pfmu_ = new PFMuonAlgo();
290  pfmu_->setParameters(pset);
291 
292  // Muon parameters
293  muonHCAL_= pset.getParameter<std::vector<double> >("muon_HCAL");
294  muonECAL_= pset.getParameter<std::vector<double> >("muon_ECAL");
295  muonHO_= pset.getParameter<std::vector<double> >("muon_HO");
296  assert ( muonHCAL_.size() == 2 && muonECAL_.size() == 2 && muonHO_.size() == 2);
297  nSigmaTRACK_= pset.getParameter<double>("nsigma_TRACK");
298  ptError_= pset.getParameter<double>("pt_Error");
299  factors45_ = pset.getParameter<std::vector<double> >("factors_45");
300  assert ( factors45_.size() == 2 );
301 }
T getParameter(std::string const &) const
double ptError_
Definition: PFAlgo.h:393
std::vector< double > muonHCAL_
Variables for muons and fakes.
Definition: PFAlgo.h:389
void setParameters(const edm::ParameterSet &)
Definition: PFMuonAlgo.cc:29
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:355
std::vector< double > factors45_
Definition: PFAlgo.h:394
std::vector< double > muonECAL_
Definition: PFAlgo.h:390
std::vector< double > muonHO_
Definition: PFAlgo.h:391
double nSigmaTRACK_
Definition: PFAlgo.h:392
void PFAlgo::setPFPhotonParameters ( bool  usePFPhoton,
std::string  mvaWeightFileConvID,
double  mvaConvCut,
bool  useReg,
std::string  X0_Map,
const std::shared_ptr< PFEnergyCalibration > &  thePFEnergyCalibration,
double  sumPtTrackIsoForPhoton,
double  sumPtTrackIsoSlopeForPhoton 
)

Definition at line 153 of file PFAlgo.cc.

References MillePedeFileConverter_cfg::e, AlCaHLTBitMon_ParallelJobs::p, pfpho_, primaryVertex_, MetAnalyzer::pv(), particleFlow_cfi::usePFPhotons, usePFPhotons_, and useVertices_.

Referenced by setCandConnectorParameters().

161  {
162 
164 
165  //for MVA pass PV if there is one in the collection otherwise pass a dummy
167  if(useVertices_)
168  {
169  dummy = primaryVertex_;
170  }
171  else { // create a dummy PV
173  e(0, 0) = 0.0015 * 0.0015;
174  e(1, 1) = 0.0015 * 0.0015;
175  e(2, 2) = 15. * 15.;
176  reco::Vertex::Point p(0, 0, 0);
177  dummy = reco::Vertex(p, e, 0, 0, 0);
178  }
179  // pv=&dummy;
180  if(! usePFPhotons_) return;
181  FILE * filePhotonConvID = fopen(mvaWeightFileConvID.c_str(), "r");
182  if (filePhotonConvID) {
183  fclose(filePhotonConvID);
184  }
185  else {
186  string err = "PFAlgo: cannot open weight file '";
187  err += mvaWeightFileConvID;
188  err += "'";
189  throw invalid_argument( err );
190  }
191  const reco::Vertex* pv=&dummy;
192  pfpho_ = new PFPhotonAlgo(mvaWeightFileConvID,
193  mvaConvCut,
194  useReg,
195  X0_Map,
196  *pv,
200  );
201  return;
202 }
math::Error< dimension >::type Error
covariance error matrix (3x3)
Definition: Vertex.h:43
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:354
def pv(vc)
Definition: MetAnalyzer.py:7
reco::Vertex primaryVertex_
Definition: PFAlgo.h:425
math::XYZPoint Point
point in the space
Definition: Vertex.h:39
std::shared_ptr< PFEnergyCalibration > thePFEnergyCalibration()
return the pointer to the calibration function
Definition: PFAlgo.h:235
bool useVertices_
Definition: PFAlgo.h:426
bool usePFPhotons_
Definition: PFAlgo.h:341
void PFAlgo::setPFPhotonRegWeights ( const GBRForest LCorrForestEB,
const GBRForest LCorrForestEE,
const GBRForest GCorrForestBarrel,
const GBRForest GCorrForestEndcapHr9,
const GBRForest GCorrForestEndcapLr9,
const GBRForest PFEcalResolution 
)

Definition at line 274 of file PFAlgo.cc.

References pfpho_, and PFPhotonAlgo::setGBRForest().

Referenced by setCandConnectorParameters().

280  {
281 
282  pfpho_->setGBRForest(LCorrForestEB,LCorrForestEE,
283  GCorrForestBarrel, GCorrForestEndcapHr9,
284  GCorrForestEndcapLr9, PFEcalResolution);
285 }
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:354
void setGBRForest(const GBRForest *LCorrForest, const GBRForest *GCorrForest, const GBRForest *ResForest)
Definition: PFPhotonAlgo.h:49
void PFAlgo::setPFVertexParameters ( bool  useVertex,
const reco::VertexCollection primaryVertices 
)

Definition at line 364 of file PFAlgo.cc.

References MillePedeFileConverter_cfg::e, nVtx_, AlCaHLTBitMon_ParallelJobs::p, pfmu_, pfpho_, primaryVertex_, PFMuonAlgo::setInputsForCleaning(), PFPhotonAlgo::setnPU(), PFPhotonAlgo::setPhotonPrimaryVtx(), usePFPhotons_, VerticesFromLeptons_cfi::useVertex, and useVertices_.

Referenced by setCandConnectorParameters().

365  {
367 
368  //Set the vertices for muon cleaning
370 
371 
372  //Now find the primary vertex!
373  bool primaryVertexFound = false;
374  nVtx_ = primaryVertices->size();
375  if(usePFPhotons_){
376  pfpho_->setnPU(nVtx_);
377  }
378  for(auto const& vertex : *primaryVertices)
379  {
380  if(vertex.isValid()&&(!vertex.isFake()))
381  {
382  primaryVertex_ = vertex;
383  primaryVertexFound = true;
384  break;
385  }
386  }
387  //Use vertices if the user wants to but only if it exists a good vertex
388  useVertices_ = useVertex && primaryVertexFound;
389  if(usePFPhotons_) {
390  if (useVertices_ ){
392  }
393  else{
395  e(0, 0) = 0.0015 * 0.0015;
396  e(1, 1) = 0.0015 * 0.0015;
397  e(2, 2) = 15. * 15.;
398  reco::Vertex::Point p(0, 0, 0);
399  reco::Vertex dummy = reco::Vertex(p, e, 0, 0, 0);
400  // std::cout << " PFPho " << pfpho_ << std::endl;
401  pfpho_->setPhotonPrimaryVtx(dummy);
402  }
403  }
404 }
void setnPU(int nVtx)
Definition: PFPhotonAlgo.h:75
math::Error< dimension >::type Error
covariance error matrix (3x3)
Definition: Vertex.h:43
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:355
int nVtx_
Definition: PFAlgo.h:382
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:354
reco::Vertex primaryVertex_
Definition: PFAlgo.h:425
math::XYZPoint Point
point in the space
Definition: Vertex.h:39
bool useVertices_
Definition: PFAlgo.h:426
primaryVertices
Definition: jets_cff.py:135
void setPhotonPrimaryVtx(const reco::Vertex &primary)
Definition: PFPhotonAlgo.h:78
bool usePFPhotons_
Definition: PFAlgo.h:341
void setInputsForCleaning(const reco::VertexCollection *)
Definition: PFMuonAlgo.cc:1168
void PFAlgo::setPhotonExtraRef ( const edm::OrphanHandle< reco::PFCandidatePhotonExtraCollection > &  pf_extrah)

Definition at line 3813 of file PFAlgo.cc.

References runEdmFileComparison::found, CustomPhysics_cfi::gamma, pfCandidates_, pfPhotonExtra_, muons2muons_cfi::photon, and usePFPhotons_.

Referenced by setCandConnectorParameters().

3813  {
3814  if(!usePFPhotons_) return;
3815  for(auto& cand : *pfCandidates_) {
3816  // select the electrons and add the extra
3817  if(cand.particleId()==PFCandidate::gamma && cand.mva_nothing_gamma() > 0.99) {
3818  if(cand.superClusterRef().isNonnull()) {
3819  bool found = false;
3820  unsigned int pcextra = 0;
3821  for(auto const& photon : pfPhotonExtra_) {
3822  if(cand.superClusterRef() == photon.superClusterRef()) {
3823  reco::PFCandidatePhotonExtraRef theRef(ph_extrah,pcextra);
3824  cand.setPFPhotonExtraRef(theRef);
3825  found = true;
3826  break;
3827  }
3828  ++pcextra;
3829  }
3830  if(!found)
3831  cand.setPFPhotonExtraRef((PFCandidatePhotonExtraRef())); // null ref
3832  }
3833  else {
3834  cand.setPFPhotonExtraRef((PFCandidatePhotonExtraRef())); // null ref
3835  }
3836  }
3837  }
3838 }
edm::Ref< PFCandidatePhotonExtraCollection > PFCandidatePhotonExtraRef
persistent reference to a PFCandidatePhotonExtra
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:286
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
Definition: PFAlgo.h:297
bool usePFPhotons_
Definition: PFAlgo.h:341
void PFAlgo::setPostHFCleaningParameters ( bool  postHFCleaning,
double  minHFCleaningPt,
double  minSignificance,
double  maxSignificance,
double  minSignificanceReduction,
double  maxDeltaPhiPt,
double  minDeltaMet 
)

Definition at line 329 of file PFAlgo.cc.

References particleFlow_cfi::maxDeltaPhiPt, maxDeltaPhiPt_, particleFlow_cfi::maxSignificance, maxSignificance_, particleFlow_cfi::minDeltaMet, minDeltaMet_, particleFlow_cfi::minHFCleaningPt, minHFCleaningPt_, particleFlow_cfi::minSignificance, minSignificance_, particleFlow_cfi::minSignificanceReduction, minSignificanceReduction_, particleFlow_cfi::postHFCleaning, and postHFCleaning_.

Referenced by setCandConnectorParameters().

std::shared_ptr<PFEnergyCalibration> PFAlgo::thePFEnergyCalibration ( )
inline

return the pointer to the calibration function

Definition at line 235 of file PFAlgo.h.

References patPFMETCorrections_cff::algo, calibration_, neutralHadronEnergyResolution(), nSigmaHCAL(), operator<<, MillePedeFileConverter_cfg::out, processBlock(), reconstructCluster(), reconstructTrack(), and setHcalDepthInfo().

Referenced by setCandConnectorParameters().

235  {
236  return calibration_;
237  }
std::shared_ptr< PFEnergyCalibration > calibration_
Definition: PFAlgo.h:328
std::unique_ptr< reco::PFCandidateCollection> PFAlgo::transferCandidates ( )
inline
Returns
unique_ptr to the collection of candidates (transfers ownership)

Definition at line 230 of file PFAlgo.h.

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

230  {
232  }
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:286
std::unique_ptr< reco::PFCandidateCollection > connect(std::unique_ptr< reco::PFCandidateCollection > &pfCand)
PFCandConnector connector_
Definition: PFAlgo.h:386
std::unique_ptr<reco::PFCandidateCollection> PFAlgo::transferCleanedCandidates ( )
inline
Returns
collection of cleaned HF candidates

Definition at line 225 of file PFAlgo.h.

References eostools::move(), and pfCleanedCandidates_.

225  {
227  }
std::unique_ptr< reco::PFCandidateCollection > pfCleanedCandidates_
Definition: PFAlgo.h:292
def move(src, dest)
Definition: eostools.py:511
std::unique_ptr<reco::PFCandidateCollection> PFAlgo::transferElectronCandidates ( )
inline
Returns
the unfiltered electron collection

Definition at line 202 of file PFAlgo.h.

References eostools::move(), and pfElectronCandidates_.

202  {
204  }
std::unique_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
Definition: PFAlgo.h:288
def move(src, dest)
Definition: eostools.py:511
std::unique_ptr<reco::PFCandidateElectronExtraCollection> PFAlgo::transferElectronExtra ( )
inline
Returns
the unfiltered electron extra collection

Definition at line 208 of file PFAlgo.h.

References pfElectronExtra_, and mps_fire::result.

208  {
209  auto result = std::make_unique<reco::PFCandidateElectronExtraCollection>();
210  result->insert(result->end(),pfElectronExtra_.begin(),pfElectronExtra_.end());
211  return result;
212  }
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
Definition: PFAlgo.h:295
std::unique_ptr< reco::PFCandidatePhotonExtraCollection> PFAlgo::transferPhotonExtra ( )
inline
Returns
the unfiltered photon extra collection

Definition at line 217 of file PFAlgo.h.

References pfPhotonExtra_, and mps_fire::result.

217  {
218  auto result = std::make_unique<reco::PFCandidatePhotonExtraCollection>();
219  result->insert(result->end(),pfPhotonExtra_.begin(),pfPhotonExtra_.end());
220  return result;
221  }
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
Definition: PFAlgo.h:297

Friends And Related Function Documentation

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

Referenced by thePFEnergyCalibration().

Member Data Documentation

int PFAlgo::algo_
private

Definition at line 333 of file PFAlgo.h.

Referenced by setAlgo().

bool PFAlgo::applyCrackCorrectionsElectrons_
private

Definition at line 342 of file PFAlgo.h.

Referenced by setPFEleParameters().

reco::PFBlockHandle PFAlgo::blockHandle_
private

input block handle (full framework case)

Definition at line 320 of file PFAlgo.h.

Referenced by createBlockRef(), and reconstructParticles().

std::shared_ptr<PFEnergyCalibration> PFAlgo::calibration_
private

Definition at line 328 of file PFAlgo.h.

Referenced by operator<<(), processBlock(), setParameters(), and thePFEnergyCalibration().

double PFAlgo::coneEcalIsoForEgammaSC_
private

Definition at line 348 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::coneTrackIsoForEgammaSC_
private

Definition at line 351 of file PFAlgo.h.

Referenced by setPFEleParameters().

PFCandConnector PFAlgo::connector_
private

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

Definition at line 386 of file PFAlgo.h.

Referenced by setCandConnectorParameters(), setDebug(), and transferCandidates().

bool PFAlgo::debug_
private
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 381 of file PFAlgo.h.

Referenced by processBlock(), reconstructTrack(), and setDisplacedVerticesParameters().

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

Definition at line 394 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

float PFAlgo::goodPixelTrackDeadHcal_chi2n_
private

Definition at line 406 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodPixelTrackDeadHcal_dxy_
private

Definition at line 409 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodPixelTrackDeadHcal_dz_
private

Definition at line 410 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

int PFAlgo::goodPixelTrackDeadHcal_maxLost3Hit_
private

Definition at line 407 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

int PFAlgo::goodPixelTrackDeadHcal_maxLost4Hit_
private

Definition at line 408 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodPixelTrackDeadHcal_maxPt_
private

Definition at line 404 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodPixelTrackDeadHcal_minEta_
private

Definition at line 403 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodPixelTrackDeadHcal_ptErrRel_
private

Definition at line 405 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodTrackDeadHcal_chi2n_
private

Definition at line 398 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodTrackDeadHcal_dxy_
private

Definition at line 401 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

int PFAlgo::goodTrackDeadHcal_layers_
private

Definition at line 399 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodTrackDeadHcal_ptErrRel_
private

Variables for track cleaning in bad HCal areas.

Definition at line 397 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodTrackDeadHcal_validFr_
private

Definition at line 400 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

double PFAlgo::maxDeltaPhiPt_
private

Definition at line 420 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::maxSignificance_
private

Definition at line 418 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minDeltaMet_
private

Definition at line 421 of file PFAlgo.h.

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

double PFAlgo::minHFCleaningPt_
private

Definition at line 416 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minSignificance_
private

Definition at line 417 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minSignificanceReduction_
private

Definition at line 419 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

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

Definition at line 390 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

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

Definition at line 428 of file PFAlgo.h.

Referenced by reconstructParticles(), and setMuonHandle().

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

Variables for muons and fakes.

Definition at line 389 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

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

Definition at line 391 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

double PFAlgo::mvaEleCut_
private

Definition at line 339 of file PFAlgo.h.

Referenced by setPFEleParameters().

std::string PFAlgo::mvaWeightFileEleID_
private

Variables for PFElectrons.

Definition at line 337 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::nSigmaECAL_
private

number of sigma to judge energy excess in ECAL

Definition at line 323 of file PFAlgo.h.

Referenced by operator<<(), processBlock(), and setParameters().

double PFAlgo::nSigmaHCAL_
private

number of sigma to judge energy excess in HCAL

Definition at line 326 of file PFAlgo.h.

Referenced by nSigmaHCAL(), operator<<(), and setParameters().

double PFAlgo::nSigmaTRACK_
private

Definition at line 392 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

unsigned int PFAlgo::nTrackIsoForEgammaSC_
private

Definition at line 352 of file PFAlgo.h.

Referenced by setPFEleParameters().

int PFAlgo::nVtx_
private

Definition at line 382 of file PFAlgo.h.

Referenced by processBlock(), and setPFVertexParameters().

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

Definition at line 292 of file PFAlgo.h.

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

PFEGammaFilters* PFAlgo::pfegamma_
private

Definition at line 360 of file PFAlgo.h.

Referenced by processBlock(), setDebug(), setEGammaParameters(), and ~PFAlgo().

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

Definition at line 362 of file PFAlgo.h.

Referenced by processBlock(), and setEGammaCollections().

PFElectronAlgo* PFAlgo::pfele_
private

Definition at line 353 of file PFAlgo.h.

Referenced by processBlock(), setEGElectronCollection(), setPFEleParameters(), and ~PFAlgo().

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

the unfiltered electron collection

Definition at line 288 of file PFAlgo.h.

Referenced by processBlock(), reconstructParticles(), setElectronExtraRef(), and transferElectronCandidates().

reco::PFCandidateElectronExtraCollection PFAlgo::pfElectronExtra_
private

the unfiltered electron collection

Definition at line 295 of file PFAlgo.h.

Referenced by processBlock(), reconstructParticles(), setElectronExtraRef(), and transferElectronExtra().

PFMuonAlgo* PFAlgo::pfmu_
private
PFPhotonAlgo* PFAlgo::pfpho_
private
std::unique_ptr<reco::PFCandidateCollection> PFAlgo::pfPhotonCandidates_
private

the unfiltered photon collection

Definition at line 290 of file PFAlgo.h.

Referenced by processBlock(), and reconstructParticles().

reco::PFCandidatePhotonExtraCollection PFAlgo::pfPhotonExtra_
private

the extra photon collection

Definition at line 297 of file PFAlgo.h.

Referenced by processBlock(), reconstructParticles(), setPhotonExtraRef(), and transferPhotonExtra().

bool PFAlgo::postHFCleaning_
private

Definition at line 414 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

bool PFAlgo::postMuonCleaning_
private

Definition at line 415 of file PFAlgo.h.

reco::Vertex PFAlgo::primaryVertex_
private
double PFAlgo::ptError_
private

Definition at line 393 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

bool PFAlgo::rejectTracks_Bad_
private

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

Definition at line 372 of file PFAlgo.h.

Referenced by processBlock(), and setDisplacedVerticesParameters().

bool PFAlgo::rejectTracks_Step45_
private

Definition at line 373 of file PFAlgo.h.

Referenced by processBlock(), and setDisplacedVerticesParameters().

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

Definition at line 338 of file PFAlgo.h.

double PFAlgo::sumEtEcalIsoForEgammaSC_barrel_
private

Definition at line 346 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumEtEcalIsoForEgammaSC_endcap_
private

Definition at line 347 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumPtTrackIsoForEgammaSC_barrel_
private

Definition at line 349 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumPtTrackIsoForEgammaSC_endcap_
private

Definition at line 350 of file PFAlgo.h.

Referenced by setPFEleParameters().

std::shared_ptr<PFEnergyCalibrationHF> PFAlgo::thepfEnergyCalibrationHF_
private

Definition at line 329 of file PFAlgo.h.

Referenced by processBlock(), and setParameters().

std::shared_ptr<PFSCEnergyCalibration> PFAlgo::thePFSCEnergyCalibration_
private

Definition at line 330 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::useBestMuonTrack_
private

Definition at line 422 of file PFAlgo.h.

bool PFAlgo::useEGammaFilters_
private

Variables for NEW EGAMMA selection.

Definition at line 359 of file PFAlgo.h.

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

bool PFAlgo::useEGammaSupercluster_
private

Definition at line 345 of file PFAlgo.h.

Referenced by setPFEleParameters().

bool PFAlgo::useEGElectrons_
private

Definition at line 344 of file PFAlgo.h.

Referenced by setEGElectronCollection(), and setPFEleParameters().

bool PFAlgo::useHO_
private

Definition at line 332 of file PFAlgo.h.

Referenced by processBlock(), and setHOTag().

bool PFAlgo::usePFConversions_
private

Definition at line 376 of file PFAlgo.h.

Referenced by processBlock(), and setDisplacedVerticesParameters().

bool PFAlgo::usePFDecays_
private

Definition at line 377 of file PFAlgo.h.

Referenced by isFromSecInt(), and setDisplacedVerticesParameters().

bool PFAlgo::usePFElectrons_
private

Definition at line 340 of file PFAlgo.h.

Referenced by processBlock(), setElectronExtraRef(), setPFEleParameters(), and ~PFAlgo().

bool PFAlgo::usePFMuonMomAssign_
private

Definition at line 368 of file PFAlgo.h.

bool PFAlgo::usePFNuclearInteractions_
private

Definition at line 375 of file PFAlgo.h.

Referenced by isFromSecInt(), and setDisplacedVerticesParameters().

bool PFAlgo::usePFPhotons_
private
bool PFAlgo::usePFSCEleCalib_
private

Definition at line 343 of file PFAlgo.h.

Referenced by setPFEleParameters().

bool PFAlgo::useProtectionsForJetMET_
private

Definition at line 361 of file PFAlgo.h.

Referenced by processBlock(), and setEGammaParameters().

bool PFAlgo::useVertices_
private

Definition at line 426 of file PFAlgo.h.

Referenced by reconstructCluster(), setPFPhotonParameters(), and setPFVertexParameters().

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

Definition at line 363 of file PFAlgo.h.

Referenced by setEGammaCollections().

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

Definition at line 364 of file PFAlgo.h.

Referenced by setEGammaCollections().