CMS 3D CMS Logo

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

#include <PFAlgo.h>

Inheritance diagram for PFAlgo:
PFAlgoTestBenchConversions PFAlgoTestBenchElectrons

Public Member Functions

void checkCleaning (const reco::PFRecHitCollection &cleanedHF)
 Check HF Cleaning. More...
 
PFMuonAlgogetPFMuonAlgo ()
 
 PFAlgo ()
 constructor More...
 
const std::unique_ptr< reco::PFCandidateCollection > & pfCandidates () const
 
void reconstructParticles (const reco::PFBlockHandle &blockHandle)
 
virtual void reconstructParticles (const reco::PFBlockCollection &blocks)
 reconstruct particles More...
 
void setAlgo (int algo)
 
void setCandConnectorParameters (const edm::ParameterSet &iCfgCandConnector)
 
void setCandConnectorParameters (bool bCorrect, bool bCalibPrimary, double dptRel_PrimaryTrack, double dptRel_MergedTrack, double ptErrorSecondary, const std::vector< double > &nuclCalibFactors)
 
void setDebug (bool debug)
 
void setDisplacedVerticesParameters (bool rejectTracks_Bad, bool rejectTracks_Step45, bool usePFNuclearInteractions, bool usePFConversions, bool usePFDecays, double dptRel_DispVtx)
 
void setEGammaCollections (const edm::View< reco::PFCandidate > &pfEgammaCandidates, const edm::ValueMap< reco::GsfElectronRef > &valueMapGedElectrons, const edm::ValueMap< reco::PhotonRef > &valueMapGedPhotons)
 
void setEGammaParameters (bool use_EGammaFilters, std::string ele_iso_path_mvaWeightFile, double ele_iso_pt, double ele_iso_mva_barrel, double ele_iso_mva_endcap, double ele_iso_combIso_barrel, double ele_iso_combIso_endcap, double ele_noniso_mva, unsigned int ele_missinghits, bool useProtectionsForJetMET, const edm::ParameterSet &ele_protectionsForJetMET, double ph_MinEt, double ph_combIso, double ph_HoE, double ph_sietaieta_eb, double ph_sietaieta_ee, const edm::ParameterSet &ph_protectionsForJetMET)
 
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 boost::shared_ptr< PFEnergyCalibration > &calibration, const boost::shared_ptr< PFEnergyCalibrationHF > &thepfEnergyCalibrationHF)
 
void setPFEleParameters (double mvaEleCut, std::string mvaWeightFileEleID, bool usePFElectrons, const boost::shared_ptr< PFSCEnergyCalibration > &thePFSCEnergyCalibration, const boost::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 boost::shared_ptr< PFEnergyCalibration > &thePFEnergyCalibration, double sumPtTrackIsoForPhoton, double sumPtTrackIsoSlopeForPhoton)
 
void setPFPhotonRegWeights (const GBRForest *LCorrForestEB, const GBRForest *LCorrForestEE, const GBRForest *GCorrForestBarrel, const GBRForest *GCorrForestEndcapHr9, const GBRForest *GCorrForestEndcapLr9, const GBRForest *PFEcalResolution)
 
void setPFVertexParameters (bool useVertex, const reco::VertexCollection *primaryVertices)
 
void setPhotonExtraRef (const edm::OrphanHandle< reco::PFCandidatePhotonExtraCollection > &pf_extrah)
 
void setPostHFCleaningParameters (bool postHFCleaning, double minHFCleaningPt, double minSignificance, double maxSignificance, double minSignificanceReduction, double maxDeltaPhiPt, double minDeltaMet)
 
boost::shared_ptr< PFEnergyCalibrationthePFEnergyCalibration ()
 return the pointer to the calibration function More...
 
std::unique_ptr< reco::PFCandidateCollectiontransferCandidates ()
 
std::unique_ptr< reco::PFCandidateCollectiontransferCleanedCandidates ()
 
std::unique_ptr< reco::PFCandidateCollectiontransferElectronCandidates ()
 
std::unique_ptr< reco::PFCandidateElectronExtraCollectiontransferElectronExtra ()
 
std::unique_ptr< reco::PFCandidatePhotonExtraCollectiontransferPhotonExtra ()
 
virtual ~PFAlgo ()
 destructor More...
 

Protected Member Functions

void associatePSClusters (unsigned iEcal, reco::PFBlockElement::Type psElementType, const reco::PFBlock &block, const edm::OwnVector< reco::PFBlockElement > &elements, const reco::PFBlock::LinkData &linkData, std::vector< bool > &active, std::vector< double > &psEne)
 Associate PS clusters to a given ECAL cluster, and return their energy. More...
 
bool 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 ()
 
virtual void processBlock (const reco::PFBlockRef &blockref, std::list< reco::PFBlockRef > &hcalBlockRefs, std::list< reco::PFBlockRef > &ecalBlockRefs)
 
unsigned reconstructCluster (const reco::PFCluster &cluster, double particleEnergy, bool useDirection=false, double particleX=0., double particleY=0., double particleZ=0.)
 
unsigned reconstructTrack (const reco::PFBlockElement &elt, bool allowLoose=false)
 

Protected Attributes

std::unique_ptr< reco::PFCandidateCollectionpfCandidates_
 
std::unique_ptr< reco::PFCandidateCollectionpfCleanedCandidates_
 
std::unique_ptr< reco::PFCandidateCollectionpfElectronCandidates_
 the unfiltered electron collection More...
 
reco::PFCandidateElectronExtraCollection pfElectronExtra_
 the unfiltered electron collection More...
 
std::unique_ptr< reco::PFCandidateCollectionpfPhotonCandidates_
 the unfiltered photon collection More...
 
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
 the extra photon collection More...
 

Private Member Functions

reco::PFBlockRef createBlockRef (const reco::PFBlockCollection &blocks, unsigned bi)
 

Private Attributes

int algo_
 
bool applyCrackCorrectionsElectrons_
 
reco::PFBlockHandle blockHandle_
 input block handle (full framework case) More...
 
boost::shared_ptr< PFEnergyCalibrationcalibration_
 
double coneEcalIsoForEgammaSC_
 
double coneTrackIsoForEgammaSC_
 
PFCandConnector connector_
 
bool debug_
 
double dptRel_DispVtx_
 
std::vector< double > factors45_
 
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_
 
PFEGammaFilterspfegamma_
 
const edm::View< reco::PFCandidate > * pfEgammaCandidates_
 
PFElectronAlgopfele_
 
PFMuonAlgopfmu_
 
PFPhotonAlgopfpho_
 
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_
 
boost::shared_ptr< PFEnergyCalibrationHFthepfEnergyCalibrationHF_
 
boost::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 52 of file PFAlgo.h.

Constructor & Destructor Documentation

PFAlgo::PFAlgo ( )

constructor

Definition at line 59 of file PFAlgo.cc.

61  nSigmaECAL_(0),
62  nSigmaHCAL_(1),
63  algo_(1),
64  debug_(false),
65  pfele_(nullptr),
66  pfpho_(nullptr),
67  pfegamma_(nullptr),
68  useVertices_(false)
69 {}
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:328
PFElectronAlgo * pfele_
Definition: PFAlgo.h:355
int algo_
Definition: PFAlgo.h:335
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:356
PFEGammaFilters * pfegamma_
Definition: PFAlgo.h:362
std::vector< reco::PFCandidate > PFCandidateCollection
collection of PFCandidates
bool useVertices_
Definition: PFAlgo.h:411
bool debug_
Definition: PFAlgo.h:336
double nSigmaECAL_
number of sigma to judge energy excess in ECAL
Definition: PFAlgo.h:325
PFAlgo::~PFAlgo ( )
virtual

destructor

Definition at line 71 of file PFAlgo.cc.

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

