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 (bool debug)
 constructor More...
 
const std::unique_ptr< reco::PFCandidateCollection > & pfCandidates () const
 
void reconstructParticles (const reco::PFBlockHandle &blockHandle, PFEGammaFilters const *pfegamma)
 
void reconstructParticles (const reco::PFBlockCollection &blocks, PFEGammaFilters const *pfegamma)
 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 setDisplacedVerticesParameters (bool rejectTracks_Bad, bool rejectTracks_Step45, bool usePFNuclearInteractions, bool usePFConversions, bool usePFDecays, double dptRel_DispVtx)
 
void setEGammaCollections (const edm::View< reco::PFCandidate > &pfEgammaCandidates, const edm::ValueMap< reco::GsfElectronRef > &valueMapGedElectrons, const edm::ValueMap< reco::PhotonRef > &valueMapGedPhotons)
 
void setEGammaParameters (bool use_EGammaFilters, bool useProtectionsForJetMET)
 
void setEGElectronCollection (const reco::GsfElectronCollection &egelectrons)
 
void 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, reco::VertexCollection const &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...
 
reco::PFCandidateCollection transferCandidates ()
 
std::unique_ptr< reco::PFCandidateCollectiontransferCleanedCandidates ()
 
std::unique_ptr< reco::PFCandidateCollectiontransferElectronCandidates ()
 
std::unique_ptr< reco::PFCandidateElectronExtraCollectiontransferElectronExtra ()
 
std::unique_ptr< reco::PFCandidatePhotonExtraCollectiontransferPhotonExtra ()
 

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, PFEGammaFilters const *pfegamma)
 
unsigned reconstructCluster (const reco::PFCluster &cluster, double particleEnergy, bool useDirection=false, double particleX=0., double particleY=0., double particleZ=0.)
 
unsigned reconstructTrack (const reco::PFBlockElement &elt, bool allowLoose=false)
 
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_
 
const 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_
 
const edm::View< reco::PFCandidate > * pfEgammaCandidates_
 
std::unique_ptr< PFElectronAlgopfele_
 
std::unique_ptr< reco::PFCandidateCollectionpfElectronCandidates_
 the unfiltered electron collection More...
 
reco::PFCandidateElectronExtraCollection pfElectronExtra_
 the unfiltered electron collection More...
 
PFMuonAlgopfmu_
 
std::unique_ptr< 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 50 of file PFAlgo.h.

Constructor & Destructor Documentation

PFAlgo::PFAlgo ( bool  debug)

constructor

Definition at line 49 of file PFAlgo.cc.

51  nSigmaECAL_(0),
52  nSigmaHCAL_(1),
53  algo_(1),
54  debug_(debug),
55  pfele_(nullptr),
56  pfpho_(nullptr),
58  useVertices_(false)
59 {}
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:264
std::unique_ptr< PFElectronAlgo > pfele_
Definition: PFAlgo.h:331
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:304
PFCandConnector connector_
Definition: PFAlgo.h:363
int algo_
Definition: PFAlgo.h:311
std::unique_ptr< PFPhotonAlgo > pfpho_
Definition: PFAlgo.h:332
std::vector< reco::PFCandidate > PFCandidateCollection
collection of PFCandidates
#define debug
Definition: HDRShower.cc:19
bool useVertices_
Definition: PFAlgo.h:403
const bool debug_
Definition: PFAlgo.h:312
double nSigmaECAL_
number of sigma to judge energy excess in ECAL
Definition: PFAlgo.h:301

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 3421 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().

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

3614  {
3615 
3616 
3617  // No hits to recover, leave.
3618  if ( cleanedHits.empty() ) return;
3619 
3620  //Compute met and met significance (met/sqrt(SumEt))
3621  double metX = 0.;
3622  double metY = 0.;
3623  double sumet = 0;
3624  std::vector<unsigned int> hitsToBeAdded;
3625  for(auto const& pfc : *pfCandidates_) {
3626  metX += pfc.px();
3627  metY += pfc.py();
3628  sumet += pfc.pt();
3629  }
3630  double met2 = metX*metX+metY*metY;
3631  double met2_Original = met2;
3632  // Select events with large MET significance.
3633  // double significance = std::sqrt(met2/sumet);
3634  // double significanceCor = significance;
3635  double metXCor = metX;
3636  double metYCor = metY;
3637  double sumetCor = sumet;
3638  double met2Cor = met2;
3639  bool next = true;
3640  unsigned iCor = 1E9;
3641 
3642  // Find the cleaned hit with the largest effect on the MET
3643  while ( next ) {
3644 
3645  double metReduc = -1.;
3646  // Loop on the candidates
3647  for(unsigned i=0; i<cleanedHits.size(); ++i) {
3648  const PFRecHit& hit = cleanedHits[i];
3649  double length = std::sqrt(hit.position().mag2());
3650  double px = hit.energy() * hit.position().x()/length;
3651  double py = hit.energy() * hit.position().y()/length;
3652  double pt = std::sqrt(px*px + py*py);
3653 
3654  // Check that it is not already scheculed to be cleaned
3655  bool skip = false;
3656  for(unsigned int hitIdx : hitsToBeAdded) {
3657  if ( i == hitIdx ) skip = true;
3658  if ( skip ) break;
3659  }
3660  if ( skip ) continue;
3661 
3662  // Now add the candidate to the MET
3663  double metXInt = metX + px;
3664  double metYInt = metY + py;
3665  double sumetInt = sumet + pt;
3666  double met2Int = metXInt*metXInt+metYInt*metYInt;
3667 
3668  // And check if it could contribute to a MET reduction
3669  if ( met2Int < met2Cor ) {
3670  metXCor = metXInt;
3671  metYCor = metYInt;
3672  metReduc = (met2-met2Int)/met2Int;
3673  met2Cor = met2Int;
3674  sumetCor = sumetInt;
3675  // significanceCor = std::sqrt(met2Cor/sumetCor);
3676  iCor = i;
3677  }
3678  }
3679  //
3680  // If the MET must be significanly reduced, schedule the candidate to be added
3681  //
3682  if ( metReduc > minDeltaMet_ ) {
3683  hitsToBeAdded.push_back(iCor);
3684  metX = metXCor;
3685  metY = metYCor;
3686  sumet = sumetCor;
3687  met2 = met2Cor;
3688  } else {
3689  // Otherwise just stop the loop
3690  next = false;
3691  }
3692  }
3693  //
3694  // At least 10 GeV MET reduction
3695  if ( std::sqrt(met2_Original) - std::sqrt(met2) > 5. ) {
3696  if ( debug_ ) {
3697  std::cout << hitsToBeAdded.size() << " hits were re-added " << std::endl;
3698  std::cout << "MET reduction = " << std::sqrt(met2_Original) << " -> "
3699  << std::sqrt(met2Cor) << " = " << std::sqrt(met2Cor) - std::sqrt(met2_Original)
3700  << std::endl;
3701  std::cout << "Added after cleaning check : " << std::endl;
3702  }
3703  for(unsigned int hitIdx : hitsToBeAdded) {
3704  const PFRecHit& hit = cleanedHits[hitIdx];
3705  PFCluster cluster(hit.layer(), hit.energy(),
3706  hit.position().x(), hit.position().y(), hit.position().z() );
3707  reconstructCluster(cluster,hit.energy());
3708  if ( debug_ ) {
3709  std::cout << pfCandidates_->back() << ". time = " << hit.time() << std::endl;
3710  }
3711  }
3712  }
3713 
3714 }
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:398
float time() const
timing for cleaned hits
Definition: PFRecHit.h:118
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:264
unsigned reconstructCluster(const reco::PFCluster &cluster, double particleEnergy, bool useDirection=false, double particleX=0., double particleY=0., double particleZ=0.)
Definition: PFAlgo.cc:3215
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
const bool debug_
Definition: PFAlgo.h:312
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 3409 of file PFAlgo.cc.

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

