CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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::auto_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
< PFEnergyCalibration
thePFEnergyCalibration ()
 return the pointer to the calibration function More...
 
std::auto_ptr
< reco::PFCandidateCollection
transferCandidates ()
 
std::auto_ptr
< reco::PFCandidateCollection > & 
transferCleanedCandidates ()
 
std::auto_ptr
< reco::PFCandidateCollection
transferElectronCandidates ()
 
std::auto_ptr
< reco::PFCandidateElectronExtraCollection
transferElectronExtra ()
 
std::auto_ptr
< reco::PFCandidatePhotonExtraCollection
transferPhotonExtra ()
 
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::auto_ptr
< reco::PFCandidateCollection
pfCandidates_
 
std::auto_ptr
< reco::PFCandidateCollection
pfCleanedCandidates_
 
std::auto_ptr
< reco::PFCandidateCollection
pfElectronCandidates_
 the unfiltered electron collection More...
 
reco::PFCandidateElectronExtraCollection pfElectronExtra_
 the unfiltered electron collection More...
 
std::auto_ptr
< reco::PFCandidateCollection
pfPhotonCandidates_
 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
< PFEnergyCalibration
calibration_
 
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
< PFEnergyCalibrationHF
thepfEnergyCalibrationHF_
 
boost::shared_ptr
< PFSCEnergyCalibration
thePFSCEnergyCalibration_
 
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 58 of file PFAlgo.cc.

60  nSigmaECAL_(0),
61  nSigmaHCAL_(1),
62  algo_(1),
63  debug_(false),
64  pfele_(0),
65  pfpho_(0),
66  pfegamma_(0),
67  useVertices_(false)
68 {}
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
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
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 70 of file PFAlgo.cc.

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

70  {
71  if (usePFElectrons_) delete pfele_;
72  if (usePFPhotons_) delete pfpho_;
73  if (useEGammaFilters_) delete pfegamma_;
74 }
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 3401 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().