71  {
72  if (usePFElectrons_) delete pfele_;
73  if (usePFPhotons_) delete pfpho_;
74  if (useEGammaFilters_) delete pfegamma_;
75 }
PFElectronAlgo * pfele_
Definition: PFAlgo.h:355
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:356
PFEGammaFilters * pfegamma_
Definition: PFAlgo.h:362
bool useEGammaFilters_
Variables for NEW EGAMMA selection.
Definition: PFAlgo.h:361
bool usePFPhotons_
Definition: PFAlgo.h:343
bool usePFElectrons_
Definition: PFAlgo.h:342

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 
)
protected

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

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

3370  {
3371 
3372  // Find all PS clusters with type psElement associated to ECAL cluster iEcal,
3373  // within all PFBlockElement "elements" of a given PFBlock "block"
3374  // psElement can be reco::PFBlockElement::PS1 or reco::PFBlockElement::PS2
3375  // Returns a vector of PS cluster energies, and updates the "active" vector.
3376 
3377  // Find all PS clusters linked to the iEcal cluster
3378  std::multimap<double, unsigned> sortedPS;
3379  typedef std::multimap<double, unsigned>::iterator IE;
3380  block.associatedElements( iEcal, linkData,
3381  sortedPS, psElementType,
3383 
3384  // Loop over these PS clusters
3385  double totalPS = 0.;
3386  for ( IE ips=sortedPS.begin(); ips!=sortedPS.end(); ++ips ) {
3387 
3388  // CLuster index and distance to iEcal
3389  unsigned iPS = ips->second;
3390  // double distPS = ips->first;
3391 
3392  // Ignore clusters already in use
3393  if (!active[iPS]) continue;
3394 
3395  // Check that this cluster is not closer to another ECAL cluster
3396  std::multimap<double, unsigned> sortedECAL;
3397  block.associatedElements( iPS, linkData,
3398  sortedECAL,
3401  unsigned jEcal = sortedECAL.begin()->second;
3402  if ( jEcal != iEcal ) continue;
3403 
3404  // Update PS energy
3405  PFBlockElement::Type pstype = elements[ iPS ].type();
3406  assert( pstype == psElementType );
3407  PFClusterRef psclusterref = elements[iPS].clusterRef();
3408  assert(!psclusterref.isNull() );
3409  totalPS += psclusterref->energy();
3410  psEne[0] += psclusterref->energy();
3411  active[iPS] = false;
3412  }
3413 
3414 
3415 }
bool isNull() const
Checks for null.
Definition: Ref.h:250
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 3562 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, reco::LeafCandidate::pt(), reco::LeafCandidate::px(), reco::LeafCandidate::py(), reconstructCluster(), createPayload::skip, mathSSE::sqrt(), reco::PFRecHit::time(), Basic3DVector< T >::x(), Basic3DVector< T >::y(), and Basic3DVector< T >::z().

Referenced by setCandConnectorParameters().

3562  {
3563 
3564 
3565  // No hits to recover, leave.
3566  if ( cleanedHits.empty() ) return;
3567 
3568  //Compute met and met significance (met/sqrt(SumEt))
3569  double metX = 0.;
3570  double metY = 0.;
3571  double sumet = 0;
3572  std::vector<unsigned int> hitsToBeAdded;
3573  for(unsigned i=0; i<pfCandidates_->size(); i++) {
3574  const PFCandidate& pfc = (*pfCandidates_)[i];
3575  metX += pfc.px();
3576  metY += pfc.py();
3577  sumet += pfc.pt();
3578  }
3579  double met2 = metX*metX+metY*metY;
3580  double met2_Original = met2;
3581  // Select events with large MET significance.
3582  // double significance = std::sqrt(met2/sumet);
3583  // double significanceCor = significance;
3584  double metXCor = metX;
3585  double metYCor = metY;
3586  double sumetCor = sumet;
3587  double met2Cor = met2;
3588  bool next = true;
3589  unsigned iCor = 1E9;
3590 
3591  // Find the cleaned hit with the largest effect on the MET
3592  while ( next ) {
3593 
3594  double metReduc = -1.;
3595  // Loop on the candidates
3596  for(unsigned i=0; i<cleanedHits.size(); ++i) {
3597  const PFRecHit& hit = cleanedHits[i];
3598  double length = std::sqrt(hit.position().mag2());
3599  double px = hit.energy() * hit.position().x()/length;
3600  double py = hit.energy() * hit.position().y()/length;
3601  double pt = std::sqrt(px*px + py*py);
3602 
3603  // Check that it is not already scheculed to be cleaned
3604  bool skip = false;
3605  for(unsigned j=0; j<hitsToBeAdded.size(); ++j) {
3606  if ( i == hitsToBeAdded[j] ) skip = true;
3607  if ( skip ) break;
3608  }
3609  if ( skip ) continue;
3610 
3611  // Now add the candidate to the MET
3612  double metXInt = metX + px;
3613  double metYInt = metY + py;
3614  double sumetInt = sumet + pt;
3615  double met2Int = metXInt*metXInt+metYInt*metYInt;
3616 
3617  // And check if it could contribute to a MET reduction
3618  if ( met2Int < met2Cor ) {
3619  metXCor = metXInt;
3620  metYCor = metYInt;
3621  metReduc = (met2-met2Int)/met2Int;
3622  met2Cor = met2Int;
3623  sumetCor = sumetInt;
3624  // significanceCor = std::sqrt(met2Cor/sumetCor);
3625  iCor = i;
3626  }
3627  }
3628  //
3629  // If the MET must be significanly reduced, schedule the candidate to be added
3630  //
3631  if ( metReduc > minDeltaMet_ ) {
3632  hitsToBeAdded.push_back(iCor);
3633  metX = metXCor;
3634  metY = metYCor;
3635  sumet = sumetCor;
3636  met2 = met2Cor;
3637  } else {
3638  // Otherwise just stop the loop
3639  next = false;
3640  }
3641  }
3642  //
3643  // At least 10 GeV MET reduction
3644  if ( std::sqrt(met2_Original) - std::sqrt(met2) > 5. ) {
3645  if ( debug_ ) {
3646  std::cout << hitsToBeAdded.size() << " hits were re-added " << std::endl;
3647  std::cout << "MET reduction = " << std::sqrt(met2_Original) << " -> "
3648  << std::sqrt(met2Cor) << " = " << std::sqrt(met2Cor) - std::sqrt(met2_Original)
3649  << std::endl;
3650  std::cout << "Added after cleaning check : " << std::endl;
3651  }
3652  for(unsigned j=0; j<hitsToBeAdded.size(); ++j) {
3653  const PFRecHit& hit = cleanedHits[hitsToBeAdded[j]];
3654  PFCluster cluster(hit.layer(), hit.energy(),
3655  hit.position().x(), hit.position().y(), hit.position().z() );
3656  reconstructCluster(cluster,hit.energy());
3657  if ( debug_ ) {
3658  std::cout << pfCandidates_->back() << ". time = " << hit.time() << std::endl;
3659  }
3660  }
3661  }
3662 
3663 }
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:406
float time() const
timing for cleaned hits
Definition: PFRecHit.h:118
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
unsigned reconstructCluster(const reco::PFCluster &cluster, double particleEnergy, bool useDirection=false, double particleX=0., double particleY=0., double particleZ=0.)
Definition: PFAlgo.cc:3186
double px() const final
x coordinate of momentum vector
double pt() const final
transverse momentum
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:31
T z() const
Cartesian z coordinate.
T sqrt(T t)
Definition: SSEVec.h:18
float energy() const
rechit energy
Definition: PFRecHit.h:114
double py() const final
y coordinate of momentum vector
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:39
bool debug_
Definition: PFAlgo.h:336
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 3352 of file PFAlgo.cc.

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

Referenced by reconstructParticles().

3353  {
3354 
3355  if( blockHandle_.isValid() ) {
3356  return reco::PFBlockRef( blockHandle_, bi );
3357  }
3358  else {
3359  return reco::PFBlockRef( &blocks, bi );
3360  }
3361 }
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:322
PFMuonAlgo * PFAlgo::getPFMuonAlgo ( )

Definition at line 93 of file PFAlgo.cc.

References pfmu_.

Referenced by setCandConnectorParameters().

93  {
94  return pfmu_;
95 }
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:357
bool PFAlgo::isFromSecInt ( const reco::PFBlockElement eTrack,
std::string  order 
) const
protected

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

3419  {
3420 
3423  // reco::PFBlockElement::TrackType T_FROM_GAMMACONV = reco::PFBlockElement::T_FROM_GAMMACONV;
3425 
3426  bool bPrimary = (order.find("primary") != string::npos);
3427  bool bSecondary = (order.find("secondary") != string::npos);
3428  bool bAll = (order.find("all") != string::npos);
3429 
3430  bool isToDisp = usePFNuclearInteractions_ && eTrack.trackType(T_TO_DISP);
3431  bool isFromDisp = usePFNuclearInteractions_ && eTrack.trackType(T_FROM_DISP);
3432 
3433  if (bPrimary && isToDisp) return true;
3434  if (bSecondary && isFromDisp ) return true;
3435  if (bAll && ( isToDisp || isFromDisp ) ) return true;
3436 
3437 // bool isFromConv = usePFConversions_ && eTrack.trackType(T_FROM_GAMMACONV);
3438 
3439 // if ((bAll || bSecondary)&& isFromConv) return true;
3440 
3441  bool isFromDecay = (bAll || bSecondary) && usePFDecays_ && eTrack.trackType(T_FROM_V0);
3442 
3443  return isFromDecay;
3444 
3445 
3446 }
bool usePFNuclearInteractions_
Definition: PFAlgo.h:377
virtual bool trackType(TrackType trType) const
bool usePFDecays_
Definition: PFAlgo.h:379
double PFAlgo::neutralHadronEnergyResolution ( double  clusterEnergy,
double  clusterEta 
) const
protected

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

References mathSSE::sqrt().

Referenced by processBlock(), and thePFEnergyCalibration().

3300  {
3301 
3302  // Add a protection
3303  if ( clusterEnergyHCAL < 1. ) clusterEnergyHCAL = 1.;
3304 
3305  double resol = fabs(eta) < 1.48 ?
3306  sqrt (1.02*1.02/clusterEnergyHCAL + 0.065*0.065)
3307  :
3308  sqrt (1.20*1.20/clusterEnergyHCAL + 0.028*0.028);
3309 
3310  return resol;
3311 
3312 }
T sqrt(T t)
Definition: SSEVec.h:18
double PFAlgo::nSigmaHCAL ( double  clusterEnergy,
double  clusterEta 
) const
protected

Definition at line 3315 of file PFAlgo.cc.

References JetChargeProducer_cfi::exp, and nSigmaHCAL_.

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

3315  {
3316  double nS = fabs(eta) < 1.48 ?
3317  nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL/100.))
3318  :
3319  nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL/100.));
3320 
3321  return nS;
3322 }
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:328
const std::unique_ptr<reco::PFCandidateCollection>& PFAlgo::pfCandidates ( ) const
inline
Returns
collection of candidates