Referenced by reconstructParticles().

3410  {
3411 
3412  if( blockHandle_.isValid() ) {
3413  return reco::PFBlockRef( blockHandle_, bi );
3414  }
3415  else {
3416  return reco::PFBlockRef( &blocks, bi );
3417  }
3418 }
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:298
PFMuonAlgo * PFAlgo::getPFMuonAlgo ( )

Definition at line 76 of file PFAlgo.cc.

References pfmu_.

Referenced by PFProducer::produce(), and setCandConnectorParameters().

76  {
77  return pfmu_;
78 }
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:333
bool PFAlgo::isFromSecInt ( const reco::PFBlockElement eTrack,
std::string  order 
) const
private

Definition at line 3475 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().

3475  {
3476 
3479  // reco::PFBlockElement::TrackType T_FROM_GAMMACONV = reco::PFBlockElement::T_FROM_GAMMACONV;
3481 
3482  bool bPrimary = (order.find("primary") != string::npos);
3483  bool bSecondary = (order.find("secondary") != string::npos);
3484  bool bAll = (order.find("all") != string::npos);
3485 
3486  bool isToDisp = usePFNuclearInteractions_ && eTrack.trackType(T_TO_DISP);
3487  bool isFromDisp = usePFNuclearInteractions_ && eTrack.trackType(T_FROM_DISP);
3488 
3489  if (bPrimary && isToDisp) return true;
3490  if (bSecondary && isFromDisp ) return true;
3491  if (bAll && ( isToDisp || isFromDisp ) ) return true;
3492 
3493 // bool isFromConv = usePFConversions_ && eTrack.trackType(T_FROM_GAMMACONV);
3494 
3495 // if ((bAll || bSecondary)&& isFromConv) return true;
3496 
3497  bool isFromDecay = (bAll || bSecondary) && usePFDecays_ && eTrack.trackType(T_FROM_V0);
3498 
3499  return isFromDecay;
3500 
3501 
3502 }
bool usePFNuclearInteractions_
Definition: PFAlgo.h:352
virtual bool trackType(TrackType trType) const
bool usePFDecays_
Definition: PFAlgo.h:354
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 3360 of file PFAlgo.cc.

References mathSSE::sqrt().

Referenced by processBlock(), and thePFEnergyCalibration().

3360  {
3361 
3362  // Add a protection
3363  if ( clusterEnergyHCAL < 1. ) clusterEnergyHCAL = 1.;
3364 
3365  double resol = fabs(eta) < 1.48 ?
3366  sqrt (1.02*1.02/clusterEnergyHCAL + 0.065*0.065)
3367  :
3368  sqrt (1.20*1.20/clusterEnergyHCAL + 0.028*0.028);
3369 
3370  return resol;
3371 
3372 }
T sqrt(T t)
Definition: SSEVec.h:18
double PFAlgo::nSigmaHCAL ( double  clusterEnergy,
double  clusterEta 
) const
private

Definition at line 3375 of file PFAlgo.cc.

References JetChargeProducer_cfi::exp, and nSigmaHCAL_.

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

3375  {
3376  double nS = fabs(eta) < 1.48 ?
3377  nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL/100.))
3378  :
3379  nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL/100.));
3380 
3381  return nS;
3382 }
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:304
const std::unique_ptr<reco::PFCandidateCollection>& PFAlgo::pfCandidates ( ) const
inline
Returns
collection of candidates

Definition at line 175 of file PFAlgo.h.

References pfCandidates_.

Referenced by operator<<().

175  {
176  return pfCandidates_;
177  }
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:264
void PFAlgo::postCleaning ( )
private

Definition at line 3511 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(), met_cff::significance, createPayload::skip, and mathSSE::sqrt().

Referenced by reconstructParticles().

3511  {
3512 
3513  // Check if the post HF Cleaning was requested - if not, do nothing
3514  if ( !postHFCleaning_ ) return;
3515 
3516  //Compute met and met significance (met/sqrt(SumEt))
3517  double metX = 0.;
3518  double metY = 0.;
3519  double sumet = 0;
3520  std::vector<unsigned int> pfCandidatesToBeRemoved;
3521  for(auto const& pfc : *pfCandidates_) {
3522  metX += pfc.px();
3523  metY += pfc.py();
3524  sumet += pfc.pt();
3525  }
3526  double met2 = metX*metX+metY*metY;
3527  // Select events with large MET significance.
3528  double significance = std::sqrt(met2/sumet);
3529  double significanceCor = significance;
3530  if ( significance > minSignificance_ ) {
3531 
3532  double metXCor = metX;
3533  double metYCor = metY;
3534  double sumetCor = sumet;
3535  double met2Cor = met2;
3536  double deltaPhi = 3.14159;
3537  double deltaPhiPt = 100.;
3538  bool next = true;
3539  unsigned iCor = 1E9;
3540 
3541  // Find the HF candidate with the largest effect on the MET
3542  while ( next ) {
3543 
3544  double metReduc = -1.;
3545  // Loop on the candidates
3546  for(unsigned i=0; i<pfCandidates_->size(); ++i) {
3547  const PFCandidate& pfc = (*pfCandidates_)[i];
3548 
3549  // Check that the pfCandidate is in the HF
3550  if ( pfc.particleId() != reco::PFCandidate::h_HF &&
3551  pfc.particleId() != reco::PFCandidate::egamma_HF ) continue;
3552 
3553  // Check if has meaningful pt
3554  if ( pfc.pt() < minHFCleaningPt_ ) continue;
3555 
3556  // Check that it is not already scheculed to be cleaned
3557  const bool skip = std::any_of(pfCandidatesToBeRemoved.begin(), pfCandidatesToBeRemoved.end(),
3558  [&](unsigned int j){ return i == j; });
3559  if ( skip ) continue;
3560 
3561  // Check that the pt and the MET are aligned
3562  deltaPhi = std::acos((metX*pfc.px()+metY*pfc.py())/(pfc.pt()*std::sqrt(met2)));
3563  deltaPhiPt = deltaPhi*pfc.pt();
3564  if ( deltaPhiPt > maxDeltaPhiPt_ ) continue;
3565 
3566  // Now remove the candidate from the MET
3567  double metXInt = metX - pfc.px();
3568  double metYInt = metY - pfc.py();
3569  double sumetInt = sumet - pfc.pt();
3570  double met2Int = metXInt*metXInt+metYInt*metYInt;
3571  if ( met2Int < met2Cor ) {
3572  metXCor = metXInt;
3573  metYCor = metYInt;
3574  metReduc = (met2-met2Int)/met2Int;
3575  met2Cor = met2Int;
3576  sumetCor = sumetInt;
3577  significanceCor = std::sqrt(met2Cor/sumetCor);
3578  iCor = i;
3579  }
3580  }
3581  //
3582  // If the MET must be significanly reduced, schedule the candidate to be cleaned
3583  if ( metReduc > minDeltaMet_ ) {
3584  pfCandidatesToBeRemoved.push_back(iCor);
3585  metX = metXCor;
3586  metY = metYCor;
3587  sumet = sumetCor;
3588  met2 = met2Cor;
3589  } else {
3590  // Otherwise just stop the loop
3591  next = false;
3592  }
3593  }
3594  //
3595  // The significance must be significantly reduced to indeed clean the candidates
3596  if ( significance - significanceCor > minSignificanceReduction_ &&
3597  significanceCor < maxSignificance_ ) {
3598  std::cout << "Significance reduction = " << significance << " -> "
3599  << significanceCor << " = " << significanceCor - significance
3600  << std::endl;
3601  for(unsigned int toRemove : pfCandidatesToBeRemoved) {
3602  std::cout << "Removed : " << (*pfCandidates_)[toRemove] << std::endl;
3603  pfCleanedCandidates_->push_back( (*pfCandidates_)[toRemove] );
3604  (*pfCandidates_)[toRemove].rescaleMomentum(1E-6);
3605  //reco::PFCandidate::ParticleType unknown = reco::PFCandidate::X;
3606  //(*pfCandidates_)[toRemove].setParticleType(unknown);
3607  }
3608  }
3609  }
3610 
3611 }
double maxDeltaPhiPt_
Definition: PFAlgo.h:397
double maxSignificance_
Definition: PFAlgo.h:395
double minHFCleaningPt_
Definition: PFAlgo.h:393
double minDeltaMet_
Definition: PFAlgo.h:398
double minSignificance_
Definition: PFAlgo.h:394
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:264
double px() const final
x coordinate of momentum vector
double pt() const final
transverse momentum
double minSignificanceReduction_
Definition: PFAlgo.h:396
std::unique_ptr< reco::PFCandidateCollection > pfCleanedCandidates_
Definition: PFAlgo.h:270
bool postHFCleaning_
Definition: PFAlgo.h:391
T sqrt(T t)
Definition: SSEVec.h:18
double py() const final
y coordinate of momentum vector
significance
Definition: met_cff.py:19
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,
PFEGammaFilters const *  pfegamma 
)
private

