CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
List of all members | Public Member Functions | Protected Member Functions | Protected Attributes | Private Member Functions | Private Attributes | Friends
PFAlgo Class Reference

#include <PFAlgo.h>

Inheritance diagram for PFAlgo:
PFAlgoTestBenchConversions PFAlgoTestBenchElectrons

Public Member Functions

void checkCleaning (const reco::PFRecHitCollection &cleanedHF)
 Check HF Cleaning. More...
 
 PFAlgo ()
 constructor More...
 
const std::auto_ptr
< reco::PFCandidateCollection > & 
pfCandidates () const
 
void postMuonCleaning (const edm::Handle< reco::MuonCollection > &muonh, const reco::VertexCollection &primaryVertices)
 
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, 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 setEGElectronCollection (const reco::GsfElectronCollection &egelectrons)
 
void setElectronExtraRef (const edm::OrphanHandle< reco::PFCandidateElectronExtraCollection > &extrah)
 
void setHOTag (bool ho)
 
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 setPFMuonAndFakeParameters (std::vector< double > muonHCAL, std::vector< double > muonECAL, std::vector< double > muonHO, double nSigmaTRACK, double ptError, std::vector< double > factors45, bool usePFMuonMomAssign, bool useBestMuonTrack)
 
void setPFPhotonParameters (bool usePFPhoton, std::string mvaWeightFileConvID, double mvaConvCut, bool useReg, std::string X0_Map, const boost::shared_ptr< PFEnergyCalibration > &thePFEnergyCalibration, double sumPtTrackIsoForPhoton, double sumPtTrackIsoSlopeForPhoton)
 
void setPFPhotonRegWeights (const GBRForest *LCorrForestEB, const GBRForest *LCorrForestEE, const GBRForest *GCorrForestBarrel, const GBRForest *GCorrForestEndcapHr9, const GBRForest *GCorrForestEndcapLr9, const GBRForest *PFEcalResolution)
 
void setPFVertexParameters (bool useVertex, const reco::VertexCollection &primaryVertices)
 
void setPhotonExtraRef (const edm::OrphanHandle< reco::PFCandidatePhotonExtraCollection > &pf_extrah)
 
void setPostHFCleaningParameters (bool postHFCleaning, double minHFCleaningPt, double minSignificance, double maxSignificance, double minSignificanceReduction, double maxDeltaPhiPt, double minDeltaMet)
 
boost::shared_ptr
< PFEnergyCalibration
thePFEnergyCalibration ()
 return the pointer to the calibration function More...
 
std::auto_ptr
< reco::PFCandidateCollection
transferAddedMuonCandidates ()
 
std::auto_ptr
< reco::PFCandidateCollection
transferCandidates ()
 
std::auto_ptr
< reco::PFCandidateCollection > & 
transferCleanedCandidates ()
 
std::auto_ptr
< reco::PFCandidateCollection
transferCleanedTrackerAndGlobalMuonCandidates ()
 
std::auto_ptr
< reco::PFCandidateCollection
transferCosmicsMuonCleanedCandidates ()
 
std::auto_ptr
< reco::PFCandidateCollection
transferElectronCandidates ()
 
std::auto_ptr
< reco::PFCandidateElectronExtraCollection
transferElectronExtra ()
 
std::auto_ptr
< reco::PFCandidateCollection
transferFakeMuonCleanedCandidates ()
 
std::auto_ptr
< reco::PFCandidatePhotonExtraCollection
transferPhotonExtra ()
 
std::auto_ptr
< reco::PFCandidateCollection
transferPunchThroughHadronCleanedCandidates ()
 
std::auto_ptr
< reco::PFCandidateCollection
transferPunchThroughMuonCleanedCandidates ()
 
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)
 

Protected Attributes

std::auto_ptr
< reco::PFCandidateCollection
pfAddedMuonCandidates_
 the collection of added muon candidates More...
 
std::auto_ptr
< reco::PFCandidateCollection
pfCandidates_
 
std::auto_ptr
< reco::PFCandidateCollection
pfCleanedCandidates_
 
std::auto_ptr
< reco::PFCandidateCollection
pfCleanedTrackerAndGlobalMuonCandidates_
 the collection of tracker/global cleaned muon candidates More...
 
std::auto_ptr
< reco::PFCandidateCollection
pfCosmicsMuonCleanedCandidates_
 the collection of cosmics cleaned muon candidates More...
 
std::auto_ptr
< reco::PFCandidateCollection
pfElectronCandidates_
 the unfiltered electron collection More...
 
reco::PFCandidateElectronExtraCollection pfElectronExtra_
 the unfiltered electron collection More...
 
std::auto_ptr
< reco::PFCandidateCollection
pfFakeMuonCleanedCandidates_
 the collection of fake cleaned muon candidates More...
 
std::auto_ptr
< reco::PFCandidateCollection
pfPhotonCandidates_
 the unfiltered photon collection More...
 
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
 the extra photon collection More...
 
std::auto_ptr
< reco::PFCandidateCollection
pfPunchThroughHadronCleanedCandidates_
 the collection of punch-through cleaned neutral hadron candidates More...
 
std::auto_ptr
< reco::PFCandidateCollection
pfPunchThroughMuonCleanedCandidates_
 the collection of punch-through cleaned muon candidates More...
 

Private Member Functions

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

Private Attributes

int algo_
 
bool applyCrackCorrectionsElectrons_
 
reco::PFBlockHandle blockHandle_
 input block handle (full framework case) More...
 
boost::shared_ptr
< PFEnergyCalibration
calibration_
 
double coneEcalIsoForEgammaSC_
 
double coneTrackIsoForEgammaSC_
 
PFCandConnector connector_
 
bool debug_
 
double dptRel_DispVtx_
 
std::vector< double > factors45_
 
double maxDeltaPhiPt_
 
double maxSignificance_
 
double minDeltaMet_
 
double minHFCleaningPt_
 
double minSignificance_
 
double minSignificanceReduction_
 
std::vector< double > muonECAL_
 
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_
 
PFElectronAlgopfele_
 
PFPhotonAlgopfpho_
 
bool postHFCleaning_
 
bool postMuonCleaning_
 
reco::Vertex primaryVertex_
 
double ptError_
 
bool rejectTracks_Bad_
 
bool rejectTracks_Step45_
 
std::vector< double > setchi2Values_
 
double sumEtEcalIsoForEgammaSC_barrel_
 
double sumEtEcalIsoForEgammaSC_endcap_
 
double sumPtTrackIsoForEgammaSC_barrel_
 
double sumPtTrackIsoForEgammaSC_endcap_
 
boost::shared_ptr
< PFEnergyCalibrationHF
thepfEnergyCalibrationHF_
 
boost::shared_ptr
< PFSCEnergyCalibration
thePFSCEnergyCalibration_
 
double useBestMuonTrack_
 
bool useEGammaSupercluster_
 
bool useEGElectrons_
 
bool useHO_
 
bool usePFConversions_
 
bool usePFDecays_
 
bool usePFElectrons_
 
bool usePFMuonMomAssign_
 
bool usePFNuclearInteractions_
 
bool usePFPhotons_
 
bool usePFSCEleCalib_
 
bool useVertices_
 

Friends

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

Detailed Description

Definition at line 48 of file PFAlgo.h.

Constructor & Destructor Documentation

PFAlgo::PFAlgo ( )

constructor

Definition at line 57 of file PFAlgo.cc.

59  nSigmaECAL_(0),
60  nSigmaHCAL_(1),
61  algo_(1),
62  debug_(false),
63  pfele_(0),
64  pfpho_(0),
65  useVertices_(false)
66 {}
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:349
PFElectronAlgo * pfele_
Definition: PFAlgo.h:376
int algo_
Definition: PFAlgo.h:356
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:377
std::vector< reco::PFCandidate > PFCandidateCollection
collection of PFCandidates
bool useVertices_
Definition: PFAlgo.h:421
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:293
bool debug_
Definition: PFAlgo.h:357
double nSigmaECAL_
number of sigma to judge energy excess in ECAL
Definition: PFAlgo.h:346
PFAlgo::~PFAlgo ( )
virtual

destructor

Definition at line 68 of file PFAlgo.cc.

References pfele_, pfpho_, usePFElectrons_, and usePFPhotons_.

68  {
69  if (usePFElectrons_) delete pfele_;
70  if (usePFPhotons_) delete pfpho_;
71 }
PFElectronAlgo * pfele_
Definition: PFAlgo.h:376
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:377
bool usePFPhotons_
Definition: PFAlgo.h:364
bool usePFElectrons_
Definition: PFAlgo.h:363

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

3312  {
3313 
3314  // Find all PS clusters with type psElement associated to ECAL cluster iEcal,
3315  // within all PFBlockElement "elements" of a given PFBlock "block"
3316  // psElement can be reco::PFBlockElement::PS1 or reco::PFBlockElement::PS2
3317  // Returns a vector of PS cluster energies, and updates the "active" vector.
3318 
3319  // Find all PS clusters linked to the iEcal cluster
3320  std::multimap<double, unsigned> sortedPS;
3321  typedef std::multimap<double, unsigned>::iterator IE;
3322  block.associatedElements( iEcal, linkData,
3323  sortedPS, psElementType,
3325 
3326  // Loop over these PS clusters
3327  double totalPS = 0.;
3328  for ( IE ips=sortedPS.begin(); ips!=sortedPS.end(); ++ips ) {
3329 
3330  // CLuster index and distance to iEcal
3331  unsigned iPS = ips->second;
3332  // double distPS = ips->first;
3333 
3334  // Ignore clusters already in use
3335  if (!active[iPS]) continue;
3336 
3337  // Check that this cluster is not closer to another ECAL cluster
3338  std::multimap<double, unsigned> sortedECAL;
3339  block.associatedElements( iPS, linkData,
3340  sortedECAL,
3343  unsigned jEcal = sortedECAL.begin()->second;
3344  if ( jEcal != iEcal ) continue;
3345 
3346  // Update PS energy
3347  PFBlockElement::Type pstype = elements[ iPS ].type();
3348  assert( pstype == psElementType );
3349  PFClusterRef psclusterref = elements[iPS].clusterRef();
3350  assert(!psclusterref.isNull() );
3351  totalPS += psclusterref->energy();
3352  psEne[0] += psclusterref->energy();
3353  active[iPS] = false;
3354  }
3355 
3356 
3357 }
bool isNull() const
Checks for null.
Definition: Ref.h:247
void associatedElements(unsigned i, const LinkData &linkData, std::multimap< double, unsigned > &sortedAssociates, reco::PFBlockElement::Type type=PFBlockElement::NONE, LinkTest test=LINKTEST_RECHIT) const
Definition: PFBlock.cc:75
void PFAlgo::checkCleaning ( const reco::PFRecHitCollection cleanedHF)

Check HF Cleaning.

Definition at line 3504 of file PFAlgo.cc.

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

Referenced by PFRootEventManager::particleFlow().

3504  {
3505 
3506 
3507  // No hits to recover, leave.
3508  if ( !cleanedHits.size() ) return;
3509 
3510  //Compute met and met significance (met/sqrt(SumEt))
3511  double metX = 0.;
3512  double metY = 0.;
3513  double sumet = 0;
3514  std::vector<unsigned int> hitsToBeAdded;
3515  for(unsigned i=0; i<pfCandidates_->size(); i++) {
3516  const PFCandidate& pfc = (*pfCandidates_)[i];
3517  metX += pfc.px();
3518  metY += pfc.py();
3519  sumet += pfc.pt();
3520  }
3521  double met2 = metX*metX+metY*metY;
3522  double met2_Original = met2;
3523  // Select events with large MET significance.
3524  // double significance = std::sqrt(met2/sumet);
3525  // double significanceCor = significance;
3526  double metXCor = metX;
3527  double metYCor = metY;
3528  double sumetCor = sumet;
3529  double met2Cor = met2;
3530  bool next = true;
3531  unsigned iCor = 1E9;
3532 
3533  // Find the cleaned hit with the largest effect on the MET
3534  while ( next ) {
3535 
3536  double metReduc = -1.;
3537  // Loop on the candidates
3538  for(unsigned i=0; i<cleanedHits.size(); ++i) {
3539  const PFRecHit& hit = cleanedHits[i];
3540  double length = std::sqrt(hit.position().Mag2());
3541  double px = hit.energy() * hit.position().x()/length;
3542  double py = hit.energy() * hit.position().y()/length;
3543  double pt = std::sqrt(px*px + py*py);
3544 
3545  // Check that it is not already scheculed to be cleaned
3546  bool skip = false;
3547  for(unsigned j=0; j<hitsToBeAdded.size(); ++j) {
3548  if ( i == hitsToBeAdded[j] ) skip = true;
3549  if ( skip ) break;
3550  }
3551  if ( skip ) continue;
3552 
3553  // Now add the candidate to the MET
3554  double metXInt = metX + px;
3555  double metYInt = metY + py;
3556  double sumetInt = sumet + pt;
3557  double met2Int = metXInt*metXInt+metYInt*metYInt;
3558 
3559  // And check if it could contribute to a MET reduction
3560  if ( met2Int < met2Cor ) {
3561  metXCor = metXInt;
3562  metYCor = metYInt;
3563  metReduc = (met2-met2Int)/met2Int;
3564  met2Cor = met2Int;
3565  sumetCor = sumetInt;
3566  // significanceCor = std::sqrt(met2Cor/sumetCor);
3567  iCor = i;
3568  }
3569  }
3570  //
3571  // If the MET must be significanly reduced, schedule the candidate to be added
3572  //
3573  if ( metReduc > minDeltaMet_ ) {
3574  hitsToBeAdded.push_back(iCor);
3575  metX = metXCor;
3576  metY = metYCor;
3577  sumet = sumetCor;
3578  met2 = met2Cor;
3579  } else {
3580  // Otherwise just stop the loop
3581  next = false;
3582  }
3583  }
3584  //
3585  // At least 10 GeV MET reduction
3586  if ( std::sqrt(met2_Original) - std::sqrt(met2) > 5. ) {
3587  if ( debug_ ) {
3588  std::cout << hitsToBeAdded.size() << " hits were re-added " << std::endl;
3589  std::cout << "MET reduction = " << std::sqrt(met2_Original) << " -> "
3590  << std::sqrt(met2Cor) << " = " << std::sqrt(met2Cor) - std::sqrt(met2_Original)
3591  << std::endl;
3592  std::cout << "Added after cleaning check : " << std::endl;
3593  }
3594  for(unsigned j=0; j<hitsToBeAdded.size(); ++j) {
3595  const PFRecHit& hit = cleanedHits[hitsToBeAdded[j]];
3596  PFCluster cluster(hit.layer(), hit.energy(),
3597  hit.position().x(), hit.position().y(), hit.position().z() );
3598  reconstructCluster(cluster,hit.energy());
3599  if ( debug_ ) {
3600  std::cout << pfCandidates_->back() << ". time = " << hit.time() << std::endl;
3601  }
3602  }
3603  }
3604 
3605 }
int i
Definition: DBlmapReader.cc:9
Particle flow cluster, see clustering algorithm in PFClusterAlgo.
Definition: PFCluster.h:42
double minDeltaMet_
Definition: PFAlgo.h:416
unsigned reconstructCluster(const reco::PFCluster &cluster, double particleEnergy, bool useDirection=false, double particleX=0., double particleY=0., double particleZ=0.)
Definition: PFAlgo.cc:3129
PFLayer::Layer layer() const
rechit layer
Definition: PFRecHit.h:102
Particle flow rechit (rechit + geometry and topology information). See clustering algorithm in PFClus...
Definition: PFRecHit.h:31
T sqrt(T t)
Definition: SSEVec.h:46
int j
Definition: DBlmapReader.cc:9
const math::XYZPoint & position() const
is seed ?
Definition: PFRecHit.h:135
virtual double px() const
x coordinate of momentum vector
virtual double pt() const
transverse momentum
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:33
double energy() const
rechit energy
Definition: PFRecHit.h:105
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:293
bool debug_
Definition: PFAlgo.h:357
tuple cout
Definition: gather_cfg.py:121
double time() const
timing for cleaned hits
Definition: PFRecHit.h:111
virtual double py() const
y coordinate of momentum vector
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 3294 of file PFAlgo.cc.

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

Referenced by reconstructParticles().

3295  {
3296 
3297  if( blockHandle_.isValid() ) {
3298  return reco::PFBlockRef( blockHandle_, bi );
3299  }
3300  else {
3301  return reco::PFBlockRef( &blocks, bi );
3302  }
3303 }
edm::Ref< PFBlockCollection > PFBlockRef
persistent reference to PFCluster objects
Definition: PFBlockFwd.h:20
bool isValid() const
Definition: HandleBase.h:76
list blocks
Definition: gather_cfg.py:90
reco::PFBlockHandle blockHandle_
input block handle (full framework case)
Definition: PFAlgo.h:343
bool PFAlgo::isFromSecInt ( const reco::PFBlockElement eTrack,
std::string  order 
) const
protected

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

3361  {
3362 
3365  // reco::PFBlockElement::TrackType T_FROM_GAMMACONV = reco::PFBlockElement::T_FROM_GAMMACONV;
3367 
3368  bool bPrimary = (order.find("primary") != string::npos);
3369  bool bSecondary = (order.find("secondary") != string::npos);
3370  bool bAll = (order.find("all") != string::npos);
3371 
3372  bool isToDisp = usePFNuclearInteractions_ && eTrack.trackType(T_TO_DISP);
3373  bool isFromDisp = usePFNuclearInteractions_ && eTrack.trackType(T_FROM_DISP);
3374 
3375  if (bPrimary && isToDisp) return true;
3376  if (bSecondary && isFromDisp ) return true;
3377  if (bAll && ( isToDisp || isFromDisp ) ) return true;
3378 
3379 // bool isFromConv = usePFConversions_ && eTrack.trackType(T_FROM_GAMMACONV);
3380 
3381 // if ((bAll || bSecondary)&& isFromConv) return true;
3382 
3383  bool isFromDecay = (bAll || bSecondary) && usePFDecays_ && eTrack.trackType(T_FROM_V0);
3384 
3385  return isFromDecay;
3386 
3387 
3388 }
bool usePFNuclearInteractions_
Definition: PFAlgo.h:387
virtual bool trackType(TrackType trType) const
bool usePFDecays_
Definition: PFAlgo.h:389
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 3241 of file PFAlgo.cc.

References mathSSE::sqrt().

Referenced by processBlock().

3241  {
3242 
3243  // Add a protection
3244  if ( clusterEnergyHCAL < 1. ) clusterEnergyHCAL = 1.;
3245 
3246  double resol = fabs(eta) < 1.48 ?
3247  sqrt (1.02*1.02/clusterEnergyHCAL + 0.065*0.065)
3248  :
3249  sqrt (1.20*1.20/clusterEnergyHCAL + 0.028*0.028);
3250 
3251  return resol;
3252 
3253 }
T eta() const
T sqrt(T t)
Definition: SSEVec.h:46
double PFAlgo::nSigmaHCAL ( double  clusterEnergy,
double  clusterEta 
) const
protected

Definition at line 3256 of file PFAlgo.cc.

References create_public_lumi_plots::exp, and nSigmaHCAL_.

Referenced by processBlock(), and setParameters().

3256  {
3257  double nS = fabs(eta) < 1.48 ?
3258  nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL/100.))
3259  :
3260  nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL/100.));
3261 
3262  return nS;
3263 }
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:349
T eta() const
const std::auto_ptr< reco::PFCandidateCollection >& PFAlgo::pfCandidates ( ) const
inline
Returns
collection of candidates