Definition at line 196 of file PFAlgo.h.

References pfCandidates_.

Referenced by operator<<().

196  {
197  return pfCandidates_;
198  }
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
void PFAlgo::postCleaning ( )
protected

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

3455  {
3456 
3457  // Check if the post HF Cleaning was requested - if not, do nothing
3458  if ( !postHFCleaning_ ) return;
3459 
3460  //Compute met and met significance (met/sqrt(SumEt))
3461  double metX = 0.;
3462  double metY = 0.;
3463  double sumet = 0;
3464  std::vector<unsigned int> pfCandidatesToBeRemoved;
3465  for(unsigned i=0; i<pfCandidates_->size(); i++) {
3466  const PFCandidate& pfc = (*pfCandidates_)[i];
3467  metX += pfc.px();
3468  metY += pfc.py();
3469  sumet += pfc.pt();
3470  }
3471  double met2 = metX*metX+metY*metY;
3472  // Select events with large MET significance.
3473  double significance = std::sqrt(met2/sumet);
3474  double significanceCor = significance;
3475  if ( significance > minSignificance_ ) {
3476 
3477  double metXCor = metX;
3478  double metYCor = metY;
3479  double sumetCor = sumet;
3480  double met2Cor = met2;
3481  double deltaPhi = 3.14159;
3482  double deltaPhiPt = 100.;
3483  bool next = true;
3484  unsigned iCor = 1E9;
3485 
3486  // Find the HF candidate with the largest effect on the MET
3487  while ( next ) {
3488 
3489  double metReduc = -1.;
3490  // Loop on the candidates
3491  for(unsigned i=0; i<pfCandidates_->size(); ++i) {
3492  const PFCandidate& pfc = (*pfCandidates_)[i];
3493 
3494  // Check that the pfCandidate is in the HF
3495  if ( pfc.particleId() != reco::PFCandidate::h_HF &&
3496  pfc.particleId() != reco::PFCandidate::egamma_HF ) continue;
3497 
3498  // Check if has meaningful pt
3499  if ( pfc.pt() < minHFCleaningPt_ ) continue;
3500 
3501  // Check that it is not already scheculed to be cleaned
3502  bool skip = false;
3503  for(unsigned j=0; j<pfCandidatesToBeRemoved.size(); ++j) {
3504  if ( i == pfCandidatesToBeRemoved[j] ) skip = true;
3505  if ( skip ) break;
3506  }
3507  if ( skip ) continue;
3508 
3509  // Check that the pt and the MET are aligned
3510  deltaPhi = std::acos((metX*pfc.px()+metY*pfc.py())/(pfc.pt()*std::sqrt(met2)));
3511  deltaPhiPt = deltaPhi*pfc.pt();
3512  if ( deltaPhiPt > maxDeltaPhiPt_ ) continue;
3513 
3514  // Now remove the candidate from the MET
3515  double metXInt = metX - pfc.px();
3516  double metYInt = metY - pfc.py();
3517  double sumetInt = sumet - pfc.pt();
3518  double met2Int = metXInt*metXInt+metYInt*metYInt;
3519  if ( met2Int < met2Cor ) {
3520  metXCor = metXInt;
3521  metYCor = metYInt;
3522  metReduc = (met2-met2Int)/met2Int;
3523  met2Cor = met2Int;
3524  sumetCor = sumetInt;
3525  significanceCor = std::sqrt(met2Cor/sumetCor);
3526  iCor = i;
3527  }
3528  }
3529  //
3530  // If the MET must be significanly reduced, schedule the candidate to be cleaned
3531  if ( metReduc > minDeltaMet_ ) {
3532  pfCandidatesToBeRemoved.push_back(iCor);
3533  metX = metXCor;
3534  metY = metYCor;
3535  sumet = sumetCor;
3536  met2 = met2Cor;
3537  } else {
3538  // Otherwise just stop the loop
3539  next = false;
3540  }
3541  }
3542  //
3543  // The significance must be significantly reduced to indeed clean the candidates
3544  if ( significance - significanceCor > minSignificanceReduction_ &&
3545  significanceCor < maxSignificance_ ) {
3546  std::cout << "Significance reduction = " << significance << " -> "
3547  << significanceCor << " = " << significanceCor - significance
3548  << std::endl;
3549  for(unsigned j=0; j<pfCandidatesToBeRemoved.size(); ++j) {
3550  std::cout << "Removed : " << (*pfCandidates_)[pfCandidatesToBeRemoved[j]] << std::endl;
3551  pfCleanedCandidates_->push_back( (*pfCandidates_)[ pfCandidatesToBeRemoved[j] ] );
3552  (*pfCandidates_)[pfCandidatesToBeRemoved[j]].rescaleMomentum(1E-6);
3553  //reco::PFCandidate::ParticleType unknown = reco::PFCandidate::X;
3554  //(*pfCandidates_)[pfCandidatesToBeRemoved[j]].setParticleType(unknown);
3555  }
3556  }
3557  }
3558 
3559 }
double maxDeltaPhiPt_
Definition: PFAlgo.h:405
double maxSignificance_
Definition: PFAlgo.h:403
double minHFCleaningPt_
Definition: PFAlgo.h:401
double minDeltaMet_
Definition: PFAlgo.h:406
double minSignificance_
Definition: PFAlgo.h:402
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
double px() const final
x coordinate of momentum vector
double pt() const final
transverse momentum
double minSignificanceReduction_
Definition: PFAlgo.h:404
std::unique_ptr< reco::PFCandidateCollection > pfCleanedCandidates_
Definition: PFAlgo.h:290
bool postHFCleaning_
Definition: PFAlgo.h:399
T sqrt(T t)
Definition: SSEVec.h:18
double py() const final
y coordinate of momentum vector
significance
Definition: met_cff.py:30
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:39
virtual ParticleType particleId() const
Definition: PFCandidate.h:373
void PFAlgo::processBlock ( const reco::PFBlockRef blockref,
std::list< reco::PFBlockRef > &  hcalBlockRefs,
std::list< reco::PFBlockRef > &  ecalBlockRefs 
)
protectedvirtual