3407  {
3408 
3409  // Find all PS clusters with type psElement associated to ECAL cluster iEcal,
3410  // within all PFBlockElement "elements" of a given PFBlock "block"
3411  // psElement can be reco::PFBlockElement::PS1 or reco::PFBlockElement::PS2
3412  // Returns a vector of PS cluster energies, and updates the "active" vector.
3413 
3414  // Find all PS clusters linked to the iEcal cluster
3415  std::multimap<double, unsigned> sortedPS;
3416  typedef std::multimap<double, unsigned>::iterator IE;
3417  block.associatedElements( iEcal, linkData,
3418  sortedPS, psElementType,
3420 
3421  // Loop over these PS clusters
3422  double totalPS = 0.;
3423  for ( IE ips=sortedPS.begin(); ips!=sortedPS.end(); ++ips ) {
3424 
3425  // CLuster index and distance to iEcal
3426  unsigned iPS = ips->second;
3427  // double distPS = ips->first;
3428 
3429  // Ignore clusters already in use
3430  if (!active[iPS]) continue;
3431 
3432  // Check that this cluster is not closer to another ECAL cluster
3433  std::multimap<double, unsigned> sortedECAL;
3434  block.associatedElements( iPS, linkData,
3435  sortedECAL,
3438  unsigned jEcal = sortedECAL.begin()->second;
3439  if ( jEcal != iEcal ) continue;
3440 
3441  // Update PS energy
3442  PFBlockElement::Type pstype = elements[ iPS ].type();
3443  assert( pstype == psElementType );
3444  PFClusterRef psclusterref = elements[iPS].clusterRef();
3445  assert(!psclusterref.isNull() );
3446  totalPS += psclusterref->energy();
3447  psEne[0] += psclusterref->energy();
3448  active[iPS] = false;
3449  }
3450 
3451 
3452 }
bool isNull() const
Checks for null.
Definition: Ref.h:247
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 3599 of file PFAlgo.cc.

References gather_cfg::cout, debug_, reco::PFRecHit::energy(), i, j, reco::PFRecHit::layer(), minDeltaMet_, GetRecoTauVFromDQM_MC_cff::next, pfCandidates_, reco::PFRecHit::position(), RecoTauCleanerPlugins::pt, reco::LeafCandidate::pt(), reco::LeafCandidate::px(), reco::LeafCandidate::py(), reconstructCluster(), runGlobalFakeInputProducer::skip, mathSSE::sqrt(), and reco::PFRecHit::time().

3599  {
3600 
3601 
3602  // No hits to recover, leave.
3603  if ( !cleanedHits.size() ) return;
3604 
3605  //Compute met and met significance (met/sqrt(SumEt))
3606  double metX = 0.;
3607  double metY = 0.;
3608  double sumet = 0;
3609  std::vector<unsigned int> hitsToBeAdded;
3610  for(unsigned i=0; i<pfCandidates_->size(); i++) {
3611  const PFCandidate& pfc = (*pfCandidates_)[i];
3612  metX += pfc.px();
3613  metY += pfc.py();
3614  sumet += pfc.pt();
3615  }
3616  double met2 = metX*metX+metY*metY;
3617  double met2_Original = met2;
3618  // Select events with large MET significance.
3619  // double significance = std::sqrt(met2/sumet);
3620  // double significanceCor = significance;
3621  double metXCor = metX;
3622  double metYCor = metY;
3623  double sumetCor = sumet;
3624  double met2Cor = met2;
3625  bool next = true;
3626  unsigned iCor = 1E9;
3627 
3628  // Find the cleaned hit with the largest effect on the MET
3629  while ( next ) {
3630 
3631  double metReduc = -1.;
3632  // Loop on the candidates
3633  for(unsigned i=0; i<cleanedHits.size(); ++i) {
3634  const PFRecHit& hit = cleanedHits[i];
3635  double length = std::sqrt(hit.position().Mag2());
3636  double px = hit.energy() * hit.position().x()/length;
3637  double py = hit.energy() * hit.position().y()/length;
3638  double pt = std::sqrt(px*px + py*py);
3639 
3640  // Check that it is not already scheculed to be cleaned
3641  bool skip = false;
3642  for(unsigned j=0; j<hitsToBeAdded.size(); ++j) {
3643  if ( i == hitsToBeAdded[j] ) skip = true;
3644  if ( skip ) break;
3645  }
3646  if ( skip ) continue;
3647 
3648  // Now add the candidate to the MET
3649  double metXInt = metX + px;
3650  double metYInt = metY + py;
3651  double sumetInt = sumet + pt;
3652  double met2Int = metXInt*metXInt+metYInt*metYInt;
3653 
3654  // And check if it could contribute to a MET reduction
3655  if ( met2Int < met2Cor ) {
3656  metXCor = metXInt;
3657  metYCor = metYInt;
3658  metReduc = (met2-met2Int)/met2Int;
3659  met2Cor = met2Int;
3660  sumetCor = sumetInt;
3661  // significanceCor = std::sqrt(met2Cor/sumetCor);
3662  iCor = i;
3663  }
3664  }
3665  //
3666  // If the MET must be significanly reduced, schedule the candidate to be added
3667  //
3668  if ( metReduc > minDeltaMet_ ) {
3669  hitsToBeAdded.push_back(iCor);
3670  metX = metXCor;
3671  metY = metYCor;
3672  sumet = sumetCor;
3673  met2 = met2Cor;
3674  } else {
3675  // Otherwise just stop the loop
3676  next = false;
3677  }
3678  }
3679  //
3680  // At least 10 GeV MET reduction
3681  if ( std::sqrt(met2_Original) - std::sqrt(met2) > 5. ) {
3682  if ( debug_ ) {
3683  std::cout << hitsToBeAdded.size() << " hits were re-added " << std::endl;
3684  std::cout << "MET reduction = " << std::sqrt(met2_Original) << " -> "
3685  << std::sqrt(met2Cor) << " = " << std::sqrt(met2Cor) - std::sqrt(met2_Original)
3686  << std::endl;
3687  std::cout << "Added after cleaning check : " << std::endl;
3688  }
3689  for(unsigned j=0; j<hitsToBeAdded.size(); ++j) {
3690  const PFRecHit& hit = cleanedHits[hitsToBeAdded[j]];
3691  PFCluster cluster(hit.layer(), hit.energy(),
3692  hit.position().x(), hit.position().y(), hit.position().z() );
3693  reconstructCluster(cluster,hit.energy());
3694  if ( debug_ ) {
3695  std::cout << pfCandidates_->back() << ". time = " << hit.time() << std::endl;
3696  }
3697  }
3698  }
3699 
3700 }
int i
Definition: DBlmapReader.cc:9
Particle flow cluster, see clustering algorithm in PFClusterAlgo.
Definition: PFCluster.h:47
double minDeltaMet_
Definition: PFAlgo.h:406
unsigned reconstructCluster(const reco::PFCluster &cluster, double particleEnergy, bool useDirection=false, double particleX=0., double particleY=0., double particleZ=0.)
Definition: PFAlgo.cc:3224
virtual double py() const GCC11_FINAL
y coordinate of momentum vector
PFLayer::Layer layer() const
rechit layer
Definition: PFRecHit.h:104
Particle flow rechit (rechit + geometry and topology information). See clustering algorithm in PFClus...
Definition: PFRecHit.h:35
T sqrt(T t)
Definition: SSEVec.h:48
virtual double px() const GCC11_FINAL
x coordinate of momentum vector
int j
Definition: DBlmapReader.cc:9
const math::XYZPoint & position() const
rechit cell centre x, y, z
Definition: PFRecHit.h:123
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:38
double energy() const
rechit energy
Definition: PFRecHit.h:107
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
bool debug_
Definition: PFAlgo.h:336
tuple cout
Definition: gather_cfg.py:121
double time() const
timing for cleaned hits
Definition: PFRecHit.h:111
virtual float pt() const GCC11_FINAL
transverse momentum
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 3389 of file PFAlgo.cc.

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

Referenced by reconstructParticles().

3390  {
3391 
3392  if( blockHandle_.isValid() ) {
3393  return reco::PFBlockRef( blockHandle_, bi );
3394  }
3395  else {
3396  return reco::PFBlockRef( &blocks, bi );
3397  }
3398 }
edm::Ref< PFBlockCollection > PFBlockRef
persistent reference to PFCluster objects
Definition: PFBlockFwd.h:20
bool isValid() const
Definition: HandleBase.h:76
list blocks
Definition: gather_cfg.py:90
reco::PFBlockHandle blockHandle_
input block handle (full framework case)
Definition: PFAlgo.h:322
PFMuonAlgo * PFAlgo::getPFMuonAlgo ( )

Definition at line 92 of file PFAlgo.cc.

References pfmu_.

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

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

3456  {
3457 
3460  // reco::PFBlockElement::TrackType T_FROM_GAMMACONV = reco::PFBlockElement::T_FROM_GAMMACONV;
3462 
3463  bool bPrimary = (order.find("primary") != string::npos);
3464  bool bSecondary = (order.find("secondary") != string::npos);
3465  bool bAll = (order.find("all") != string::npos);
3466 
3467  bool isToDisp = usePFNuclearInteractions_ && eTrack.trackType(T_TO_DISP);
3468  bool isFromDisp = usePFNuclearInteractions_ && eTrack.trackType(T_FROM_DISP);
3469 
3470  if (bPrimary && isToDisp) return true;
3471  if (bSecondary && isFromDisp ) return true;
3472  if (bAll && ( isToDisp || isFromDisp ) ) return true;
3473 
3474 // bool isFromConv = usePFConversions_ && eTrack.trackType(T_FROM_GAMMACONV);
3475 
3476 // if ((bAll || bSecondary)&& isFromConv) return true;
3477 
3478  bool isFromDecay = (bAll || bSecondary) && usePFDecays_ && eTrack.trackType(T_FROM_V0);
3479 
3480  return isFromDecay;
3481 
3482 
3483 }
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 3336 of file PFAlgo.cc.

References mathSSE::sqrt().

Referenced by processBlock().

3336  {
3337 
3338  // Add a protection
3339  if ( clusterEnergyHCAL < 1. ) clusterEnergyHCAL = 1.;
3340 
3341  double resol = fabs(eta) < 1.48 ?
3342  sqrt (1.02*1.02/clusterEnergyHCAL + 0.065*0.065)
3343  :
3344  sqrt (1.20*1.20/clusterEnergyHCAL + 0.028*0.028);
3345 
3346  return resol;
3347 
3348 }
T eta() const
T sqrt(T t)
Definition: SSEVec.h:48
double PFAlgo::nSigmaHCAL ( double  clusterEnergy,
double  clusterEta 
) const
protected

Definition at line 3351 of file PFAlgo.cc.

References create_public_lumi_plots::exp, and nSigmaHCAL_.

Referenced by processBlock(), and setParameters().

3351  {
3352  double nS = fabs(eta) < 1.48 ?
3353  nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL/100.))
3354  :
3355  nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL/100.));
3356 
3357  return nS;
3358 }
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:328
T eta() const
const std::auto_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::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
void PFAlgo::postCleaning ( )
protected