Definition at line 176 of file PFAlgo.h.

References pfCandidates_.

Referenced by operator<<().

176  {
177  return pfCandidates_;
178  }
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:293
void PFAlgo::postCleaning ( )
protected

Definition at line 3397 of file PFAlgo.cc.

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

Referenced by reconstructParticles().

3397  {
3398 
3399  // Check if the post HF Cleaning was requested - if not, do nothing
3400  if ( !postHFCleaning_ ) return;
3401 
3402  //Compute met and met significance (met/sqrt(SumEt))
3403  double metX = 0.;
3404  double metY = 0.;
3405  double sumet = 0;
3406  std::vector<unsigned int> pfCandidatesToBeRemoved;
3407  for(unsigned i=0; i<pfCandidates_->size(); i++) {
3408  const PFCandidate& pfc = (*pfCandidates_)[i];
3409  metX += pfc.px();
3410  metY += pfc.py();
3411  sumet += pfc.pt();
3412  }
3413  double met2 = metX*metX+metY*metY;
3414  // Select events with large MET significance.
3415  double significance = std::sqrt(met2/sumet);
3416  double significanceCor = significance;
3417  if ( significance > minSignificance_ ) {
3418 
3419  double metXCor = metX;
3420  double metYCor = metY;
3421  double sumetCor = sumet;
3422  double met2Cor = met2;
3423  double deltaPhi = 3.14159;
3424  double deltaPhiPt = 100.;
3425  bool next = true;
3426  unsigned iCor = 1E9;
3427 
3428  // Find the HF candidate with the largest effect on the MET
3429  while ( next ) {
3430 
3431  double metReduc = -1.;
3432  // Loop on the candidates
3433  for(unsigned i=0; i<pfCandidates_->size(); ++i) {
3434  const PFCandidate& pfc = (*pfCandidates_)[i];
3435 
3436  // Check that the pfCandidate is in the HF
3437  if ( pfc.particleId() != reco::PFCandidate::h_HF &&
3438  pfc.particleId() != reco::PFCandidate::egamma_HF ) continue;
3439 
3440  // Check if has meaningful pt
3441  if ( pfc.pt() < minHFCleaningPt_ ) continue;
3442 
3443  // Check that it is not already scheculed to be cleaned
3444  bool skip = false;
3445  for(unsigned j=0; j<pfCandidatesToBeRemoved.size(); ++j) {
3446  if ( i == pfCandidatesToBeRemoved[j] ) skip = true;
3447  if ( skip ) break;
3448  }
3449  if ( skip ) continue;
3450 
3451  // Check that the pt and the MET are aligned
3452  deltaPhi = std::acos((metX*pfc.px()+metY*pfc.py())/(pfc.pt()*std::sqrt(met2)));
3453  deltaPhiPt = deltaPhi*pfc.pt();
3454  if ( deltaPhiPt > maxDeltaPhiPt_ ) continue;
3455 
3456  // Now remove the candidate from the MET
3457  double metXInt = metX - pfc.px();
3458  double metYInt = metY - pfc.py();
3459  double sumetInt = sumet - pfc.pt();
3460  double met2Int = metXInt*metXInt+metYInt*metYInt;
3461  if ( met2Int < met2Cor ) {
3462  metXCor = metXInt;
3463  metYCor = metYInt;
3464  metReduc = (met2-met2Int)/met2Int;
3465  met2Cor = met2Int;
3466  sumetCor = sumetInt;
3467  significanceCor = std::sqrt(met2Cor/sumetCor);
3468  iCor = i;
3469  }
3470  }
3471  //
3472  // If the MET must be significanly reduced, schedule the candidate to be cleaned
3473  if ( metReduc > minDeltaMet_ ) {
3474  pfCandidatesToBeRemoved.push_back(iCor);
3475  metX = metXCor;
3476  metY = metYCor;
3477  sumet = sumetCor;
3478  met2 = met2Cor;
3479  } else {
3480  // Otherwise just stop the loop
3481  next = false;
3482  }
3483  }
3484  //
3485  // The significance must be significantly reduced to indeed clean the candidates
3486  if ( significance - significanceCor > minSignificanceReduction_ &&
3487  significanceCor < maxSignificance_ ) {
3488  std::cout << "Significance reduction = " << significance << " -> "
3489  << significanceCor << " = " << significanceCor - significance
3490  << std::endl;
3491  for(unsigned j=0; j<pfCandidatesToBeRemoved.size(); ++j) {
3492  std::cout << "Removed : " << (*pfCandidates_)[pfCandidatesToBeRemoved[j]] << std::endl;
3493  pfCleanedCandidates_->push_back( (*pfCandidates_)[ pfCandidatesToBeRemoved[j] ] );
3494  (*pfCandidates_)[pfCandidatesToBeRemoved[j]].rescaleMomentum(1E-6);
3495  //reco::PFCandidate::ParticleType unknown = reco::PFCandidate::X;
3496  //(*pfCandidates_)[pfCandidatesToBeRemoved[j]].setParticleType(unknown);
3497  }
3498  }
3499  }
3500 
3501 }
int i
Definition: DBlmapReader.cc:9
double maxDeltaPhiPt_
Definition: PFAlgo.h:415
double maxSignificance_
Definition: PFAlgo.h:413
double minHFCleaningPt_
Definition: PFAlgo.h:411
double minDeltaMet_
Definition: PFAlgo.h:416
double minSignificance_
Definition: PFAlgo.h:412
std::auto_ptr< reco::PFCandidateCollection > pfCleanedCandidates_
Definition: PFAlgo.h:299
double minSignificanceReduction_
Definition: PFAlgo.h:414
bool postHFCleaning_
Definition: PFAlgo.h:409
T sqrt(T t)
Definition: SSEVec.h:46
int j
Definition: DBlmapReader.cc:9
virtual double px() const
x coordinate of momentum vector
virtual double pt() const
transverse momentum
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:33
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:293
tuple cout
Definition: gather_cfg.py:121
virtual ParticleType particleId() const
Definition: PFCandidate.h:324
virtual double py() const
y coordinate of momentum vector
void PFAlgo::postMuonCleaning ( const edm::Handle< reco::MuonCollection > &  muonh,
const reco::VertexCollection primaryVertices 
)

Definition at line 3609 of file PFAlgo.cc.

References DeDxDiscriminatorTools::charge(), gather_cfg::cout, dPhi(), PFRecoTauDiscriminationAgainstElectronDeadECAL_cfi::dR, reco::PFCandidate::elementsInBlocks(), relval_parameters_module::energy, reco::LeafCandidate::eta(), reco::PFCandidate::h, reco::PFCandidate::h0, i, PFMuonAlgo::isIsolatedMuon(), edm::Ref< C, T, F >::isNonnull(), edm::Ref< C, T, F >::key(), max(), reco::PFCandidate::mu, reco::PFCandidate::muonRef(), reco::LeafCandidate::p(), p4, reco::PFCandidate::particleId(), pfAddedMuonCandidates_, pfCandidates_, pfCleanedTrackerAndGlobalMuonCandidates_, pfCosmicsMuonCleanedCandidates_, pfFakeMuonCleanedCandidates_, pfMuons_cff::pfMuons, pfPunchThroughHadronCleanedCandidates_, pfPunchThroughMuonCleanedCandidates_, primaryVertex_, reco::LeafCandidate::pt(), reco::LeafCandidate::px(), reco::LeafCandidate::py(), CosmicsPD_Skims::radius, reco::PFCandidate::rawEcalEnergy(), reco::PFCandidate::rawHcalEnergy(), findQualityFiles::size, mathSSE::sqrt(), reco::PFCandidate::trackRef(), useBestMuonTrack_, reco::PFCandidate::vx(), reco::PFCandidate::vy(), reco::Vertex::x(), and reco::Vertex::y().

Referenced by PFRootEventManager::particleFlow().