process one block. can be reimplemented in more sophisticated algorithms

Reimplemented in PFAlgoTestBenchConversions, and PFAlgoTestBenchElectrons.

Definition at line 538 of file PFAlgo.cc.

References a, funct::abs(), patPFMETCorrections_cff::algo, associatePSClusters(), b, edm::OwnVector< T, P >::begin(), groupFilesInBlocks::block, fftjetpileupestimator_calo_uncalib_cfi::c0, alignmentValidation::c1, calibration_, MessageLogger_cfi::cerr, reco::LeafCandidate::charge(), muons2muons_cfi::chargedHadron, trackerTree::check(), reco::TrackBase::conversionStep, gather_cfg::cout, debug_, dptRel_DispVtx_, reco::PFCandidate::e, RecoEcal_EventContent_cff::ec, ECAL, 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, dedxEstimators_cff::fraction, reco::PFCandidate::gamma, PFElectronAlgo::getAllElectronCandidates(), PFElectronAlgo::getElectronCandidates(), PFElectronAlgo::getElectronExtra(), reco::PFBlockElement::GSF, HCAL, reco::PFBlockElement::HCAL, PFLayer::HF_EM, PFLayer::HF_HAD, reco::TrackBase::highPurity, reco::PFBlockElement::HO, hcaldqm::constants::HO, mps_fire::i, cuy::ii, diffTreeTool::index, PFEGammaFilters::isElectron(), PFEGammaFilters::isElectronSafeForJetMET(), PFElectronAlgo::isElectronValidCandidate(), isFromSecInt(), PFMuonAlgo::isIsolatedMuon(), PFMuonAlgo::isLooseMuon(), PFMuonAlgo::isMuon(), edm::Ref< C, T, F >::isNonnull(), edm::Ref< C, T, F >::isNull(), PFEGammaFilters::isPhotonSafeForJetMET(), PFPhotonAlgo::isPhotonValidCandidate(), reco::PFBlock::LINKTEST_ALL, SiStripPI::max, min(), reco::PFCandidate::mu, muonECAL_, muonHCAL_, muonHO_, reco::PFCandidate::mva_e_pi(), neutralHadronEnergyResolution(), jets_cff::nMuons, nSigmaECAL_, nSigmaHCAL(), nSigmaTRACK_, nVtx_, convertSQLiteXML::ok, AlCaHLTBitMon_ParallelJobs::p, objects.autophobj::particleType, PFEGammaFilters::passElectronSelection(), PFEGammaFilters::passPhotonSelection(), pfCandidates_, pfegamma_, pfEgammaCandidates_, pfele_, pfElectronCandidates_, pfElectronExtra_, pfpho_, pfPhotonCandidates_, pfPhotonExtra_, reco::LeafCandidate::phi(), 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(), 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, reco::PFBlockElementTrack::trackType(), 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().

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

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 3186 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_, mathSSE::sqrt(), tmp, useVertices_, reco::PFCandidate::X, reco::Vertex::x(), reco::Vertex::y(), and reco::Vertex::z().

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

3191  {
3192 
3194 
3195  // need to convert the ::math::XYZPoint data member of the PFCluster class=
3196  // to a displacement vector:
3197 
3198  // Transform particleX,Y,Z to a position at ECAL/HCAL entrance
3199  double factor = 1.;
3200  if ( useDirection ) {
3201  switch( cluster.layer() ) {
3202  case PFLayer::ECAL_BARREL:
3203  case PFLayer::HCAL_BARREL1:
3204  factor = std::sqrt(cluster.position().Perp2()/(particleX*particleX+particleY*particleY));
3205  break;
3206  case PFLayer::ECAL_ENDCAP:
3207  case PFLayer::HCAL_ENDCAP:
3208  case PFLayer::HF_HAD:
3209  case PFLayer::HF_EM:
3210  factor = cluster.position().Z()/particleZ;
3211  break;
3212  default:
3213  assert(0);
3214  }
3215  }
3216  //MIKE First of all let's check if we have vertex.
3217  ::math::XYZPoint vertexPos;
3218  if(useVertices_)
3220  else
3221  vertexPos = ::math::XYZPoint(0.0,0.0,0.0);
3222 
3223 
3224  ::math::XYZVector clusterPos( cluster.position().X()-vertexPos.X(),
3225  cluster.position().Y()-vertexPos.Y(),
3226  cluster.position().Z()-vertexPos.Z());
3227  ::math::XYZVector particleDirection ( particleX*factor-vertexPos.X(),
3228  particleY*factor-vertexPos.Y(),
3229  particleZ*factor-vertexPos.Z() );
3230 
3231  //::math::XYZVector clusterPos( cluster.position().X(), cluster.position().Y(),cluster.position().Z() );
3232  //::math::XYZVector particleDirection ( particleX, particleY, particleZ );
3233 
3234  clusterPos = useDirection ? particleDirection.Unit() : clusterPos.Unit();
3235  clusterPos *= particleEnergy;
3236 
3237  // clusterPos is now a vector along the cluster direction,
3238  // with a magnitude equal to the cluster energy.
3239 
3240  double mass = 0;
3241  ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double> >
3242  momentum( clusterPos.X(), clusterPos.Y(), clusterPos.Z(), mass);
3243  // mathcore is a piece of #$%
3245  // implicit constructor not allowed
3246  tmp = momentum;
3247 
3248  // Charge
3249  int charge = 0;
3250 
3251  // Type
3252  switch( cluster.layer() ) {
3253  case PFLayer::ECAL_BARREL:
3254  case PFLayer::ECAL_ENDCAP:
3255  particleType = PFCandidate::gamma;
3256  break;
3257  case PFLayer::HCAL_BARREL1:
3258  case PFLayer::HCAL_ENDCAP:
3259  particleType = PFCandidate::h0;
3260  break;
3261  case PFLayer::HF_HAD:
3262  particleType = PFCandidate::h_HF;
3263  break;
3264  case PFLayer::HF_EM:
3265  particleType = PFCandidate::egamma_HF;
3266  break;
3267  default:
3268  assert(0);
3269  }
3270 
3271  // The pf candidate
3272  pfCandidates_->push_back( PFCandidate( charge,
3273  tmp,
3274  particleType ) );
3275 
3276  // The position at ECAL entrance (well: watch out, it is not true
3277  // for HCAL clusters... to be fixed)
3278  pfCandidates_->back().
3279  setPositionAtECALEntrance(::math::XYZPointF(cluster.position().X(),
3280  cluster.position().Y(),
3281  cluster.position().Z()));
3282 
3283  //Set the cnadidate Vertex
3284  pfCandidates_->back().setVertex(vertexPos);
3285 
3286  //*TODO* cluster time is not reliable at the moment, so only use track timing
3287 
3288  if(debug_)
3289  cout<<"** candidate: "<<pfCandidates_->back()<<endl;
3290 
3291  // returns index to the newly created PFCandidate
3292  return pfCandidates_->size()-1;
3293 
3294 }
PFLayer::Layer layer() const
cluster layer, see PFLayer.h in this directory
Definition: PFCluster.cc:128
const math::XYZPoint & position() const
cluster centroid position
Definition: CaloCluster.h:129
ParticleType
particle types
Definition: PFCandidate.h:44
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
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:410
double x() const
x coordinate
Definition: Vertex.h:111
bool useVertices_
Definition: PFAlgo.h:411
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:30
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
math::XYZVector XYZPoint
bool debug_
Definition: PFAlgo.h:336
void PFAlgo::reconstructParticles ( const reco::PFBlockHandle blockHandle)

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

