CMS 3D CMS Logo

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

#include <PFAlgo.h>

Inheritance diagram for PFAlgo:
PFAlgoTestBenchConversions PFAlgoTestBenchElectrons

Public Member Functions

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

Protected Member Functions

void associatePSClusters (unsigned iEcal, reco::PFBlockElement::Type psElementType, const reco::PFBlock &block, const edm::OwnVector< reco::PFBlockElement > &elements, const reco::PFBlock::LinkData &linkData, std::vector< bool > &active, std::vector< double > &psEne)
 Associate PS clusters to a given ECAL cluster, and return their energy. More...
 
bool isFromSecInt (const reco::PFBlockElement &eTrack, std::string order) const
 
double neutralHadronEnergyResolution (double clusterEnergy, double clusterEta) const
 todo: use PFClusterTools for this More...
 
double nSigmaHCAL (double clusterEnergy, double clusterEta) const
 
void postCleaning ()
 
virtual void processBlock (const reco::PFBlockRef &blockref, std::list< reco::PFBlockRef > &hcalBlockRefs, std::list< reco::PFBlockRef > &ecalBlockRefs)
 
unsigned reconstructCluster (const reco::PFCluster &cluster, double particleEnergy, bool useDirection=false, double particleX=0., double particleY=0., double particleZ=0.)
 
unsigned reconstructTrack (const reco::PFBlockElement &elt, bool allowLoose=false)
 
void setHcalDepthInfo (reco::PFCandidate &cand, const reco::PFCluster &cluster) const
 

Protected Attributes

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

Private Member Functions

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

Private Attributes

int algo_
 
bool applyCrackCorrectionsElectrons_
 
reco::PFBlockHandle blockHandle_
 input block handle (full framework case) More...
 
boost::shared_ptr< PFEnergyCalibrationcalibration_
 
double coneEcalIsoForEgammaSC_
 
double coneTrackIsoForEgammaSC_
 
PFCandConnector connector_
 
bool debug_
 
double dptRel_DispVtx_
 
std::vector< double > factors45_
 
double maxDeltaPhiPt_
 
double maxSignificance_
 
double minDeltaMet_
 
double minHFCleaningPt_
 
double minSignificance_
 
double minSignificanceReduction_
 
std::vector< double > muonECAL_
 
edm::Handle< reco::MuonCollectionmuonHandle_
 
std::vector< double > muonHCAL_
 Variables for muons and fakes. More...
 
std::vector< double > muonHO_
 
double mvaEleCut_
 
std::string mvaWeightFileEleID_
 Variables for PFElectrons. More...
 
double nSigmaECAL_
 number of sigma to judge energy excess in ECAL More...
 
double nSigmaHCAL_
 number of sigma to judge energy excess in HCAL More...
 
double nSigmaTRACK_
 
unsigned int nTrackIsoForEgammaSC_
 
int nVtx_
 
PFEGammaFilterspfegamma_
 
const edm::View< reco::PFCandidate > * pfEgammaCandidates_
 
PFElectronAlgopfele_
 
PFMuonAlgopfmu_
 
PFPhotonAlgopfpho_
 
bool postHFCleaning_
 
bool postMuonCleaning_
 
reco::Vertex primaryVertex_
 
double ptError_
 
bool rejectTracks_Bad_
 
bool rejectTracks_Step45_
 
std::vector< double > setchi2Values_
 
double sumEtEcalIsoForEgammaSC_barrel_
 
double sumEtEcalIsoForEgammaSC_endcap_
 
double sumPtTrackIsoForEgammaSC_barrel_
 
double sumPtTrackIsoForEgammaSC_endcap_
 
boost::shared_ptr< PFEnergyCalibrationHFthepfEnergyCalibrationHF_
 
boost::shared_ptr< PFSCEnergyCalibrationthePFSCEnergyCalibration_
 
double useBestMuonTrack_
 
bool useEGammaFilters_
 Variables for NEW EGAMMA selection. More...
 
bool useEGammaSupercluster_
 
bool useEGElectrons_
 
bool useHO_
 
bool usePFConversions_
 
bool usePFDecays_
 