3610  {
3611 
3612 
3613  bool printout = false;
3614  // Check if the post muon Cleaning was requested - if not, do nothing
3615  //if ( !postMuonCleaning_ ) return;
3616 
3617  // Estimate SumEt from pile-up
3618  double sumetPU = 0.;
3619  for (unsigned short i=1 ;i<primaryVertices.size();++i ) {
3620  if ( !primaryVertices[i].isValid() || primaryVertices[i].isFake() ) continue;
3621  primaryVertices[i];
3622  for ( reco::Vertex::trackRef_iterator itr = primaryVertices[i].tracks_begin();
3623  itr < primaryVertices[i].tracks_end(); ++itr ) {
3624  sumetPU += (*itr)->pt();
3625  }
3626  }
3627  sumetPU /= 0.65; // To estimate the neutral contribution from PU
3628  // std::cout << "Evaluation of sumetPU from " << primaryVertices.size() << " vertices : " << sumetPU << std::endl;
3629 
3630  //Compute met and met significance (met/sqrt(SumEt))
3631  double metX = 0.;
3632  double metY = 0.;
3633  double sumet = 0;
3634  double metXCosmics = 0.;
3635  double metYCosmics = 0.;
3636  double sumetCosmics = 0.;
3637 
3638  std::map<double,unsigned int> pfMuons;
3639  std::map<double,unsigned int> pfCosmics;
3640  typedef std::multimap<double, unsigned int>::iterator IE;
3641 
3642  for(unsigned i=0; i<pfCandidates_->size(); i++) {
3643  const PFCandidate& pfc = (*pfCandidates_)[i];
3644  double origin =
3645  (pfc.vx()-primaryVertex_.x())*(pfc.vx()-primaryVertex_.x()) +
3646  (pfc.vy()-primaryVertex_.y())*(pfc.vy()-primaryVertex_.y());
3647 
3648  // Compute MET
3649  metX += pfc.px();
3650  metY += pfc.py();
3651  sumet += pfc.pt();
3652 
3653  // Remember the muons and order them by decreasing energy
3654  // Remember the cosmic muons too
3655  if ( pfc.particleId() == reco::PFCandidate::mu ) {
3656  pfMuons.insert(std::pair<double,unsigned int>(-pfc.pt(),i));
3657  if ( origin > 1.0 ) {
3658  pfCosmics.insert(std::pair<double,unsigned int>(-pfc.pt(),i));
3659  metXCosmics += pfc.px();
3660  metYCosmics += pfc.py();
3661  sumetCosmics += pfc.pt();
3662  }
3663  }
3664 
3665  }
3666 
3667  double met2 = metX*metX+metY*metY;
3668  double met2Cosmics = (metX-metXCosmics)*(metX-metXCosmics)+(metY-metYCosmics)*(metY-metYCosmics);
3669 
3670  // Clean cosmic muons
3671  if ( sumetCosmics > (sumet-sumetPU)/10. && met2Cosmics < met2 ) {
3672  if ( printout )
3673  std::cout << "MEX,MEY,MET Before (Cosmics)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
3674  for ( IE imu = pfCosmics.begin(); imu != pfCosmics.end(); ++imu ) {
3675  const PFCandidate& pfc = (*pfCandidates_)[imu->second];
3676  //const PFCandidate pfcopy = pfc;
3677  pfCosmicsMuonCleanedCandidates_->push_back(pfc);
3678  if ( printout )
3679  std::cout << "Muon cleaned (cosmic). pt/d0 = " << pfc.pt() << " "
3680  << std::sqrt(pfc.vx()*pfc.vx() + pfc.vy()*pfc.vy()) << std::endl;
3681  metX -= pfc.px();
3682  metY -= pfc.py();
3683  sumet -= pfc.pt();
3684  (*pfCandidates_)[imu->second].rescaleMomentum(1E-6);
3685  }
3686  met2 = metX*metX+metY*metY;
3687  if ( printout )
3688  std::cout << "MEX,MEY,MET After (Cosmics)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
3689  }
3690 
3691  // The remaining met
3692  // double metInitial = std::sqrt(met2);
3693 
3694  // Clean mismeasured muons
3695  for ( IE imu = pfMuons.begin(); imu != pfMuons.end(); ++imu ) {
3696  const PFCandidate& pfc = (*pfCandidates_)[imu->second];
3697 
3698  // Don't care about low momentum muons
3699  if ( pfc.pt() < 20. ) continue;
3700 
3701  double metXNO = metX - pfc.px();
3702  double metYNO = metY - pfc.py();
3703  double met2NO = metXNO*metXNO + metYNO*metYNO;
3704  double sumetNO = sumet - pfc.pt();
3705  double factor = std::max(2.,2000./sumetNO);
3706 
3707  reco::MuonRef muonRef = pfc.muonRef();
3708  reco::TrackRef bestMuTrack = muonRef->muonBestTrack();
3709  if(!useBestMuonTrack_)
3710  bestMuTrack = muonRef->combinedMuon();
3711  reco::TrackRef trackerMu = muonRef->track();
3712  reco::TrackRef standAloneMu = muonRef->standAloneMuon();
3713 
3714  if ( !bestMuTrack || !trackerMu ) {
3715  if ( sumetNO-sumetPU > 500. && met2NO < met2/4.) {
3716  pfFakeMuonCleanedCandidates_->push_back(pfc);
3717  if ( printout ) {
3718  std::cout << "Muon cleaned (NO-bad) " << sumetNO << std::endl;
3719  std::cout << "sumet NO " << sumetNO << std::endl;
3720  }
3721  (*pfCandidates_)[imu->second].rescaleMomentum(1E-6);
3722  if ( printout )
3723  std::cout << "MEX,MEY,MET " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
3724  metX = metXNO;
3725  metY = metYNO;
3726  met2 = met2NO;
3727  sumet = sumetNO;
3728  if ( printout ) {
3729  std::cout << "Muon cleaned (NO/TK) ! " << std::endl;
3730  std::cout << "MEX,MEY,MET Now (NO/TK)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
3731  }
3732  }
3733  } else {
3734  /*
3735  std::cout << "PF Muon vx,vy " << pfc.vx() << " " << pfc.vy() << std::endl;
3736  std::cout << "PF Muon px,py,pt: " << pfc.px() << " " << pfc.py() << " " << pfc.pt() << std::endl;
3737  std::cout << "TK Muon px,py,pt: " << trackerMu->px() << " " << trackerMu->py() << " " << trackerMu->pt() << " " << std::endl;
3738  std::cout << "GL Muon px,py,pt: " << bestMuTrack->px() << " " << bestMuTrack->py() << " " << bestMuTrack->pt() << " " << std::endl;
3739  std::cout << "ST Muon px,py,pt: " << standAloneMu->px() << " " << standAloneMu->py() << " " << standAloneMu->pt() << " " << std::endl;
3740  std::cout << "isolated ? " << PFMuonAlgo::isIsolatedMuon(muonRef) << std::endl;
3741  */
3742  double metXTK = metXNO + trackerMu->px();
3743  double metYTK = metYNO + trackerMu->py();
3744  double met2TK = metXTK*metXTK + metYTK*metYTK;
3745 
3746  double metXGL = metXNO + bestMuTrack->px();
3747  double metYGL = metYNO + bestMuTrack->py();
3748  double met2GL = metXGL*metXGL + metYGL*metYGL;
3749 
3750  /*
3751  double metXST = metXNO + standAloneMu->px();
3752  double metYST = metYNO + standAloneMu->py();
3753  double met2ST = metXST*metXST + metYST*metYST;
3754  */
3755 
3756  /*
3757  std::cout << "sumet NO " << sumetNO << std::endl;
3758  std::cout << "MEX,MEY,MET NO" << metXNO << " " << metYNO << " " << std::sqrt(met2NO) << std::endl;
3759  std::cout << "MEX,MEY,MET TK" << metXTK << " " << metYTK << " " << std::sqrt(met2TK) << std::endl;
3760  std::cout << "MEX,MEY,MET GL" << metXGL << " " << metYGL << " " << std::sqrt(met2GL) << std::endl;
3761  std::cout << "MEX,MEY,MET ST" << metXST << " " << metYST << " " << std::sqrt(met2ST) << std::endl;
3762  */
3763 
3764  //bool fixed = false;
3765  if ( ( sumetNO-sumetPU > 250. && met2TK < met2/4. && met2TK < met2GL ) ||
3766  ( met2TK < met2/2. && trackerMu->pt() < bestMuTrack->pt()/4. && met2TK < met2GL ) ) {
3768  math::XYZTLorentzVectorD p4(trackerMu->px(),trackerMu->py(),trackerMu->pz(),
3769  std::sqrt(trackerMu->p()*trackerMu->p()+0.1057*0.1057));
3770  if ( printout )
3771  std::cout << "Muon cleaned (TK) ! " << met2TK/met2 << " " << trackerMu->pt() / bestMuTrack->pt() << std::endl;
3772  (*pfCandidates_)[imu->second].setP4(p4);
3773  if ( printout )
3774  std::cout << "MEX,MEY,MET Before (TK)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
3775  metX = metXTK;
3776  metY = metYTK;
3777  met2 = met2TK;
3778  //fixed = true;
3779  if ( printout )
3780  std::cout << "MEX,MEY,MET Now (TK)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
3781  }
3782 
3783  else if ( ( sumetNO-sumetPU > 250. && met2GL < met2/4. && met2GL < met2TK ) ||
3784  ( met2GL < met2/2. && bestMuTrack->pt() < trackerMu->pt()/4.&& met2GL < met2TK ) ) {
3786  math::XYZTLorentzVectorD p4(bestMuTrack->px(),bestMuTrack->py(),bestMuTrack->pz(),
3787  std::sqrt(bestMuTrack->p()*bestMuTrack->p()+0.1057*0.1057));
3788  if ( printout )
3789  std::cout << "Muon cleaned (GL) ! " << met2GL/met2 << " " << bestMuTrack->pt()/trackerMu->pt() << std::endl;
3790  (*pfCandidates_)[imu->second].setP4(p4);
3791  if ( printout )
3792  std::cout << "MEX,MEY,MET before (GL)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
3793  metX = metXGL;
3794  metY = metYGL;
3795  met2 = met2GL;
3796  //fixed = true;
3797  if ( printout )
3798  std::cout << "MEX,MEY,MET Now (GL)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
3799  }
3800 
3801  // Fake muons at large pseudo-rapidity
3802  bool fake =
3803  fabs ( pfc.eta() ) > 2.15 &&
3804  met2NO < met2/25. &&
3805  (met2GL < met2TK/2. || met2TK < met2GL/2.) &&
3806  standAloneMu->pt() < bestMuTrack->pt()/10. &&
3807  standAloneMu->pt() < trackerMu->pt()/10.;
3808 
3809  // Fake and/or punch-through candidates
3810  bool punchthrough1 =
3811  ( sumetNO-sumetPU > 250. && met2NO < met2/4. && (met2GL < met2TK/factor || met2TK < met2GL/factor) );
3812 
3813  // Now look for punch through candidates (i.e., muon with large neutral hadron behind)
3814  bool punchthrough2 =
3815  pfc.p() > 100. && pfc.rawHcalEnergy() > 100. &&
3816  pfc.rawEcalEnergy()+pfc.rawHcalEnergy() > pfc.p()/3. &&
3817  !PFMuonAlgo::isIsolatedMuon(muonRef) && met2NO < met2/4.;
3818 
3819  if ( punchthrough1 || punchthrough2 || fake ) {
3820 
3821  // Find the block of the muon
3822  const PFCandidate::ElementsInBlocks& eleInBlocks = pfc.elementsInBlocks();
3823  if ( !eleInBlocks.size() ) {
3824  ostringstream err;
3825  err<<"A muon has no associated elements in block. Cannot proceed with postMuonCleaning()";
3826  edm::LogError("PFAlgo")<<err.str()<<endl;
3827  } else {
3828  PFBlockRef blockRefMuon = eleInBlocks[0].first;
3829  unsigned indexMuon = eleInBlocks[0].second;
3830  for ( unsigned iele = 1; iele < eleInBlocks.size(); ++iele ) {
3831  indexMuon = eleInBlocks[iele].second;
3832  break;
3833  }
3834 
3835  // Check if the muon gave rise to a neutral hadron
3836  double iHad = 1E9;
3837  bool hadron = false;
3838  for ( unsigned i = imu->second+1; i < pfCandidates_->size(); ++i ) {
3839  const PFCandidate& pfcn = (*pfCandidates_)[i];
3840  const PFCandidate::ElementsInBlocks& ele = pfcn.elementsInBlocks();
3841  if ( !ele.size() ) {
3842  ostringstream err2;
3843  err2<<"A pfCandidate has no associated elements in block. Cannot proceed with postMuonCleaning()";
3844  edm::LogError("PFAlgo")<<err2.str()<<endl;
3845  continue;
3846  }
3847  PFBlockRef blockRefHadron = ele[0].first;
3848  unsigned indexHadron = ele[0].second;
3849  // We are out of the block -> exit the loop
3850  if ( blockRefHadron.key() != blockRefMuon.key() ) break;
3851  // Check that this particle is a neutral hadron
3852  if ( indexHadron == indexMuon &&
3853  pfcn.particleId() == reco::PFCandidate::h0 ) {
3854  iHad = i;
3855  hadron = true;
3856  }
3857  if ( hadron ) break;
3858  }
3859 
3860  if ( hadron ) {
3861  const PFCandidate& pfch = (*pfCandidates_)[iHad];
3862  pfPunchThroughMuonCleanedCandidates_->push_back(pfc);
3863  pfPunchThroughHadronCleanedCandidates_->push_back(pfch);
3864  if ( printout ) {
3865  std::cout << pfc << std::endl;
3866  std::cout << "Raw ecal/hcal : " << pfc.rawEcalEnergy() << " " << pfc.rawHcalEnergy() << std::endl;
3867  std::cout << "Hadron: " << (*pfCandidates_)[iHad] << std::endl;
3868  }
3869  double rescaleFactor = (*pfCandidates_)[iHad].p()/(*pfCandidates_)[imu->second].p();
3870  metX -= (*pfCandidates_)[imu->second].px() + (*pfCandidates_)[iHad].px();
3871  metY -= (*pfCandidates_)[imu->second].py() + (*pfCandidates_)[iHad].py();
3872  (*pfCandidates_)[imu->second].rescaleMomentum(rescaleFactor);
3873  (*pfCandidates_)[iHad].rescaleMomentum(1E-6);
3874  (*pfCandidates_)[imu->second].setParticleType(reco::PFCandidate::h);
3875  if ( printout )
3876  std::cout << "MEX,MEY,MET Before " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
3877  metX += (*pfCandidates_)[imu->second].px();
3878  metY += (*pfCandidates_)[imu->second].py();
3879  met2 = metX*metX + metY*metY;
3880  if ( printout ) {
3881  std::cout << "Muon changed to charged hadron" << std::endl;
3882  std::cout << "MEX,MEY,MET Now (NO)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
3883  }
3884  } else if ( punchthrough1 || fake ) {
3885  const PFCandidate& pfc = (*pfCandidates_)[imu->second];
3886  pfFakeMuonCleanedCandidates_->push_back(pfc);
3887  if ( printout )
3888  std::cout << "MEX,MEY,MET Before " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
3889  metX -= (*pfCandidates_)[imu->second].px();
3890  metY -= (*pfCandidates_)[imu->second].py();
3891  met2 = metX*metX + metY*metY;
3892  (*pfCandidates_)[imu->second].rescaleMomentum(1E-6);
3893  if ( printout ) {
3894  std::cout << "Muon cleaned (NO)" << std::endl;
3895  std::cout << "MEX,MEY,MET Now (NO)" << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
3896  }
3897  }
3898  }
3899  }
3900  /*
3901  if ( !fixed ) {
3902  std::cout << "TK Muon px,py,pt: " << trackerMu->px() << " " << trackerMu->py() << " " << trackerMu->pt() << " " << std::endl;
3903  std::cout << "GL Muon px,py,pt: " << bestMuTrack->px() << " " << bestMuTrack->py() << " " << bestMuTrack->pt() << " " << std::endl;
3904  std::cout << "MEX,MEY,MET PF " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
3905  std::cout << "MEX,MEY,MET NO " << metXNO << " " << metYNO << " " << std::sqrt(met2NO) << std::endl;
3906  std::cout << "MEX,MEY,MET TK " << metXTK << " " << metYTK << " " << std::sqrt(met2TK) << std::endl;
3907  std::cout << "MEX,MEY,MET GL " << metXGL << " " << metYGL << " " << std::sqrt(met2GL) << std::endl;
3908  }
3909  */
3910  }
3911 
3912  }
3913 
3914  // And now, add muons which did not make it for various reasons
3915  for ( unsigned imu = 0; imu < muonh->size(); ++imu ) {
3916  reco::MuonRef muonRef( muonh, imu );
3917  // If not used, check its effect on met
3918  reco::TrackRef bestMuTrack = muonRef->muonBestTrack();
3919  if(!useBestMuonTrack_)
3920  bestMuTrack = muonRef->combinedMuon();
3921  reco::TrackRef trackerMu = muonRef->track();
3922  reco::TrackRef standAloneMu = muonRef->standAloneMuon();
3923 
3924  // check if the muons has already been taken
3925  bool used = false;
3926  bool hadron = false;
3927  for(unsigned i=0; i<pfCandidates_->size(); i++) {
3928  const PFCandidate& pfc = (*pfCandidates_)[i];
3929  if ( !pfc.trackRef().isNonnull() ) continue;
3930 
3931  if ( pfc.trackRef().isNonnull() && pfc.trackRef() == trackerMu ) {
3932  hadron = true;
3933  }
3934 
3935  // The pf candidate is not associated to a muon
3936  // if ( !pfc.muonRef().isNonnull() || pfc.muonRef() != muonRef ) continue; ! This test is buggy !
3937  if ( !pfc.muonRef().isNonnull() ) continue;
3938 
3939  // Check if the muon is used...
3940  if ( pfc.muonRef()->track() == trackerMu || pfc.muonRef()->combinedMuon() == bestMuTrack ) {
3941  if ( printout ) {
3942  std::cout << "This muon is already used ..." << std::endl;
3943  std::cout << pfc << std::endl;
3944  std::cout << muonRef->p() << " " << muonRef->pt() << " " << muonRef->eta() << " " << muonRef->phi() << std::endl;
3945  }
3946  used = true;
3947  }
3948  else {
3949  // Check if the stand-alone muon is not a spurious copy of an existing muon
3950  // (Protection needed for HLT)
3951  if ( pfc.muonRef()->isStandAloneMuon() && muonRef->isStandAloneMuon() ) {
3952  double dEta = pfc.muonRef()->standAloneMuon()->eta() - standAloneMu->eta();
3953  double dPhi = pfc.muonRef()->standAloneMuon()->phi() - standAloneMu->phi();
3954  double dR = sqrt(dEta*dEta + dPhi*dPhi);
3955  if ( printout ) {
3956  std::cout << "StandAlone to be added ? " << std::endl;
3957  std::cout << " eta = " << pfc.muonRef()->standAloneMuon()->eta() << " " << standAloneMu->eta() << std::endl;
3958  std::cout << " phi = " << pfc.muonRef()->standAloneMuon()->phi() << " " << standAloneMu->phi() << std::endl;
3959  std::cout << " pt = " << pfc.muonRef()->standAloneMuon()->pt() << " " << standAloneMu->pt() << std::endl;
3960  std::cout << " Delta R = " << dR << std::endl;
3961  }
3962  if ( dR < 0.005 ) {
3963  used = true;
3964  if ( printout ) std::cout << "Not removed !" << std::endl;
3965  }
3966  }
3967  }
3968  if ( used ) break;
3969 
3970  }
3971 
3972  if ( used ) continue;
3973 
3974  double ptGL = muonRef->isGlobalMuon() ? bestMuTrack->pt() : 0.;
3975  double pxGL = muonRef->isGlobalMuon() ? bestMuTrack->px() : 0.;
3976  double pyGL = muonRef->isGlobalMuon() ? bestMuTrack->py() : 0.;
3977  double pzGL = muonRef->isGlobalMuon() ? bestMuTrack->pz() : 0.;
3978 
3979  double ptTK = muonRef->isTrackerMuon() ? trackerMu->pt() : 0.;
3980  double pxTK = muonRef->isTrackerMuon() ? trackerMu->px() : 0.;
3981  double pyTK = muonRef->isTrackerMuon() ? trackerMu->py() : 0.;
3982  double pzTK = muonRef->isTrackerMuon() ? trackerMu->pz() : 0.;
3983 
3984  double ptST = muonRef->isStandAloneMuon() ? standAloneMu->pt() : 0.;
3985  double pxST = muonRef->isStandAloneMuon() ? standAloneMu->px() : 0.;
3986  double pyST = muonRef->isStandAloneMuon() ? standAloneMu->py() : 0.;
3987  double pzST = muonRef->isStandAloneMuon() ? standAloneMu->pz() : 0.;
3988 
3989  //std::cout << "pT TK/GL/ST : " << ptTK << " " << ptGL << " " << ptST << std::endl;
3990 
3991  double metXTK = metX + pxTK;
3992  double metYTK = metY + pyTK;
3993  double met2TK = metXTK*metXTK + metYTK*metYTK;
3994 
3995  double metXGL = metX + pxGL;
3996  double metYGL = metY + pyGL;
3997  double met2GL = metXGL*metXGL + metYGL*metYGL;
3998 
3999  double metXST = metX + pxST;
4000  double metYST = metY + pyST;
4001  double met2ST = metXST*metXST + metYST*metYST;
4002 
4003  //std::cout << "met TK/GL/ST : " << sqrt(met2) << " " << sqrt(met2TK) << " " << sqrt(met2GL) << " " << sqrt(met2ST) << std::endl;
4004 
4005 
4006  if ( ptTK > 20. && met2TK < met2/4. && met2TK < met2GL && met2TK < met2ST ) {
4007  double energy = std::sqrt(pxTK*pxTK+pyTK*pyTK+pzTK*pzTK+0.1057*0.1057);
4008  int charge = trackerMu->charge()>0 ? 1 : -1;
4009  math::XYZTLorentzVector momentum(pxTK,pyTK,pzTK,energy);
4010  reco::PFCandidate::ParticleType particleType =
4012  double radius = std::sqrt(
4013  (trackerMu->vertex().x()-primaryVertex_.x())*(trackerMu->vertex().x()-primaryVertex_.x())+
4014  (trackerMu->vertex().y()-primaryVertex_.y())*(trackerMu->vertex().y()-primaryVertex_.y()));
4015 
4016  // Add it to the stack ( if not already in the list )
4017  if ( !hadron && radius < 1.0 ) {
4018  pfCandidates_->push_back( PFCandidate( charge,
4019  momentum,
4020  particleType ) );
4021 
4022  pfCandidates_->back().setVertexSource( PFCandidate::kTrkMuonVertex );
4023  pfCandidates_->back().setTrackRef( trackerMu );
4024  pfCandidates_->back().setMuonRef( muonRef );
4025 
4026  if ( printout ) {
4027  std::cout << "MEX,MEY,MET before " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
4028  std::cout << "Muon TK added " << std::endl;
4029  std::cout << "pT TK/GL/ST : " << ptTK << " " << ptGL << " " << ptST << std::endl;
4030  }
4031  metX += pfCandidates_->back().px();
4032  metY += pfCandidates_->back().py();
4033  met2 = metX*metX + metY*metY;
4034  if ( printout ) {
4035  std::cout << pfCandidates_->back() << std::endl;
4036  std::cout << "MEX,MEY,MET now " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
4037  }
4038 
4039  const PFCandidate& pfc = pfCandidates_->back();
4040  pfAddedMuonCandidates_->push_back(pfc);
4041 
4042  }
4043 
4044  } else if ( ptGL > 20. && met2GL < met2/4. && met2GL < met2TK && met2GL < met2ST ) {
4045 
4046  double energy = std::sqrt(pxGL*pxGL+pyGL*pyGL+pzGL*pzGL+0.1057*0.1057);
4047  int charge = bestMuTrack->charge()>0 ? 1 : -1;
4048  math::XYZTLorentzVector momentum(pxGL,pyGL,pzGL,energy);
4050  double radius = std::sqrt(
4051  (bestMuTrack->vertex().x()-primaryVertex_.x())*(bestMuTrack->vertex().x()-primaryVertex_.x())+
4052  (bestMuTrack->vertex().y()-primaryVertex_.y())*(bestMuTrack->vertex().y()-primaryVertex_.y()));
4053 
4054  // Add it to the stack
4055  if ( radius < 1.0 ) {
4056  pfCandidates_->push_back( PFCandidate( charge,
4057  momentum,
4058  particleType ) );
4059 
4060  pfCandidates_->back().setVertexSource( PFCandidate::kComMuonVertex );
4061  //if ( ptTK > 0. )
4062  if (trackerMu.isNonnull() ) pfCandidates_->back().setTrackRef( trackerMu );
4063  pfCandidates_->back().setMuonRef( muonRef );
4064 
4065  if ( printout ) {
4066  std::cout << "MEX,MEY,MET before " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
4067  std::cout << "Muon GL added " << std::endl;
4068  std::cout << "pT TK/GL/ST : " << ptTK << " " << ptGL << " " << ptST << std::endl;
4069  }
4070 
4071  metX += pfCandidates_->back().px();
4072  metY += pfCandidates_->back().py();
4073  met2 = metX*metX + metY*metY;
4074 
4075  if ( printout ) {
4076  std::cout << pfCandidates_->back() << std::endl;
4077  std::cout << "MEX,MEY,MET now " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
4078  }
4079 
4080  const PFCandidate& pfc = pfCandidates_->back();
4081  pfAddedMuonCandidates_->push_back(pfc);
4082 
4083  }
4084 
4085  } else if ( ptST > 20. && met2ST < met2/4. && met2ST < met2TK && met2ST < met2GL ) {
4086 
4087  double energy = std::sqrt(pxST*pxST+pyST*pyST+pzST*pzST+0.1057*0.1057);
4088  int charge = standAloneMu->charge()>0 ? 1 : -1;
4089  math::XYZTLorentzVector momentum(pxST,pyST,pzST,energy);
4091  double radius = std::sqrt(
4092  (standAloneMu->vertex().x()-primaryVertex_.x())*(standAloneMu->vertex().x()-primaryVertex_.x())+
4093  (standAloneMu->vertex().y()-primaryVertex_.y())*(standAloneMu->vertex().y()-primaryVertex_.y()));
4094 
4095  // Add it to the stack
4096  if ( radius < 1.0 ) {
4097  pfCandidates_->push_back( PFCandidate( charge,
4098  momentum,
4099  particleType ) );
4100 
4101  pfCandidates_->back().setVertexSource( PFCandidate::kSAMuonVertex);
4102  if (trackerMu.isNonnull() ) pfCandidates_->back().setTrackRef( trackerMu );
4103  pfCandidates_->back().setMuonRef( muonRef );
4104 
4105  if ( printout ) {
4106  std::cout << "MEX,MEY,MET before " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
4107  std::cout << "Muon ST added " << std::endl;
4108  std::cout << "pT TK/GL/ST : " << ptTK << " " << ptGL << " " << ptST << std::endl;
4109  }
4110 
4111  metX += pfCandidates_->back().px();
4112  metY += pfCandidates_->back().py();
4113  met2 = metX*metX + metY*metY;
4114 
4115  if ( printout ) {
4116  std::cout << pfCandidates_->back() << std::endl;
4117  std::cout << "MEX,MEY,MET now " << metX << " " << metY << " " << std::sqrt(met2) << std::endl;
4118  }
4119 
4120  const PFCandidate& pfc = pfCandidates_->back();
4121  pfAddedMuonCandidates_->push_back(pfc);
4122 
4123  }
4124  }
4125 
4126  }
4127 
4128  /*
4129  if ( std::sqrt(met2) > 500. ) {
4130  std::cout << "MET initial : " << metInitial << std::endl;
4131  std::cout << "MET final : " << std::sqrt(met2) << std::endl;
4132  }
4133  */
4134 
4135 }
static bool isIsolatedMuon(const reco::PFBlockElement &elt)
Definition: PFMuonAlgo.cc:76
int i
Definition: DBlmapReader.cc:9
virtual double p() const
magnitude of momentum vector
ParticleType
particle types
Definition: PFCandidate.h:38
double rawEcalEnergy() const
return corrected Ecal energy
Definition: PFCandidate.h:192
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzE4D< double > > XYZTLorentzVectorD
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:15
std::auto_ptr< reco::PFCandidateCollection > pfFakeMuonCleanedCandidates_
the collection of fake cleaned muon candidates
Definition: PFAlgo.h:305
double y() const
y coordinate
Definition: Vertex.h:97
double charge(const std::vector< uint8_t > &Ampls)
virtual double eta() const
momentum pseudorapidity
std::vector< ElementInBlock > ElementsInBlocks
Definition: PFCandidate.h:337
virtual double vx() const
x coordinate of vertex position
Definition: PFCandidate.h:375
const ElementsInBlocks & elementsInBlocks() const
Definition: PFCandidate.h:342
reco::TrackRef trackRef() const
Definition: PFCandidate.cc:339
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:30
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:250
double dPhi(double phi1, double phi2)
Definition: JetUtil.h:30
const T & max(const T &a, const T &b)
T sqrt(T t)
Definition: SSEVec.h:46
double p4[4]
Definition: TauolaWrapper.h:92
reco::Vertex primaryVertex_
Definition: PFAlgo.h:420
reco::MuonRef muonRef() const
Definition: PFCandidate.cc:355
double useBestMuonTrack_
Definition: PFAlgo.h:417
double x() const
x coordinate
Definition: Vertex.h:95
virtual double px() const
x coordinate of momentum vector
std::auto_ptr< reco::PFCandidateCollection > pfCosmicsMuonCleanedCandidates_
the collection of cosmics cleaned muon candidates
Definition: PFAlgo.h:301
virtual double pt() const
transverse momentum
key_type key() const
Accessor for product key.
Definition: Ref.h:266
virtual double vy() const
y coordinate of vertex position
Definition: PFCandidate.h:376
std::auto_ptr< reco::PFCandidateCollection > pfPunchThroughHadronCleanedCandidates_
the collection of punch-through cleaned neutral hadron candidates
Definition: PFAlgo.h:309
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:33
std::auto_ptr< reco::PFCandidateCollection > pfCleanedTrackerAndGlobalMuonCandidates_
the collection of tracker/global cleaned muon candidates
Definition: PFAlgo.h:303
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:293
std::vector< TrackBaseRef >::const_iterator trackRef_iterator
The iteratator for the vector&lt;TrackRef&gt;
Definition: Vertex.h:38
tuple cout
Definition: gather_cfg.py:121
virtual ParticleType particleId() const
Definition: PFCandidate.h:324
std::auto_ptr< reco::PFCandidateCollection > pfPunchThroughMuonCleanedCandidates_
the collection of punch-through cleaned muon candidates
Definition: PFAlgo.h:307
std::auto_ptr< reco::PFCandidateCollection > pfAddedMuonCandidates_
the collection of added muon candidates
Definition: PFAlgo.h:311
tuple size
Write out results.
virtual double py() const
y coordinate of momentum vector
double rawHcalEnergy() const
return raw Hcal energy
Definition: PFCandidate.h:202
tuple pfMuons
Definition: pfMuons_cff.py:10
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 451 of file PFAlgo.cc.