Definition at line 3492 of file PFAlgo.cc.

References gather_cfg::cout, SiPixelRawToDigiRegional_cfi::deltaPhi, reco::PFCandidate::egamma_HF, reco::PFCandidate::h_HF, i, j, 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(), runGlobalFakeInputProducer::skip, and mathSSE::sqrt().

Referenced by reconstructParticles().

3492  {
3493 
3494  // Check if the post HF Cleaning was requested - if not, do nothing
3495  if ( !postHFCleaning_ ) return;
3496 
3497  //Compute met and met significance (met/sqrt(SumEt))
3498  double metX = 0.;
3499  double metY = 0.;
3500  double sumet = 0;
3501  std::vector<unsigned int> pfCandidatesToBeRemoved;
3502  for(unsigned i=0; i<pfCandidates_->size(); i++) {
3503  const PFCandidate& pfc = (*pfCandidates_)[i];
3504  metX += pfc.px();
3505  metY += pfc.py();
3506  sumet += pfc.pt();
3507  }
3508  double met2 = metX*metX+metY*metY;
3509  // Select events with large MET significance.
3510  double significance = std::sqrt(met2/sumet);
3511  double significanceCor = significance;
3512  if ( significance > minSignificance_ ) {
3513 
3514  double metXCor = metX;
3515  double metYCor = metY;
3516  double sumetCor = sumet;
3517  double met2Cor = met2;
3518  double deltaPhi = 3.14159;
3519  double deltaPhiPt = 100.;
3520  bool next = true;
3521  unsigned iCor = 1E9;
3522 
3523  // Find the HF candidate with the largest effect on the MET
3524  while ( next ) {
3525 
3526  double metReduc = -1.;
3527  // Loop on the candidates
3528  for(unsigned i=0; i<pfCandidates_->size(); ++i) {
3529  const PFCandidate& pfc = (*pfCandidates_)[i];
3530 
3531  // Check that the pfCandidate is in the HF
3532  if ( pfc.particleId() != reco::PFCandidate::h_HF &&
3533  pfc.particleId() != reco::PFCandidate::egamma_HF ) continue;
3534 
3535  // Check if has meaningful pt
3536  if ( pfc.pt() < minHFCleaningPt_ ) continue;
3537 
3538  // Check that it is not already scheculed to be cleaned
3539  bool skip = false;
3540  for(unsigned j=0; j<pfCandidatesToBeRemoved.size(); ++j) {
3541  if ( i == pfCandidatesToBeRemoved[j] ) skip = true;
3542  if ( skip ) break;
3543  }
3544  if ( skip ) continue;
3545 
3546  // Check that the pt and the MET are aligned
3547  deltaPhi = std::acos((metX*pfc.px()+metY*pfc.py())/(pfc.pt()*std::sqrt(met2)));
3548  deltaPhiPt = deltaPhi*pfc.pt();
3549  if ( deltaPhiPt > maxDeltaPhiPt_ ) continue;
3550 
3551  // Now remove the candidate from the MET
3552  double metXInt = metX - pfc.px();
3553  double metYInt = metY - pfc.py();
3554  double sumetInt = sumet - pfc.pt();
3555  double met2Int = metXInt*metXInt+metYInt*metYInt;
3556  if ( met2Int < met2Cor ) {
3557  metXCor = metXInt;
3558  metYCor = metYInt;
3559  metReduc = (met2-met2Int)/met2Int;
3560  met2Cor = met2Int;
3561  sumetCor = sumetInt;
3562  significanceCor = std::sqrt(met2Cor/sumetCor);
3563  iCor = i;
3564  }
3565  }
3566  //
3567  // If the MET must be significanly reduced, schedule the candidate to be cleaned
3568  if ( metReduc > minDeltaMet_ ) {
3569  pfCandidatesToBeRemoved.push_back(iCor);
3570  metX = metXCor;
3571  metY = metYCor;
3572  sumet = sumetCor;
3573  met2 = met2Cor;
3574  } else {
3575  // Otherwise just stop the loop
3576  next = false;
3577  }
3578  }
3579  //
3580  // The significance must be significantly reduced to indeed clean the candidates
3581  if ( significance - significanceCor > minSignificanceReduction_ &&
3582  significanceCor < maxSignificance_ ) {
3583  std::cout << "Significance reduction = " << significance << " -> "
3584  << significanceCor << " = " << significanceCor - significance
3585  << std::endl;
3586  for(unsigned j=0; j<pfCandidatesToBeRemoved.size(); ++j) {
3587  std::cout << "Removed : " << (*pfCandidates_)[pfCandidatesToBeRemoved[j]] << std::endl;
3588  pfCleanedCandidates_->push_back( (*pfCandidates_)[ pfCandidatesToBeRemoved[j] ] );
3589  (*pfCandidates_)[pfCandidatesToBeRemoved[j]].rescaleMomentum(1E-6);
3590  //reco::PFCandidate::ParticleType unknown = reco::PFCandidate::X;
3591  //(*pfCandidates_)[pfCandidatesToBeRemoved[j]].setParticleType(unknown);
3592  }
3593  }
3594  }
3595 
3596 }
int i
Definition: DBlmapReader.cc:9
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::auto_ptr< reco::PFCandidateCollection > pfCleanedCandidates_
Definition: PFAlgo.h:290
virtual double py() const GCC11_FINAL
y coordinate of momentum vector
double minSignificanceReduction_
Definition: PFAlgo.h:404
bool postHFCleaning_
Definition: PFAlgo.h:399
T sqrt(T t)
Definition: SSEVec.h:48
virtual double px() const GCC11_FINAL
x coordinate of momentum vector
int j
Definition: DBlmapReader.cc:9
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:38
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
tuple cout
Definition: gather_cfg.py:121
virtual ParticleType particleId() const
Definition: PFCandidate.h:355
virtual float pt() const GCC11_FINAL
transverse momentum
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 537 of file PFAlgo.cc.