bool usePFElectrons_
 
bool usePFMuonMomAssign_
 
bool usePFNuclearInteractions_
 
bool usePFPhotons_
 
bool usePFSCEleCalib_
 
bool useProtectionsForJetMET_
 
bool useVertices_
 
const edm::ValueMap< reco::GsfElectronRef > * valueMapGedElectrons_
 
const edm::ValueMap< reco::PhotonRef > * valueMapGedPhotons_
 

Friends

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

Detailed Description

Definition at line 52 of file PFAlgo.h.

Constructor & Destructor Documentation

PFAlgo::PFAlgo ( )

constructor

Definition at line 59 of file PFAlgo.cc.

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

destructor

Definition at line 71 of file PFAlgo.cc.

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

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

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

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

Check HF Cleaning.

Definition at line 3596 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

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

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

Definition at line 3386 of file PFAlgo.cc.

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

Referenced by reconstructParticles().

3387  {
3388 
3389  if( blockHandle_.isValid() ) {
3390  return reco::PFBlockRef( blockHandle_, bi );
3391  }
3392  else {
3393  return reco::PFBlockRef( &blocks, bi );
3394  }
3395 }
edm::Ref< PFBlockCollection > PFBlockRef
persistent reference to PFCluster objects
Definition: PFBlockFwd.h:20
bool isValid() const
Definition: HandleBase.h:74
reco::PFBlockHandle blockHandle_
input block handle (full framework case)
Definition: PFAlgo.h:323
PFMuonAlgo * PFAlgo::getPFMuonAlgo ( )

Definition at line 93 of file PFAlgo.cc.

References pfmu_.

Referenced by setCandConnectorParameters().

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

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

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

References mathSSE::sqrt().

Referenced by processBlock(), and thePFEnergyCalibration().

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

Definition at line 3349 of file PFAlgo.cc.

References JetChargeProducer_cfi::exp, and nSigmaHCAL_.

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

3349  {
3350  double nS = fabs(eta) < 1.48 ?
3351  nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL/100.))
3352  :
3353  nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL/100.));
3354 
3355  return nS;
3356 }
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:329
const std::unique_ptr<reco::PFCandidateCollection>& PFAlgo::pfCandidates ( ) const
inline
Returns
collection of candidates

Definition at line 196 of file PFAlgo.h.

References pfCandidates_.

Referenced by operator<<().

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

Definition at line 3489 of file PFAlgo.cc.

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

Referenced by reconstructParticles().

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

process one block. can be reimplemented in more sophisticated algorithms

Reimplemented in PFAlgoTestBenchConversions, and PFAlgoTestBenchElectrons.

Definition at line 538 of file PFAlgo.cc.

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

Referenced by reconstructParticles(), and thePFEnergyCalibration().

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

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

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

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

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

Definition at line 415 of file PFAlgo.cc.

References blockHandle_.

Referenced by setCandConnectorParameters().

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

reconstruct particles

Definition at line 423 of file PFAlgo.cc.

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

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

References ALCARECOTkAlJpsiMuMu_cff::charge, reco::TrackBase::charge(), gather_cfg::cout, debug_, reco::PFBlockElementTrack::displacedVertexRef(), dptRel_DispVtx_, reco::PFCandidate::h, isFromSecInt(), reco::isMuon(), edm::Ref< C, T, F >::isNonnull(), reco::PFBlockElement::isTimeValid(), reco::PFBlockElementTrack::muonRef(), reco::TrackBase::p(), objects.autophobj::particleType, pfElectronTranslator_cfi::PFCandidate, pfCandidates_, pfmu_, reco::PFBlockElementTrack::positionAtECALEntrance(), reco::TrackBase::px(), reco::TrackBase::py(), reco::TrackBase::pz(), PFMuonAlgo::reconstructMuon(), mathSSE::sqrt(), reco::PFBlockElement::T_FROM_DISP, reco::PFCandidate::T_FROM_DISP, reco::PFBlockElement::T_TO_DISP, reco::PFCandidate::T_TO_DISP, reco::PFBlockElement::time(), reco::PFBlockElement::timeError(), HiIsolationCommonParameters_cff::track, and reco::PFBlockElementTrack::trackRef().