References a, abs, algo, associatePSClusters(), b, edm::OwnVector< T, P >::begin(), createPayload::block, alignmentValidation::c1, calibration_, dtNoiseDBValidation_cfg::cerr, CastorDataFrameFilter_impl::check(), gather_cfg::cout, debug_, dptRel_DispVtx_, ECAL, reco::PFBlockElement::ECAL, asciidump::elements, reco::PFCandidate::elementsInBlocks(), reco::LeafCandidate::energy(), eta(), factors45_, first, PFElectronAlgo::getAllElectronCandidates(), PFElectronAlgo::getElectronCandidates(), PFElectronAlgo::getElectronExtra(), reco::PFBlockElement::GSF, HCAL, reco::PFBlockElement::HCAL, PFLayer::HF_EM, PFLayer::HF_HAD, reco::TrackBase::highPurity, reco::PFBlockElement::HO, i, getHLTprescales::index, PFElectronAlgo::isElectronValidCandidate(), isFromSecInt(), PFMuonAlgo::isGlobalLooseMuon(), PFMuonAlgo::isIsolatedMuon(), PFMuonAlgo::isLooseMuon(), PFMuonAlgo::isMuon(), edm::Ref< C, T, F >::isNull(), PFPhotonAlgo::isPhotonValidCandidate(), j, reco::PFBlock::LINKTEST_ALL, max(), min, reco::PFCandidate::mu, muonECAL_, muonHCAL_, muonHO_, neutralHadronEnergyResolution(), nSigmaECAL_, nSigmaHCAL(), nSigmaTRACK_, convertSQLiteXML::ok, AlCaHLTBitMon_ParallelJobs::p, pfCandidates_, pfele_, pfElectronCandidates_, pfElectronExtra_, pfpho_, pfPhotonCandidates_, pfPhotonExtra_, primaryVertex_, PFMuonAlgo::printMuonProperties(), reco::PFBlockElement::PS1, reco::PFBlockElement::PS2, ptError_, edm::OwnVector< T, P >::push_back(), reconstructCluster(), reconstructTrack(), rejectTracks_Bad_, rejectTracks_Step45_, edm::second(), reco::PFCandidate::setEcalEnergy(), reco::PFCandidate::setHcalEnergy(), reco::PFCandidate::setHoEnergy(), reco::PFBlockElementTrack::setPositionAtECALEntrance(), edm::OwnVector< T, P >::size(), createPayload::skip, mathSSE::sqrt(), reco::PFBlockElement::T_FROM_GAMMACONV, thepfEnergyCalibrationHF_, reco::PFBlockElement::TRACK, reco::btau::trackMomentum, reco::PFBlockElementTrack::trackType(), funct::true, useBestMuonTrack_, useHO_, usePFConversions_, usePFElectrons_, usePFPhotons_, X, vdt::x, and Gflash::Z.