process one block. can be reimplemented in more sophisticated algorithms

Definition at line 465 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_, MillePedeFileConverter_cfg::e, 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, 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(), isFromSecInt(), PFMuonAlgo::isGlobalTightMuon(), PFMuonAlgo::isIsolatedMuon(), PFMuonAlgo::isLooseMuon(), PFMuonAlgo::isMuon(), edm::Ref< C, T, F >::isNonnull(), edm::Ref< C, T, F >::isNull(), PFEGammaFilters::isPhotonSafeForJetMET(), 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_, 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().

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

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

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

Definition at line 344 of file PFAlgo.cc.

References blockHandle_.

Referenced by PFProducer::produce(), and setCandConnectorParameters().

344  {
345 
346  blockHandle_ = blockHandle;
347  reconstructParticles( *blockHandle_, pfegamma );
348 }
void reconstructParticles(const reco::PFBlockHandle &blockHandle, PFEGammaFilters const *pfegamma)
Definition: PFAlgo.cc:344
reco::PFBlockHandle blockHandle_
input block handle (full framework case)
Definition: PFAlgo.h:298
void PFAlgo::reconstructParticles ( const reco::PFBlockCollection blocks,
PFEGammaFilters const *  pfegamma 
)

reconstruct particles

Definition at line 350 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().

350  {
351 
352  // reset output collection
353  if(pfCandidates_.get() )
354  pfCandidates_->clear();
355  else
357 
358  if(pfElectronCandidates_.get() )
359  pfElectronCandidates_->clear();
360  else
362 
363  // Clearing pfPhotonCandidates
364  if( pfPhotonCandidates_.get() )
365  pfPhotonCandidates_->clear();
366  else
368 
369  if(pfCleanedCandidates_.get() )
370  pfCleanedCandidates_->clear();
371  else
373 
374  // not a unique_ptr; should not be deleted after transfer
375  pfElectronExtra_.clear();
376  pfPhotonExtra_.clear();
377 
378  if( debug_ ) {
379  cout<<"*********************************************************"<<endl;
380  cout<<"***** Particle flow algorithm *****"<<endl;
381  cout<<"*********************************************************"<<endl;
382  }
383 
384  // sort elements in three lists:
385  std::list< reco::PFBlockRef > hcalBlockRefs;
386  std::list< reco::PFBlockRef > ecalBlockRefs;
387  std::list< reco::PFBlockRef > hoBlockRefs;
388  std::list< reco::PFBlockRef > otherBlockRefs;
389 
390  for( unsigned i=0; i<blocks.size(); ++i ) {
391  // reco::PFBlockRef blockref( blockh,i );
392  reco::PFBlockRef blockref = createBlockRef( blocks, i);
393 
394  const reco::PFBlock& block = *blockref;
396  elements = block.elements();
397 
398  bool singleEcalOrHcal = false;
399  if( elements.size() == 1 ){
400  if( elements[0].type() == reco::PFBlockElement::ECAL ){
401  ecalBlockRefs.push_back( blockref );
402  singleEcalOrHcal = true;
403  }
404  if( elements[0].type() == reco::PFBlockElement::HCAL ){
405  hcalBlockRefs.push_back( blockref );
406  singleEcalOrHcal = true;
407  }
408  if( elements[0].type() == reco::PFBlockElement::HO ){
409  // Single HO elements are likely to be noise. Not considered for now.
410  hoBlockRefs.push_back( blockref );
411  singleEcalOrHcal = true;
412  }
413  }
414 
415  if(!singleEcalOrHcal) {
416  otherBlockRefs.push_back( blockref );
417  }
418  }//loop blocks
419 
420  if( debug_ ){
421  cout<<"# Ecal blocks: "<<ecalBlockRefs.size()
422  <<", # Hcal blocks: "<<hcalBlockRefs.size()
423  <<", # HO blocks: "<<hoBlockRefs.size()
424  <<", # Other blocks: "<<otherBlockRefs.size()<<endl;
425  }
426 
427 
428  // loop on blocks that are not single ecal,
429  // and not single hcal.
430 
431  unsigned nblcks = 0;
432  for(auto const& other : otherBlockRefs) {
433  if ( debug_ ) std::cout << "Block number " << nblcks++ << std::endl;
434  processBlock( other, hcalBlockRefs, ecalBlockRefs, pfegamma );
435  }
436 
437  std::list< reco::PFBlockRef > empty;
438 
439  unsigned hblcks = 0;
440  // process remaining single hcal blocks
441  for(auto const& hcal : hcalBlockRefs) {
442  if ( debug_ ) std::cout << "HCAL block number " << hblcks++ << std::endl;
443  processBlock( hcal, empty, empty, pfegamma );
444  }
445 
446  unsigned eblcks = 0;
447  // process remaining single ecal blocks
448  for(auto const& ecal : ecalBlockRefs) {
449  if ( debug_ ) std::cout << "ECAL block number " << eblcks++ << std::endl;
450  processBlock( ecal, empty, empty, pfegamma );
451  }
452 
453  // Post HF Cleaning
454  postCleaning();
455 
456  //Muon post cleaning
457  pfmu_->postClean(pfCandidates_.get());
458 
459  //Add Missing muons
460  if( muonHandle_.isValid())
462 }
type
Definition: HCALResponse.h:21
void addMissingMuons(edm::Handle< reco::MuonCollection >, reco::PFCandidateCollection *cands)
Definition: PFMuonAlgo.cc:863
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:264
size_type size() const
Definition: OwnVector.h:264
const edm::OwnVector< reco::PFBlockElement > & elements() const
Definition: PFBlock.h:107
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:333
std::unique_ptr< reco::PFCandidateCollection > pfCleanedCandidates_
Definition: PFAlgo.h:270
edm::Handle< reco::MuonCollection > muonHandle_
Definition: PFAlgo.h:405
bool isValid() const
Definition: HandleBase.h:74
void processBlock(const reco::PFBlockRef &blockref, std::list< reco::PFBlockRef > &hcalBlockRefs, std::list< reco::PFBlockRef > &ecalBlockRefs, PFEGammaFilters const *pfegamma)
Definition: PFAlgo.cc:465
reco::PFBlockRef createBlockRef(const reco::PFBlockCollection &blocks, unsigned bi)
Definition: PFAlgo.cc:3409
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
Definition: PFAlgo.h:275
std::unique_ptr< reco::PFCandidateCollection > pfPhotonCandidates_
the unfiltered photon collection
Definition: PFAlgo.h:268
std::vector< reco::PFCandidate > PFCandidateCollection
collection of PFCandidates
std::unique_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
Definition: PFAlgo.h:266
const bool debug_
Definition: PFAlgo.h:312
void postCleaning()
Definition: PFAlgo.cc:3511
void postClean(reco::PFCandidateCollection *)
Definition: PFMuonAlgo.cc:759
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
Definition: PFAlgo.h:273
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 3136 of file PFAlgo.cc.