References a, funct::abs(), associatePSClusters(), b, edm::OwnVector< T, P >::begin(), createPayload::block, alignmentValidation::c1, calibration_, dtNoiseDBValidation_cfg::cerr, reco::LeafCandidate::charge(), CastorDataFrameFilter_impl::check(), gather_cfg::cout, debug_, dptRel_DispVtx_, reco::PFCandidate::e, ECAL, reco::PFBlockElement::ECAL, reco::PFCandidate::egammaExtraRef(), asciidump::elements, reco::PFCandidate::elementsInBlocks(), reco::LeafCandidate::energy(), eta(), reco::LeafCandidate::eta(), factors45_, first, 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, i, cuy::ii, cmsHarvester::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(), j, reco::PFBlock::LINKTEST_ALL, max(), bookConverter::min, reco::PFCandidate::mu, muonECAL_, muonHCAL_, muonHO_, reco::PFCandidate::mva_e_pi(), neutralHadronEnergyResolution(), nSigmaECAL_, nSigmaHCAL(), nSigmaTRACK_, nVtx_, convertSQLiteXML::ok, AlCaHLTBitMon_ParallelJobs::p, 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(), reconstructCluster(), reconstructTrack(), edm::View< T >::refAt(), rejectTracks_Bad_, rejectTracks_Step45_, edm::second(), reco::PFCandidate::set_mva_e_pi(), 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(), runGlobalFakeInputProducer::skip, mathSSE::sqrt(), 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(), reco::Vertex::y(), Gflash::Z, and reco::Vertex::z().

Referenced by reconstructParticles().

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

References DeDxDiscriminatorTools::charge(), gather_cfg::cout, debug_, PFLayer::ECAL_BARREL, PFLayer::ECAL_ENDCAP, PFLayer::HCAL_BARREL1, PFLayer::HCAL_ENDCAP, PFLayer::HF_EM, PFLayer::HF_HAD, reco::PFCluster::layer(), 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(), and processBlock().

3229  {
3230 
3232 
3233  // need to convert the ::math::XYZPoint data member of the PFCluster class=
3234  // to a displacement vector:
3235 
3236  // Transform particleX,Y,Z to a position at ECAL/HCAL entrance
3237  double factor = 1.;
3238  if ( useDirection ) {
3239  switch( cluster.layer() ) {
3240  case PFLayer::ECAL_BARREL:
3241  case PFLayer::HCAL_BARREL1:
3242  factor = std::sqrt(cluster.position().Perp2()/(particleX*particleX+particleY*particleY));
3243  break;
3244  case PFLayer::ECAL_ENDCAP:
3245  case PFLayer::HCAL_ENDCAP:
3246  case PFLayer::HF_HAD:
3247  case PFLayer::HF_EM:
3248  factor = cluster.position().Z()/particleZ;
3249  break;
3250  default:
3251  assert(0);
3252  }
3253  }
3254  //MIKE First of all let's check if we have vertex.
3255  ::math::XYZPoint vertexPos;
3256  if(useVertices_)
3258  else
3259  vertexPos = ::math::XYZPoint(0.0,0.0,0.0);
3260 
3261 
3262  ::math::XYZVector clusterPos( cluster.position().X()-vertexPos.X(),
3263  cluster.position().Y()-vertexPos.Y(),
3264  cluster.position().Z()-vertexPos.Z());
3265  ::math::XYZVector particleDirection ( particleX*factor-vertexPos.X(),
3266  particleY*factor-vertexPos.Y(),
3267  particleZ*factor-vertexPos.Z() );
3268 
3269  //::math::XYZVector clusterPos( cluster.position().X(), cluster.position().Y(),cluster.position().Z() );
3270  //::math::XYZVector particleDirection ( particleX, particleY, particleZ );
3271 
3272  clusterPos = useDirection ? particleDirection.Unit() : clusterPos.Unit();
3273  clusterPos *= particleEnergy;
3274 
3275  // clusterPos is now a vector along the cluster direction,
3276  // with a magnitude equal to the cluster energy.
3277 
3278  double mass = 0;
3279  ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double> >
3280  momentum( clusterPos.X(), clusterPos.Y(), clusterPos.Z(), mass);
3281  // mathcore is a piece of #$%
3283  // implicit constructor not allowed
3284  tmp = momentum;
3285 
3286  // Charge
3287  int charge = 0;
3288 
3289  // Type
3290  switch( cluster.layer() ) {
3291  case PFLayer::ECAL_BARREL:
3292  case PFLayer::ECAL_ENDCAP:
3293  particleType = PFCandidate::gamma;
3294  break;
3295  case PFLayer::HCAL_BARREL1:
3296  case PFLayer::HCAL_ENDCAP:
3297  particleType = PFCandidate::h0;
3298  break;
3299  case PFLayer::HF_HAD:
3300  particleType = PFCandidate::h_HF;
3301  break;
3302  case PFLayer::HF_EM:
3303  particleType = PFCandidate::egamma_HF;
3304  break;
3305  default:
3306  assert(0);
3307  }
3308 
3309  // The pf candidate
3310  pfCandidates_->push_back( PFCandidate( charge,
3311  tmp,
3312  particleType ) );
3313 
3314  // The position at ECAL entrance (well: watch out, it is not true
3315  // for HCAL clusters... to be fixed)
3316  pfCandidates_->back().
3317  setPositionAtECALEntrance(::math::XYZPointF(cluster.position().X(),
3318  cluster.position().Y(),
3319  cluster.position().Z()));
3320 
3321  //Set the cnadidate Vertex
3322  pfCandidates_->back().setVertex(vertexPos);
3323 
3324  if(debug_)
3325  cout<<"** candidate: "<<pfCandidates_->back()<<endl;
3326 
3327  // returns index to the newly created PFCandidate
3328  return pfCandidates_->size()-1;
3329 
3330 }
PFLayer::Layer layer() const
cluster layer, see PFLayer.h in this directory
Definition: PFCluster.cc:85
const math::XYZPoint & position() const
cluster centroid position
Definition: CaloCluster.h:124
ParticleType
particle types
Definition: PFCandidate.h:43
double y() const
y coordinate
Definition: Vertex.h:110
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< float > > XYZPointF
point in space with cartesian internal representation
Definition: Point3D.h:10
double charge(const std::vector< uint8_t > &Ampls)
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
T sqrt(T t)
Definition: SSEVec.h:48
double z() const
y coordinate
Definition: Vertex.h:112
reco::Vertex primaryVertex_
Definition: PFAlgo.h:410
double x() const
x coordinate
Definition: Vertex.h:108
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
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:38
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
bool debug_
Definition: PFAlgo.h:336
tuple cout
Definition: gather_cfg.py:121
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 414 of file PFAlgo.cc.

References blockHandle_.

414  {
415 
416  blockHandle_ = blockHandle;
418 }
void reconstructParticles(const reco::PFBlockHandle &blockHandle)
Definition: PFAlgo.cc:414
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 422 of file PFAlgo.cc.

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

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