Referenced by reconstructParticles().

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

References DeDxDiscriminatorTools::charge(), gather_cfg::cout, debug_, PFLayer::ECAL_BARREL, PFLayer::ECAL_ENDCAP, PFLayer::HCAL_BARREL1, PFLayer::HCAL_ENDCAP, PFLayer::HF_EM, PFLayer::HF_HAD, reco::PFCluster::layer(), scaleCards::mass, pfCandidates_, reco::CaloCluster::position(), primaryVertex_, mathSSE::sqrt(), tmp, useVertices_, reco::PFCandidate::X, reco::Vertex::x(), reco::Vertex::y(), and reco::Vertex::z().

Referenced by checkCleaning(), and processBlock().

3134  {
3135 
3137 
3138  // need to convert the math::XYZPoint data member of the PFCluster class=
3139  // to a displacement vector:
3140 
3141  // Transform particleX,Y,Z to a position at ECAL/HCAL entrance
3142  double factor = 1.;
3143  if ( useDirection ) {
3144  switch( cluster.layer() ) {
3145  case PFLayer::ECAL_BARREL:
3146  case PFLayer::HCAL_BARREL1:
3147  factor = std::sqrt(cluster.position().Perp2()/(particleX*particleX+particleY*particleY));
3148  break;
3149  case PFLayer::ECAL_ENDCAP:
3150  case PFLayer::HCAL_ENDCAP:
3151  case PFLayer::HF_HAD:
3152  case PFLayer::HF_EM:
3153  factor = cluster.position().Z()/particleZ;
3154  break;
3155  default:
3156  assert(0);
3157  }
3158  }
3159  //MIKE First of all let's check if we have vertex.
3160  math::XYZPoint vertexPos;
3161  if(useVertices_)
3163  else
3164  vertexPos = math::XYZPoint(0.0,0.0,0.0);
3165 
3166 
3167  math::XYZVector clusterPos( cluster.position().X()-vertexPos.X(),
3168  cluster.position().Y()-vertexPos.Y(),
3169  cluster.position().Z()-vertexPos.Z());
3170  math::XYZVector particleDirection ( particleX*factor-vertexPos.X(),
3171  particleY*factor-vertexPos.Y(),
3172  particleZ*factor-vertexPos.Z() );
3173 
3174  //math::XYZVector clusterPos( cluster.position().X(), cluster.position().Y(),cluster.position().Z() );
3175  //math::XYZVector particleDirection ( particleX, particleY, particleZ );
3176 
3177  clusterPos = useDirection ? particleDirection.Unit() : clusterPos.Unit();
3178  clusterPos *= particleEnergy;
3179 
3180  // clusterPos is now a vector along the cluster direction,
3181  // with a magnitude equal to the cluster energy.
3182 
3183  double mass = 0;
3184  ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double> >
3185  momentum( clusterPos.X(), clusterPos.Y(), clusterPos.Z(), mass);
3186  // mathcore is a piece of #$%
3188  // implicit constructor not allowed
3189  tmp = momentum;
3190 
3191  // Charge
3192  int charge = 0;
3193 
3194  // Type
3195  switch( cluster.layer() ) {
3196  case PFLayer::ECAL_BARREL:
3197  case PFLayer::ECAL_ENDCAP:
3198  particleType = PFCandidate::gamma;
3199  break;
3200  case PFLayer::HCAL_BARREL1:
3201  case PFLayer::HCAL_ENDCAP:
3202  particleType = PFCandidate::h0;
3203  break;
3204  case PFLayer::HF_HAD:
3205  particleType = PFCandidate::h_HF;
3206  break;
3207  case PFLayer::HF_EM:
3208  particleType = PFCandidate::egamma_HF;
3209  break;
3210  default:
3211  assert(0);
3212  }
3213 
3214  // The pf candidate
3215  pfCandidates_->push_back( PFCandidate( charge,
3216  tmp,
3217  particleType ) );
3218 
3219  // The position at ECAL entrance (well: watch out, it is not true
3220  // for HCAL clusters... to be fixed)
3221  pfCandidates_->back().
3222  setPositionAtECALEntrance(math::XYZPointF(cluster.position().X(),
3223  cluster.position().Y(),
3224  cluster.position().Z()));
3225 
3226  //Set the cnadidate Vertex
3227  pfCandidates_->back().setVertex(vertexPos);
3228 
3229  if(debug_)
3230  cout<<"** candidate: "<<pfCandidates_->back()<<endl;
3231 
3232  // returns index to the newly created PFCandidate
3233  return pfCandidates_->size()-1;
3234 
3235 }
PFLayer::Layer layer() const
cluster layer, see PFLayer.h in this directory
Definition: PFCluster.cc:81
const math::XYZPoint & position() const
cluster centroid position
Definition: CaloCluster.h:123
ParticleType
particle types
Definition: PFCandidate.h:38
double y() const
y coordinate
Definition: Vertex.h:97
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< float > > XYZPointF
point in space with cartesian internal representation
Definition: Point3D.h:11
double charge(const std::vector< uint8_t > &Ampls)
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:30
T sqrt(T t)
Definition: SSEVec.h:46
double z() const
y coordinate
Definition: Vertex.h:99
reco::Vertex primaryVertex_
Definition: PFAlgo.h:420
double x() const
x coordinate
Definition: Vertex.h:95
bool useVertices_
Definition: PFAlgo.h:421
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:31
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:13
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:33
tuple mass
Definition: scaleCards.py:27
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:293
bool debug_
Definition: PFAlgo.h:357
tuple cout
Definition: gather_cfg.py:121
void PFAlgo::reconstructParticles ( const reco::PFBlockHandle blockHandle)

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

Definition at line 305 of file PFAlgo.cc.

References blockHandle_.

Referenced by PFRootEventManager::particleFlow().

305  {
306 
307  blockHandle_ = blockHandle;
309 }
void reconstructParticles(const reco::PFBlockHandle &blockHandle)
Definition: PFAlgo.cc:305
reco::PFBlockHandle blockHandle_
input block handle (full framework case)
Definition: PFAlgo.h:343
void PFAlgo::reconstructParticles ( const reco::PFBlockCollection blocks)
virtual

reconstruct particles

Definition at line 313 of file PFAlgo.cc.

References createPayload::block, gather_cfg::cout, createBlockRef(), debug_, reco::PFBlockElement::ECAL, reco::PFBlock::elements(), asciidump::elements, relativeConstraints::empty, reco::PFBlockElement::HCAL, reco::PFBlockElement::HO, i, pfAddedMuonCandidates_, pfCandidates_, pfCleanedCandidates_, pfCleanedTrackerAndGlobalMuonCandidates_, pfCosmicsMuonCleanedCandidates_, pfElectronCandidates_, pfElectronExtra_, pfFakeMuonCleanedCandidates_, pfPhotonCandidates_, pfPhotonExtra_, pfPunchThroughHadronCleanedCandidates_, pfPunchThroughMuonCleanedCandidates_, postCleaning(), processBlock(), and edm::OwnVector< T, P >::size().

313  {
314 
315  // reset output collection
316  if(pfCandidates_.get() )
317  pfCandidates_->clear();
318  else
320 
321  if(pfElectronCandidates_.get() )
322  pfElectronCandidates_->clear();
323  else
325 
326  // Clearing pfPhotonCandidates
327  if( pfPhotonCandidates_.get() )
328  pfPhotonCandidates_->clear();
329  else
331 
332  if(pfCleanedCandidates_.get() )
333  pfCleanedCandidates_->clear();
334  else
336 
339  else
341 
344  else
346 
349  else
351 
354  else
356 
359  else
361 
362  if(pfAddedMuonCandidates_.get() )
363  pfAddedMuonCandidates_->clear();
364  else
366 
367  // not a auto_ptr; shout not be deleted after transfer
368  pfElectronExtra_.clear();
369  pfPhotonExtra_.clear();
370 
371  if( debug_ ) {
372  cout<<"*********************************************************"<<endl;
373  cout<<"***** Particle flow algorithm *****"<<endl;
374  cout<<"*********************************************************"<<endl;
375  }
376 
377  // sort elements in three lists:
378  std::list< reco::PFBlockRef > hcalBlockRefs;
379  std::list< reco::PFBlockRef > ecalBlockRefs;
380  std::list< reco::PFBlockRef > hoBlockRefs;
381  std::list< reco::PFBlockRef > otherBlockRefs;
382 
383  for( unsigned i=0; i<blocks.size(); ++i ) {
384  // reco::PFBlockRef blockref( blockh,i );
385  reco::PFBlockRef blockref = createBlockRef( blocks, i);
386 
387  const reco::PFBlock& block = *blockref;
389  elements = block.elements();
390 
391  bool singleEcalOrHcal = false;
392  if( elements.size() == 1 ){
393  if( elements[0].type() == reco::PFBlockElement::ECAL ){
394  ecalBlockRefs.push_back( blockref );
395  singleEcalOrHcal = true;
396  }
397  if( elements[0].type() == reco::PFBlockElement::HCAL ){
398  hcalBlockRefs.push_back( blockref );
399  singleEcalOrHcal = true;
400  }
401  if( elements[0].type() == reco::PFBlockElement::HO ){
402  // Single HO elements are likely to be noise. Not considered for now.
403  hoBlockRefs.push_back( blockref );
404  singleEcalOrHcal = true;
405  }
406  }
407 
408  if(!singleEcalOrHcal) {
409  otherBlockRefs.push_back( blockref );
410  }
411  }//loop blocks
412 
413  if( debug_ ){
414  cout<<"# Ecal blocks: "<<ecalBlockRefs.size()
415  <<", # Hcal blocks: "<<hcalBlockRefs.size()
416  <<", # HO blocks: "<<hoBlockRefs.size()
417  <<", # Other blocks: "<<otherBlockRefs.size()<<endl;
418  }
419 
420 
421  // loop on blocks that are not single ecal,
422  // and not single hcal.
423 
424  unsigned nblcks = 0;
425  for( IBR io = otherBlockRefs.begin(); io!=otherBlockRefs.end(); ++io) {
426  if ( debug_ ) std::cout << "Block number " << nblcks++ << std::endl;
427  processBlock( *io, hcalBlockRefs, ecalBlockRefs );
428  }
429 
430  std::list< reco::PFBlockRef > empty;
431 
432  unsigned hblcks = 0;
433  // process remaining single hcal blocks
434  for( IBR ih = hcalBlockRefs.begin(); ih!=hcalBlockRefs.end(); ++ih) {
435  if ( debug_ ) std::cout << "HCAL block number " << hblcks++ << std::endl;
436  processBlock( *ih, empty, empty );
437  }
438 
439  unsigned eblcks = 0;
440  // process remaining single ecal blocks
441  for( IBR ie = ecalBlockRefs.begin(); ie!=ecalBlockRefs.end(); ++ie) {
442  if ( debug_ ) std::cout << "ECAL block number " << eblcks++ << std::endl;
443  processBlock( *ie, empty, empty );
444  }
445 
446  // Post HF Cleaning
447  postCleaning();
448 }
type
Definition: HCALResponse.h:22
int i
Definition: DBlmapReader.cc:9
std::auto_ptr< reco::PFCandidateCollection > pfPhotonCandidates_
the unfiltered photon collection
Definition: PFAlgo.h:297
std::auto_ptr< reco::PFCandidateCollection > pfFakeMuonCleanedCandidates_
the collection of fake cleaned muon candidates
Definition: PFAlgo.h:305
size_type size() const
Definition: OwnVector.h:247
virtual void processBlock(const reco::PFBlockRef &blockref, std::list< reco::PFBlockRef > &hcalBlockRefs, std::list< reco::PFBlockRef > &ecalBlockRefs)
Definition: PFAlgo.cc:451
list elements
Definition: asciidump.py:414
const edm::OwnVector< reco::PFBlockElement > & elements() const
Definition: PFBlock.h:107
std::auto_ptr< reco::PFCandidateCollection > pfCleanedCandidates_
Definition: PFAlgo.h:299
reco::PFBlockRef createBlockRef(const reco::PFBlockCollection &blocks, unsigned bi)
Definition: PFAlgo.cc:3294
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
Definition: PFAlgo.h:316
std::vector< reco::PFCandidate > PFCandidateCollection
collection of PFCandidates
std::list< reco::PFBlockRef >::iterator IBR
Definition: PFAlgo.cc:53
std::auto_ptr< reco::PFCandidateCollection > pfCosmicsMuonCleanedCandidates_
the collection of cosmics cleaned muon candidates
Definition: PFAlgo.h:301
list blocks
Definition: gather_cfg.py:90
std::auto_ptr< reco::PFCandidateCollection > pfPunchThroughHadronCleanedCandidates_
the collection of punch-through cleaned neutral hadron candidates
Definition: PFAlgo.h:309
std::auto_ptr< reco::PFCandidateCollection > pfCleanedTrackerAndGlobalMuonCandidates_
the collection of tracker/global cleaned muon candidates
Definition: PFAlgo.h:303
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:293
bool debug_
Definition: PFAlgo.h:357
tuple cout
Definition: gather_cfg.py:121
std::auto_ptr< reco::PFCandidateCollection > pfPunchThroughMuonCleanedCandidates_
the collection of punch-through cleaned muon candidates
Definition: PFAlgo.h:307
std::auto_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
Definition: PFAlgo.h:295
void postCleaning()
Definition: PFAlgo.cc:3397
std::auto_ptr< reco::PFCandidateCollection > pfAddedMuonCandidates_
the collection of added muon candidates
Definition: PFAlgo.h:311
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
Definition: PFAlgo.h:314
Block of elements.
Definition: PFBlock.h:30
unsigned PFAlgo::reconstructTrack ( const reco::PFBlockElement elt)
protected