References ALCARECOTkAlJpsiMuMu_cff::charge, reco::TrackBase::charge(), gather_cfg::cout, debug_, dptRel_DispVtx_, randomXiThetaGunProducer_cfi::energy, 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().

3136  {
3137 
3138  const auto* eltTrack = dynamic_cast<const reco::PFBlockElementTrack*>(&elt);
3139 
3140  const reco::TrackRef& trackRef = eltTrack->trackRef();
3141  const reco::Track& track = *trackRef;
3142  const reco::MuonRef& muonRef = eltTrack->muonRef();
3143  int charge = track.charge()>0 ? 1 : -1;
3144 
3145  // Assume this particle is a charged Hadron
3146  double px = track.px();
3147  double py = track.py();
3148  double pz = track.pz();
3149  double energy = sqrt(track.p()*track.p() + 0.13957*0.13957);
3150 
3151  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;
3152 
3153 
3154  // Create a PF Candidate
3155  ::math::XYZTLorentzVector momentum(px,py,pz,energy);
3158 
3159  // Add it to the stack
3160  pfCandidates_->push_back( PFCandidate( charge,
3161  momentum,
3162  particleType ) );
3163  //Set vertex and stuff like this
3164  pfCandidates_->back().setVertexSource( PFCandidate::kTrkVertex );
3165  pfCandidates_->back().setTrackRef( trackRef );
3166  pfCandidates_->back().setPositionAtECALEntrance( eltTrack->positionAtECALEntrance());
3167  if( muonRef.isNonnull())
3168  pfCandidates_->back().setMuonRef( muonRef );
3169 
3170 
3171  //Set time
3172  if (elt.isTimeValid()) pfCandidates_->back().setTime( elt.time(), elt.timeError() );
3173 
3174  //OK Now try to reconstruct the particle as a muon
3175  bool isMuon=pfmu_->reconstructMuon(pfCandidates_->back(),muonRef,allowLoose);
3176  bool isFromDisp = isFromSecInt(elt, "secondary");
3177 
3178 
3179  if ((!isMuon) && isFromDisp) {
3180  double Dpt = trackRef->ptError();
3181  double dptRel = Dpt/trackRef->pt()*100;
3182  //If the track is ill measured it is better to not refit it, since the track information probably would not be used.
3183  //In the PFAlgo we use the trackref information. If the track error is too big the refitted information might be very different
3184  // from the not refitted one.
3185  if (dptRel < dptRel_DispVtx_){
3186  if (debug_)
3187  cout << "Not refitted px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
3188  //reco::TrackRef trackRef = eltTrack->trackRef();
3189  reco::PFDisplacedVertexRef vRef = eltTrack->displacedVertexRef(reco::PFBlockElement::T_FROM_DISP)->displacedVertexRef();
3190  reco::Track trackRefit = vRef->refittedTrack(trackRef);
3191  //change the momentum with the refitted track
3192  ::math::XYZTLorentzVector momentum(trackRefit.px(),
3193  trackRefit.py(),
3194  trackRefit.pz(),
3195  sqrt(trackRefit.p()*trackRefit.p() + 0.13957*0.13957));
3196  if (debug_)
3197  cout << "Refitted px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
3198  }
3199  pfCandidates_->back().setFlag( reco::PFCandidate::T_FROM_DISP, true);
3200  pfCandidates_->back().setDisplacedVertexRef( eltTrack->displacedVertexRef(reco::PFBlockElement::T_FROM_DISP)->displacedVertexRef(), reco::PFCandidate::T_FROM_DISP);
3201  }
3202 
3203  // 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
3204  if(isFromSecInt(elt, "primary") && !isMuon) {
3205  pfCandidates_->back().setFlag( reco::PFCandidate::T_TO_DISP, true);
3206  pfCandidates_->back().setDisplacedVertexRef( eltTrack->displacedVertexRef(reco::PFBlockElement::T_TO_DISP)->displacedVertexRef(), reco::PFCandidate::T_TO_DISP);
3207  }
3208 
3209  // returns index to the newly created PFCandidate
3210  return pfCandidates_->size()-1;
3211 }
double p() const
momentum vector magnitude
Definition: TrackBase.h:648
bool isFromSecInt(const reco::PFBlockElement &eTrack, std::string order) const
Definition: PFAlgo.cc:3475
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:264
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:333
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:358
int charge() const
track electric charge
Definition: TrackBase.h:600
const bool debug_
Definition: PFAlgo.h:312
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:627
void PFAlgo::setAlgo ( int  algo)
inline

Definition at line 58 of file PFAlgo.h.

References patPFMETCorrections_cff::algo, and algo_.

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

Definition at line 244 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 PFProducer::PFProducer(), and setCandConnectorParameters().