References DeDxDiscriminatorTools::charge(), reco::TrackBase::charge(), gather_cfg::cout, debug_, reco::PFBlockElementTrack::displacedVertexRef(), dptRel_DispVtx_, relval_parameters_module::energy, reco::PFCandidate::h, isFromSecInt(), reco::isMuon(), edm::Ref< C, T, F >::isNonnull(), reco::PFBlockElementTrack::muonRef(), reco::TrackBase::p(), 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, and reco::PFBlockElementTrack::trackRef().

Referenced by processBlock().

3150  {
3151 
3152  const reco::PFBlockElementTrack* eltTrack
3153  = dynamic_cast<const reco::PFBlockElementTrack*>(&elt);
3154 
3155  reco::TrackRef trackRef = eltTrack->trackRef();
3156  const reco::Track& track = *trackRef;
3157  reco::MuonRef muonRef = eltTrack->muonRef();
3158  int charge = track.charge()>0 ? 1 : -1;
3159 
3160  // Assume this particle is a charged Hadron
3161  double px = track.px();
3162  double py = track.py();
3163  double pz = track.pz();
3164  double energy = sqrt(track.p()*track.p() + 0.13957*0.13957);
3165 
3166  // Create a PF Candidate
3167  ::math::XYZTLorentzVector momentum(px,py,pz,energy);
3168  reco::PFCandidate::ParticleType particleType
3170 
3171  // Add it to the stack
3172  pfCandidates_->push_back( PFCandidate( charge,
3173  momentum,
3174  particleType ) );
3175  //Set vertex and stuff like this
3176  pfCandidates_->back().setVertexSource( PFCandidate::kTrkVertex );
3177  pfCandidates_->back().setTrackRef( trackRef );
3178  pfCandidates_->back().setPositionAtECALEntrance( eltTrack->positionAtECALEntrance());
3179  if( muonRef.isNonnull())
3180  pfCandidates_->back().setMuonRef( muonRef );
3181 
3182 
3183 
3184  //OK Now try to reconstruct the particle as a muon
3185  bool isMuon=pfmu_->reconstructMuon(pfCandidates_->back(),muonRef,allowLoose);
3186  bool isFromDisp = isFromSecInt(elt, "secondary");
3187 
3188 
3189  if ((!isMuon) && isFromDisp) {
3190  double Dpt = trackRef->ptError();
3191  double dptRel = Dpt/trackRef->pt()*100;
3192  //If the track is ill measured it is better to not refit it, since the track information probably would not be used.
3193  //In the PFAlgo we use the trackref information. If the track error is too big the refitted information might be very different
3194  // from the not refitted one.
3195  if (dptRel < dptRel_DispVtx_){
3196  if (debug_)
3197  cout << "Not refitted px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
3198  //reco::TrackRef trackRef = eltTrack->trackRef();
3200  reco::Track trackRefit = vRef->refittedTrack(trackRef);
3201  //change the momentum with the refitted track
3202  ::math::XYZTLorentzVector momentum(trackRefit.px(),
3203  trackRefit.py(),
3204  trackRefit.pz(),
3205  sqrt(trackRefit.p()*trackRefit.p() + 0.13957*0.13957));
3206  if (debug_)
3207  cout << "Refitted px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
3208  }
3209  pfCandidates_->back().setFlag( reco::PFCandidate::T_FROM_DISP, true);
3210  pfCandidates_->back().setDisplacedVertexRef( eltTrack->displacedVertexRef(reco::PFBlockElement::T_FROM_DISP)->displacedVertexRef(), reco::PFCandidate::T_FROM_DISP);
3211  }
3212 
3213  // 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
3214  if(isFromSecInt(elt, "primary") && !isMuon) {
3215  pfCandidates_->back().setFlag( reco::PFCandidate::T_TO_DISP, true);
3216  pfCandidates_->back().setDisplacedVertexRef( eltTrack->displacedVertexRef(reco::PFBlockElement::T_TO_DISP)->displacedVertexRef(), reco::PFCandidate::T_TO_DISP);
3217  }
3218  // returns index to the newly created PFCandidate
3219  return pfCandidates_->size()-1;
3220 }
double p() const
momentum vector magnitude
Definition: TrackBase.h:127
bool isFromSecInt(const reco::PFBlockElement &eTrack, std::string order) const
Definition: PFAlgo.cc:3456
const reco::TrackRef & trackRef() const
ParticleType
particle types
Definition: PFCandidate.h:43
bool isMuon(const Candidate &part)
Definition: pdgIdUtils.h:11
double px() const
x coordinate of momentum vector
Definition: TrackBase.h:131
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:357
double charge(const std::vector< uint8_t > &Ampls)
const math::XYZPointF & positionAtECALEntrance() const
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:250
T sqrt(T t)
Definition: SSEVec.h:48
double pz() const
z coordinate of momentum vector
Definition: TrackBase.h:135
double dptRel_DispVtx_
Definition: PFAlgo.h:383
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:38
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
const PFDisplacedTrackerVertexRef & displacedVertexRef(TrackType trType) const
bool debug_
Definition: PFAlgo.h:336
tuple cout
Definition: gather_cfg.py:121
int charge() const
track electric charge
Definition: TrackBase.h:111
const reco::MuonRef & muonRef() const
double py() const
y coordinate of momentum vector
Definition: TrackBase.h:133
bool reconstructMuon(reco::PFCandidate &, const reco::MuonRef &, bool allowLoose=false)
Definition: PFMuonAlgo.cc:685
void PFAlgo::setAlgo ( int  algo)
inline

Definition at line 63 of file PFAlgo.h.

References algo_.

63 {algo_ = algo;}
int algo_
Definition: PFAlgo.h:335
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 connector_, and PFCandConnector::setParameters().

82  {
83  connector_.setParameters(bCorrect, bCalibPrimary, dptRel_PrimaryTrack, dptRel_MergedTrack, ptErrorSecondary, nuclCalibFactors);
84  }
PFCandConnector connector_
Definition: PFAlgo.h:388
void setParameters(const edm::ParameterSet &iCfgCandConnector)
void PFAlgo::setDebug ( bool  debug)
inline

Definition at line 66 of file PFAlgo.h.

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

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

References dptRel_DispVtx_, rejectTracks_Bad_, rejectTracks_Step45_, usePFConversions_, usePFDecays_, and usePFNuclearInteractions_.