Definition at line 415 of file PFAlgo.cc.

References blockHandle_.

Referenced by setCandConnectorParameters().

415  {
416 
417  blockHandle_ = blockHandle;
419 }
void reconstructParticles(const reco::PFBlockHandle &blockHandle)
Definition: PFAlgo.cc:415
reco::PFBlockHandle blockHandle_
input block handle (full framework case)
Definition: PFAlgo.h:322
void PFAlgo::reconstructParticles ( const reco::PFBlockCollection blocks)
virtual

reconstruct particles

Definition at line 423 of file PFAlgo.cc.

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

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

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

References ALCARECOTkAlJpsiMuMu_cff::charge, reco::TrackBase::charge(), gather_cfg::cout, debug_, reco::PFBlockElementTrack::displacedVertexRef(), dptRel_DispVtx_, reco::PFCandidate::h, isFromSecInt(), reco::isMuon(), edm::Ref< C, T, F >::isNonnull(), reco::PFBlockElement::isTimeValid(), reco::PFBlockElementTrack::muonRef(), reco::TrackBase::p(), objects.autophobj::particleType, pfElectronTranslator_cfi::PFCandidate, pfCandidates_, pfmu_, reco::PFBlockElementTrack::positionAtECALEntrance(), 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(), HiIsolationCommonParameters_cff::track, and reco::PFBlockElementTrack::trackRef().

Referenced by processBlock(), and thePFEnergyCalibration().

3109  {
3110 
3111  const reco::PFBlockElementTrack* eltTrack
3112  = dynamic_cast<const reco::PFBlockElementTrack*>(&elt);
3113 
3114  const reco::TrackRef& trackRef = eltTrack->trackRef();
3115  const reco::Track& track = *trackRef;
3116  const reco::MuonRef& muonRef = eltTrack->muonRef();
3117  int charge = track.charge()>0 ? 1 : -1;
3118 
3119  // Assume this particle is a charged Hadron
3120  double px = track.px();
3121  double py = track.py();
3122  double pz = track.pz();
3123  double energy = sqrt(track.p()*track.p() + 0.13957*0.13957);
3124 
3125  // Create a PF Candidate
3126  ::math::XYZTLorentzVector momentum(px,py,pz,energy);
3129 
3130  // Add it to the stack
3131  pfCandidates_->push_back( PFCandidate( charge,
3132  momentum,
3133  particleType ) );
3134  //Set vertex and stuff like this
3135  pfCandidates_->back().setVertexSource( PFCandidate::kTrkVertex );
3136  pfCandidates_->back().setTrackRef( trackRef );
3137  pfCandidates_->back().setPositionAtECALEntrance( eltTrack->positionAtECALEntrance());
3138  if( muonRef.isNonnull())
3139  pfCandidates_->back().setMuonRef( muonRef );
3140 
3141 
3142  //Set time
3143  if (elt.isTimeValid()) pfCandidates_->back().setTime( elt.time(), elt.timeError() );
3144 
3145  //OK Now try to reconstruct the particle as a muon
3146  bool isMuon=pfmu_->reconstructMuon(pfCandidates_->back(),muonRef,allowLoose);
3147  bool isFromDisp = isFromSecInt(elt, "secondary");
3148 
3149 
3150  if ((!isMuon) && isFromDisp) {
3151  double Dpt = trackRef->ptError();
3152  double dptRel = Dpt/trackRef->pt()*100;
3153  //If the track is ill measured it is better to not refit it, since the track information probably would not be used.
3154  //In the PFAlgo we use the trackref information. If the track error is too big the refitted information might be very different
3155  // from the not refitted one.
3156  if (dptRel < dptRel_DispVtx_){
3157  if (debug_)
3158  cout << "Not refitted px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
3159  //reco::TrackRef trackRef = eltTrack->trackRef();
3161  reco::Track trackRefit = vRef->refittedTrack(trackRef);
3162  //change the momentum with the refitted track
3163  ::math::XYZTLorentzVector momentum(trackRefit.px(),
3164  trackRefit.py(),
3165  trackRefit.pz(),
3166  sqrt(trackRefit.p()*trackRefit.p() + 0.13957*0.13957));
3167  if (debug_)
3168  cout << "Refitted px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
3169  }
3170  pfCandidates_->back().setFlag( reco::PFCandidate::T_FROM_DISP, true);
3171  pfCandidates_->back().setDisplacedVertexRef( eltTrack->displacedVertexRef(reco::PFBlockElement::T_FROM_DISP)->displacedVertexRef(), reco::PFCandidate::T_FROM_DISP);
3172  }
3173 
3174  // 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
3175  if(isFromSecInt(elt, "primary") && !isMuon) {
3176  pfCandidates_->back().setFlag( reco::PFCandidate::T_TO_DISP, true);
3177  pfCandidates_->back().setDisplacedVertexRef( eltTrack->displacedVertexRef(reco::PFBlockElement::T_TO_DISP)->displacedVertexRef(), reco::PFCandidate::T_TO_DISP);
3178  }
3179 
3180  // returns index to the newly created PFCandidate
3181  return pfCandidates_->size()-1;
3182 }
double p() const
momentum vector magnitude
Definition: TrackBase.h:615
bool isFromSecInt(const reco::PFBlockElement &eTrack, std::string order) const
Definition: PFAlgo.cc:3419
ParticleType
particle types
Definition: PFCandidate.h:44
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:253
bool isMuon(const Candidate &part)
Definition: pdgIdUtils.h:11
float time() const
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
const reco::TrackRef & trackRef() const override
double px() const
x coordinate of momentum vector
Definition: TrackBase.h:627
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:357
const math::XYZPointF & positionAtECALEntrance() const
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
bool isTimeValid() const
do we have a valid time information
T sqrt(T t)
Definition: SSEVec.h:18
double pz() const
z coordinate of momentum vector
Definition: TrackBase.h:639
const PFDisplacedTrackerVertexRef & displacedVertexRef(TrackType trType) const override
double dptRel_DispVtx_
Definition: PFAlgo.h:383
bool debug_
Definition: PFAlgo.h:336
int charge() const
track electric charge
Definition: TrackBase.h:567
const reco::MuonRef & muonRef() const override
double py() const
y coordinate of momentum vector
Definition: TrackBase.h:633
float timeError() const
bool reconstructMuon(reco::PFCandidate &, const reco::MuonRef &, bool allowLoose=false)
Definition: PFMuonAlgo.cc:717
void PFAlgo::setAlgo ( int  algo)
inline

Definition at line 63 of file PFAlgo.h.

References patPFMETCorrections_cff::algo, and algo_.

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

Definition at line 73 of file PFAlgo.h.

References connector_, and PFCandConnector::setParameters().