245 {
246  goodTrackDeadHcal_ptErrRel_ = pset.getParameter<double>("goodTrackDeadHcal_ptErrRel");
247  goodTrackDeadHcal_chi2n_ = pset.getParameter<double>("goodTrackDeadHcal_chi2n");
248  goodTrackDeadHcal_layers_ = pset.getParameter<uint32_t>("goodTrackDeadHcal_layers");
249  goodTrackDeadHcal_validFr_ = pset.getParameter<double>("goodTrackDeadHcal_validFr");
250  goodTrackDeadHcal_dxy_ = pset.getParameter<double>("goodTrackDeadHcal_dxy");
251 
252  goodPixelTrackDeadHcal_minEta_ = pset.getParameter<double>("goodPixelTrackDeadHcal_minEta");
253  goodPixelTrackDeadHcal_maxPt_ = pset.getParameter<double>("goodPixelTrackDeadHcal_maxPt");
254  goodPixelTrackDeadHcal_ptErrRel_ = pset.getParameter<double>("goodPixelTrackDeadHcal_ptErrRel");
255  goodPixelTrackDeadHcal_chi2n_ = pset.getParameter<double>("goodPixelTrackDeadHcal_chi2n");
256  goodPixelTrackDeadHcal_maxLost3Hit_ = pset.getParameter<int32_t>("goodPixelTrackDeadHcal_maxLost3Hit");
257  goodPixelTrackDeadHcal_maxLost4Hit_ = pset.getParameter<int32_t>("goodPixelTrackDeadHcal_maxLost4Hit");
258  goodPixelTrackDeadHcal_dxy_ = pset.getParameter<double>("goodPixelTrackDeadHcal_dxy");
259  goodPixelTrackDeadHcal_dz_ = pset.getParameter<double>("goodPixelTrackDeadHcal_dz");
260 }
T getParameter(std::string const &) const
float goodTrackDeadHcal_dxy_
Definition: PFAlgo.h:378
float goodPixelTrackDeadHcal_minEta_
Definition: PFAlgo.h:380
float goodPixelTrackDeadHcal_dxy_
Definition: PFAlgo.h:386
float goodTrackDeadHcal_validFr_
Definition: PFAlgo.h:377
int goodPixelTrackDeadHcal_maxLost3Hit_
Definition: PFAlgo.h:384
float goodPixelTrackDeadHcal_maxPt_
Definition: PFAlgo.h:381
int goodTrackDeadHcal_layers_
Definition: PFAlgo.h:376
float goodPixelTrackDeadHcal_ptErrRel_
Definition: PFAlgo.h:382
float goodTrackDeadHcal_ptErrRel_
Variables for track cleaning in bad HCal areas.
Definition: PFAlgo.h:374
int goodPixelTrackDeadHcal_maxLost4Hit_
Definition: PFAlgo.h:385
float goodPixelTrackDeadHcal_chi2n_
Definition: PFAlgo.h:383
float goodTrackDeadHcal_chi2n_
Definition: PFAlgo.h:375
float goodPixelTrackDeadHcal_dz_
Definition: PFAlgo.h:387
void PFAlgo::setCandConnectorParameters ( const edm::ParameterSet iCfgCandConnector)
inline

Definition at line 67 of file PFAlgo.h.

References connector_, and PFCandConnector::setParameters().

Referenced by PFProducer::PFProducer().

67  {
68  connector_.setParameters(iCfgCandConnector);
69  }
PFCandConnector connector_
Definition: PFAlgo.h:363
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 71 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::setDisplacedVerticesParameters ( bool  rejectTracks_Bad,
bool  rejectTracks_Step45,
bool  usePFNuclearInteractions,
bool  usePFConversions,
bool  usePFDecays,
double  dptRel_DispVtx 
)

Definition at line 285 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 PFProducer::PFProducer(), and 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 204 of file PFAlgo.cc.

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

Referenced by PFProducer::produce(), and setCandConnectorParameters().

206  {
207  if(useEGammaFilters_) {
209  valueMapGedElectrons_ = & valueMapGedElectrons;
210  valueMapGedPhotons_ = & valueMapGedPhotons;
211  }
212 }
const edm::ValueMap< reco::PhotonRef > * valueMapGedPhotons_
Definition: PFAlgo.h:341
const edm::View< reco::PFCandidate > * pfEgammaCandidates_
Definition: PFAlgo.h:339
bool useEGammaFilters_
Variables for NEW EGAMMA selection.
Definition: PFAlgo.h:337
const edm::ValueMap< reco::GsfElectronRef > * valueMapGedElectrons_
Definition: PFAlgo.h:340
void PFAlgo::setEGammaParameters ( bool  use_EGammaFilters,
bool  useProtectionsForJetMET 
)

Definition at line 195 of file PFAlgo.cc.

References useEGammaFilters_, hltParticleFlowForJets_cfi::useProtectionsForJetMET, and useProtectionsForJetMET_.

Referenced by PFProducer::PFProducer(), and setCandConnectorParameters().

196 {
197 
198  useEGammaFilters_ = use_EGammaFilters;
199 
200  if(!useEGammaFilters_ ) return;
201 
203 }
bool useProtectionsForJetMET_
Definition: PFAlgo.h:338
bool useEGammaFilters_
Variables for NEW EGAMMA selection.
Definition: PFAlgo.h:337
void PFAlgo::setEGElectronCollection ( const reco::GsfElectronCollection egelectrons)

Definition at line 3506 of file PFAlgo.cc.

References pfele_, and useEGElectrons_.

Referenced by PFProducer::produce(), and setCandConnectorParameters().

3506  {
3507  if(useEGElectrons_ && pfele_) pfele_->setEGElectronCollection(egelectrons);
3508 }
std::unique_ptr< PFElectronAlgo > pfele_
Definition: PFAlgo.h:331
bool useEGElectrons_
Definition: PFAlgo.h:322
void PFAlgo::setElectronExtraRef ( const edm::OrphanHandle< reco::PFCandidateElectronExtraCollection > &  extrah)

Definition at line 3718 of file PFAlgo.cc.

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

Referenced by PFProducer::produce(), and setCandConnectorParameters().

3718  {
3719  if(!usePFElectrons_) return;
3720  // std::cout << " setElectronExtraRef " << std::endl;
3721  for(auto& cand : *pfCandidates_) {
3722  // select the electrons and add the extra
3723  if(cand.particleId()==PFCandidate::e) {
3724 
3725  PFElectronExtraEqual myExtraEqual(cand.gsfTrackRef());
3726  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
3727  if(it!=pfElectronExtra_.end()) {
3728  // std::cout << " Index " << it-pfElectronExtra_.begin() << std::endl;
3729  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
3730  cand.setPFElectronExtraRef(theRef);
3731  }
3732  else {
3733  cand.setPFElectronExtraRef(PFCandidateElectronExtraRef());
3734  }
3735  }
3736  else // else save the mva and the extra as well !
3737  {
3738  if(cand.trackRef().isNonnull()) {
3739  auto it = find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),
3740  [&cand](const reco::PFCandidateElectronExtra & extra) {
3741  return cand.trackRef() == extra.kfTrackRef();
3742  });
3743  if(it!=pfElectronExtra_.end()) {
3744  cand.set_mva_e_pi(it->mvaVariable(PFCandidateElectronExtra::MVA_MVA));
3745  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
3746  cand.setPFElectronExtraRef(theRef);
3747  cand.setGsfTrackRef(it->gsfTrackRef());
3748  }
3749  }
3750  }
3751 
3752  }
3753 
3754  for(auto& ele : *pfElectronCandidates_) {
3755  // select the electrons - this test is actually not needed for this collection
3756  if(ele.particleId()==PFCandidate::e) {
3757  // find the corresponding extra
3758  PFElectronExtraEqual myExtraEqual(ele.gsfTrackRef());
3759  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
3760  if(it!=pfElectronExtra_.end()) {
3761  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
3762  ele.setPFElectronExtraRef(theRef);
3763 
3764  }
3765  }
3766  }
3767 
3768 }
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:264
edm::Ref< PFCandidateElectronExtraCollection > PFCandidateElectronExtraRef
persistent reference to a PFCandidateElectronExtra
std::unique_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
Definition: PFAlgo.h:266
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
Definition: PFAlgo.h:273
bool usePFElectrons_
Definition: PFAlgo.h:318
void PFAlgo::setHcalDepthInfo ( reco::PFCandidate cand,
const reco::PFCluster cluster 
) const
private