Reconstruct a charged hadron from a track Returns the index of the newly created candidate in pfCandidates_

Definition at line 2934 of file PFAlgo.cc.

References DeDxDiscriminatorTools::charge(), reco::TrackBase::charge(), gather_cfg::cout, debug_, reco::PFBlockElementTrack::displacedVertexRef(), dptRel_DispVtx_, relval_parameters_module::energy, reco::PFCandidate::h, reco::TrackBase::hitPattern(), isFromSecInt(), PFMuonAlgo::isGlobalTightMuon(), PFMuonAlgo::isIsolatedMuon(), PFMuonAlgo::isMuon(), edm::Ref< C, T, F >::isNonnull(), PFMuonAlgo::isTrackerTightMuon(), reco::PFCandidate::mu, reco::PFBlockElementTrack::muonRef(), reco::HitPattern::numberOfValidPixelHits(), reco::HitPattern::numberOfValidTrackerHits(), reco::TrackBase::p(), pfCandidates_, reco::PFBlockElementTrack::positionAtECALEntrance(), PFMuonAlgo::printMuonProperties(), reco::TrackBase::ptError(), reco::TrackBase::px(), reco::TrackBase::py(), reco::TrackBase::pz(), mathSSE::sqrt(), reco::PFBlockElement::T_FROM_DISP, reco::PFCandidate::T_FROM_DISP, reco::PFBlockElement::T_TO_DISP, reco::PFCandidate::T_TO_DISP, reco::PFBlockElementTrack::trackRef(), useBestMuonTrack_, and usePFMuonMomAssign_.

Referenced by processBlock().

2934  {
2935 
2936  const reco::PFBlockElementTrack* eltTrack
2937  = dynamic_cast<const reco::PFBlockElementTrack*>(&elt);
2938 
2939  reco::TrackRef trackRef = eltTrack->trackRef();
2940  const reco::Track& track = *trackRef;
2941 
2942  reco::MuonRef muonRef = eltTrack->muonRef();
2943 
2944  int charge = track.charge()>0 ? 1 : -1;
2945 
2946  // Assign the pion mass to all charged particles
2947  double px = track.px();
2948  double py = track.py();
2949  double pz = track.pz();
2950  double energy = sqrt(track.p()*track.p() + 0.13957*0.13957);
2951 
2952 
2953  // Except if it is a muon, of course !
2954  bool thisIsAMuon = PFMuonAlgo::isMuon(elt);
2955  bool thisIsAnIsolatedMuon = PFMuonAlgo::isIsolatedMuon(elt);
2956  bool thisIsAGlobalTightMuon = PFMuonAlgo::isGlobalTightMuon(elt);
2957  bool thisIsATrackerTightMuon = PFMuonAlgo::isTrackerTightMuon(elt);
2958 
2959  // Or from nuclear inetraction then use the refitted momentum
2960  bool isFromDisp = isFromSecInt(elt, "secondary");
2961  bool isToDisp = isFromSecInt(elt, "primary");
2962  //isFromNucl = false;
2963  bool globalFitUsed = false;
2964 
2965  if ( thisIsAMuon ) {
2966 
2967  //By default take muon kinematics directly from the muon object (usually determined by the track)
2968  px = muonRef->px();
2969  py = muonRef->py();
2970  pz = muonRef->pz();
2971  energy = sqrt(muonRef->p()*muonRef->p() + 0.1057*0.1057);
2972 
2973  reco::TrackBase::TrackQuality trackQualityHighPurity = TrackBase::qualityByName("highPurity");
2974  if(debug_)if(!trackRef->quality(trackQualityHighPurity))cout<<" Low Purity Track "<<endl;
2975 
2976  if(muonRef->isGlobalMuon() && !usePFMuonMomAssign_){
2977 
2978  reco::TrackRef bestMuTrack = muonRef->muonBestTrack();
2979  if(!useBestMuonTrack_)
2980  bestMuTrack = muonRef->combinedMuon();
2981 
2982  // take the global fit instead under special circumstances
2983  bool useGlobalFit = false;
2984 
2985  if(thisIsAnIsolatedMuon && (!muonRef->isTrackerMuon() || (muonRef->pt() > bestMuTrack->pt() && track.ptError() > 5.0*bestMuTrack->ptError()))) useGlobalFit = true;
2986  else if(!trackRef->quality(trackQualityHighPurity)) useGlobalFit = true;
2987  else if(muonRef->pt() > bestMuTrack->pt() &&
2988  (track.hitPattern().numberOfValidTrackerHits() < 8 || track.hitPattern().numberOfValidPixelHits() == 0 ) &&
2989  track.ptError() > 5.0*bestMuTrack->ptError()) useGlobalFit = true;
2990 
2991  if(useGlobalFit){
2992  px = bestMuTrack->px();
2993  py = bestMuTrack->py();
2994  pz = bestMuTrack->pz();
2995  energy = sqrt(bestMuTrack->p()*bestMuTrack->p() + 0.1057*0.1057);
2996  globalFitUsed = true;
2997  }
2998  }
2999  else if(usePFMuonMomAssign_){
3000  // If this option is set we take more liberties choosing the muon kinematics (not advised by the muon POG)
3001  if(thisIsAGlobalTightMuon)
3002  {
3003  // If the global muon above 10 GeV and is a tracker muon take the global pT
3004  if(muonRef->isTrackerMuon()){
3005  if(sqrt(px*px+py*py) > 10){
3006 
3007  reco::TrackRef bestMuTrack = muonRef->muonBestTrack();
3008  if(!useBestMuonTrack_)
3009  bestMuTrack = muonRef->combinedMuon();
3010 
3011  px = bestMuTrack->px();
3012  py = bestMuTrack->py();
3013  pz = bestMuTrack->pz();
3014  energy = sqrt(bestMuTrack->p()*bestMuTrack->p() + 0.1057*0.1057);
3015  globalFitUsed = true;
3016  }
3017  } // If it's not a tracker muon, choose between the global pT and the STA pT
3018  else{
3019 
3020  reco::TrackRef bestMuTrack = muonRef->combinedMuon()->normalizedChi2() < muonRef->standAloneMuon()->normalizedChi2() ?
3021  muonRef->muonBestTrack() :
3022  muonRef->standAloneMuon() ;
3023 
3024  if(!useBestMuonTrack_)
3025  bestMuTrack =
3026  muonRef->combinedMuon()->normalizedChi2() < muonRef->standAloneMuon()->normalizedChi2() ?
3027  muonRef->combinedMuon() :
3028  muonRef->standAloneMuon() ;
3029 
3030  px = bestMuTrack->px();
3031  py = bestMuTrack->py();
3032  pz = bestMuTrack->pz();
3033  energy = sqrt(bestMuTrack->p()*bestMuTrack->p() + 0.1057*0.1057);
3034  globalFitUsed = true;
3035  }
3036  } // close else if(thisIsAGlobalTightMuon)
3037  } // close (usePFPFMuonMomAssign_)
3038  }// close if(thisIsAMuon)
3039  else if (isFromDisp) {
3040  double Dpt = trackRef->ptError();
3041  double dptRel = Dpt/trackRef->pt()*100;
3042  //If the track is ill measured it is better to not refit it, since the track information probably would not be used.
3043  //In the PFAlgo we use the trackref information. If the track error is too big the refitted information might be very different
3044  // from the not refitted one.
3045  if (dptRel < dptRel_DispVtx_){
3046 
3047  if (debug_)
3048  cout << "Not refitted px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
3049  //reco::TrackRef trackRef = eltTrack->trackRef();
3051  reco::Track trackRefit = vRef->refittedTrack(trackRef);
3052  px = trackRefit.px();
3053  py = trackRefit.py();
3054  pz = trackRefit.pz();
3055  energy = sqrt(trackRefit.p()*trackRefit.p() + 0.13957*0.13957);
3056  if (debug_)
3057  cout << "Refitted px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
3058 
3059  }
3060  }
3061 
3062  if ((isFromDisp || isToDisp) && debug_) cout << "Final px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
3063 
3064  // Create a PF Candidate
3065  math::XYZTLorentzVector momentum(px,py,pz,energy);
3066  reco::PFCandidate::ParticleType particleType
3068 
3069  // Add it to the stack
3070  pfCandidates_->push_back( PFCandidate( charge,
3071  momentum,
3072  particleType ) );
3073 
3074  // displaced vertices
3075  if( isFromDisp ) {
3076  pfCandidates_->back().setFlag( reco::PFCandidate::T_FROM_DISP, true);
3077  pfCandidates_->back().setDisplacedVertexRef( eltTrack->displacedVertexRef(reco::PFBlockElement::T_FROM_DISP)->displacedVertexRef(), reco::PFCandidate::T_FROM_DISP);
3078  }
3079 
3080  // 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
3081  if( isToDisp && !thisIsAMuon ) {
3082  pfCandidates_->back().setFlag( reco::PFCandidate::T_TO_DISP, true);
3083  pfCandidates_->back().setDisplacedVertexRef( eltTrack->displacedVertexRef(reco::PFBlockElement::T_TO_DISP)->displacedVertexRef(), reco::PFCandidate::T_TO_DISP);
3084  }
3085 
3086 
3087 
3088  if ( thisIsAMuon && globalFitUsed )
3089  pfCandidates_->back().setVertexSource( PFCandidate::kComMuonVertex );
3090  else
3091  pfCandidates_->back().setVertexSource( PFCandidate::kTrkVertex );
3092 
3093  pfCandidates_->back().setTrackRef( trackRef );
3094  pfCandidates_->back().setPositionAtECALEntrance( eltTrack->positionAtECALEntrance());
3095 
3096 
3097 
3098  // setting the muon ref if there is
3099  if (muonRef.isNonnull()) {
3100  pfCandidates_->back().setMuonRef( muonRef );
3101  // setting the muon particle type if it is a global muon
3102  if ( thisIsAMuon) {
3103  particleType = reco::PFCandidate::mu;
3104  pfCandidates_->back().setParticleType( particleType );
3105  if (debug_) {
3106  if(thisIsAGlobalTightMuon) cout << "PFAlgo: particle type set to muon (global, tight), pT = " <<muonRef->pt()<< endl;
3107  else if(thisIsATrackerTightMuon) cout << "PFAlgo: particle type set to muon (tracker, tight), pT = " <<muonRef->pt()<< endl;
3108  else if(thisIsAnIsolatedMuon) cout << "PFAlgo: particle type set to muon (isolated), pT = " <<muonRef->pt()<< endl;
3109  else cout<<" problem with muon assignment "<<endl;
3111  }
3112  }
3113  }
3114 
3115  // conversion...
3116 
3117  if(debug_)
3118  cout<<"** candidate: "<<pfCandidates_->back()<<endl;
3119 
3120  // returns index to the newly created PFCandidate
3121  return pfCandidates_->size()-1;
3122 }
double p() const
momentum vector magnitude
Definition: TrackBase.h:129
static bool isIsolatedMuon(const reco::PFBlockElement &elt)
Definition: PFMuonAlgo.cc:76
bool isFromSecInt(const reco::PFBlockElement &eTrack, std::string order) const
Definition: PFAlgo.cc:3361
ParticleType
particle types
Definition: PFCandidate.h:38
static bool isMuon(const reco::PFBlockElement &elt)
Check if a block element is a muon.
Definition: PFMuonAlgo.cc:11
TrackQuality
track quality
Definition: TrackBase.h:95
double px() const
x coordinate of momentum vector
Definition: TrackBase.h:133
static void printMuonProperties(const reco::MuonRef &muonRef)
Definition: PFMuonAlgo.cc:349
double charge(const std::vector< uint8_t > &Ampls)
static bool isGlobalTightMuon(const reco::PFBlockElement &elt)
Definition: PFMuonAlgo.cc:37
const math::XYZPointF & positionAtECALEntrance() const
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:30
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:250
reco::MuonRef muonRef() const
T sqrt(T t)
Definition: SSEVec.h:46
bool usePFMuonMomAssign_
Definition: PFAlgo.h:380
double ptError() const
error on Pt (set to 1000 TeV if charge==0 for safety)
Definition: TrackBase.h:194
const HitPattern & hitPattern() const
Access the hit pattern, indicating in which Tracker layers the track has hits.
Definition: TrackBase.h:223
double pz() const
z coordinate of momentum vector
Definition: TrackBase.h:137
double useBestMuonTrack_
Definition: PFAlgo.h:417
double dptRel_DispVtx_
Definition: PFAlgo.h:393
reco::TrackRef trackRef() const
int numberOfValidTrackerHits() const
Definition: HitPattern.h:558
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:33
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:293
int numberOfValidPixelHits() const
Definition: HitPattern.h:566
bool debug_
Definition: PFAlgo.h:357
tuple cout
Definition: gather_cfg.py:121
int charge() const
track electric charge
Definition: TrackBase.h:113
double py() const
y coordinate of momentum vector
Definition: TrackBase.h:135
static bool isTrackerTightMuon(const reco::PFBlockElement &elt)
Definition: PFMuonAlgo.cc:63
PFDisplacedTrackerVertexRef displacedVertexRef(TrackType trType) const
void PFAlgo::setAlgo ( int  algo)
inline

Definition at line 59 of file PFAlgo.h.

References algo, and algo_.

Referenced by PFRootEventManager::readOptions().