73  {
74  connector_.setParameters(iCfgCandConnector);
75  }
PFCandConnector connector_
Definition: PFAlgo.h:388
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 77 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, setDisplacedVerticesParameters(), setEGammaCollections(), setEGammaParameters(), setEGElectronCollection(), setElectronExtraRef(), PFCandConnector::setParameters(), setPFEleParameters(), setPFMuonAndFakeParameters(), setPFPhotonParameters(), setPFPhotonRegWeights(), setPFVertexParameters(), setPhotonExtraRef(), setPostHFCleaningParameters(), AlCaHLTBitMon_QueryRunRegistry::string, particleFlow_cfi::sumEtEcalIsoForEgammaSC_barrel, particleFlow_cfi::sumEtEcalIsoForEgammaSC_endcap, particleFlow_cfi::sumPtTrackIsoForEgammaSC_barrel, particleFlow_cfi::sumPtTrackIsoForEgammaSC_endcap, particleFlow_cfi::sumPtTrackIsoForPhoton, particleFlow_cfi::sumPtTrackIsoSlopeForPhoton, thePFEnergyCalibration(), hltParticleFlowForJets_cfi::useEGammaSupercluster, Reconstruction_hiPF_cff::usePFConversions, particleFlow_cfi::usePFDecays, Reconstruction_hiPF_cff::usePFElectrons, hltParticleFlowForJets_cfi::usePFNuclearInteractions, hltParticleFlowForJets_cfi::usePFSCEleCalib, hltParticleFlowForJets_cfi::useProtectionsForJetMET, VerticesFromLeptons_cfi::useVertex, and particleFlow_cfi::X0_Map.

void PFAlgo::setDebug ( bool  debug)
inline

Definition at line 66 of file PFAlgo.h.

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

PFCandConnector connector_
Definition: PFAlgo.h:388
#define debug
Definition: HDRShower.cc:19
bool debug_
Definition: PFAlgo.h:336
void setDebug(bool debug)
void PFAlgo::setDisplacedVerticesParameters ( bool  rejectTracks_Bad,
bool  rejectTracks_Step45,
bool  usePFNuclearInteractions,
bool  usePFConversions,
bool  usePFDecays,
double  dptRel_DispVtx 
)

Definition at line 354 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

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

Definition at line 267 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

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

Definition at line 212 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

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

Definition at line 3450 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

3450  {
3452 }
PFElectronAlgo * pfele_
Definition: PFAlgo.h:355
bool useEGElectrons_
Definition: PFAlgo.h:346
void setEGElectronCollection(const reco::GsfElectronCollection &egelectrons)
void PFAlgo::setElectronExtraRef ( const edm::OrphanHandle< reco::PFCandidateElectronExtraCollection > &  extrah)

Definition at line 3667 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

3667  {
3668  if(!usePFElectrons_) return;
3669  // std::cout << " setElectronExtraRef " << std::endl;
3670  unsigned size=pfCandidates_->size();
3671 
3672  for(unsigned ic=0;ic<size;++ic) {
3673  // select the electrons and add the extra
3674  if((*pfCandidates_)[ic].particleId()==PFCandidate::e) {
3675 
3676  PFElectronExtraEqual myExtraEqual((*pfCandidates_)[ic].gsfTrackRef());
3677  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
3678  if(it!=pfElectronExtra_.end()) {
3679  // std::cout << " Index " << it-pfElectronExtra_.begin() << std::endl;
3680  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
3681  (*pfCandidates_)[ic].setPFElectronExtraRef(theRef);
3682  }
3683  else {
3684  (*pfCandidates_)[ic].setPFElectronExtraRef(PFCandidateElectronExtraRef());
3685  }
3686  }
3687  else // else save the mva and the extra as well !
3688  {
3689  if((*pfCandidates_)[ic].trackRef().isNonnull()) {
3690  PFElectronExtraKfEqual myExtraEqual((*pfCandidates_)[ic].trackRef());
3691  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
3692  if(it!=pfElectronExtra_.end()) {
3693  (*pfCandidates_)[ic].set_mva_e_pi(it->mvaVariable(PFCandidateElectronExtra::MVA_MVA));
3694  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
3695  (*pfCandidates_)[ic].setPFElectronExtraRef(theRef);
3696  (*pfCandidates_)[ic].setGsfTrackRef(it->gsfTrackRef());
3697  }
3698  }
3699  }
3700 
3701  }
3702 
3703  size=pfElectronCandidates_->size();
3704  for(unsigned ic=0;ic<size;++ic) {
3705  // select the electrons - this test is actually not needed for this collection
3706  if((*pfElectronCandidates_)[ic].particleId()==PFCandidate::e) {
3707  // find the corresponding extra
3708  PFElectronExtraEqual myExtraEqual((*pfElectronCandidates_)[ic].gsfTrackRef());
3709  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
3710  if(it!=pfElectronExtra_.end()) {
3711  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
3712  (*pfElectronCandidates_)[ic].setPFElectronExtraRef(theRef);
3713 
3714  }
3715  }
3716  }
3717 
3718 }
size
Write out results.
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
edm::Ref< PFCandidateElectronExtraCollection > PFCandidateElectronExtraRef
persistent reference to a PFCandidateElectronExtra
std::unique_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
Definition: PFAlgo.h:286
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
Definition: PFAlgo.h:293
bool usePFElectrons_
Definition: PFAlgo.h:342
void PFAlgo::setHOTag ( bool  ho)
inline

Definition at line 62 of file PFAlgo.h.

References photonIsolationHIProducer_cfi::ho, and useHO_.

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

Definition at line 331 of file PFAlgo.cc.

References muonHandle_, and extraflags_cff::muons.

Referenced by setPFMuonAlgo().

331  {
332  muonHandle_ = muons;
333 }
edm::Handle< reco::MuonCollection > muonHandle_
Definition: PFAlgo.h:413
void PFAlgo::setParameters ( double  nSigmaECAL,
double  nSigmaHCAL,
const boost::shared_ptr< PFEnergyCalibration > &  calibration,
const boost::shared_ptr< PFEnergyCalibrationHF > &  thepfEnergyCalibrationHF 
)

Definition at line 79 of file PFAlgo.cc.

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

Referenced by setDebug().