358  {
359 
360  rejectTracks_Bad_ = rejectTracks_Bad;
361  rejectTracks_Step45_ = rejectTracks_Step45;
362  usePFNuclearInteractions_ = usePFNuclearInteractions;
363  usePFConversions_ = usePFConversions;
364  usePFDecays_ = usePFDecays;
365  dptRel_DispVtx_ = dptRel_DispVtx;
366 
367 }
bool usePFConversions_
Definition: PFAlgo.h:378
bool rejectTracks_Step45_
Definition: PFAlgo.h:375
bool usePFNuclearInteractions_
Definition: PFAlgo.h:377
double dptRel_DispVtx_
Definition: PFAlgo.h:383
bool rejectTracks_Bad_
Definition: PFAlgo.h:374
bool usePFDecays_
Definition: PFAlgo.h:379
void PFAlgo::setEGammaCollections ( const edm::View< reco::PFCandidate > &  pfEgammaCandidates,
const edm::ValueMap< reco::GsfElectronRef > &  valueMapGedElectrons,
const edm::ValueMap< reco::PhotonRef > &  valueMapGedPhotons 
)

Definition at line 266 of file PFAlgo.cc.

References pfEgammaCandidates_, useEGammaFilters_, valueMapGedElectrons_, and valueMapGedPhotons_.

268  {
269  if(useEGammaFilters_) {
270  pfEgammaCandidates_ = & pfEgammaCandidates;
271  valueMapGedElectrons_ = & valueMapGedElectrons;
272  valueMapGedPhotons_ = & valueMapGedPhotons;
273  }
274 }
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 211 of file PFAlgo.cc.

References pfegamma_, useEGammaFilters_, and useProtectionsForJetMET_.

229 {
230 
231  useEGammaFilters_ = use_EGammaFilters;
232 
233  if(!useEGammaFilters_ ) return;
234  FILE * fileEGamma_ele_iso_ID = fopen(ele_iso_path_mvaWeightFile.c_str(), "r");
235  if (fileEGamma_ele_iso_ID) {
236  fclose(fileEGamma_ele_iso_ID);
237  }
238  else {
239  string err = "PFAlgo: cannot open weight file '";
240  err += ele_iso_path_mvaWeightFile;
241  err += "'";
242  throw invalid_argument( err );
243  }
244 
245  // ele_iso_mvaID_ = new ElectronMVAEstimator(ele_iso_path_mvaWeightFile_);
246  useProtectionsForJetMET_ = useProtectionsForJetMET;
247 
248  pfegamma_ = new PFEGammaFilters(ph_MinEt,
249  ph_combIso,
250  ph_HoE,
251  ph_sietaieta_eb,
252  ph_sietaieta_ee,
253  ph_protectionsForJetMET,
254  ele_iso_pt,
255  ele_iso_mva_barrel,
256  ele_iso_mva_endcap,
257  ele_iso_combIso_barrel,
258  ele_iso_combIso_endcap,
259  ele_noniso_mva,
260  ele_missinghits,
261  ele_iso_path_mvaWeightFile,
262  ele_protectionsForJetMET);
263 
264  return;
265 }
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 3487 of file PFAlgo.cc.

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

3487  {
3489 }
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 3704 of file PFAlgo.cc.

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

3704  {
3705  if(!usePFElectrons_) return;
3706  // std::cout << " setElectronExtraRef " << std::endl;
3707  unsigned size=pfCandidates_->size();
3708 
3709  for(unsigned ic=0;ic<size;++ic) {
3710  // select the electrons and add the extra
3711  if((*pfCandidates_)[ic].particleId()==PFCandidate::e) {
3712 
3713  PFElectronExtraEqual myExtraEqual((*pfCandidates_)[ic].gsfTrackRef());
3714  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
3715  if(it!=pfElectronExtra_.end()) {
3716  // std::cout << " Index " << it-pfElectronExtra_.begin() << std::endl;
3717  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
3718  (*pfCandidates_)[ic].setPFElectronExtraRef(theRef);
3719  }
3720  else {
3721  (*pfCandidates_)[ic].setPFElectronExtraRef(PFCandidateElectronExtraRef());
3722  }
3723  }
3724  else // else save the mva and the extra as well !
3725  {
3726  if((*pfCandidates_)[ic].trackRef().isNonnull()) {
3727  PFElectronExtraKfEqual myExtraEqual((*pfCandidates_)[ic].trackRef());
3728  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
3729  if(it!=pfElectronExtra_.end()) {
3730  (*pfCandidates_)[ic].set_mva_e_pi(it->mvaVariable(PFCandidateElectronExtra::MVA_MVA));
3731  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
3732  (*pfCandidates_)[ic].setPFElectronExtraRef(theRef);
3733  (*pfCandidates_)[ic].setGsfTrackRef(it->gsfTrackRef());
3734  }
3735  }
3736  }
3737 
3738  }
3739 
3740  size=pfElectronCandidates_->size();
3741  for(unsigned ic=0;ic<size;++ic) {
3742  // select the electrons - this test is actually not needed for this collection
3743  if((*pfElectronCandidates_)[ic].particleId()==PFCandidate::e) {
3744  // find the corresponding extra
3745  PFElectronExtraEqual myExtraEqual((*pfElectronCandidates_)[ic].gsfTrackRef());
3746  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
3747  if(it!=pfElectronExtra_.end()) {
3748  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
3749  (*pfElectronCandidates_)[ic].setPFElectronExtraRef(theRef);
3750 
3751  }
3752  }
3753  }
3754 
3755 }
edm::Ref< PFCandidateElectronExtraCollection > PFCandidateElectronExtraRef
persistent reference to a PFCandidateElectronExtra
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
std::auto_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
Definition: PFAlgo.h:286
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
Definition: PFAlgo.h:293
tuple size
Write out results.
bool usePFElectrons_
Definition: PFAlgo.h:342
void PFAlgo::setHOTag ( bool  ho)
inline

Definition at line 62 of file PFAlgo.h.

References useHO_.

62 { useHO_ = ho;}
bool useHO_
Definition: PFAlgo.h:334
void PFAlgo::setMuonHandle ( const edm::Handle< reco::MuonCollection > &  muons)

Definition at line 330 of file PFAlgo.cc.

References muonHandle_, and patZpeak::muons.

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

Definition at line 78 of file PFAlgo.cc.

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

81  {
82 
83  nSigmaECAL_ = nSigmaECAL;
85 
86  calibration_ = calibration;
87  thepfEnergyCalibrationHF_ = thepfEnergyCalibrationHF;
88 
89 }
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:3351
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 98 of file PFAlgo.cc.