Definition at line 3329 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().

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

References photonIsolationHIProducer_cfi::ho, and useHO_.

Referenced by PFProducer::PFProducer().

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

Definition at line 263 of file PFAlgo.cc.

References muonHandle_, and extraflags_cff::muons.

Referenced by PFProducer::produce(), and setPFMuonAlgo().

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

Definition at line 62 of file PFAlgo.cc.

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

Referenced by PFProducer::PFProducer(), and setPFMuonAlgo().

65  {
66 
67  nSigmaECAL_ = nSigmaECAL;
69 
70  calibration_ = calibration;
71  thepfEnergyCalibrationHF_ = thepfEnergyCalibrationHF;
72 
73 }
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:304
std::shared_ptr< PFEnergyCalibrationHF > thepfEnergyCalibrationHF_
Definition: PFAlgo.h:307
std::shared_ptr< PFEnergyCalibration > calibration_
Definition: PFAlgo.h:306
double nSigmaHCAL(double clusterEnergy, double clusterEta) const
Definition: PFAlgo.cc:3375
double nSigmaECAL_
number of sigma to judge energy excess in ECAL
Definition: PFAlgo.h:301
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 82 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_, thePFEnergyCalibration(), thePFSCEnergyCalibration_, hltParticleFlowForJets_cfi::useEGammaSupercluster, useEGammaSupercluster_, useEGElectrons_, Reconstruction_hiPF_cff::usePFElectrons, usePFElectrons_, hltParticleFlowForJets_cfi::usePFSCEleCalib, and usePFSCEleCalib_.

Referenced by PFProducer::PFProducer(), and setCandConnectorParameters().