82  {
83 
84  nSigmaECAL_ = nSigmaECAL;
86 
87  calibration_ = calibration;
88  thepfEnergyCalibrationHF_ = thepfEnergyCalibrationHF;
89 
90 }
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:328
double nSigmaHCAL(double clusterEnergy, double clusterEta) const
Definition: PFAlgo.cc:3315
boost::shared_ptr< PFEnergyCalibration > calibration_
Definition: PFAlgo.h:330
boost::shared_ptr< PFEnergyCalibrationHF > thepfEnergyCalibrationHF_
Definition: PFAlgo.h:331
double nSigmaECAL_
number of sigma to judge energy excess in ECAL
Definition: PFAlgo.h:325
void PFAlgo::setPFEleParameters ( double  mvaEleCut,
std::string  mvaWeightFileEleID,
bool  usePFElectrons,
const boost::shared_ptr< PFSCEnergyCalibration > &  thePFSCEnergyCalibration,
const boost::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 99 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

114  {
115 
116  mvaEleCut_ = mvaEleCut;
120  thePFSCEnergyCalibration_ = thePFSCEnergyCalibration;
121  useEGElectrons_ = useEGElectrons;
130 
131 
132  if(!usePFElectrons_) return;
133  mvaWeightFileEleID_ = mvaWeightFileEleID;
134  FILE * fileEleID = fopen(mvaWeightFileEleID_.c_str(), "r");
135  if (fileEleID) {
136  fclose(fileEleID);
137  }
138  else {
139  string err = "PFAlgo: cannot open weight file '";
140  err += mvaWeightFileEleID;
141  err += "'";
142  throw invalid_argument( err );
143  }
158 }
unsigned int nTrackIsoForEgammaSC_
Definition: PFAlgo.h:354
double sumEtEcalIsoForEgammaSC_endcap_
Definition: PFAlgo.h:349
double mvaEleCut_
Definition: PFAlgo.h:341
double coneEcalIsoForEgammaSC_
Definition: PFAlgo.h:350
double coneTrackIsoForEgammaSC_
Definition: PFAlgo.h:353
double sumEtEcalIsoForEgammaSC_barrel_
Definition: PFAlgo.h:348
PFElectronAlgo * pfele_
Definition: PFAlgo.h:355
bool useEGammaSupercluster_
Definition: PFAlgo.h:347
boost::shared_ptr< PFEnergyCalibration > thePFEnergyCalibration()
return the pointer to the calibration function
Definition: PFAlgo.h:234
bool useEGElectrons_
Definition: PFAlgo.h:346
std::string mvaWeightFileEleID_
Variables for PFElectrons.
Definition: PFAlgo.h:339
bool usePFSCEleCalib_
Definition: PFAlgo.h:345
boost::shared_ptr< PFSCEnergyCalibration > thePFSCEnergyCalibration_
Definition: PFAlgo.h:332
bool applyCrackCorrectionsElectrons_
Definition: PFAlgo.h:344
double sumPtTrackIsoForEgammaSC_endcap_
Definition: PFAlgo.h:352
double sumPtTrackIsoForEgammaSC_barrel_
Definition: PFAlgo.h:351
bool usePFElectrons_
Definition: PFAlgo.h:342
void PFAlgo::setPFMuonAlgo ( PFMuonAlgo algo)
inline

Definition at line 64 of file PFAlgo.h.

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

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

Definition at line 302 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

309 {
310 
311 
312 
313 
314  pfmu_ = new PFMuonAlgo();
315  pfmu_->setParameters(pset);
316 
317  // Muon parameters
318  muonHCAL_= pset.getParameter<std::vector<double> >("muon_HCAL");
319  muonECAL_= pset.getParameter<std::vector<double> >("muon_ECAL");
320  muonHO_= pset.getParameter<std::vector<double> >("muon_HO");
321  assert ( muonHCAL_.size() == 2 && muonECAL_.size() == 2 && muonHO_.size() == 2);
322  nSigmaTRACK_= pset.getParameter<double>("nsigma_TRACK");
323  ptError_= pset.getParameter<double>("pt_Error");
324  factors45_ = pset.getParameter<std::vector<double> >("factors_45");
325  assert ( factors45_.size() == 2 );
326 
327 }
T getParameter(std::string const &) const
double ptError_
Definition: PFAlgo.h:395
std::vector< double > muonHCAL_
Variables for muons and fakes.
Definition: PFAlgo.h:391
void setParameters(const edm::ParameterSet &)
Definition: PFMuonAlgo.cc:29
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:357
std::vector< double > factors45_
Definition: PFAlgo.h:396
std::vector< double > muonECAL_
Definition: PFAlgo.h:392
std::vector< double > muonHO_
Definition: PFAlgo.h:393
double nSigmaTRACK_
Definition: PFAlgo.h:394
void PFAlgo::setPFPhotonParameters ( bool  usePFPhoton,
std::string  mvaWeightFileConvID,
double  mvaConvCut,
bool  useReg,
std::string  X0_Map,
const boost::shared_ptr< PFEnergyCalibration > &  thePFEnergyCalibration,
double  sumPtTrackIsoForPhoton,
double  sumPtTrackIsoSlopeForPhoton 
)

Definition at line 161 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

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

Definition at line 289 of file PFAlgo.cc.

References pfpho_, and PFPhotonAlgo::setGBRForest().

Referenced by setCandConnectorParameters().

295  {
296 
297  pfpho_->setGBRForest(LCorrForestEB,LCorrForestEE,
298  GCorrForestBarrel, GCorrForestEndcapHr9,
299  GCorrForestEndcapLr9, PFEcalResolution);
300 }
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:356
void setGBRForest(const GBRForest *LCorrForest, const GBRForest *GCorrForest, const GBRForest *ResForest)
Definition: PFPhotonAlgo.h:49
void PFAlgo::setPFVertexParameters ( bool  useVertex,
const reco::VertexCollection primaryVertices 
)

Definition at line 372 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

373  {
375 
376  //Set the vertices for muon cleaning
378 
379 
380  //Now find the primary vertex!
381  bool primaryVertexFound = false;
382  nVtx_ = primaryVertices->size();
383  if(usePFPhotons_){
384  pfpho_->setnPU(nVtx_);
385  }
386  for (unsigned short i=0 ;i<primaryVertices->size();++i)
387  {
388  if(primaryVertices->at(i).isValid()&&(!primaryVertices->at(i).isFake()))
389  {
391  primaryVertexFound = true;
392  break;
393  }
394  }
395  //Use vertices if the user wants to but only if it exists a good vertex
396  useVertices_ = useVertex && primaryVertexFound;
397  if(usePFPhotons_) {
398  if (useVertices_ ){
400  }
401  else{
403  e(0, 0) = 0.0015 * 0.0015;
404  e(1, 1) = 0.0015 * 0.0015;
405  e(2, 2) = 15. * 15.;
406  reco::Vertex::Point p(0, 0, 0);
407  reco::Vertex dummy = reco::Vertex(p, e, 0, 0, 0);
408  // std::cout << " PFPho " << pfpho_ << std::endl;
409  pfpho_->setPhotonPrimaryVtx(dummy);
410  }
411  }
412 }
void setnPU(int nVtx)
Definition: PFPhotonAlgo.h:75
math::Error< dimension >::type Error
covariance error matrix (3x3)
Definition: Vertex.h:43
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:357
int nVtx_
Definition: PFAlgo.h:384
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:356
reco::Vertex primaryVertex_
Definition: PFAlgo.h:410
math::XYZPoint Point
point in the space
Definition: Vertex.h:39
bool useVertices_
Definition: PFAlgo.h:411
primaryVertices
Definition: jets_cff.py:130
void setPhotonPrimaryVtx(const reco::Vertex &primary)
Definition: PFPhotonAlgo.h:78
bool usePFPhotons_
Definition: PFAlgo.h:343
void setInputsForCleaning(const reco::VertexCollection *)
Definition: PFMuonAlgo.cc:1168
void PFAlgo::setPhotonExtraRef ( const edm::OrphanHandle< reco::PFCandidatePhotonExtraCollection > &  pf_extrah)

Definition at line 3719 of file PFAlgo.cc.

References runEdmFileComparison::found, CustomPhysics_cfi::gamma, pfCandidates_, pfPhotonExtra_, findQualityFiles::size, and usePFPhotons_.

Referenced by setCandConnectorParameters().

3719  {
3720  if(!usePFPhotons_) return;
3721  unsigned int size=pfCandidates_->size();
3722  unsigned int sizePhExtra = pfPhotonExtra_.size();
3723  for(unsigned ic=0;ic<size;++ic) {
3724  // select the electrons and add the extra
3725  if((*pfCandidates_)[ic].particleId()==PFCandidate::gamma && (*pfCandidates_)[ic].mva_nothing_gamma() > 0.99) {
3726  if((*pfCandidates_)[ic].superClusterRef().isNonnull()) {
3727  bool found = false;
3728  for(unsigned pcextra=0;pcextra<sizePhExtra;++pcextra) {
3729  if((*pfCandidates_)[ic].superClusterRef() == pfPhotonExtra_[pcextra].superClusterRef()) {
3730  reco::PFCandidatePhotonExtraRef theRef(ph_extrah,pcextra);
3731  (*pfCandidates_)[ic].setPFPhotonExtraRef(theRef);
3732  found = true;
3733  break;
3734  }
3735  }
3736  if(!found)
3737  (*pfCandidates_)[ic].setPFPhotonExtraRef((PFCandidatePhotonExtraRef())); // null ref
3738  }
3739  else {
3740  (*pfCandidates_)[ic].setPFPhotonExtraRef((PFCandidatePhotonExtraRef())); // null ref
3741  }
3742  }
3743  }
3744 }
size
Write out results.
edm::Ref< PFCandidatePhotonExtraCollection > PFCandidatePhotonExtraRef
persistent reference to a PFCandidatePhotonExtra
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
Definition: PFAlgo.h:295
bool usePFPhotons_
Definition: PFAlgo.h:343
void PFAlgo::setPostHFCleaningParameters ( bool  postHFCleaning,
double  minHFCleaningPt,
double  minSignificance,
double  maxSignificance,
double  minSignificanceReduction,
double  maxDeltaPhiPt,
double  minDeltaMet 
)

Definition at line 337 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

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

return the pointer to the calibration function

Definition at line 234 of file PFAlgo.h.

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

Referenced by setCandConnectorParameters().

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

Definition at line 229 of file PFAlgo.h.

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

229  {
231  }
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
std::unique_ptr< reco::PFCandidateCollection > connect(std::unique_ptr< reco::PFCandidateCollection > &pfCand)
PFCandConnector connector_
Definition: PFAlgo.h:388
std::unique_ptr<reco::PFCandidateCollection> PFAlgo::transferCleanedCandidates ( )
inline
Returns
collection of cleaned HF candidates

Definition at line 224 of file PFAlgo.h.

References eostools::move(), and pfCleanedCandidates_.

224  {
226  }
std::unique_ptr< reco::PFCandidateCollection > pfCleanedCandidates_
Definition: PFAlgo.h:290
def move(src, dest)
Definition: eostools.py:510
std::unique_ptr<reco::PFCandidateCollection> PFAlgo::transferElectronCandidates ( )
inline
Returns
the unfiltered electron collection

Definition at line 201 of file PFAlgo.h.

References eostools::move(), and pfElectronCandidates_.

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

Definition at line 207 of file PFAlgo.h.

References pfElectronExtra_, and mps_fire::result.

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

Definition at line 216 of file PFAlgo.h.

References pfPhotonExtra_, and mps_fire::result.

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

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

Referenced by setAlgo().

bool PFAlgo::applyCrackCorrectionsElectrons_
private

Definition at line 344 of file PFAlgo.h.

Referenced by setPFEleParameters().

reco::PFBlockHandle PFAlgo::blockHandle_
private

input block handle (full framework case)

Definition at line 322 of file PFAlgo.h.

Referenced by createBlockRef(), and reconstructParticles().

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

Definition at line 330 of file PFAlgo.h.

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

double PFAlgo::coneEcalIsoForEgammaSC_
private

Definition at line 350 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::coneTrackIsoForEgammaSC_
private

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

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

bool PFAlgo::debug_
private
double PFAlgo::dptRel_DispVtx_
private

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

Definition at line 383 of file PFAlgo.h.

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

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

Definition at line 396 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

double PFAlgo::maxDeltaPhiPt_
private

Definition at line 405 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::maxSignificance_
private

Definition at line 403 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minDeltaMet_
private

Definition at line 406 of file PFAlgo.h.

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

double PFAlgo::minHFCleaningPt_
private

Definition at line 401 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minSignificance_
private

Definition at line 402 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minSignificanceReduction_
private

Definition at line 404 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

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

Definition at line 392 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

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

Definition at line 413 of file PFAlgo.h.

Referenced by reconstructParticles(), and setMuonHandle().

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

Variables for muons and fakes.

Definition at line 391 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

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

Definition at line 393 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

double PFAlgo::mvaEleCut_
private

Definition at line 341 of file PFAlgo.h.

Referenced by setPFEleParameters().

std::string PFAlgo::mvaWeightFileEleID_
private

Variables for PFElectrons.

Definition at line 339 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::nSigmaECAL_
private

number of sigma to judge energy excess in ECAL

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

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

double PFAlgo::nSigmaTRACK_
private

Definition at line 394 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

unsigned int PFAlgo::nTrackIsoForEgammaSC_
private

Definition at line 354 of file PFAlgo.h.

Referenced by setPFEleParameters().

int PFAlgo::nVtx_
private

Definition at line 384 of file PFAlgo.h.

Referenced by processBlock(), and setPFVertexParameters().

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

Definition at line 290 of file PFAlgo.h.

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

PFEGammaFilters* PFAlgo::pfegamma_
private

Definition at line 362 of file PFAlgo.h.

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

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

Definition at line 364 of file PFAlgo.h.

Referenced by processBlock(), and setEGammaCollections().

PFElectronAlgo* PFAlgo::pfele_
private

Definition at line 355 of file PFAlgo.h.

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

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

the unfiltered electron collection

Definition at line 286 of file PFAlgo.h.

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

reco::PFCandidateElectronExtraCollection PFAlgo::pfElectronExtra_
protected

the unfiltered electron collection

Definition at line 293 of file PFAlgo.h.

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

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

the unfiltered photon collection

Definition at line 288 of file PFAlgo.h.

Referenced by processBlock(), and reconstructParticles().

reco::PFCandidatePhotonExtraCollection PFAlgo::pfPhotonExtra_
protected

the extra photon collection

Definition at line 295 of file PFAlgo.h.

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

bool PFAlgo::postHFCleaning_
private

Definition at line 399 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

bool PFAlgo::postMuonCleaning_
private

Definition at line 400 of file PFAlgo.h.

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

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

Referenced by processBlock(), and setDisplacedVerticesParameters().

bool PFAlgo::rejectTracks_Step45_
private

Definition at line 375 of file PFAlgo.h.

Referenced by processBlock(), and setDisplacedVerticesParameters().

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

Definition at line 340 of file PFAlgo.h.

double PFAlgo::sumEtEcalIsoForEgammaSC_barrel_
private

Definition at line 348 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumEtEcalIsoForEgammaSC_endcap_
private

Definition at line 349 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumPtTrackIsoForEgammaSC_barrel_
private

Definition at line 351 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumPtTrackIsoForEgammaSC_endcap_
private

Definition at line 352 of file PFAlgo.h.

Referenced by setPFEleParameters().

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

Definition at line 331 of file PFAlgo.h.

Referenced by processBlock(), and setParameters().

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

Definition at line 332 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::useBestMuonTrack_
private

Definition at line 407 of file PFAlgo.h.

bool PFAlgo::useEGammaFilters_
private

Variables for NEW EGAMMA selection.

Definition at line 361 of file PFAlgo.h.

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

bool PFAlgo::useEGammaSupercluster_
private

Definition at line 347 of file PFAlgo.h.

Referenced by setPFEleParameters().

bool PFAlgo::useEGElectrons_
private

Definition at line 346 of file PFAlgo.h.

Referenced by setEGElectronCollection(), and setPFEleParameters().

bool PFAlgo::useHO_
private

Definition at line 334 of file PFAlgo.h.

Referenced by processBlock(), and setHOTag().

bool PFAlgo::usePFConversions_
private

Definition at line 378 of file PFAlgo.h.

Referenced by processBlock(), and setDisplacedVerticesParameters().

bool PFAlgo::usePFDecays_
private

Definition at line 379 of file PFAlgo.h.

Referenced by isFromSecInt(), and setDisplacedVerticesParameters().

bool PFAlgo::usePFElectrons_
private

Definition at line 342 of file PFAlgo.h.

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

bool PFAlgo::usePFMuonMomAssign_
private

Definition at line 370 of file PFAlgo.h.

bool PFAlgo::usePFNuclearInteractions_
private

Definition at line 377 of file PFAlgo.h.

Referenced by isFromSecInt(), and setDisplacedVerticesParameters().

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

Definition at line 345 of file PFAlgo.h.

Referenced by setPFEleParameters().

bool PFAlgo::useProtectionsForJetMET_
private

Definition at line 363 of file PFAlgo.h.

Referenced by processBlock(), and setEGammaParameters().

bool PFAlgo::useVertices_
private

Definition at line 411 of file PFAlgo.h.

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

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

Definition at line 365 of file PFAlgo.h.

Referenced by setEGammaCollections().

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

Definition at line 366 of file PFAlgo.h.

Referenced by setEGammaCollections().