Referenced by processBlock(), and thePFEnergyCalibration().

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

Definition at line 63 of file PFAlgo.h.

References patPFMETCorrections_cff::algo, and algo_.

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

Definition at line 73 of file PFAlgo.h.

References connector_, and PFCandConnector::setParameters().

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

Definition at line 77 of file PFAlgo.h.

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

void PFAlgo::setDebug ( bool  debug)
inline

Definition at line 66 of file PFAlgo.h.

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

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

Definition at line 354 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

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

Definition at line 267 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

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

Definition at line 212 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

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

Definition at line 3484 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

3484  {
3486 }
PFElectronAlgo * pfele_
Definition: PFAlgo.h:356
bool useEGElectrons_
Definition: PFAlgo.h:347
void setEGElectronCollection(const reco::GsfElectronCollection &egelectrons)
void PFAlgo::setElectronExtraRef ( const edm::OrphanHandle< reco::PFCandidateElectronExtraCollection > &  extrah)

Definition at line 3701 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

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

Definition at line 3303 of file PFAlgo.cc.

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

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

3303  {
3304  std::array<double,7> energyPerDepth;
3305  std::fill(energyPerDepth.begin(), energyPerDepth.end(), 0.0);
3306  for (auto & hitRefAndFrac : cluster.recHitFractions()) {
3307  const auto & hit = *hitRefAndFrac.recHitRef();
3308  if (DetId(hit.detId()).det() == DetId::Hcal) {
3309  if (hit.depth() == 0) {
3310  edm::LogWarning("setHcalDepthInfo") << "Depth zero found";
3311  continue;
3312  }
3313  if (hit.depth() < 1 || hit.depth() > 7) {
3314  throw cms::Exception("CorruptData") << "Bogus depth " << hit.depth() << " at detid " << hit.detId() << "\n";
3315  }
3316  energyPerDepth[hit.depth()-1] += hitRefAndFrac.fraction()*hit.energy();
3317  }
3318  }
3319  double sum = std::accumulate(energyPerDepth.begin(), energyPerDepth.end(), 0.);
3320  std::array<float,7> depthFractions;
3321  if (sum > 0) {
3322  for (unsigned int i = 0; i < depthFractions.size(); ++i) {
3323  depthFractions[i] = energyPerDepth[i]/sum;
3324  }
3325  } else {
3326  std::fill(depthFractions.begin(), depthFractions.end(), 0.f);
3327  }
3328  cand.setHcalDepthEnergyFractions(depthFractions);
3329 }
void setHcalDepthEnergyFractions(const std::array< float, 7 > &fracs)
set the fraction of hcal energy as function of depth (index 0..6 for depth 1..7)
Definition: PFCandidate.h:432
Definition: DetId.h:18
const std::vector< reco::PFRecHitFraction > & recHitFractions() const
vector of rechit fractions
Definition: PFCluster.h:72
void PFAlgo::setHOTag ( bool  ho)
inline

Definition at line 62 of file PFAlgo.h.

References photonIsolationHIProducer_cfi::ho, and useHO_.

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

Definition at line 331 of file PFAlgo.cc.

References muonHandle_, and nano_cff::muons.

Referenced by setPFMuonAlgo().

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

Definition at line 79 of file PFAlgo.cc.

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

Referenced by setDebug().