59 {algo_ = algo;}
int algo_
Definition: PFAlgo.h:356
LimitAlgo * algo
Definition: Combine.cc:60
void PFAlgo::setCandConnectorParameters ( const edm::ParameterSet iCfgCandConnector)
inline

Definition at line 68 of file PFAlgo.h.

References connector_, and PFCandConnector::setParameters().

Referenced by PFRootEventManager::readOptions().

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

Definition at line 72 of file PFAlgo.h.

References connector_, and PFCandConnector::setParameters().

77  {
78  connector_.setParameters(bCorrect, bCalibPrimary, dptRel_PrimaryTrack, dptRel_MergedTrack, ptErrorSecondary, nuclCalibFactors);
79  }
PFCandConnector connector_
Definition: PFAlgo.h:398
void setParameters(const edm::ParameterSet &iCfgCandConnector)
void PFAlgo::setDebug ( bool  debug)
inline

Definition at line 61 of file PFAlgo.h.

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

Referenced by PFRootEventManager::readOptions().

PFCandConnector connector_
Definition: PFAlgo.h:398
bool debug_
Definition: PFAlgo.h:357
#define debug
Definition: MEtoEDMFormat.h:34
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 264 of file PFAlgo.cc.

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

Referenced by PFRootEventManager::readOptions().

269  {
270 
271  rejectTracks_Bad_ = rejectTracks_Bad;
272  rejectTracks_Step45_ = rejectTracks_Step45;
273  usePFNuclearInteractions_ = usePFNuclearInteractions;
274  usePFConversions_ = usePFConversions;
275  usePFDecays_ = usePFDecays;
276  dptRel_DispVtx_ = dptRel_DispVtx;
277 
278 }
bool usePFConversions_
Definition: PFAlgo.h:388
bool rejectTracks_Step45_
Definition: PFAlgo.h:385
bool usePFNuclearInteractions_
Definition: PFAlgo.h:387
double dptRel_DispVtx_
Definition: PFAlgo.h:393
bool rejectTracks_Bad_
Definition: PFAlgo.h:384
bool usePFDecays_
Definition: PFAlgo.h:389
void PFAlgo::setEGElectronCollection ( const reco::GsfElectronCollection egelectrons)

Definition at line 3392 of file PFAlgo.cc.

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

Referenced by PFRootEventManager::particleFlow().

3392  {
3394 }
PFElectronAlgo * pfele_
Definition: PFAlgo.h:376
bool useEGElectrons_
Definition: PFAlgo.h:367
void setEGElectronCollection(const reco::GsfElectronCollection &egelectrons)
void PFAlgo::setElectronExtraRef ( const edm::OrphanHandle< reco::PFCandidateElectronExtraCollection > &  extrah)

Definition at line 4137 of file PFAlgo.cc.

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

Referenced by PFRootEventManager::particleFlow().

4137  {
4138  if(!usePFElectrons_) return;
4139  // std::cout << " setElectronExtraRef " << std::endl;
4140  unsigned size=pfCandidates_->size();
4141 
4142  for(unsigned ic=0;ic<size;++ic) {
4143  // select the electrons and add the extra
4144  if((*pfCandidates_)[ic].particleId()==PFCandidate::e) {
4145 
4146  PFElectronExtraEqual myExtraEqual((*pfCandidates_)[ic].gsfTrackRef());
4147  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
4148  if(it!=pfElectronExtra_.end()) {
4149  // std::cout << " Index " << it-pfElectronExtra_.begin() << std::endl;
4150  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
4151  (*pfCandidates_)[ic].setPFElectronExtraRef(theRef);
4152  }
4153  else {
4154  (*pfCandidates_)[ic].setPFElectronExtraRef(PFCandidateElectronExtraRef());
4155  }
4156  }
4157  else // else save the mva and the extra as well !
4158  {
4159  if((*pfCandidates_)[ic].trackRef().isNonnull()) {
4160  PFElectronExtraKfEqual myExtraEqual((*pfCandidates_)[ic].trackRef());
4161  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
4162  if(it!=pfElectronExtra_.end()) {
4163  (*pfCandidates_)[ic].set_mva_e_pi(it->mvaVariable(PFCandidateElectronExtra::MVA_MVA));
4164  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
4165  (*pfCandidates_)[ic].setPFElectronExtraRef(theRef);
4166  (*pfCandidates_)[ic].setGsfTrackRef(it->gsfTrackRef());
4167  }
4168  }
4169  }
4170 
4171  }
4172 
4173  size=pfElectronCandidates_->size();
4174  for(unsigned ic=0;ic<size;++ic) {
4175  // select the electrons - this test is actually not needed for this collection
4176  if((*pfElectronCandidates_)[ic].particleId()==PFCandidate::e) {
4177  // find the corresponding extra
4178  PFElectronExtraEqual myExtraEqual((*pfElectronCandidates_)[ic].gsfTrackRef());
4179  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
4180  if(it!=pfElectronExtra_.end()) {
4181  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
4182  (*pfElectronCandidates_)[ic].setPFElectronExtraRef(theRef);
4183 
4184  }
4185  }
4186  }
4187 
4188 }
edm::Ref< PFCandidateElectronExtraCollection > PFCandidateElectronExtraRef
persistent reference to a PFCandidateElectronExtra
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:293
std::auto_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
Definition: PFAlgo.h:295
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
Definition: PFAlgo.h:314
tuple size
Write out results.
bool usePFElectrons_
Definition: PFAlgo.h:363
void PFAlgo::setHOTag ( bool  ho)
inline

Definition at line 58 of file PFAlgo.h.

References useHO_.

Referenced by PFRootEventManager::readOptions().

58 { useHO_ = ho;}
bool useHO_
Definition: PFAlgo.h:355
void PFAlgo::setParameters ( double  nSigmaECAL,
double  nSigmaHCAL,
const boost::shared_ptr< PFEnergyCalibration > &  calibration,
const boost::shared_ptr< PFEnergyCalibrationHF > &  thepfEnergyCalibrationHF 
)

Definition at line 75 of file PFAlgo.cc.

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

Referenced by PFRootEventManager::readOptions().

78  {
79 
80  nSigmaECAL_ = nSigmaECAL;
82 
83  calibration_ = calibration;
84  thepfEnergyCalibrationHF_ = thepfEnergyCalibrationHF;
85 
86 }
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:349
double nSigmaHCAL(double clusterEnergy, double clusterEta) const
Definition: PFAlgo.cc:3256
boost::shared_ptr< PFEnergyCalibration > calibration_
Definition: PFAlgo.h:351
boost::shared_ptr< PFEnergyCalibrationHF > thepfEnergyCalibrationHF_
Definition: PFAlgo.h:352
double nSigmaECAL_
number of sigma to judge energy excess in ECAL
Definition: PFAlgo.h:346
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 90 of file PFAlgo.cc.

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

Referenced by PFRootEventManager::readOptions().

105  {
106 
107  mvaEleCut_ = mvaEleCut;
108  usePFElectrons_ = usePFElectrons;
109  applyCrackCorrectionsElectrons_ = applyCrackCorrections;
110  usePFSCEleCalib_ = usePFSCEleCalib;
111  thePFSCEnergyCalibration_ = thePFSCEnergyCalibration;
112  useEGElectrons_ = useEGElectrons;
113  useEGammaSupercluster_ = useEGammaSupercluster;
114  sumEtEcalIsoForEgammaSC_barrel_ = sumEtEcalIsoForEgammaSC_barrel;
115  sumEtEcalIsoForEgammaSC_endcap_ = sumEtEcalIsoForEgammaSC_endcap;
116  coneEcalIsoForEgammaSC_ = coneEcalIsoForEgammaSC;
117  sumPtTrackIsoForEgammaSC_barrel_ = sumPtTrackIsoForEgammaSC_barrel;
118  sumPtTrackIsoForEgammaSC_endcap_ = sumPtTrackIsoForEgammaSC_endcap;
119  coneTrackIsoForEgammaSC_ = coneTrackIsoForEgammaSC;
120  nTrackIsoForEgammaSC_ = nTrackIsoForEgammaSC;
121 
122 
123  if(!usePFElectrons_) return;
124  mvaWeightFileEleID_ = mvaWeightFileEleID;
125  FILE * fileEleID = fopen(mvaWeightFileEleID_.c_str(), "r");
126  if (fileEleID) {
127  fclose(fileEleID);
128  }
129  else {
130  string err = "PFAlgo: cannot open weight file '";
131  err += mvaWeightFileEleID;
132  err += "'";
133  throw invalid_argument( err );
134  }
149 }
unsigned int nTrackIsoForEgammaSC_
Definition: PFAlgo.h:375
double sumEtEcalIsoForEgammaSC_endcap_
Definition: PFAlgo.h:370
double mvaEleCut_
Definition: PFAlgo.h:362
double coneEcalIsoForEgammaSC_
Definition: PFAlgo.h:371
double coneTrackIsoForEgammaSC_
Definition: PFAlgo.h:374
double sumEtEcalIsoForEgammaSC_barrel_
Definition: PFAlgo.h:369
PFElectronAlgo * pfele_
Definition: PFAlgo.h:376
bool useEGammaSupercluster_
Definition: PFAlgo.h:368
boost::shared_ptr< PFEnergyCalibration > thePFEnergyCalibration()
return the pointer to the calibration function
Definition: PFAlgo.h:244
bool useEGElectrons_
Definition: PFAlgo.h:367
std::string mvaWeightFileEleID_
Variables for PFElectrons.
Definition: PFAlgo.h:360
bool usePFSCEleCalib_
Definition: PFAlgo.h:366
boost::shared_ptr< PFSCEnergyCalibration > thePFSCEnergyCalibration_
Definition: PFAlgo.h:353
bool applyCrackCorrectionsElectrons_
Definition: PFAlgo.h:365
double sumPtTrackIsoForEgammaSC_endcap_
Definition: PFAlgo.h:373
double sumPtTrackIsoForEgammaSC_barrel_
Definition: PFAlgo.h:372
bool usePFElectrons_
Definition: PFAlgo.h:363
void PFAlgo::setPFMuonAndFakeParameters ( std::vector< double >  muonHCAL,
std::vector< double >  muonECAL,
std::vector< double >  muonHO,
double  nSigmaTRACK,
double  ptError,
std::vector< double >  factors45,
bool  usePFMuonMomAssign,
bool  useBestMuonTrack 
)

Definition at line 227 of file PFAlgo.cc.

References factors45_, muonECAL_, muonHCAL_, muonHO_, nSigmaTRACK_, ptError_, useBestMuonTrack_, and usePFMuonMomAssign_.

Referenced by PFRootEventManager::readOptions().

235 {
236  muonHCAL_ = muonHCAL;
237  muonECAL_ = muonECAL;
238  muonHO_ = muonHO;
239  nSigmaTRACK_ = nSigmaTRACK;
240  ptError_ = ptError;
241  factors45_ = factors45;
242  usePFMuonMomAssign_ = usePFMuonMomAssign;
243  useBestMuonTrack_ = useBestMuonTrack;
244 }
double ptError_
Definition: PFAlgo.h:405
std::vector< double > muonHCAL_
Variables for muons and fakes.
Definition: PFAlgo.h:401
std::vector< double > factors45_
Definition: PFAlgo.h:406
bool usePFMuonMomAssign_
Definition: PFAlgo.h:380
std::vector< double > muonECAL_
Definition: PFAlgo.h:402
double useBestMuonTrack_
Definition: PFAlgo.h:417
std::vector< double > muonHO_
Definition: PFAlgo.h:403
double nSigmaTRACK_
Definition: PFAlgo.h:404
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 152 of file PFAlgo.cc.

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

Referenced by PFRootEventManager::readOptions().

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

Definition at line 214 of file PFAlgo.cc.

References pfpho_, and PFPhotonAlgo::setGBRForest().

Referenced by PFRootEventManager::readOptions().

220  {
221 
222  pfpho_->setGBRForest(LCorrForestEB,LCorrForestEE,
223  GCorrForestBarrel, GCorrForestEndcapHr9,
224  GCorrForestEndcapLr9, PFEcalResolution);
225 }
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:377
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 282 of file PFAlgo.cc.

References i, pfpho_, primaryVertex_, PFPhotonAlgo::setnPU(), usePFPhotons_, and useVertices_.

Referenced by PFRootEventManager::particleFlow().

283  {
284  useVertices_ = useVertex;
285  //Now find the primary vertex!
286  bool primaryVertexFound = false;
287  int nVtx=primaryVertices.size();
288  if(usePFPhotons_)pfpho_->setnPU(nVtx);
289 
290  for (unsigned short i=0 ;i<primaryVertices.size();++i)
291  {
292  if(primaryVertices[i].isValid()&&(!primaryVertices[i].isFake()))
293  {
294  primaryVertex_ = primaryVertices[i];
295  primaryVertexFound = true;
296  break;
297  }
298  }
299  //Use vertices if the user wants to but only if it exists a good vertex
300  useVertices_ = useVertex && primaryVertexFound;
301 
302 }
int i
Definition: DBlmapReader.cc:9
void setnPU(int nVtx)
Definition: PFPhotonAlgo.h:75
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:377
reco::Vertex primaryVertex_
Definition: PFAlgo.h:420
bool useVertices_
Definition: PFAlgo.h:421
bool usePFPhotons_
Definition: PFAlgo.h:364
void PFAlgo::setPhotonExtraRef ( const edm::OrphanHandle< reco::PFCandidatePhotonExtraCollection > &  pf_extrah)

Definition at line 4189 of file PFAlgo.cc.

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

4189  {
4190  if(!usePFPhotons_) return;
4191  unsigned int size=pfCandidates_->size();
4192  unsigned int sizePhExtra = pfPhotonExtra_.size();
4193  for(unsigned ic=0;ic<size;++ic) {
4194  // select the electrons and add the extra
4195  if((*pfCandidates_)[ic].particleId()==PFCandidate::gamma && (*pfCandidates_)[ic].mva_nothing_gamma() > 0.99) {
4196  if((*pfCandidates_)[ic].superClusterRef().isNonnull()) {
4197  bool found = false;
4198  for(unsigned pcextra=0;pcextra<sizePhExtra;++pcextra) {
4199  if((*pfCandidates_)[ic].superClusterRef() == pfPhotonExtra_[pcextra].superClusterRef()) {
4200  reco::PFCandidatePhotonExtraRef theRef(ph_extrah,pcextra);
4201  (*pfCandidates_)[ic].setPFPhotonExtraRef(theRef);
4202  found = true;
4203  break;
4204  }
4205  }
4206  if(!found)
4207  (*pfCandidates_)[ic].setPFPhotonExtraRef((PFCandidatePhotonExtraRef())); // null ref
4208  }
4209  else {
4210  (*pfCandidates_)[ic].setPFPhotonExtraRef((PFCandidatePhotonExtraRef())); // null ref
4211  }
4212  }
4213  }
4214 }
edm::Ref< PFCandidatePhotonExtraCollection > PFCandidatePhotonExtraRef
persistent reference to a PFCandidatePhotonExtra
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
Definition: PFAlgo.h:316
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:293
bool usePFPhotons_
Definition: PFAlgo.h:364
tuple size
Write out results.
void PFAlgo::setPostHFCleaningParameters ( bool  postHFCleaning,
double  minHFCleaningPt,
double  minSignificance,
double  maxSignificance,
double  minSignificanceReduction,
double  maxDeltaPhiPt,
double  minDeltaMet 
)