References applyCrackCorrectionsElectrons_, coneEcalIsoForEgammaSC_, coneTrackIsoForEgammaSC_, mvaEleCut_, mvaWeightFileEleID_, nTrackIsoForEgammaSC_, pfele_, sumEtEcalIsoForEgammaSC_barrel_, sumEtEcalIsoForEgammaSC_endcap_, sumPtTrackIsoForEgammaSC_barrel_, sumPtTrackIsoForEgammaSC_endcap_, thePFSCEnergyCalibration_, useEGammaSupercluster_, useEGElectrons_, usePFElectrons_, and usePFSCEleCalib_.

113  {
114 
115  mvaEleCut_ = mvaEleCut;
116  usePFElectrons_ = usePFElectrons;
117  applyCrackCorrectionsElectrons_ = applyCrackCorrections;
118  usePFSCEleCalib_ = usePFSCEleCalib;
119  thePFSCEnergyCalibration_ = thePFSCEnergyCalibration;
120  useEGElectrons_ = useEGElectrons;
121  useEGammaSupercluster_ = useEGammaSupercluster;
122  sumEtEcalIsoForEgammaSC_barrel_ = sumEtEcalIsoForEgammaSC_barrel;
123  sumEtEcalIsoForEgammaSC_endcap_ = sumEtEcalIsoForEgammaSC_endcap;
124  coneEcalIsoForEgammaSC_ = coneEcalIsoForEgammaSC;
125  sumPtTrackIsoForEgammaSC_barrel_ = sumPtTrackIsoForEgammaSC_barrel;
126  sumPtTrackIsoForEgammaSC_endcap_ = sumPtTrackIsoForEgammaSC_endcap;
127  coneTrackIsoForEgammaSC_ = coneTrackIsoForEgammaSC;
128  nTrackIsoForEgammaSC_ = nTrackIsoForEgammaSC;
129 
130 
131  if(!usePFElectrons_) return;
132  mvaWeightFileEleID_ = mvaWeightFileEleID;
133  FILE * fileEleID = fopen(mvaWeightFileEleID_.c_str(), "r");
134  if (fileEleID) {
135  fclose(fileEleID);
136  }
137  else {
138  string err = "PFAlgo: cannot open weight file '";
139  err += mvaWeightFileEleID;
140  err += "'";
141  throw invalid_argument( err );
142  }
157 }
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 pfmu_.

64 {pfmu_ =algo;}
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:357
void PFAlgo::setPFMuonAndFakeParameters ( const edm::ParameterSet pset)

Definition at line 301 of file PFAlgo.cc.

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

308 {
309 
310 
311 
312 
313  pfmu_ = new PFMuonAlgo();
314  pfmu_->setParameters(pset);
315 
316  // Muon parameters
317  muonHCAL_= pset.getParameter<std::vector<double> >("muon_HCAL");
318  muonECAL_= pset.getParameter<std::vector<double> >("muon_ECAL");
319  muonHO_= pset.getParameter<std::vector<double> >("muon_HO");
320  assert ( muonHCAL_.size() == 2 && muonECAL_.size() == 2 && muonHO_.size() == 2);
321  nSigmaTRACK_= pset.getParameter<double>("nsigma_TRACK");
322  ptError_= pset.getParameter<double>("pt_Error");
323  factors45_ = pset.getParameter<std::vector<double> >("factors_45");
324  assert ( factors45_.size() == 2 );
325 
326 }
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 160 of file PFAlgo.cc.

References alignCSCRings::e, AlCaHLTBitMon_ParallelJobs::p, pfpho_, primaryVertex_, usePFPhotons_, and useVertices_.

168  {
169 
170  usePFPhotons_ = usePFPhotons;
171 
172  //for MVA pass PV if there is one in the collection otherwise pass a dummy
173  reco::Vertex dummy;
174  if(useVertices_)
175  {
176  dummy = primaryVertex_;
177  }
178  else { // create a dummy PV
180  e(0, 0) = 0.0015 * 0.0015;
181  e(1, 1) = 0.0015 * 0.0015;
182  e(2, 2) = 15. * 15.;
183  reco::Vertex::Point p(0, 0, 0);
184  dummy = reco::Vertex(p, e, 0, 0, 0);
185  }
186  // pv=&dummy;
187  if(! usePFPhotons_) return;
188  FILE * filePhotonConvID = fopen(mvaWeightFileConvID.c_str(), "r");
189  if (filePhotonConvID) {
190  fclose(filePhotonConvID);
191  }
192  else {
193  string err = "PFAlgo: cannot open weight file '";
194  err += mvaWeightFileConvID;
195  err += "'";
196  throw invalid_argument( err );
197  }
198  const reco::Vertex* pv=&dummy;
199  pfpho_ = new PFPhotonAlgo(mvaWeightFileConvID,
200  mvaConvCut,
201  useReg,
202  X0_Map,
203  *pv,
205  sumPtTrackIsoForPhoton,
206  sumPtTrackIsoSlopeForPhoton
207  );
208  return;
209 }
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
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 288 of file PFAlgo.cc.

References pfpho_, and PFPhotonAlgo::setGBRForest().

294  {
295 
296  pfpho_->setGBRForest(LCorrForestEB,LCorrForestEE,
297  GCorrForestBarrel, GCorrForestEndcapHr9,
298  GCorrForestEndcapLr9, PFEcalResolution);
299 }
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 371 of file PFAlgo.cc.

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

372  {
373  useVertices_ = useVertex;
374 
375  //Set the vertices for muon cleaning
376  pfmu_->setInputsForCleaning(primaryVertices);
377 
378 
379  //Now find the primary vertex!
380  bool primaryVertexFound = false;
381  nVtx_ = primaryVertices->size();
382  if(usePFPhotons_){
383  pfpho_->setnPU(nVtx_);
384  }
385  for (unsigned short i=0 ;i<primaryVertices->size();++i)
386  {
387  if(primaryVertices->at(i).isValid()&&(!primaryVertices->at(i).isFake()))
388  {
389  primaryVertex_ = primaryVertices->at(i);
390  primaryVertexFound = true;
391  break;
392  }
393  }
394  //Use vertices if the user wants to but only if it exists a good vertex
395  useVertices_ = useVertex && primaryVertexFound;
396  if(usePFPhotons_) {
397  if (useVertices_ ){
399  }
400  else{
402  e(0, 0) = 0.0015 * 0.0015;
403  e(1, 1) = 0.0015 * 0.0015;
404  e(2, 2) = 15. * 15.;
405  reco::Vertex::Point p(0, 0, 0);
406  reco::Vertex dummy = reco::Vertex(p, e, 0, 0, 0);
407  // std::cout << " PFPho " << pfpho_ << std::endl;
408  pfpho_->setPhotonPrimaryVtx(dummy);
409  }
410  }
411 }
int i
Definition: DBlmapReader.cc:9
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
void setPhotonPrimaryVtx(const reco::Vertex &primary)
Definition: PFPhotonAlgo.h:78
bool usePFPhotons_
Definition: PFAlgo.h:343
void setInputsForCleaning(const reco::VertexCollection *)
Definition: PFMuonAlgo.cc:1163
void PFAlgo::setPhotonExtraRef ( const edm::OrphanHandle< reco::PFCandidatePhotonExtraCollection > &  pf_extrah)