82  {
83 
84  nSigmaECAL_ = nSigmaECAL;
86 
87  calibration_ = calibration;
88  thepfEnergyCalibrationHF_ = thepfEnergyCalibrationHF;
89 
90 }
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:329
double nSigmaHCAL(double clusterEnergy, double clusterEta) const
Definition: PFAlgo.cc:3349
boost::shared_ptr< PFEnergyCalibration > calibration_
Definition: PFAlgo.h:331
boost::shared_ptr< PFEnergyCalibrationHF > thepfEnergyCalibrationHF_
Definition: PFAlgo.h:332
double nSigmaECAL_
number of sigma to judge energy excess in ECAL
Definition: PFAlgo.h:326
void PFAlgo::setPFEleParameters ( double  mvaEleCut,
std::string  mvaWeightFileEleID,
bool  usePFElectrons,
const boost::shared_ptr< PFSCEnergyCalibration > &  thePFSCEnergyCalibration,
const boost::shared_ptr< PFEnergyCalibration > &  thePFEnergyCalibration,
double  sumEtEcalIsoForEgammaSC_barrel,
double  sumEtEcalIsoForEgammaSC_endcap,
double  coneEcalIsoForEgammaSC,
double  sumPtTrackIsoForEgammaSC_barrel,
double  sumPtTrackIsoForEgammaSC_endcap,
unsigned int  nTrackIsoForEgammaSC,
double  coneTrackIsoForEgammaSC,
bool  applyCrackCorrections = false,
bool  usePFSCEleCalib = true,
bool  useEGElectrons = false,
bool  useEGammaSupercluster = true 
)

Definition at line 99 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

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

Definition at line 64 of file PFAlgo.h.

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

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

Definition at line 302 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

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

Definition at line 161 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

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

Definition at line 289 of file PFAlgo.cc.

References pfpho_, and PFPhotonAlgo::setGBRForest().

Referenced by setCandConnectorParameters().

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

Definition at line 372 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

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

Definition at line 3753 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

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

Definition at line 337 of file PFAlgo.cc.

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

Referenced by setCandConnectorParameters().

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

return the pointer to the calibration function

Definition at line 234 of file PFAlgo.h.

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

Referenced by setCandConnectorParameters().

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

Definition at line 229 of file PFAlgo.h.

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

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

Definition at line 224 of file PFAlgo.h.

References eostools::move(), and pfCleanedCandidates_.

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

Definition at line 201 of file PFAlgo.h.

References eostools::move(), and pfElectronCandidates_.

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

Definition at line 207 of file PFAlgo.h.

References pfElectronExtra_, and mps_fire::result.

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

Definition at line 216 of file PFAlgo.h.

References pfPhotonExtra_, and mps_fire::result.

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

Friends And Related Function Documentation

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

Referenced by thePFEnergyCalibration().

Member Data Documentation

int PFAlgo::algo_
private

Definition at line 336 of file PFAlgo.h.

Referenced by setAlgo().

bool PFAlgo::applyCrackCorrectionsElectrons_
private

Definition at line 345 of file PFAlgo.h.

Referenced by setPFEleParameters().

reco::PFBlockHandle PFAlgo::blockHandle_
private

input block handle (full framework case)

Definition at line 323 of file PFAlgo.h.

Referenced by createBlockRef(), and reconstructParticles().

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

Definition at line 331 of file PFAlgo.h.

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

double PFAlgo::coneEcalIsoForEgammaSC_
private

Definition at line 351 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::coneTrackIsoForEgammaSC_
private

Definition at line 354 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 389 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 384 of file PFAlgo.h.

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

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

Definition at line 397 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

double PFAlgo::maxDeltaPhiPt_
private

Definition at line 406 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::maxSignificance_
private

Definition at line 404 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minDeltaMet_
private

Definition at line 407 of file PFAlgo.h.

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

double PFAlgo::minHFCleaningPt_
private

Definition at line 402 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minSignificance_
private

Definition at line 403 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minSignificanceReduction_
private

Definition at line 405 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

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

Definition at line 393 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

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

Definition at line 414 of file PFAlgo.h.

Referenced by reconstructParticles(), and setMuonHandle().

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

Variables for muons and fakes.

Definition at line 392 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

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

Definition at line 394 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

double PFAlgo::mvaEleCut_
private

Definition at line 342 of file PFAlgo.h.

Referenced by setPFEleParameters().

std::string PFAlgo::mvaWeightFileEleID_
private

Variables for PFElectrons.

Definition at line 340 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::nSigmaECAL_
private

number of sigma to judge energy excess in ECAL

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

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

double PFAlgo::nSigmaTRACK_
private

Definition at line 395 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

unsigned int PFAlgo::nTrackIsoForEgammaSC_
private

Definition at line 355 of file PFAlgo.h.

Referenced by setPFEleParameters().

int PFAlgo::nVtx_
private