Definition at line 247 of file PFAlgo.cc.

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

Referenced by PFRootEventManager::readOptions().

253  {
254  postHFCleaning_ = postHFCleaning;
255  minHFCleaningPt_ = minHFCleaningPt;
256  minSignificance_ = minSignificance;
257  maxSignificance_ = maxSignificance;
258  minSignificanceReduction_= minSignificanceReduction;
259  maxDeltaPhiPt_ = maxDeltaPhiPt;
260  minDeltaMet_ = minDeltaMet;
261 }
double maxDeltaPhiPt_
Definition: PFAlgo.h:415
double maxSignificance_
Definition: PFAlgo.h:413
double minHFCleaningPt_
Definition: PFAlgo.h:411
double minDeltaMet_
Definition: PFAlgo.h:416
double minSignificance_
Definition: PFAlgo.h:412
double minSignificanceReduction_
Definition: PFAlgo.h:414
bool postHFCleaning_
Definition: PFAlgo.h:409
boost::shared_ptr<PFEnergyCalibration> PFAlgo::thePFEnergyCalibration ( )
inline

return the pointer to the calibration function

Definition at line 244 of file PFAlgo.h.

References calibration_.

244  {
245  return calibration_;
246  }
boost::shared_ptr< PFEnergyCalibration > calibration_
Definition: PFAlgo.h:351
std::auto_ptr< reco::PFCandidateCollection > PFAlgo::transferAddedMuonCandidates ( )
inline
Returns
collection of added muon candidates

Definition at line 234 of file PFAlgo.h.

References pfAddedMuonCandidates_.

234  {
235  return pfAddedMuonCandidates_;
236  }
std::auto_ptr< reco::PFCandidateCollection > pfAddedMuonCandidates_
the collection of added muon candidates
Definition: PFAlgo.h:311
std::auto_ptr< reco::PFCandidateCollection > PFAlgo::transferCandidates ( )
inline
Returns
auto_ptr to the collection of candidates (transfers ownership)

Definition at line 239 of file PFAlgo.h.

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

Referenced by PFRootEventManager::particleFlow().

239  {
241  }
std::auto_ptr< reco::PFCandidateCollection > connect(std::auto_ptr< reco::PFCandidateCollection > &pfCand)
PFCandConnector connector_
Definition: PFAlgo.h:398
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:293
std::auto_ptr< reco::PFCandidateCollection >& PFAlgo::transferCleanedCandidates ( )
inline
Returns
collection of cleaned HF candidates

Definition at line 204 of file PFAlgo.h.

References pfCleanedCandidates_.

204  {
205  return pfCleanedCandidates_;
206  }
std::auto_ptr< reco::PFCandidateCollection > pfCleanedCandidates_
Definition: PFAlgo.h:299
std::auto_ptr< reco::PFCandidateCollection > PFAlgo::transferCleanedTrackerAndGlobalMuonCandidates ( )
inline
Returns
collection of tracker/global cleaned muon candidates

Definition at line 214 of file PFAlgo.h.

References pfCleanedTrackerAndGlobalMuonCandidates_.

214  {
216  }
std::auto_ptr< reco::PFCandidateCollection > pfCleanedTrackerAndGlobalMuonCandidates_
the collection of tracker/global cleaned muon candidates
Definition: PFAlgo.h:303
std::auto_ptr< reco::PFCandidateCollection > PFAlgo::transferCosmicsMuonCleanedCandidates ( )
inline
Returns
collection of cosmics cleaned muon candidates

Definition at line 209 of file PFAlgo.h.

References pfCosmicsMuonCleanedCandidates_.

209  {
211  }
std::auto_ptr< reco::PFCandidateCollection > pfCosmicsMuonCleanedCandidates_
the collection of cosmics cleaned muon candidates
Definition: PFAlgo.h:301
std::auto_ptr< reco::PFCandidateCollection> PFAlgo::transferElectronCandidates ( )
inline
Returns
the unfiltered electron collection

Definition at line 181 of file PFAlgo.h.

References pfElectronCandidates_.

181  {
182  return pfElectronCandidates_;
183  }
std::auto_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
Definition: PFAlgo.h:295
std::auto_ptr< reco::PFCandidateElectronExtraCollection> PFAlgo::transferElectronExtra ( )
inline
Returns
the unfiltered electron extra collection

Definition at line 187 of file PFAlgo.h.

References pfElectronExtra_, and query::result.

Referenced by PFRootEventManager::particleFlow().

187  {
188  std::auto_ptr< reco::PFCandidateElectronExtraCollection> result(new reco::PFCandidateElectronExtraCollection);
189  result->insert(result->end(),pfElectronExtra_.begin(),pfElectronExtra_.end());
190  return result;
191  }
tuple result
Definition: query.py:137
std::vector< reco::PFCandidateElectronExtra > PFCandidateElectronExtraCollection
collection of PFCandidateElectronExtras
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
Definition: PFAlgo.h:314
std::auto_ptr< reco::PFCandidateCollection > PFAlgo::transferFakeMuonCleanedCandidates ( )
inline
Returns
collection of fake cleaned muon candidates

Definition at line 219 of file PFAlgo.h.

References pfFakeMuonCleanedCandidates_.

219  {
221  }
std::auto_ptr< reco::PFCandidateCollection > pfFakeMuonCleanedCandidates_
the collection of fake cleaned muon candidates
Definition: PFAlgo.h:305
std::auto_ptr< reco::PFCandidatePhotonExtraCollection> PFAlgo::transferPhotonExtra ( )
inline
Returns
the unfiltered photon extra collection

Definition at line 196 of file PFAlgo.h.

References pfPhotonExtra_, and query::result.

196  {
197  std::auto_ptr< reco::PFCandidatePhotonExtraCollection> result(new reco::PFCandidatePhotonExtraCollection);
198  result->insert(result->end(),pfPhotonExtra_.begin(),pfPhotonExtra_.end());
199  return result;
200  }
tuple result
Definition: query.py:137
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
Definition: PFAlgo.h:316
std::vector< reco::PFCandidatePhotonExtra > PFCandidatePhotonExtraCollection
collection of PFCandidatePhotonExtras
std::auto_ptr< reco::PFCandidateCollection > PFAlgo::transferPunchThroughHadronCleanedCandidates ( )
inline
Returns
collection of punch-through cleaned neutral hadron candidates

Definition at line 229 of file PFAlgo.h.

References pfPunchThroughHadronCleanedCandidates_.

229  {
231  }
std::auto_ptr< reco::PFCandidateCollection > pfPunchThroughHadronCleanedCandidates_
the collection of punch-through cleaned neutral hadron candidates
Definition: PFAlgo.h:309
std::auto_ptr< reco::PFCandidateCollection > PFAlgo::transferPunchThroughMuonCleanedCandidates ( )
inline
Returns
collection of punch-through cleaned muon candidates

Definition at line 224 of file PFAlgo.h.

References pfPunchThroughMuonCleanedCandidates_.

224  {
226  }
std::auto_ptr< reco::PFCandidateCollection > pfPunchThroughMuonCleanedCandidates_
the collection of punch-through cleaned muon candidates
Definition: PFAlgo.h:307

Friends And Related Function Documentation

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

Member Data Documentation

int PFAlgo::algo_
private

Definition at line 356 of file PFAlgo.h.

Referenced by setAlgo().

bool PFAlgo::applyCrackCorrectionsElectrons_
private

Definition at line 365 of file PFAlgo.h.

Referenced by setPFEleParameters().

reco::PFBlockHandle PFAlgo::blockHandle_
private

input block handle (full framework case)

Definition at line 343 of file PFAlgo.h.

Referenced by createBlockRef(), and reconstructParticles().

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

Definition at line 351 of file PFAlgo.h.

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

double PFAlgo::coneEcalIsoForEgammaSC_
private

Definition at line 371 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::coneTrackIsoForEgammaSC_
private

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

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

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

Definition at line 406 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

double PFAlgo::maxDeltaPhiPt_
private

Definition at line 415 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::maxSignificance_
private

Definition at line 413 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minDeltaMet_
private

Definition at line 416 of file PFAlgo.h.

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

double PFAlgo::minHFCleaningPt_
private

Definition at line 411 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minSignificance_
private

Definition at line 412 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minSignificanceReduction_
private

Definition at line 414 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

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

Definition at line 402 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

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

Variables for muons and fakes.

Definition at line 401 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

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

Definition at line 403 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

double PFAlgo::mvaEleCut_
private

Definition at line 362 of file PFAlgo.h.

Referenced by setPFEleParameters().

std::string PFAlgo::mvaWeightFileEleID_
private

Variables for PFElectrons.

Definition at line 360 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::nSigmaECAL_
private

number of sigma to judge energy excess in ECAL

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

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

double PFAlgo::nSigmaTRACK_
private

Definition at line 404 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

unsigned int PFAlgo::nTrackIsoForEgammaSC_
private

Definition at line 375 of file PFAlgo.h.

Referenced by setPFEleParameters().

std::auto_ptr< reco::PFCandidateCollection > PFAlgo::pfAddedMuonCandidates_
protected

the collection of added muon candidates

Definition at line 311 of file PFAlgo.h.

Referenced by postMuonCleaning(), reconstructParticles(), and transferAddedMuonCandidates().

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

Definition at line 299 of file PFAlgo.h.

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

std::auto_ptr< reco::PFCandidateCollection > PFAlgo::pfCleanedTrackerAndGlobalMuonCandidates_
protected

the collection of tracker/global cleaned muon candidates

Definition at line 303 of file PFAlgo.h.

Referenced by postMuonCleaning(), reconstructParticles(), and transferCleanedTrackerAndGlobalMuonCandidates().

std::auto_ptr< reco::PFCandidateCollection > PFAlgo::pfCosmicsMuonCleanedCandidates_
protected

the collection of cosmics cleaned muon candidates

Definition at line 301 of file PFAlgo.h.

Referenced by postMuonCleaning(), reconstructParticles(), and transferCosmicsMuonCleanedCandidates().

PFElectronAlgo* PFAlgo::pfele_
private

Definition at line 376 of file PFAlgo.h.

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

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

the unfiltered electron collection

Definition at line 295 of file PFAlgo.h.

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

reco::PFCandidateElectronExtraCollection PFAlgo::pfElectronExtra_
protected

the unfiltered electron collection

Definition at line 314 of file PFAlgo.h.

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

std::auto_ptr< reco::PFCandidateCollection > PFAlgo::pfFakeMuonCleanedCandidates_
protected

the collection of fake cleaned muon candidates

Definition at line 305 of file PFAlgo.h.

Referenced by postMuonCleaning(), reconstructParticles(), and transferFakeMuonCleanedCandidates().

PFPhotonAlgo* PFAlgo::pfpho_
private
std::auto_ptr< reco::PFCandidateCollection > PFAlgo::pfPhotonCandidates_
protected

the unfiltered photon collection

Definition at line 297 of file PFAlgo.h.

Referenced by processBlock(), and reconstructParticles().

reco::PFCandidatePhotonExtraCollection PFAlgo::pfPhotonExtra_
protected

the extra photon collection

Definition at line 316 of file PFAlgo.h.

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

std::auto_ptr< reco::PFCandidateCollection > PFAlgo::pfPunchThroughHadronCleanedCandidates_
protected

the collection of punch-through cleaned neutral hadron candidates

Definition at line 309 of file PFAlgo.h.

Referenced by postMuonCleaning(), reconstructParticles(), and transferPunchThroughHadronCleanedCandidates().

std::auto_ptr< reco::PFCandidateCollection > PFAlgo::pfPunchThroughMuonCleanedCandidates_
protected

the collection of punch-through cleaned muon candidates

Definition at line 307 of file PFAlgo.h.

Referenced by postMuonCleaning(), reconstructParticles(), and transferPunchThroughMuonCleanedCandidates().

bool PFAlgo::postHFCleaning_
private

Definition at line 409 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

bool PFAlgo::postMuonCleaning_
private

Definition at line 410 of file PFAlgo.h.

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

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

Referenced by processBlock(), and setDisplacedVerticesParameters().

bool PFAlgo::rejectTracks_Step45_
private

Definition at line 385 of file PFAlgo.h.

Referenced by processBlock(), and setDisplacedVerticesParameters().

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

Definition at line 361 of file PFAlgo.h.

double PFAlgo::sumEtEcalIsoForEgammaSC_barrel_
private

Definition at line 369 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumEtEcalIsoForEgammaSC_endcap_
private

Definition at line 370 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumPtTrackIsoForEgammaSC_barrel_
private

Definition at line 372 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumPtTrackIsoForEgammaSC_endcap_
private

Definition at line 373 of file PFAlgo.h.

Referenced by setPFEleParameters().

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

Definition at line 352 of file PFAlgo.h.

Referenced by processBlock(), and setParameters().

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

Definition at line 353 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::useBestMuonTrack_
private
bool PFAlgo::useEGammaSupercluster_
private

Definition at line 368 of file PFAlgo.h.

Referenced by setPFEleParameters().

bool PFAlgo::useEGElectrons_
private

Definition at line 367 of file PFAlgo.h.

Referenced by setEGElectronCollection(), and setPFEleParameters().

bool PFAlgo::useHO_
private

Definition at line 355 of file PFAlgo.h.

Referenced by processBlock(), and setHOTag().

bool PFAlgo::usePFConversions_
private

Definition at line 388 of file PFAlgo.h.

Referenced by processBlock(), and setDisplacedVerticesParameters().

bool PFAlgo::usePFDecays_
private

Definition at line 389 of file PFAlgo.h.

Referenced by isFromSecInt(), and setDisplacedVerticesParameters().

bool PFAlgo::usePFElectrons_
private

Definition at line 363 of file PFAlgo.h.

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

bool PFAlgo::usePFMuonMomAssign_
private

Definition at line 380 of file PFAlgo.h.

Referenced by reconstructTrack(), and setPFMuonAndFakeParameters().

bool PFAlgo::usePFNuclearInteractions_
private

Definition at line 387 of file PFAlgo.h.

Referenced by isFromSecInt(), and setDisplacedVerticesParameters().

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

Definition at line 366 of file PFAlgo.h.

Referenced by setPFEleParameters().

bool PFAlgo::useVertices_
private

Definition at line 421 of file PFAlgo.h.

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