Definition at line 3756 of file PFAlgo.cc.

References newFWLiteAna::found, pfCandidates_, pfPhotonExtra_, findQualityFiles::size, and usePFPhotons_.

3756  {
3757  if(!usePFPhotons_) return;
3758  unsigned int size=pfCandidates_->size();
3759  unsigned int sizePhExtra = pfPhotonExtra_.size();
3760  for(unsigned ic=0;ic<size;++ic) {
3761  // select the electrons and add the extra
3762  if((*pfCandidates_)[ic].particleId()==PFCandidate::gamma && (*pfCandidates_)[ic].mva_nothing_gamma() > 0.99) {
3763  if((*pfCandidates_)[ic].superClusterRef().isNonnull()) {
3764  bool found = false;
3765  for(unsigned pcextra=0;pcextra<sizePhExtra;++pcextra) {
3766  if((*pfCandidates_)[ic].superClusterRef() == pfPhotonExtra_[pcextra].superClusterRef()) {
3767  reco::PFCandidatePhotonExtraRef theRef(ph_extrah,pcextra);
3768  (*pfCandidates_)[ic].setPFPhotonExtraRef(theRef);
3769  found = true;
3770  break;
3771  }
3772  }
3773  if(!found)
3774  (*pfCandidates_)[ic].setPFPhotonExtraRef((PFCandidatePhotonExtraRef())); // null ref
3775  }
3776  else {
3777  (*pfCandidates_)[ic].setPFPhotonExtraRef((PFCandidatePhotonExtraRef())); // null ref
3778  }
3779  }
3780  }
3781 }
edm::Ref< PFCandidatePhotonExtraCollection > PFCandidatePhotonExtraRef
persistent reference to a PFCandidatePhotonExtra
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
Definition: PFAlgo.h:295
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
bool usePFPhotons_
Definition: PFAlgo.h:343
tuple size
Write out results.
void PFAlgo::setPostHFCleaningParameters ( bool  postHFCleaning,
double  minHFCleaningPt,
double  minSignificance,
double  maxSignificance,
double  minSignificanceReduction,
double  maxDeltaPhiPt,
double  minDeltaMet 
)

Definition at line 336 of file PFAlgo.cc.

References maxDeltaPhiPt_, maxSignificance_, minDeltaMet_, minHFCleaningPt_, minSignificance_, minSignificanceReduction_, and postHFCleaning_.

342  {
343  postHFCleaning_ = postHFCleaning;
344  minHFCleaningPt_ = minHFCleaningPt;
345  minSignificance_ = minSignificance;
346  maxSignificance_ = maxSignificance;
347  minSignificanceReduction_= minSignificanceReduction;
348  maxDeltaPhiPt_ = maxDeltaPhiPt;
349  minDeltaMet_ = minDeltaMet;
350 }
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
double minSignificanceReduction_
Definition: PFAlgo.h:404
bool postHFCleaning_
Definition: PFAlgo.h:399
boost::shared_ptr<PFEnergyCalibration> PFAlgo::thePFEnergyCalibration ( )
inline

return the pointer to the calibration function

Definition at line 234 of file PFAlgo.h.

References calibration_.

234  {
235  return calibration_;
236  }
boost::shared_ptr< PFEnergyCalibration > calibration_
Definition: PFAlgo.h:330
std::auto_ptr< reco::PFCandidateCollection > PFAlgo::transferCandidates ( )
inline
Returns
auto_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::auto_ptr< reco::PFCandidateCollection > connect(std::auto_ptr< reco::PFCandidateCollection > &pfCand)
PFCandConnector connector_
Definition: PFAlgo.h:388
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:284
std::auto_ptr< reco::PFCandidateCollection >& PFAlgo::transferCleanedCandidates ( )
inline
Returns
collection of cleaned HF candidates

Definition at line 224 of file PFAlgo.h.

References pfCleanedCandidates_.

224  {
225  return pfCleanedCandidates_;
226  }
std::auto_ptr< reco::PFCandidateCollection > pfCleanedCandidates_
Definition: PFAlgo.h:290
std::auto_ptr< reco::PFCandidateCollection> PFAlgo::transferElectronCandidates ( )
inline
Returns
the unfiltered electron collection

Definition at line 201 of file PFAlgo.h.

References pfElectronCandidates_.

201  {
202  return pfElectronCandidates_;
203  }
std::auto_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
Definition: PFAlgo.h:286
std::auto_ptr< reco::PFCandidateElectronExtraCollection> PFAlgo::transferElectronExtra ( )
inline
Returns
the unfiltered electron extra collection

Definition at line 207 of file PFAlgo.h.

References pfElectronExtra_, and query::result.

207  {
208  std::auto_ptr< reco::PFCandidateElectronExtraCollection> result(new reco::PFCandidateElectronExtraCollection);
209  result->insert(result->end(),pfElectronExtra_.begin(),pfElectronExtra_.end());
210  return result;
211  }
tuple result
Definition: query.py:137
std::vector< reco::PFCandidateElectronExtra > PFCandidateElectronExtraCollection
collection of PFCandidateElectronExtras
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
Definition: PFAlgo.h:293
std::auto_ptr< reco::PFCandidatePhotonExtraCollection> PFAlgo::transferPhotonExtra ( )
inline
Returns
the unfiltered photon extra collection

Definition at line 216 of file PFAlgo.h.

References pfPhotonExtra_, and query::result.

216  {
217  std::auto_ptr< reco::PFCandidatePhotonExtraCollection> result(new reco::PFCandidatePhotonExtraCollection);
218  result->insert(result->end(),pfPhotonExtra_.begin(),pfPhotonExtra_.end());
219  return result;
220  }
tuple result
Definition: query.py:137
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
Definition: PFAlgo.h:295
std::vector< reco::PFCandidatePhotonExtra > PFCandidatePhotonExtraCollection
collection of PFCandidatePhotonExtras

Friends And Related Function Documentation

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

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::auto_ptr< reco::PFCandidateCollection > PFAlgo::pfCandidates_
protected
std::auto_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::auto_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::auto_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().