Definition at line 385 of file PFAlgo.h.

Referenced by processBlock(), and setPFVertexParameters().

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

Definition at line 291 of file PFAlgo.h.

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

PFEGammaFilters* PFAlgo::pfegamma_
private

Definition at line 363 of file PFAlgo.h.

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

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

Definition at line 365 of file PFAlgo.h.

Referenced by processBlock(), and setEGammaCollections().

PFElectronAlgo* PFAlgo::pfele_
private

Definition at line 356 of file PFAlgo.h.

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

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

the unfiltered electron collection

Definition at line 287 of file PFAlgo.h.

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

reco::PFCandidateElectronExtraCollection PFAlgo::pfElectronExtra_
protected

the unfiltered electron collection

Definition at line 294 of file PFAlgo.h.

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

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

the unfiltered photon collection

Definition at line 289 of file PFAlgo.h.

Referenced by processBlock(), and reconstructParticles().

reco::PFCandidatePhotonExtraCollection PFAlgo::pfPhotonExtra_
protected

the extra photon collection

Definition at line 296 of file PFAlgo.h.

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

bool PFAlgo::postHFCleaning_
private

Definition at line 400 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

bool PFAlgo::postMuonCleaning_
private

Definition at line 401 of file PFAlgo.h.

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

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

Referenced by processBlock(), and setDisplacedVerticesParameters().

bool PFAlgo::rejectTracks_Step45_
private

Definition at line 376 of file PFAlgo.h.

Referenced by processBlock(), and setDisplacedVerticesParameters().

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

Definition at line 341 of file PFAlgo.h.

double PFAlgo::sumEtEcalIsoForEgammaSC_barrel_
private

Definition at line 349 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumEtEcalIsoForEgammaSC_endcap_
private

Definition at line 350 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumPtTrackIsoForEgammaSC_barrel_
private

Definition at line 352 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumPtTrackIsoForEgammaSC_endcap_
private

Definition at line 353 of file PFAlgo.h.

Referenced by setPFEleParameters().

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

Definition at line 332 of file PFAlgo.h.

Referenced by processBlock(), and setParameters().

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

Definition at line 333 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::useBestMuonTrack_
private

Definition at line 408 of file PFAlgo.h.

bool PFAlgo::useEGammaFilters_
private

Variables for NEW EGAMMA selection.

Definition at line 362 of file PFAlgo.h.

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

bool PFAlgo::useEGammaSupercluster_
private

Definition at line 348 of file PFAlgo.h.

Referenced by setPFEleParameters().

bool PFAlgo::useEGElectrons_
private

Definition at line 347 of file PFAlgo.h.

Referenced by setEGElectronCollection(), and setPFEleParameters().

bool PFAlgo::useHO_
private

Definition at line 335 of file PFAlgo.h.

Referenced by processBlock(), and setHOTag().

bool PFAlgo::usePFConversions_
private

Definition at line 379 of file PFAlgo.h.

Referenced by processBlock(), and setDisplacedVerticesParameters().

bool PFAlgo::usePFDecays_
private

Definition at line 380 of file PFAlgo.h.

Referenced by isFromSecInt(), and setDisplacedVerticesParameters().

bool PFAlgo::usePFElectrons_
private

Definition at line 343 of file PFAlgo.h.

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

bool PFAlgo::usePFMuonMomAssign_
private

Definition at line 371 of file PFAlgo.h.

bool PFAlgo::usePFNuclearInteractions_
private

Definition at line 378 of file PFAlgo.h.

Referenced by isFromSecInt(), and setDisplacedVerticesParameters().

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

Definition at line 346 of file PFAlgo.h.

Referenced by setPFEleParameters().

bool PFAlgo::useProtectionsForJetMET_
private

Definition at line 364 of file PFAlgo.h.

Referenced by processBlock(), and setEGammaParameters().

bool PFAlgo::useVertices_
private

Definition at line 412 of file PFAlgo.h.

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

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

Definition at line 366 of file PFAlgo.h.

Referenced by setEGammaCollections().

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

Definition at line 367 of file PFAlgo.h.

Referenced by setEGammaCollections().