97  {
98 
99  mvaEleCut_ = mvaEleCut;
103  thePFSCEnergyCalibration_ = thePFSCEnergyCalibration;
104  useEGElectrons_ = useEGElectrons;
113 
114 
115  if(!usePFElectrons_) return;
116  mvaWeightFileEleID_ = mvaWeightFileEleID;
117  FILE * fileEleID = fopen(mvaWeightFileEleID_.c_str(), "r");
118  if (fileEleID) {
119  fclose(fileEleID);
120  }
121  else {
122  string err = "PFAlgo: cannot open weight file '";
123  err += mvaWeightFileEleID;
124  err += "'";
125  throw invalid_argument( err );
126  }
127  pfele_= std::make_unique<PFElectronAlgo>(mvaEleCut_,mvaWeightFileEleID_,
141 }
unsigned int nTrackIsoForEgammaSC_
Definition: PFAlgo.h:330
double sumEtEcalIsoForEgammaSC_endcap_
Definition: PFAlgo.h:325
double mvaEleCut_
Definition: PFAlgo.h:317
double coneEcalIsoForEgammaSC_
Definition: PFAlgo.h:326
std::unique_ptr< PFElectronAlgo > pfele_
Definition: PFAlgo.h:331
double coneTrackIsoForEgammaSC_
Definition: PFAlgo.h:329
double sumEtEcalIsoForEgammaSC_barrel_
Definition: PFAlgo.h:324
bool useEGammaSupercluster_
Definition: PFAlgo.h:323
bool useEGElectrons_
Definition: PFAlgo.h:322
std::string mvaWeightFileEleID_
Variables for PFElectrons.
Definition: PFAlgo.h:315
bool usePFSCEleCalib_
Definition: PFAlgo.h:321
std::shared_ptr< PFEnergyCalibration > thePFEnergyCalibration()
return the pointer to the calibration function
Definition: PFAlgo.h:213
std::shared_ptr< PFSCEnergyCalibration > thePFSCEnergyCalibration_
Definition: PFAlgo.h:308
bool applyCrackCorrectionsElectrons_
Definition: PFAlgo.h:320
double sumPtTrackIsoForEgammaSC_endcap_
Definition: PFAlgo.h:328
double sumPtTrackIsoForEgammaSC_barrel_
Definition: PFAlgo.h:327
bool usePFElectrons_
Definition: PFAlgo.h:318
void PFAlgo::setPFMuonAlgo ( PFMuonAlgo algo)
inline
void PFAlgo::setPFMuonAndFakeParameters ( const edm::ParameterSet pset)

Definition at line 228 of file PFAlgo.cc.

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

Referenced by PFProducer::PFProducer(), and setCandConnectorParameters().

229 {
230  pfmu_ = new PFMuonAlgo(pset);
231 
232  // Muon parameters
233  muonHCAL_= pset.getParameter<std::vector<double> >("muon_HCAL");
234  muonECAL_= pset.getParameter<std::vector<double> >("muon_ECAL");
235  muonHO_= pset.getParameter<std::vector<double> >("muon_HO");
236  assert ( muonHCAL_.size() == 2 && muonECAL_.size() == 2 && muonHO_.size() == 2);
237  nSigmaTRACK_= pset.getParameter<double>("nsigma_TRACK");
238  ptError_= pset.getParameter<double>("pt_Error");
239  factors45_ = pset.getParameter<std::vector<double> >("factors_45");
240  assert ( factors45_.size() == 2 );
241 }
T getParameter(std::string const &) const
double ptError_
Definition: PFAlgo.h:370
std::vector< double > muonHCAL_
Variables for muons and fakes.
Definition: PFAlgo.h:366
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:333
std::vector< double > factors45_
Definition: PFAlgo.h:371
std::vector< double > muonECAL_
Definition: PFAlgo.h:367
std::vector< double > muonHO_
Definition: PFAlgo.h:368
double nSigmaTRACK_
Definition: PFAlgo.h:369
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 144 of file PFAlgo.cc.

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

Referenced by PFProducer::PFProducer(), and setCandConnectorParameters().

152  {
153 
155 
156  //for MVA pass PV if there is one in the collection otherwise pass a dummy
158  if(useVertices_)
159  {
160  dummy = primaryVertex_;
161  }
162  else { // create a dummy PV
164  e(0, 0) = 0.0015 * 0.0015;
165  e(1, 1) = 0.0015 * 0.0015;
166  e(2, 2) = 15. * 15.;
167  reco::Vertex::Point p(0, 0, 0);
168  dummy = reco::Vertex(p, e, 0, 0, 0);
169  }
170  // pv=&dummy;
171  if(! usePFPhotons_) return;
172  FILE * filePhotonConvID = fopen(mvaWeightFileConvID.c_str(), "r");
173  if (filePhotonConvID) {
174  fclose(filePhotonConvID);
175  }
176  else {
177  string err = "PFAlgo: cannot open weight file '";
178  err += mvaWeightFileConvID;
179  err += "'";
180  throw invalid_argument( err );
181  }
182  const reco::Vertex* pv=&dummy;
183  pfpho_ = std::make_unique<PFPhotonAlgo>(mvaWeightFileConvID,
184  mvaConvCut,
185  useReg,
186  X0_Map,
187  *pv,
191  );
192  return;
193 }
math::Error< dimension >::type Error
covariance error matrix (3x3)
Definition: Vertex.h:43
std::unique_ptr< PFPhotonAlgo > pfpho_
Definition: PFAlgo.h:332
def pv(vc)
Definition: MetAnalyzer.py:7
reco::Vertex primaryVertex_
Definition: PFAlgo.h:402
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:213
bool useVertices_
Definition: PFAlgo.h:403
bool usePFPhotons_
Definition: PFAlgo.h:319
void PFAlgo::setPFPhotonRegWeights ( const GBRForest LCorrForestEB,
const GBRForest LCorrForestEE,
const GBRForest GCorrForestBarrel,
const GBRForest GCorrForestEndcapHr9,
const GBRForest GCorrForestEndcapLr9,
const GBRForest PFEcalResolution 
)

Definition at line 215 of file PFAlgo.cc.

References pfpho_.

Referenced by PFProducer::beginRun(), and setCandConnectorParameters().

221  {
222 
223  pfpho_->setGBRForest(LCorrForestEB,LCorrForestEE,
224  GCorrForestBarrel, GCorrForestEndcapHr9,
225  GCorrForestEndcapLr9, PFEcalResolution);
226 }
std::unique_ptr< PFPhotonAlgo > pfpho_
Definition: PFAlgo.h:332
void PFAlgo::setPFVertexParameters ( bool  useVertex,
reco::VertexCollection const &  primaryVertices 
)

Definition at line 302 of file PFAlgo.cc.

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

Referenced by PFProducer::produce(), and setCandConnectorParameters().

303 {
305 
306  //Set the vertices for muon cleaning
308 
309 
310  //Now find the primary vertex!
311  bool primaryVertexFound = false;
312  nVtx_ = primaryVertices.size();
313  if(usePFPhotons_){
314  pfpho_->setnPU(nVtx_);
315  }
316  for(auto const& vertex : primaryVertices)
317  {
318  if(vertex.isValid()&&(!vertex.isFake()))
319  {
320  primaryVertex_ = vertex;
321  primaryVertexFound = true;
322  break;
323  }
324  }
325  //Use vertices if the user wants to but only if it exists a good vertex
326  useVertices_ = useVertex && primaryVertexFound;
327  if(usePFPhotons_) {
328  if (useVertices_ ){
329  pfpho_->setPhotonPrimaryVtx(primaryVertex_ );
330  }
331  else{
333  e(0, 0) = 0.0015 * 0.0015;
334  e(1, 1) = 0.0015 * 0.0015;
335  e(2, 2) = 15. * 15.;
336  reco::Vertex::Point p(0, 0, 0);
337  reco::Vertex dummy = reco::Vertex(p, e, 0, 0, 0);
338  // std::cout << " PFPho " << pfpho_ << std::endl;
339  pfpho_->setPhotonPrimaryVtx(dummy);
340  }
341  }
342 }
math::Error< dimension >::type Error
covariance error matrix (3x3)
Definition: Vertex.h:43
void setInputsForCleaning(reco::VertexCollection const &)
Definition: PFMuonAlgo.cc:1078
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:333
int nVtx_
Definition: PFAlgo.h:359
std::unique_ptr< PFPhotonAlgo > pfpho_
Definition: PFAlgo.h:332
reco::Vertex primaryVertex_
Definition: PFAlgo.h:402
math::XYZPoint Point
point in the space
Definition: Vertex.h:39
bool useVertices_
Definition: PFAlgo.h:403
primaryVertices
Definition: jets_cff.py:26
bool usePFPhotons_
Definition: PFAlgo.h:319
void PFAlgo::setPhotonExtraRef ( const edm::OrphanHandle< reco::PFCandidatePhotonExtraCollection > &  pf_extrah)

Definition at line 3769 of file PFAlgo.cc.

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

Referenced by PFProducer::produce(), and setCandConnectorParameters().

3769  {
3770  if(!usePFPhotons_) return;
3771  for(auto& cand : *pfCandidates_) {
3772  // select the electrons and add the extra
3773  if(cand.particleId()==PFCandidate::gamma && cand.mva_nothing_gamma() > 0.99) {
3774  if(cand.superClusterRef().isNonnull()) {
3775  bool found = false;
3776  unsigned int pcextra = 0;
3777  for(auto const& photon : pfPhotonExtra_) {
3778  if(cand.superClusterRef() == photon.superClusterRef()) {
3779  reco::PFCandidatePhotonExtraRef theRef(ph_extrah,pcextra);
3780  cand.setPFPhotonExtraRef(theRef);
3781  found = true;
3782  break;
3783  }
3784  ++pcextra;
3785  }
3786  if(!found)
3787  cand.setPFPhotonExtraRef((PFCandidatePhotonExtraRef())); // null ref
3788  }
3789  else {
3790  cand.setPFPhotonExtraRef((PFCandidatePhotonExtraRef())); // null ref
3791  }
3792  }
3793  }
3794 }
edm::Ref< PFCandidatePhotonExtraCollection > PFCandidatePhotonExtraRef
persistent reference to a PFCandidatePhotonExtra
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:264
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
Definition: PFAlgo.h:275
bool usePFPhotons_
Definition: PFAlgo.h:319
void PFAlgo::setPostHFCleaningParameters ( bool  postHFCleaning,
double  minHFCleaningPt,
double  minSignificance,
double  maxSignificance,
double  minSignificanceReduction,
double  maxDeltaPhiPt,
double  minDeltaMet 
)

Definition at line 268 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 PFProducer::PFProducer(), and setCandConnectorParameters().

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

return the pointer to the calibration function

Definition at line 213 of file PFAlgo.h.

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

Referenced by PFProducer::beginRun(), setCandConnectorParameters(), setPFEleParameters(), and setPFPhotonParameters().

213  {
214  return calibration_;
215  }
std::shared_ptr< PFEnergyCalibration > calibration_
Definition: PFAlgo.h:306
reco::PFCandidateCollection PFAlgo::transferCandidates ( )
inline
Returns
the collection of candidates

Definition at line 208 of file PFAlgo.h.

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

Referenced by PFProducer::produce().

208  {
210  }
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:264
PFCandConnector connector_
Definition: PFAlgo.h:363
reco::PFCandidateCollection connect(reco::PFCandidateCollection &pfCand) const
std::unique_ptr<reco::PFCandidateCollection> PFAlgo::transferCleanedCandidates ( )
inline
Returns
collection of cleaned HF candidates

Definition at line 203 of file PFAlgo.h.

References eostools::move(), and pfCleanedCandidates_.

Referenced by PFProducer::produce().

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

Definition at line 180 of file PFAlgo.h.

References eostools::move(), and pfElectronCandidates_.

Referenced by PFProducer::produce().

180  {
182  }
std::unique_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
Definition: PFAlgo.h:266
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 186 of file PFAlgo.h.

References pfElectronExtra_, and mps_fire::result.

Referenced by PFProducer::produce().

186  {
187  auto result = std::make_unique<reco::PFCandidateElectronExtraCollection>();
188  result->insert(result->end(),pfElectronExtra_.begin(),pfElectronExtra_.end());
189  return result;
190  }
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
Definition: PFAlgo.h:273
std::unique_ptr< reco::PFCandidatePhotonExtraCollection> PFAlgo::transferPhotonExtra ( )
inline
Returns
the unfiltered photon extra collection

Definition at line 195 of file PFAlgo.h.

References pfPhotonExtra_, and mps_fire::result.

Referenced by PFProducer::produce().

195  {
196  auto result = std::make_unique<reco::PFCandidatePhotonExtraCollection>();
197  result->insert(result->end(),pfPhotonExtra_.begin(),pfPhotonExtra_.end());
198  return result;
199  }
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
Definition: PFAlgo.h:275

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 311 of file PFAlgo.h.

Referenced by setAlgo().

bool PFAlgo::applyCrackCorrectionsElectrons_
private

Definition at line 320 of file PFAlgo.h.

Referenced by setPFEleParameters().

reco::PFBlockHandle PFAlgo::blockHandle_
private

input block handle (full framework case)

Definition at line 298 of file PFAlgo.h.

Referenced by createBlockRef(), and reconstructParticles().

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

Definition at line 306 of file PFAlgo.h.

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

double PFAlgo::coneEcalIsoForEgammaSC_
private

Definition at line 326 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::coneTrackIsoForEgammaSC_
private

Definition at line 329 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 363 of file PFAlgo.h.

Referenced by setCandConnectorParameters(), and transferCandidates().

const 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 358 of file PFAlgo.h.

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

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

Definition at line 371 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

float PFAlgo::goodPixelTrackDeadHcal_chi2n_
private

Definition at line 383 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodPixelTrackDeadHcal_dxy_
private

Definition at line 386 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodPixelTrackDeadHcal_dz_
private

Definition at line 387 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

int PFAlgo::goodPixelTrackDeadHcal_maxLost3Hit_
private

Definition at line 384 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

int PFAlgo::goodPixelTrackDeadHcal_maxLost4Hit_
private

Definition at line 385 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodPixelTrackDeadHcal_maxPt_
private

Definition at line 381 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodPixelTrackDeadHcal_minEta_
private

Definition at line 380 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodPixelTrackDeadHcal_ptErrRel_
private

Definition at line 382 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodTrackDeadHcal_chi2n_
private

Definition at line 375 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodTrackDeadHcal_dxy_
private

Definition at line 378 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

int PFAlgo::goodTrackDeadHcal_layers_
private

Definition at line 376 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 374 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

float PFAlgo::goodTrackDeadHcal_validFr_
private

Definition at line 377 of file PFAlgo.h.

Referenced by processBlock(), and setBadHcalTrackParams().

double PFAlgo::maxDeltaPhiPt_
private

Definition at line 397 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::maxSignificance_
private

Definition at line 395 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minDeltaMet_
private

Definition at line 398 of file PFAlgo.h.

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

double PFAlgo::minHFCleaningPt_
private

Definition at line 393 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minSignificance_
private

Definition at line 394 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minSignificanceReduction_
private

Definition at line 396 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

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

Definition at line 367 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

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

Definition at line 405 of file PFAlgo.h.

Referenced by reconstructParticles(), and setMuonHandle().

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

Variables for muons and fakes.

Definition at line 366 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

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

Definition at line 368 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

double PFAlgo::mvaEleCut_
private

Definition at line 317 of file PFAlgo.h.

Referenced by setPFEleParameters().

std::string PFAlgo::mvaWeightFileEleID_
private

Variables for PFElectrons.

Definition at line 315 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::nSigmaECAL_
private

number of sigma to judge energy excess in ECAL

Definition at line 301 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 304 of file PFAlgo.h.

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

double PFAlgo::nSigmaTRACK_
private

Definition at line 369 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

unsigned int PFAlgo::nTrackIsoForEgammaSC_
private

Definition at line 330 of file PFAlgo.h.

Referenced by setPFEleParameters().

int PFAlgo::nVtx_
private

Definition at line 359 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 270 of file PFAlgo.h.

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

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

Definition at line 339 of file PFAlgo.h.

Referenced by processBlock(), and setEGammaCollections().

std::unique_ptr<PFElectronAlgo> PFAlgo::pfele_
private

Definition at line 331 of file PFAlgo.h.

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

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

the unfiltered electron collection

Definition at line 266 of file PFAlgo.h.

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

reco::PFCandidateElectronExtraCollection PFAlgo::pfElectronExtra_
private

the unfiltered electron collection

Definition at line 273 of file PFAlgo.h.

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

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

the unfiltered photon collection

Definition at line 268 of file PFAlgo.h.

Referenced by processBlock(), and reconstructParticles().

reco::PFCandidatePhotonExtraCollection PFAlgo::pfPhotonExtra_
private

the extra photon collection

Definition at line 275 of file PFAlgo.h.

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

bool PFAlgo::postHFCleaning_
private

Definition at line 391 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

bool PFAlgo::postMuonCleaning_
private

Definition at line 392 of file PFAlgo.h.

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

Definition at line 370 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 349 of file PFAlgo.h.

Referenced by processBlock(), and setDisplacedVerticesParameters().

bool PFAlgo::rejectTracks_Step45_
private

Definition at line 350 of file PFAlgo.h.

Referenced by processBlock(), and setDisplacedVerticesParameters().

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

Definition at line 316 of file PFAlgo.h.

double PFAlgo::sumEtEcalIsoForEgammaSC_barrel_
private

Definition at line 324 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumEtEcalIsoForEgammaSC_endcap_
private

Definition at line 325 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumPtTrackIsoForEgammaSC_barrel_
private

Definition at line 327 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumPtTrackIsoForEgammaSC_endcap_
private

Definition at line 328 of file PFAlgo.h.

Referenced by setPFEleParameters().

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

Definition at line 307 of file PFAlgo.h.

Referenced by processBlock(), and setParameters().

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

Definition at line 308 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::useBestMuonTrack_
private

Definition at line 399 of file PFAlgo.h.

bool PFAlgo::useEGammaFilters_
private

Variables for NEW EGAMMA selection.

Definition at line 337 of file PFAlgo.h.

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

bool PFAlgo::useEGammaSupercluster_
private

Definition at line 323 of file PFAlgo.h.

Referenced by setPFEleParameters().

bool PFAlgo::useEGElectrons_
private

Definition at line 322 of file PFAlgo.h.

Referenced by setEGElectronCollection(), and setPFEleParameters().

bool PFAlgo::useHO_
private

Definition at line 310 of file PFAlgo.h.

Referenced by processBlock(), and setHOTag().

bool PFAlgo::usePFConversions_
private

Definition at line 353 of file PFAlgo.h.

Referenced by processBlock(), and setDisplacedVerticesParameters().

bool PFAlgo::usePFDecays_
private

Definition at line 354 of file PFAlgo.h.

Referenced by isFromSecInt(), and setDisplacedVerticesParameters().

bool PFAlgo::usePFElectrons_
private

Definition at line 318 of file PFAlgo.h.

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

bool PFAlgo::usePFMuonMomAssign_
private

Definition at line 345 of file PFAlgo.h.

bool PFAlgo::usePFNuclearInteractions_
private

Definition at line 352 of file PFAlgo.h.

Referenced by isFromSecInt(), and setDisplacedVerticesParameters().

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

Definition at line 321 of file PFAlgo.h.

Referenced by setPFEleParameters().

bool PFAlgo::useProtectionsForJetMET_
private

Definition at line 338 of file PFAlgo.h.

Referenced by processBlock(), and setEGammaParameters().

bool PFAlgo::useVertices_
private

Definition at line 403 of file PFAlgo.h.

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

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

Definition at line 340 of file PFAlgo.h.

Referenced by setEGammaCollections().

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

Definition at line 341 of file PFAlgo.h.

Referenced by setEGammaCollections().