CMS 3D CMS Logo

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

#include <PFAlgo.h>

Inheritance diagram for PFAlgo:
PFAlgoTestBenchConversions PFAlgoTestBenchElectrons

Public Member Functions

void checkCleaning (const reco::PFRecHitCollection &cleanedHF)
 Check HF Cleaning. More...
 
PFMuonAlgogetPFMuonAlgo ()
 
 PFAlgo ()
 constructor More...
 
const std::auto_ptr
< reco::PFCandidateCollection > & 
pfCandidates () const
 
void reconstructParticles (const reco::PFBlockHandle &blockHandle)
 
virtual void reconstructParticles (const reco::PFBlockCollection &blocks)
 reconstruct particles More...
 
void setAlgo (int algo)
 
void setCandConnectorParameters (const edm::ParameterSet &iCfgCandConnector)
 
void setCandConnectorParameters (bool bCorrect, bool bCalibPrimary, double dptRel_PrimaryTrack, double dptRel_MergedTrack, double ptErrorSecondary, 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 setMuonHandle (const edm::Handle< reco::MuonCollection > &)
 
void setParameters (double nSigmaECAL, double nSigmaHCAL, const boost::shared_ptr< PFEnergyCalibration > &calibration, const boost::shared_ptr< PFEnergyCalibrationHF > &thepfEnergyCalibrationHF)
 
void setPFEleParameters (double mvaEleCut, std::string mvaWeightFileEleID, bool usePFElectrons, const boost::shared_ptr< PFSCEnergyCalibration > &thePFSCEnergyCalibration, const boost::shared_ptr< PFEnergyCalibration > &thePFEnergyCalibration, double sumEtEcalIsoForEgammaSC_barrel, double sumEtEcalIsoForEgammaSC_endcap, double coneEcalIsoForEgammaSC, double sumPtTrackIsoForEgammaSC_barrel, double sumPtTrackIsoForEgammaSC_endcap, unsigned int nTrackIsoForEgammaSC, double coneTrackIsoForEgammaSC, bool applyCrackCorrections=false, bool usePFSCEleCalib=true, bool useEGElectrons=false, bool useEGammaSupercluster=true)
 
void setPFMuonAlgo (PFMuonAlgo *algo)
 
void setPFMuonAndFakeParameters (const edm::ParameterSet &pset)
 
void setPFPhotonParameters (bool usePFPhoton, std::string mvaWeightFileConvID, double mvaConvCut, bool useReg, std::string X0_Map, const boost::shared_ptr< PFEnergyCalibration > &thePFEnergyCalibration, double sumPtTrackIsoForPhoton, double sumPtTrackIsoSlopeForPhoton)
 
void setPFPhotonRegWeights (const GBRForest *LCorrForestEB, const GBRForest *LCorrForestEE, const GBRForest *GCorrForestBarrel, const GBRForest *GCorrForestEndcapHr9, const GBRForest *GCorrForestEndcapLr9, const GBRForest *PFEcalResolution)
 
void setPFVertexParameters (bool useVertex, const reco::VertexCollection *primaryVertices)
 
void setPhotonExtraRef (const edm::OrphanHandle< reco::PFCandidatePhotonExtraCollection > &pf_extrah)
 
void setPostHFCleaningParameters (bool postHFCleaning, double minHFCleaningPt, double minSignificance, double maxSignificance, double minSignificanceReduction, double maxDeltaPhiPt, double minDeltaMet)
 
boost::shared_ptr
< PFEnergyCalibration
thePFEnergyCalibration ()
 return the pointer to the calibration function More...
 
std::auto_ptr
< reco::PFCandidateCollection
transferCandidates ()
 
std::auto_ptr
< reco::PFCandidateCollection > & 
transferCleanedCandidates ()
 
std::auto_ptr
< reco::PFCandidateCollection
transferElectronCandidates ()
 
std::auto_ptr
< reco::PFCandidateElectronExtraCollection
transferElectronExtra ()
 
std::auto_ptr
< reco::PFCandidatePhotonExtraCollection
transferPhotonExtra ()
 
virtual ~PFAlgo ()
 destructor More...
 

Protected Member Functions

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

Protected Attributes

std::auto_ptr
< reco::PFCandidateCollection
pfCandidates_
 
std::auto_ptr
< reco::PFCandidateCollection
pfCleanedCandidates_
 
std::auto_ptr
< reco::PFCandidateCollection
pfElectronCandidates_
 the unfiltered electron collection More...
 
reco::PFCandidateElectronExtraCollection pfElectronExtra_
 the unfiltered electron collection More...
 
std::auto_ptr
< reco::PFCandidateCollection
pfPhotonCandidates_
 the unfiltered photon collection More...
 
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
 the extra photon collection More...
 

Private Member Functions

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

Private Attributes

int algo_
 
bool applyCrackCorrectionsElectrons_
 
reco::PFBlockHandle blockHandle_
 input block handle (full framework case) More...
 
boost::shared_ptr
< PFEnergyCalibration
calibration_
 
double coneEcalIsoForEgammaSC_
 
double coneTrackIsoForEgammaSC_
 
PFCandConnector connector_
 
bool debug_
 
double dptRel_DispVtx_
 
std::vector< double > factors45_
 
double maxDeltaPhiPt_
 
double maxSignificance_
 
double minDeltaMet_
 
double minHFCleaningPt_
 
double minSignificance_
 
double minSignificanceReduction_
 
std::vector< double > muonECAL_
 
edm::Handle< reco::MuonCollectionmuonHandle_
 
std::vector< double > muonHCAL_
 Variables for muons and fakes. More...
 
std::vector< double > muonHO_
 
double mvaEleCut_
 
std::string mvaWeightFileEleID_
 Variables for PFElectrons. More...
 
double nSigmaECAL_
 number of sigma to judge energy excess in ECAL More...
 
double nSigmaHCAL_
 number of sigma to judge energy excess in HCAL More...
 
double nSigmaTRACK_
 
unsigned int nTrackIsoForEgammaSC_
 
PFElectronAlgopfele_
 
PFMuonAlgopfmu_
 
PFPhotonAlgopfpho_
 
bool postHFCleaning_
 
bool postMuonCleaning_
 
reco::Vertex primaryVertex_
 
double ptError_
 
bool rejectTracks_Bad_
 
bool rejectTracks_Step45_
 
std::vector< double > setchi2Values_
 
double sumEtEcalIsoForEgammaSC_barrel_
 
double sumEtEcalIsoForEgammaSC_endcap_
 
double sumPtTrackIsoForEgammaSC_barrel_
 
double sumPtTrackIsoForEgammaSC_endcap_
 
boost::shared_ptr
< PFEnergyCalibrationHF
thepfEnergyCalibrationHF_
 
boost::shared_ptr
< PFSCEnergyCalibration
thePFSCEnergyCalibration_
 
double useBestMuonTrack_
 
bool 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 50 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:302
PFElectronAlgo * pfele_
Definition: PFAlgo.h:329
int algo_
Definition: PFAlgo.h:309
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:330
std::vector< reco::PFCandidate > PFCandidateCollection
collection of PFCandidates
bool useVertices_
Definition: PFAlgo.h:375
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:258
bool debug_
Definition: PFAlgo.h:310
double nSigmaECAL_
number of sigma to judge energy excess in ECAL
Definition: PFAlgo.h:299
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:329
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:330
bool usePFPhotons_
Definition: PFAlgo.h:317
bool usePFElectrons_
Definition: PFAlgo.h:316

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

3173  {
3174 
3175  // Find all PS clusters with type psElement associated to ECAL cluster iEcal,
3176  // within all PFBlockElement "elements" of a given PFBlock "block"
3177  // psElement can be reco::PFBlockElement::PS1 or reco::PFBlockElement::PS2
3178  // Returns a vector of PS cluster energies, and updates the "active" vector.
3179 
3180  // Find all PS clusters linked to the iEcal cluster
3181  std::multimap<double, unsigned> sortedPS;
3182  typedef std::multimap<double, unsigned>::iterator IE;
3183  block.associatedElements( iEcal, linkData,
3184  sortedPS, psElementType,
3186 
3187  // Loop over these PS clusters
3188  double totalPS = 0.;
3189  for ( IE ips=sortedPS.begin(); ips!=sortedPS.end(); ++ips ) {
3190 
3191  // CLuster index and distance to iEcal
3192  unsigned iPS = ips->second;
3193  // double distPS = ips->first;
3194 
3195  // Ignore clusters already in use
3196  if (!active[iPS]) continue;
3197 
3198  // Check that this cluster is not closer to another ECAL cluster
3199  std::multimap<double, unsigned> sortedECAL;
3200  block.associatedElements( iPS, linkData,
3201  sortedECAL,
3204  unsigned jEcal = sortedECAL.begin()->second;
3205  if ( jEcal != iEcal ) continue;
3206 
3207  // Update PS energy
3208  PFBlockElement::Type pstype = elements[ iPS ].type();
3209  assert( pstype == psElementType );
3210  PFClusterRef psclusterref = elements[iPS].clusterRef();
3211  assert(!psclusterref.isNull() );
3212  totalPS += psclusterref->energy();
3213  psEne[0] += psclusterref->energy();
3214  active[iPS] = false;
3215  }
3216 
3217 
3218 }
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 3365 of file PFAlgo.cc.

References gather_cfg::cout, debug_, reco::PFRecHit::energy(), i, j, reco::PFRecHit::layer(), minDeltaMet_, 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().

3365  {
3366 
3367 
3368  // No hits to recover, leave.
3369  if ( !cleanedHits.size() ) return;
3370 
3371  //Compute met and met significance (met/sqrt(SumEt))
3372  double metX = 0.;
3373  double metY = 0.;
3374  double sumet = 0;
3375  std::vector<unsigned int> hitsToBeAdded;
3376  for(unsigned i=0; i<pfCandidates_->size(); i++) {
3377  const PFCandidate& pfc = (*pfCandidates_)[i];
3378  metX += pfc.px();
3379  metY += pfc.py();
3380  sumet += pfc.pt();
3381  }
3382  double met2 = metX*metX+metY*metY;
3383  double met2_Original = met2;
3384  // Select events with large MET significance.
3385  // double significance = std::sqrt(met2/sumet);
3386  // double significanceCor = significance;
3387  double metXCor = metX;
3388  double metYCor = metY;
3389  double sumetCor = sumet;
3390  double met2Cor = met2;
3391  bool next = true;
3392  unsigned iCor = 1E9;
3393 
3394  // Find the cleaned hit with the largest effect on the MET
3395  while ( next ) {
3396 
3397  double metReduc = -1.;
3398  // Loop on the candidates
3399  for(unsigned i=0; i<cleanedHits.size(); ++i) {
3400  const PFRecHit& hit = cleanedHits[i];
3401  double length = std::sqrt(hit.position().Mag2());
3402  double px = hit.energy() * hit.position().x()/length;
3403  double py = hit.energy() * hit.position().y()/length;
3404  double pt = std::sqrt(px*px + py*py);
3405 
3406  // Check that it is not already scheculed to be cleaned
3407  bool skip = false;
3408  for(unsigned j=0; j<hitsToBeAdded.size(); ++j) {
3409  if ( i == hitsToBeAdded[j] ) skip = true;
3410  if ( skip ) break;
3411  }
3412  if ( skip ) continue;
3413 
3414  // Now add the candidate to the MET
3415  double metXInt = metX + px;
3416  double metYInt = metY + py;
3417  double sumetInt = sumet + pt;
3418  double met2Int = metXInt*metXInt+metYInt*metYInt;
3419 
3420  // And check if it could contribute to a MET reduction
3421  if ( met2Int < met2Cor ) {
3422  metXCor = metXInt;
3423  metYCor = metYInt;
3424  metReduc = (met2-met2Int)/met2Int;
3425  met2Cor = met2Int;
3426  sumetCor = sumetInt;
3427  // significanceCor = std::sqrt(met2Cor/sumetCor);
3428  iCor = i;
3429  }
3430  }
3431  //
3432  // If the MET must be significanly reduced, schedule the candidate to be added
3433  //
3434  if ( metReduc > minDeltaMet_ ) {
3435  hitsToBeAdded.push_back(iCor);
3436  metX = metXCor;
3437  metY = metYCor;
3438  sumet = sumetCor;
3439  met2 = met2Cor;
3440  } else {
3441  // Otherwise just stop the loop
3442  next = false;
3443  }
3444  }
3445  //
3446  // At least 10 GeV MET reduction
3447  if ( std::sqrt(met2_Original) - std::sqrt(met2) > 5. ) {
3448  if ( debug_ ) {
3449  std::cout << hitsToBeAdded.size() << " hits were re-added " << std::endl;
3450  std::cout << "MET reduction = " << std::sqrt(met2_Original) << " -> "
3451  << std::sqrt(met2Cor) << " = " << std::sqrt(met2Cor) - std::sqrt(met2_Original)
3452  << std::endl;
3453  std::cout << "Added after cleaning check : " << std::endl;
3454  }
3455  for(unsigned j=0; j<hitsToBeAdded.size(); ++j) {
3456  const PFRecHit& hit = cleanedHits[hitsToBeAdded[j]];
3457  PFCluster cluster(hit.layer(), hit.energy(),
3458  hit.position().x(), hit.position().y(), hit.position().z() );
3459  reconstructCluster(cluster,hit.energy());
3460  if ( debug_ ) {
3461  std::cout << pfCandidates_->back() << ". time = " << hit.time() << std::endl;
3462  }
3463  }
3464  }
3465 
3466 }
int i
Definition: DBlmapReader.cc:9
Particle flow cluster, see clustering algorithm in PFClusterAlgo.
Definition: PFCluster.h:42
double minDeltaMet_
Definition: PFAlgo.h:370
unsigned reconstructCluster(const reco::PFCluster &cluster, double particleEnergy, bool useDirection=false, double particleX=0., double particleY=0., double particleZ=0.)
Definition: PFAlgo.cc:2990
virtual double py() const GCC11_FINAL
y coordinate of momentum vector
PFLayer::Layer layer() const
rechit layer
Definition: PFRecHit.h:108
Particle flow rechit (rechit + geometry and topology information). See clustering algorithm in PFClus...
Definition: PFRecHit.h:31
T sqrt(T t)
Definition: SSEVec.h:48
virtual double px() const GCC11_FINAL
x coordinate of momentum vector
int j
Definition: DBlmapReader.cc:9
const math::XYZPoint & position() const
is seed ?
Definition: PFRecHit.h:141
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:35
double energy() const
rechit energy
Definition: PFRecHit.h:111
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:258
bool debug_
Definition: PFAlgo.h:310
tuple cout
Definition: gather_cfg.py:121
double time() const
timing for cleaned hits
Definition: PFRecHit.h:117
virtual float pt() const GCC11_FINAL
transverse momentum
reco::PFBlockRef PFAlgo::createBlockRef ( const reco::PFBlockCollection blocks,
unsigned  bi 
)
private

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

Definition at line 3155 of file PFAlgo.cc.

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

Referenced by reconstructParticles().

3156  {
3157 
3158  if( blockHandle_.isValid() ) {
3159  return reco::PFBlockRef( blockHandle_, bi );
3160  }
3161  else {
3162  return reco::PFBlockRef( &blocks, bi );
3163  }
3164 }
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:296
PFMuonAlgo * PFAlgo::getPFMuonAlgo ( )

Definition at line 89 of file PFAlgo.cc.

References pfmu_.

89  {
90  return pfmu_;
91 }
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:331
bool PFAlgo::isFromSecInt ( const reco::PFBlockElement eTrack,
std::string  order 
) const
protected

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

3222  {
3223 
3226  // reco::PFBlockElement::TrackType T_FROM_GAMMACONV = reco::PFBlockElement::T_FROM_GAMMACONV;
3228 
3229  bool bPrimary = (order.find("primary") != string::npos);
3230  bool bSecondary = (order.find("secondary") != string::npos);
3231  bool bAll = (order.find("all") != string::npos);
3232 
3233  bool isToDisp = usePFNuclearInteractions_ && eTrack.trackType(T_TO_DISP);
3234  bool isFromDisp = usePFNuclearInteractions_ && eTrack.trackType(T_FROM_DISP);
3235 
3236  if (bPrimary && isToDisp) return true;
3237  if (bSecondary && isFromDisp ) return true;
3238  if (bAll && ( isToDisp || isFromDisp ) ) return true;
3239 
3240 // bool isFromConv = usePFConversions_ && eTrack.trackType(T_FROM_GAMMACONV);
3241 
3242 // if ((bAll || bSecondary)&& isFromConv) return true;
3243 
3244  bool isFromDecay = (bAll || bSecondary) && usePFDecays_ && eTrack.trackType(T_FROM_V0);
3245 
3246  return isFromDecay;
3247 
3248 
3249 }
bool usePFNuclearInteractions_
Definition: PFAlgo.h:341
virtual bool trackType(TrackType trType) const
bool usePFDecays_
Definition: PFAlgo.h:343
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 3102 of file PFAlgo.cc.

References mathSSE::sqrt().

Referenced by processBlock().

3102  {
3103 
3104  // Add a protection
3105  if ( clusterEnergyHCAL < 1. ) clusterEnergyHCAL = 1.;
3106 
3107  double resol = fabs(eta) < 1.48 ?
3108  sqrt (1.02*1.02/clusterEnergyHCAL + 0.065*0.065)
3109  :
3110  sqrt (1.20*1.20/clusterEnergyHCAL + 0.028*0.028);
3111 
3112  return resol;
3113 
3114 }
T eta() const
T sqrt(T t)
Definition: SSEVec.h:48
double PFAlgo::nSigmaHCAL ( double  clusterEnergy,
double  clusterEta 
) const
protected

Definition at line 3117 of file PFAlgo.cc.

References create_public_lumi_plots::exp, and nSigmaHCAL_.

Referenced by processBlock(), and setParameters().

3117  {
3118  double nS = fabs(eta) < 1.48 ?
3119  nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL/100.))
3120  :
3121  nSigmaHCAL_ * (1. + exp(-clusterEnergyHCAL/100.));
3122 
3123  return nS;
3124 }
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
Definition: PFAlgo.h:302
T eta() const
const std::auto_ptr< reco::PFCandidateCollection >& PFAlgo::pfCandidates ( ) const
inline
Returns
collection of candidates

Definition at line 170 of file PFAlgo.h.

References pfCandidates_.

Referenced by operator<<().

170  {
171  return pfCandidates_;
172  }
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:258
void PFAlgo::postCleaning ( )
protected

Definition at line 3258 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_, reco::PFCandidate::particleId(), pfCandidates_, pfCleanedCandidates_, postHFCleaning_, reco::LeafCandidate::pt(), reco::LeafCandidate::px(), reco::LeafCandidate::py(), createPayload::skip, and mathSSE::sqrt().

Referenced by reconstructParticles().

3258  {
3259 
3260  // Check if the post HF Cleaning was requested - if not, do nothing
3261  if ( !postHFCleaning_ ) return;
3262 
3263  //Compute met and met significance (met/sqrt(SumEt))
3264  double metX = 0.;
3265  double metY = 0.;
3266  double sumet = 0;
3267  std::vector<unsigned int> pfCandidatesToBeRemoved;
3268  for(unsigned i=0; i<pfCandidates_->size(); i++) {
3269  const PFCandidate& pfc = (*pfCandidates_)[i];
3270  metX += pfc.px();
3271  metY += pfc.py();
3272  sumet += pfc.pt();
3273  }
3274  double met2 = metX*metX+metY*metY;
3275  // Select events with large MET significance.
3276  double significance = std::sqrt(met2/sumet);
3277  double significanceCor = significance;
3278  if ( significance > minSignificance_ ) {
3279 
3280  double metXCor = metX;
3281  double metYCor = metY;
3282  double sumetCor = sumet;
3283  double met2Cor = met2;
3284  double deltaPhi = 3.14159;
3285  double deltaPhiPt = 100.;
3286  bool next = true;
3287  unsigned iCor = 1E9;
3288 
3289  // Find the HF candidate with the largest effect on the MET
3290  while ( next ) {
3291 
3292  double metReduc = -1.;
3293  // Loop on the candidates
3294  for(unsigned i=0; i<pfCandidates_->size(); ++i) {
3295  const PFCandidate& pfc = (*pfCandidates_)[i];
3296 
3297  // Check that the pfCandidate is in the HF
3298  if ( pfc.particleId() != reco::PFCandidate::h_HF &&
3299  pfc.particleId() != reco::PFCandidate::egamma_HF ) continue;
3300 
3301  // Check if has meaningful pt
3302  if ( pfc.pt() < minHFCleaningPt_ ) continue;
3303 
3304  // Check that it is not already scheculed to be cleaned
3305  bool skip = false;
3306  for(unsigned j=0; j<pfCandidatesToBeRemoved.size(); ++j) {
3307  if ( i == pfCandidatesToBeRemoved[j] ) skip = true;
3308  if ( skip ) break;
3309  }
3310  if ( skip ) continue;
3311 
3312  // Check that the pt and the MET are aligned
3313  deltaPhi = std::acos((metX*pfc.px()+metY*pfc.py())/(pfc.pt()*std::sqrt(met2)));
3314  deltaPhiPt = deltaPhi*pfc.pt();
3315  if ( deltaPhiPt > maxDeltaPhiPt_ ) continue;
3316 
3317  // Now remove the candidate from the MET
3318  double metXInt = metX - pfc.px();
3319  double metYInt = metY - pfc.py();
3320  double sumetInt = sumet - pfc.pt();
3321  double met2Int = metXInt*metXInt+metYInt*metYInt;
3322  if ( met2Int < met2Cor ) {
3323  metXCor = metXInt;
3324  metYCor = metYInt;
3325  metReduc = (met2-met2Int)/met2Int;
3326  met2Cor = met2Int;
3327  sumetCor = sumetInt;
3328  significanceCor = std::sqrt(met2Cor/sumetCor);
3329  iCor = i;
3330  }
3331  }
3332  //
3333  // If the MET must be significanly reduced, schedule the candidate to be cleaned
3334  if ( metReduc > minDeltaMet_ ) {
3335  pfCandidatesToBeRemoved.push_back(iCor);
3336  metX = metXCor;
3337  metY = metYCor;
3338  sumet = sumetCor;
3339  met2 = met2Cor;
3340  } else {
3341  // Otherwise just stop the loop
3342  next = false;
3343  }
3344  }
3345  //
3346  // The significance must be significantly reduced to indeed clean the candidates
3347  if ( significance - significanceCor > minSignificanceReduction_ &&
3348  significanceCor < maxSignificance_ ) {
3349  std::cout << "Significance reduction = " << significance << " -> "
3350  << significanceCor << " = " << significanceCor - significance
3351  << std::endl;
3352  for(unsigned j=0; j<pfCandidatesToBeRemoved.size(); ++j) {
3353  std::cout << "Removed : " << (*pfCandidates_)[pfCandidatesToBeRemoved[j]] << std::endl;
3354  pfCleanedCandidates_->push_back( (*pfCandidates_)[ pfCandidatesToBeRemoved[j] ] );
3355  (*pfCandidates_)[pfCandidatesToBeRemoved[j]].rescaleMomentum(1E-6);
3356  //reco::PFCandidate::ParticleType unknown = reco::PFCandidate::X;
3357  //(*pfCandidates_)[pfCandidatesToBeRemoved[j]].setParticleType(unknown);
3358  }
3359  }
3360  }
3361 
3362 }
int i
Definition: DBlmapReader.cc:9
double maxDeltaPhiPt_
Definition: PFAlgo.h:369
double maxSignificance_
Definition: PFAlgo.h:367
double minHFCleaningPt_
Definition: PFAlgo.h:365
double minDeltaMet_
Definition: PFAlgo.h:370
double minSignificance_
Definition: PFAlgo.h:366
std::auto_ptr< reco::PFCandidateCollection > pfCleanedCandidates_
Definition: PFAlgo.h:264
virtual double py() const GCC11_FINAL
y coordinate of momentum vector
double minSignificanceReduction_
Definition: PFAlgo.h:368
bool postHFCleaning_
Definition: PFAlgo.h:363
T sqrt(T t)
Definition: SSEVec.h:48
virtual double px() const GCC11_FINAL
x coordinate of momentum vector
int j
Definition: DBlmapReader.cc:9
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:35
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:258
tuple cout
Definition: gather_cfg.py:121
virtual ParticleType particleId() const
Definition: PFCandidate.h:347
virtual float pt() const GCC11_FINAL
transverse momentum
void PFAlgo::processBlock ( const reco::PFBlockRef blockref,
std::list< reco::PFBlockRef > &  hcalBlockRefs,
std::list< reco::PFBlockRef > &  ecalBlockRefs 
)
protectedvirtual

process one block. can be reimplemented in more sophisticated algorithms

Reimplemented in PFAlgoTestBenchConversions, and PFAlgoTestBenchElectrons.

Definition at line 466 of file PFAlgo.cc.

References a, abs, associatePSClusters(), b, edm::OwnVector< T, P >::begin(), Association::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, cuy::ii, getHLTprescales::index, PFElectronAlgo::isElectronValidCandidate(), isFromSecInt(), 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_, reco::btau::neutralEnergy, neutralHadronEnergyResolution(), nSigmaECAL_, nSigmaHCAL(), nSigmaTRACK_, convertSQLiteXML::ok, AlCaHLTBitMon_ParallelJobs::p, pfCandidates_, pfele_, pfElectronCandidates_, pfElectronExtra_, pfpho_, pfPhotonCandidates_, pfPhotonExtra_, primaryVertex_, 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, useHO_, usePFConversions_, usePFElectrons_, usePFPhotons_, x, X, and Gflash::Z.

Referenced by reconstructParticles().

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

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

Referenced by checkCleaning(), and processBlock().

2995  {
2996 
2998 
2999  // need to convert the math::XYZPoint data member of the PFCluster class=
3000  // to a displacement vector:
3001 
3002  // Transform particleX,Y,Z to a position at ECAL/HCAL entrance
3003  double factor = 1.;
3004  if ( useDirection ) {
3005  switch( cluster.layer() ) {
3006  case PFLayer::ECAL_BARREL:
3007  case PFLayer::HCAL_BARREL1:
3008  factor = std::sqrt(cluster.position().Perp2()/(particleX*particleX+particleY*particleY));
3009  break;
3010  case PFLayer::ECAL_ENDCAP:
3011  case PFLayer::HCAL_ENDCAP:
3012  case PFLayer::HF_HAD:
3013  case PFLayer::HF_EM:
3014  factor = cluster.position().Z()/particleZ;
3015  break;
3016  default:
3017  assert(0);
3018  }
3019  }
3020  //MIKE First of all let's check if we have vertex.
3021  math::XYZPoint vertexPos;
3022  if(useVertices_)
3024  else
3025  vertexPos = math::XYZPoint(0.0,0.0,0.0);
3026 
3027 
3028  math::XYZVector clusterPos( cluster.position().X()-vertexPos.X(),
3029  cluster.position().Y()-vertexPos.Y(),
3030  cluster.position().Z()-vertexPos.Z());
3031  math::XYZVector particleDirection ( particleX*factor-vertexPos.X(),
3032  particleY*factor-vertexPos.Y(),
3033  particleZ*factor-vertexPos.Z() );
3034 
3035  //math::XYZVector clusterPos( cluster.position().X(), cluster.position().Y(),cluster.position().Z() );
3036  //math::XYZVector particleDirection ( particleX, particleY, particleZ );
3037 
3038  clusterPos = useDirection ? particleDirection.Unit() : clusterPos.Unit();
3039  clusterPos *= particleEnergy;
3040 
3041  // clusterPos is now a vector along the cluster direction,
3042  // with a magnitude equal to the cluster energy.
3043 
3044  double mass = 0;
3045  ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double> >
3046  momentum( clusterPos.X(), clusterPos.Y(), clusterPos.Z(), mass);
3047  // mathcore is a piece of #$%
3049  // implicit constructor not allowed
3050  tmp = momentum;
3051 
3052  // Charge
3053  int charge = 0;
3054 
3055  // Type
3056  switch( cluster.layer() ) {
3057  case PFLayer::ECAL_BARREL:
3058  case PFLayer::ECAL_ENDCAP:
3059  particleType = PFCandidate::gamma;
3060  break;
3061  case PFLayer::HCAL_BARREL1:
3062  case PFLayer::HCAL_ENDCAP:
3063  particleType = PFCandidate::h0;
3064  break;
3065  case PFLayer::HF_HAD:
3066  particleType = PFCandidate::h_HF;
3067  break;
3068  case PFLayer::HF_EM:
3069  particleType = PFCandidate::egamma_HF;
3070  break;
3071  default:
3072  assert(0);
3073  }
3074 
3075  // The pf candidate
3076  pfCandidates_->push_back( PFCandidate( charge,
3077  tmp,
3078  particleType ) );
3079 
3080  // The position at ECAL entrance (well: watch out, it is not true
3081  // for HCAL clusters... to be fixed)
3082  pfCandidates_->back().
3083  setPositionAtECALEntrance(math::XYZPointF(cluster.position().X(),
3084  cluster.position().Y(),
3085  cluster.position().Z()));
3086 
3087  //Set the cnadidate Vertex
3088  pfCandidates_->back().setVertex(vertexPos);
3089 
3090  if(debug_)
3091  cout<<"** candidate: "<<pfCandidates_->back()<<endl;
3092 
3093  // returns index to the newly created PFCandidate
3094  return pfCandidates_->size()-1;
3095 
3096 }
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:40
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:48
double z() const
y coordinate
Definition: Vertex.h:99
reco::Vertex primaryVertex_
Definition: PFAlgo.h:374
double x() const
x coordinate
Definition: Vertex.h:95
bool useVertices_
Definition: PFAlgo.h:375
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:35
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:258
bool debug_
Definition: PFAlgo.h:310
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 343 of file PFAlgo.cc.

References blockHandle_.

Referenced by PFRootEventManager::particleFlow().

343  {
344 
345  blockHandle_ = blockHandle;
347 }
void reconstructParticles(const reco::PFBlockHandle &blockHandle)
Definition: PFAlgo.cc:343
reco::PFBlockHandle blockHandle_
input block handle (full framework case)
Definition: PFAlgo.h:296
void PFAlgo::reconstructParticles ( const reco::PFBlockCollection blocks)
virtual

reconstruct particles

Definition at line 351 of file PFAlgo.cc.

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

351  {
352 
353  // reset output collection
354  if(pfCandidates_.get() )
355  pfCandidates_->clear();
356  else
358 
359  if(pfElectronCandidates_.get() )
360  pfElectronCandidates_->clear();
361  else
363 
364  // Clearing pfPhotonCandidates
365  if( pfPhotonCandidates_.get() )
366  pfPhotonCandidates_->clear();
367  else
369 
370  if(pfCleanedCandidates_.get() )
371  pfCleanedCandidates_->clear();
372  else
374 
375  // not a auto_ptr; shout not be deleted after transfer
376  pfElectronExtra_.clear();
377  pfPhotonExtra_.clear();
378 
379  if( debug_ ) {
380  cout<<"*********************************************************"<<endl;
381  cout<<"***** Particle flow algorithm *****"<<endl;
382  cout<<"*********************************************************"<<endl;
383  }
384 
385  // sort elements in three lists:
386  std::list< reco::PFBlockRef > hcalBlockRefs;
387  std::list< reco::PFBlockRef > ecalBlockRefs;
388  std::list< reco::PFBlockRef > hoBlockRefs;
389  std::list< reco::PFBlockRef > otherBlockRefs;
390 
391  for( unsigned i=0; i<blocks.size(); ++i ) {
392  // reco::PFBlockRef blockref( blockh,i );
393  reco::PFBlockRef blockref = createBlockRef( blocks, i);
394 
395  const reco::PFBlock& block = *blockref;
397  elements = block.elements();
398 
399  bool singleEcalOrHcal = false;
400  if( elements.size() == 1 ){
401  if( elements[0].type() == reco::PFBlockElement::ECAL ){
402  ecalBlockRefs.push_back( blockref );
403  singleEcalOrHcal = true;
404  }
405  if( elements[0].type() == reco::PFBlockElement::HCAL ){
406  hcalBlockRefs.push_back( blockref );
407  singleEcalOrHcal = true;
408  }
409  if( elements[0].type() == reco::PFBlockElement::HO ){
410  // Single HO elements are likely to be noise. Not considered for now.
411  hoBlockRefs.push_back( blockref );
412  singleEcalOrHcal = true;
413  }
414  }
415 
416  if(!singleEcalOrHcal) {
417  otherBlockRefs.push_back( blockref );
418  }
419  }//loop blocks
420 
421  if( debug_ ){
422  cout<<"# Ecal blocks: "<<ecalBlockRefs.size()
423  <<", # Hcal blocks: "<<hcalBlockRefs.size()
424  <<", # HO blocks: "<<hoBlockRefs.size()
425  <<", # Other blocks: "<<otherBlockRefs.size()<<endl;
426  }
427 
428 
429  // loop on blocks that are not single ecal,
430  // and not single hcal.
431 
432  unsigned nblcks = 0;
433  for( IBR io = otherBlockRefs.begin(); io!=otherBlockRefs.end(); ++io) {
434  if ( debug_ ) std::cout << "Block number " << nblcks++ << std::endl;
435  processBlock( *io, hcalBlockRefs, ecalBlockRefs );
436  }
437 
438  std::list< reco::PFBlockRef > empty;
439 
440  unsigned hblcks = 0;
441  // process remaining single hcal blocks
442  for( IBR ih = hcalBlockRefs.begin(); ih!=hcalBlockRefs.end(); ++ih) {
443  if ( debug_ ) std::cout << "HCAL block number " << hblcks++ << std::endl;
444  processBlock( *ih, empty, empty );
445  }
446 
447  unsigned eblcks = 0;
448  // process remaining single ecal blocks
449  for( IBR ie = ecalBlockRefs.begin(); ie!=ecalBlockRefs.end(); ++ie) {
450  if ( debug_ ) std::cout << "ECAL block number " << eblcks++ << std::endl;
451  processBlock( *ie, empty, empty );
452  }
453 
454  // Post HF Cleaning
455  postCleaning();
456 
457  //Muon post cleaning
458  pfmu_->postClean(pfCandidates_.get());
459 
460  //Add Missing muons
461  if( muonHandle_.isValid())
463 }
type
Definition: HCALResponse.h:21
int i
Definition: DBlmapReader.cc:9
void addMissingMuons(edm::Handle< reco::MuonCollection >, reco::PFCandidateCollection *cands)
Definition: PFMuonAlgo.cc:948
std::auto_ptr< reco::PFCandidateCollection > pfPhotonCandidates_
the unfiltered photon collection
Definition: PFAlgo.h:262
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:466
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:264
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:331
edm::Handle< reco::MuonCollection > muonHandle_
Definition: PFAlgo.h:377
bool isValid() const
Definition: HandleBase.h:76
block
Formating index page&#39;s pieces.
Definition: Association.py:232
reco::PFBlockRef createBlockRef(const reco::PFBlockCollection &blocks, unsigned bi)
Definition: PFAlgo.cc:3155
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
Definition: PFAlgo.h:269
std::vector< reco::PFCandidate > PFCandidateCollection
collection of PFCandidates
list blocks
Definition: gather_cfg.py:90
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:258
bool debug_
Definition: PFAlgo.h:310
tuple cout
Definition: gather_cfg.py:121
std::list< reco::PFBlockRef >::iterator IBR
std::auto_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
Definition: PFAlgo.h:260
void postCleaning()
Definition: PFAlgo.cc:3258
void postClean(reco::PFCandidateCollection *)
Definition: PFMuonAlgo.cc:846
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
Definition: PFAlgo.h:267
Block of elements.
Definition: PFBlock.h:30
unsigned PFAlgo::reconstructTrack ( const reco::PFBlockElement elt,
bool  allowLoose = false 
)
protected

Reconstruct a charged particle from a track Returns the index of the newly created candidate in pfCandidates_ Michalis added a flag here to treat muons inside jets

Definition at line 2916 of file PFAlgo.cc.

References DeDxDiscriminatorTools::charge(), reco::TrackBase::charge(), gather_cfg::cout, debug_, reco::PFBlockElementTrack::displacedVertexRef(), dptRel_DispVtx_, relval_parameters_module::energy, reco::PFCandidate::h, isFromSecInt(), reco::isMuon(), edm::Ref< C, T, F >::isNonnull(), reco::PFBlockElementTrack::muonRef(), reco::TrackBase::p(), pfCandidates_, pfmu_, reco::PFBlockElementTrack::positionAtECALEntrance(), reco::TrackBase::px(), reco::TrackBase::py(), reco::TrackBase::pz(), PFMuonAlgo::reconstructMuon(), mathSSE::sqrt(), reco::PFBlockElement::T_FROM_DISP, reco::PFCandidate::T_FROM_DISP, reco::PFBlockElement::T_TO_DISP, reco::PFCandidate::T_TO_DISP, and reco::PFBlockElementTrack::trackRef().

Referenced by processBlock().

2916  {
2917 
2918  const reco::PFBlockElementTrack* eltTrack
2919  = dynamic_cast<const reco::PFBlockElementTrack*>(&elt);
2920 
2921  reco::TrackRef trackRef = eltTrack->trackRef();
2922  const reco::Track& track = *trackRef;
2923  reco::MuonRef muonRef = eltTrack->muonRef();
2924  int charge = track.charge()>0 ? 1 : -1;
2925 
2926  // Assume this particle is a charged Hadron
2927  double px = track.px();
2928  double py = track.py();
2929  double pz = track.pz();
2930  double energy = sqrt(track.p()*track.p() + 0.13957*0.13957);
2931 
2932  // Create a PF Candidate
2933  math::XYZTLorentzVector momentum(px,py,pz,energy);
2934  reco::PFCandidate::ParticleType particleType
2936 
2937  // Add it to the stack
2938  pfCandidates_->push_back( PFCandidate( charge,
2939  momentum,
2940  particleType ) );
2941  //Set vertex and stuff like this
2942  pfCandidates_->back().setVertexSource( PFCandidate::kTrkVertex );
2943  pfCandidates_->back().setTrackRef( trackRef );
2944  pfCandidates_->back().setPositionAtECALEntrance( eltTrack->positionAtECALEntrance());
2945  if( muonRef.isNonnull())
2946  pfCandidates_->back().setMuonRef( muonRef );
2947 
2948 
2949 
2950  //OK Now try to reconstruct the particle as a muon
2951  bool isMuon=pfmu_->reconstructMuon(pfCandidates_->back(),muonRef,allowLoose);
2952  bool isFromDisp = isFromSecInt(elt, "secondary");
2953 
2954 
2955  if ((!isMuon) && isFromDisp) {
2956  double Dpt = trackRef->ptError();
2957  double dptRel = Dpt/trackRef->pt()*100;
2958  //If the track is ill measured it is better to not refit it, since the track information probably would not be used.
2959  //In the PFAlgo we use the trackref information. If the track error is too big the refitted information might be very different
2960  // from the not refitted one.
2961  if (dptRel < dptRel_DispVtx_){
2962  if (debug_)
2963  cout << "Not refitted px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
2964  //reco::TrackRef trackRef = eltTrack->trackRef();
2966  reco::Track trackRefit = vRef->refittedTrack(trackRef);
2967  //change the momentum with the refitted track
2968  math::XYZTLorentzVector momentum(trackRefit.px(),
2969  trackRefit.py(),
2970  trackRefit.pz(),
2971  sqrt(trackRefit.p()*trackRefit.p() + 0.13957*0.13957));
2972  if (debug_)
2973  cout << "Refitted px = " << px << " py = " << py << " pz = " << pz << " energy = " << energy << endl;
2974  }
2975  pfCandidates_->back().setFlag( reco::PFCandidate::T_FROM_DISP, true);
2976  pfCandidates_->back().setDisplacedVertexRef( eltTrack->displacedVertexRef(reco::PFBlockElement::T_FROM_DISP)->displacedVertexRef(), reco::PFCandidate::T_FROM_DISP);
2977  }
2978 
2979  // 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
2980  if(isFromSecInt(elt, "primary") && !isMuon) {
2981  pfCandidates_->back().setFlag( reco::PFCandidate::T_TO_DISP, true);
2982  pfCandidates_->back().setDisplacedVertexRef( eltTrack->displacedVertexRef(reco::PFBlockElement::T_TO_DISP)->displacedVertexRef(), reco::PFCandidate::T_TO_DISP);
2983  }
2984  // returns index to the newly created PFCandidate
2985  return pfCandidates_->size()-1;
2986 }
double p() const
momentum vector magnitude
Definition: TrackBase.h:129
bool isFromSecInt(const reco::PFBlockElement &eTrack, std::string order) const
Definition: PFAlgo.cc:3222
ParticleType
particle types
Definition: PFCandidate.h:40
bool isMuon(const Candidate &part)
Definition: pdgIdUtils.h:11
double px() const
x coordinate of momentum vector
Definition: TrackBase.h:133
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:331
double charge(const std::vector< uint8_t > &Ampls)
const math::XYZPointF & positionAtECALEntrance() const
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:30
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:250
reco::MuonRef muonRef() const
T sqrt(T t)
Definition: SSEVec.h:48
double pz() const
z coordinate of momentum vector
Definition: TrackBase.h:137
double dptRel_DispVtx_
Definition: PFAlgo.h:347
reco::TrackRef trackRef() const
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:35
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:258
bool debug_
Definition: PFAlgo.h:310
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
bool reconstructMuon(reco::PFCandidate &, const reco::MuonRef &, bool allowLoose=false)
Definition: PFMuonAlgo.cc:685
PFDisplacedTrackerVertexRef displacedVertexRef(TrackType trType) const
void PFAlgo::setAlgo ( int  algo)
inline

Definition at line 61 of file PFAlgo.h.

References algo_.

Referenced by PFRootEventManager::readOptions().

61 {algo_ = algo;}
int algo_
Definition: PFAlgo.h:309
void PFAlgo::setCandConnectorParameters ( const edm::ParameterSet iCfgCandConnector)
inline

Definition at line 71 of file PFAlgo.h.

References connector_, and PFCandConnector::setParameters().

Referenced by PFRootEventManager::readOptions().

71  {
72  connector_.setParameters(iCfgCandConnector);
73  }
PFCandConnector connector_
Definition: PFAlgo.h:352
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 75 of file PFAlgo.h.

References connector_, and PFCandConnector::setParameters().

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

Definition at line 64 of file PFAlgo.h.

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

Referenced by PFRootEventManager::readOptions().

PFCandConnector connector_
Definition: PFAlgo.h:352
bool debug_
Definition: PFAlgo.h:310
#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 282 of file PFAlgo.cc.

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

Referenced by PFRootEventManager::readOptions().

287  {
288 
289  rejectTracks_Bad_ = rejectTracks_Bad;
290  rejectTracks_Step45_ = rejectTracks_Step45;
291  usePFNuclearInteractions_ = usePFNuclearInteractions;
292  usePFConversions_ = usePFConversions;
293  usePFDecays_ = usePFDecays;
294  dptRel_DispVtx_ = dptRel_DispVtx;
295 
296 }
bool usePFConversions_
Definition: PFAlgo.h:342
bool rejectTracks_Step45_
Definition: PFAlgo.h:339
bool usePFNuclearInteractions_
Definition: PFAlgo.h:341
double dptRel_DispVtx_
Definition: PFAlgo.h:347
bool rejectTracks_Bad_
Definition: PFAlgo.h:338
bool usePFDecays_
Definition: PFAlgo.h:343
void PFAlgo::setEGElectronCollection ( const reco::GsfElectronCollection egelectrons)

Definition at line 3253 of file PFAlgo.cc.

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

Referenced by PFRootEventManager::particleFlow().

3253  {
3255 }
PFElectronAlgo * pfele_
Definition: PFAlgo.h:329
bool useEGElectrons_
Definition: PFAlgo.h:320
void setEGElectronCollection(const reco::GsfElectronCollection &egelectrons)
void PFAlgo::setElectronExtraRef ( const edm::OrphanHandle< reco::PFCandidateElectronExtraCollection > &  extrah)

Definition at line 3470 of file PFAlgo.cc.

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

Referenced by PFRootEventManager::particleFlow().

3470  {
3471  if(!usePFElectrons_) return;
3472  // std::cout << " setElectronExtraRef " << std::endl;
3473  unsigned size=pfCandidates_->size();
3474 
3475  for(unsigned ic=0;ic<size;++ic) {
3476  // select the electrons and add the extra
3477  if((*pfCandidates_)[ic].particleId()==PFCandidate::e) {
3478 
3479  PFElectronExtraEqual myExtraEqual((*pfCandidates_)[ic].gsfTrackRef());
3480  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
3481  if(it!=pfElectronExtra_.end()) {
3482  // std::cout << " Index " << it-pfElectronExtra_.begin() << std::endl;
3483  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
3484  (*pfCandidates_)[ic].setPFElectronExtraRef(theRef);
3485  }
3486  else {
3487  (*pfCandidates_)[ic].setPFElectronExtraRef(PFCandidateElectronExtraRef());
3488  }
3489  }
3490  else // else save the mva and the extra as well !
3491  {
3492  if((*pfCandidates_)[ic].trackRef().isNonnull()) {
3493  PFElectronExtraKfEqual myExtraEqual((*pfCandidates_)[ic].trackRef());
3494  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
3495  if(it!=pfElectronExtra_.end()) {
3496  (*pfCandidates_)[ic].set_mva_e_pi(it->mvaVariable(PFCandidateElectronExtra::MVA_MVA));
3497  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
3498  (*pfCandidates_)[ic].setPFElectronExtraRef(theRef);
3499  (*pfCandidates_)[ic].setGsfTrackRef(it->gsfTrackRef());
3500  }
3501  }
3502  }
3503 
3504  }
3505 
3506  size=pfElectronCandidates_->size();
3507  for(unsigned ic=0;ic<size;++ic) {
3508  // select the electrons - this test is actually not needed for this collection
3509  if((*pfElectronCandidates_)[ic].particleId()==PFCandidate::e) {
3510  // find the corresponding extra
3511  PFElectronExtraEqual myExtraEqual((*pfElectronCandidates_)[ic].gsfTrackRef());
3512  std::vector<PFCandidateElectronExtra>::const_iterator it=find_if(pfElectronExtra_.begin(),pfElectronExtra_.end(),myExtraEqual);
3513  if(it!=pfElectronExtra_.end()) {
3514  reco::PFCandidateElectronExtraRef theRef(extrah,it-pfElectronExtra_.begin());
3515  (*pfElectronCandidates_)[ic].setPFElectronExtraRef(theRef);
3516 
3517  }
3518  }
3519  }
3520 
3521 }
edm::Ref< PFCandidateElectronExtraCollection > PFCandidateElectronExtraRef
persistent reference to a PFCandidateElectronExtra
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:258
std::auto_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
Definition: PFAlgo.h:260
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
Definition: PFAlgo.h:267
tuple size
Write out results.
bool usePFElectrons_
Definition: PFAlgo.h:316
void PFAlgo::setHOTag ( bool  ho)
inline

Definition at line 60 of file PFAlgo.h.

References useHO_.

Referenced by PFRootEventManager::readOptions().

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

Definition at line 259 of file PFAlgo.cc.

References muonHandle_, and patZpeak::muons.

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

Definition at line 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:302
double nSigmaHCAL(double clusterEnergy, double clusterEta) const
Definition: PFAlgo.cc:3117
boost::shared_ptr< PFEnergyCalibration > calibration_
Definition: PFAlgo.h:304
boost::shared_ptr< PFEnergyCalibrationHF > thepfEnergyCalibrationHF_
Definition: PFAlgo.h:305
double nSigmaECAL_
number of sigma to judge energy excess in ECAL
Definition: PFAlgo.h:299
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 95 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().

110  {
111 
112  mvaEleCut_ = mvaEleCut;
113  usePFElectrons_ = usePFElectrons;
114  applyCrackCorrectionsElectrons_ = applyCrackCorrections;
115  usePFSCEleCalib_ = usePFSCEleCalib;
116  thePFSCEnergyCalibration_ = thePFSCEnergyCalibration;
117  useEGElectrons_ = useEGElectrons;
118  useEGammaSupercluster_ = useEGammaSupercluster;
119  sumEtEcalIsoForEgammaSC_barrel_ = sumEtEcalIsoForEgammaSC_barrel;
120  sumEtEcalIsoForEgammaSC_endcap_ = sumEtEcalIsoForEgammaSC_endcap;
121  coneEcalIsoForEgammaSC_ = coneEcalIsoForEgammaSC;
122  sumPtTrackIsoForEgammaSC_barrel_ = sumPtTrackIsoForEgammaSC_barrel;
123  sumPtTrackIsoForEgammaSC_endcap_ = sumPtTrackIsoForEgammaSC_endcap;
124  coneTrackIsoForEgammaSC_ = coneTrackIsoForEgammaSC;
125  nTrackIsoForEgammaSC_ = nTrackIsoForEgammaSC;
126 
127 
128  if(!usePFElectrons_) return;
129  mvaWeightFileEleID_ = mvaWeightFileEleID;
130  FILE * fileEleID = fopen(mvaWeightFileEleID_.c_str(), "r");
131  if (fileEleID) {
132  fclose(fileEleID);
133  }
134  else {
135  string err = "PFAlgo: cannot open weight file '";
136  err += mvaWeightFileEleID;
137  err += "'";
138  throw invalid_argument( err );
139  }
154 }
unsigned int nTrackIsoForEgammaSC_
Definition: PFAlgo.h:328
double sumEtEcalIsoForEgammaSC_endcap_
Definition: PFAlgo.h:323
double mvaEleCut_
Definition: PFAlgo.h:315
double coneEcalIsoForEgammaSC_
Definition: PFAlgo.h:324
double coneTrackIsoForEgammaSC_
Definition: PFAlgo.h:327
double sumEtEcalIsoForEgammaSC_barrel_
Definition: PFAlgo.h:322
PFElectronAlgo * pfele_
Definition: PFAlgo.h:329
bool useEGammaSupercluster_
Definition: PFAlgo.h:321
boost::shared_ptr< PFEnergyCalibration > thePFEnergyCalibration()
return the pointer to the calibration function
Definition: PFAlgo.h:208
bool useEGElectrons_
Definition: PFAlgo.h:320
std::string mvaWeightFileEleID_
Variables for PFElectrons.
Definition: PFAlgo.h:313
bool usePFSCEleCalib_
Definition: PFAlgo.h:319
boost::shared_ptr< PFSCEnergyCalibration > thePFSCEnergyCalibration_
Definition: PFAlgo.h:306
bool applyCrackCorrectionsElectrons_
Definition: PFAlgo.h:318
double sumPtTrackIsoForEgammaSC_endcap_
Definition: PFAlgo.h:326
double sumPtTrackIsoForEgammaSC_barrel_
Definition: PFAlgo.h:325
bool usePFElectrons_
Definition: PFAlgo.h:316
void PFAlgo::setPFMuonAlgo ( PFMuonAlgo algo)
inline

Definition at line 62 of file PFAlgo.h.

References pfmu_.

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

Definition at line 230 of file PFAlgo.cc.

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

Referenced by PFRootEventManager::readOptions().

237 {
238 
239 
240 
241 
242  pfmu_ = new PFMuonAlgo();
243  pfmu_->setParameters(pset);
244 
245  // Muon parameters
246  muonHCAL_= pset.getParameter<std::vector<double> >("muon_HCAL");
247  muonECAL_= pset.getParameter<std::vector<double> >("muon_ECAL");
248  muonHO_= pset.getParameter<std::vector<double> >("muon_HO");
249  assert ( muonHCAL_.size() == 2 && muonECAL_.size() == 2 && muonHO_.size() == 2);
250  nSigmaTRACK_= pset.getParameter<double>("nsigma_TRACK");
251  ptError_= pset.getParameter<double>("pt_Error");
252  factors45_ = pset.getParameter<std::vector<double> >("factors_45");
253  assert ( factors45_.size() == 2 );
254 
255 }
T getParameter(std::string const &) const
double ptError_
Definition: PFAlgo.h:359
std::vector< double > muonHCAL_
Variables for muons and fakes.
Definition: PFAlgo.h:355
void setParameters(const edm::ParameterSet &)
Definition: PFMuonAlgo.cc:29
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:331
std::vector< double > factors45_
Definition: PFAlgo.h:360
std::vector< double > muonECAL_
Definition: PFAlgo.h:356
std::vector< double > muonHO_
Definition: PFAlgo.h:357
double nSigmaTRACK_
Definition: PFAlgo.h:358
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 157 of file PFAlgo.cc.

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

Referenced by PFRootEventManager::readOptions().

165  {
166 
167  usePFPhotons_ = usePFPhotons;
168 
169  //for MVA pass PV if there is one in the collection otherwise pass a dummy
170  reco::Vertex dummy;
171  if(useVertices_)
172  {
173  dummy = primaryVertex_;
174  }
175  else { // create a dummy PV
177  e(0, 0) = 0.0015 * 0.0015;
178  e(1, 1) = 0.0015 * 0.0015;
179  e(2, 2) = 15. * 15.;
180  reco::Vertex::Point p(0, 0, 0);
181  dummy = reco::Vertex(p, e, 0, 0, 0);
182  }
183  // pv=&dummy;
184  if(! usePFPhotons_) return;
185  FILE * filePhotonConvID = fopen(mvaWeightFileConvID.c_str(), "r");
186  if (filePhotonConvID) {
187  fclose(filePhotonConvID);
188  }
189  else {
190  string err = "PFAlgo: cannot open weight file '";
191  err += mvaWeightFileConvID;
192  err += "'";
193  throw invalid_argument( err );
194  }
195  const reco::Vertex* pv=&dummy;
196  pfpho_ = new PFPhotonAlgo(mvaWeightFileConvID,
197  mvaConvCut,
198  useReg,
199  X0_Map,
200  *pv,
202  sumPtTrackIsoForPhoton,
203  sumPtTrackIsoSlopeForPhoton
204  );
205  return;
206 }
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:208
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:330
reco::Vertex primaryVertex_
Definition: PFAlgo.h:374
math::XYZPoint Point
point in the space
Definition: Vertex.h:40
bool useVertices_
Definition: PFAlgo.h:375
bool usePFPhotons_
Definition: PFAlgo.h:317
void PFAlgo::setPFPhotonRegWeights ( const GBRForest LCorrForestEB,
const GBRForest LCorrForestEE,
const GBRForest GCorrForestBarrel,
const GBRForest GCorrForestEndcapHr9,
const GBRForest GCorrForestEndcapLr9,
const GBRForest PFEcalResolution 
)

Definition at line 217 of file PFAlgo.cc.

References pfpho_, and PFPhotonAlgo::setGBRForest().

Referenced by PFRootEventManager::readOptions().

223  {
224 
225  pfpho_->setGBRForest(LCorrForestEB,LCorrForestEE,
226  GCorrForestBarrel, GCorrForestEndcapHr9,
227  GCorrForestEndcapLr9, PFEcalResolution);
228 }
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:330
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 300 of file PFAlgo.cc.

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

Referenced by PFRootEventManager::particleFlow().

301  {
302  useVertices_ = useVertex;
303 
304  //Set the vertices for muon cleaning
305  pfmu_->setInputsForCleaning(primaryVertices);
306 
307 
308  //Now find the primary vertex!
309  bool primaryVertexFound = false;
310  int nVtx=primaryVertices->size();
311  if(usePFPhotons_){
312  pfpho_->setnPU(nVtx);
313  }
314  for (unsigned short i=0 ;i<primaryVertices->size();++i)
315  {
316  if(primaryVertices->at(i).isValid()&&(!primaryVertices->at(i).isFake()))
317  {
318  primaryVertex_ = primaryVertices->at(i);
319  primaryVertexFound = true;
320  break;
321  }
322  }
323  //Use vertices if the user wants to but only if it exists a good vertex
324  useVertices_ = useVertex && primaryVertexFound;
325  if(usePFPhotons_) {
326  if (useVertices_ ){
328  }
329  else{
331  e(0, 0) = 0.0015 * 0.0015;
332  e(1, 1) = 0.0015 * 0.0015;
333  e(2, 2) = 15. * 15.;
334  reco::Vertex::Point p(0, 0, 0);
335  reco::Vertex dummy = reco::Vertex(p, e, 0, 0, 0);
336  // std::cout << " PFPho " << pfpho_ << std::endl;
337  pfpho_->setPhotonPrimaryVtx(dummy);
338  }
339  }
340 }
int i
Definition: DBlmapReader.cc:9
void setnPU(int nVtx)
Definition: PFPhotonAlgo.h:75
math::Error< dimension >::type Error
covariance error matrix (3x3)
Definition: Vertex.h:44
PFMuonAlgo * pfmu_
Definition: PFAlgo.h:331
PFPhotonAlgo * pfpho_
Definition: PFAlgo.h:330
reco::Vertex primaryVertex_
Definition: PFAlgo.h:374
math::XYZPoint Point
point in the space
Definition: Vertex.h:40
bool useVertices_
Definition: PFAlgo.h:375
void setPhotonPrimaryVtx(const reco::Vertex &primary)
Definition: PFPhotonAlgo.h:78
bool usePFPhotons_
Definition: PFAlgo.h:317
void setInputsForCleaning(const reco::VertexCollection *)
Definition: PFMuonAlgo.cc:1163
void PFAlgo::setPhotonExtraRef ( const edm::OrphanHandle< reco::PFCandidatePhotonExtraCollection > &  pf_extrah)

Definition at line 3522 of file PFAlgo.cc.

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

3522  {
3523  if(!usePFPhotons_) return;
3524  unsigned int size=pfCandidates_->size();
3525  unsigned int sizePhExtra = pfPhotonExtra_.size();
3526  for(unsigned ic=0;ic<size;++ic) {
3527  // select the electrons and add the extra
3528  if((*pfCandidates_)[ic].particleId()==PFCandidate::gamma && (*pfCandidates_)[ic].mva_nothing_gamma() > 0.99) {
3529  if((*pfCandidates_)[ic].superClusterRef().isNonnull()) {
3530  bool found = false;
3531  for(unsigned pcextra=0;pcextra<sizePhExtra;++pcextra) {
3532  if((*pfCandidates_)[ic].superClusterRef() == pfPhotonExtra_[pcextra].superClusterRef()) {
3533  reco::PFCandidatePhotonExtraRef theRef(ph_extrah,pcextra);
3534  (*pfCandidates_)[ic].setPFPhotonExtraRef(theRef);
3535  found = true;
3536  break;
3537  }
3538  }
3539  if(!found)
3540  (*pfCandidates_)[ic].setPFPhotonExtraRef((PFCandidatePhotonExtraRef())); // null ref
3541  }
3542  else {
3543  (*pfCandidates_)[ic].setPFPhotonExtraRef((PFCandidatePhotonExtraRef())); // null ref
3544  }
3545  }
3546  }
3547 }
edm::Ref< PFCandidatePhotonExtraCollection > PFCandidatePhotonExtraRef
persistent reference to a PFCandidatePhotonExtra
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
Definition: PFAlgo.h:269
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:258
bool usePFPhotons_
Definition: PFAlgo.h:317
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 265 of file PFAlgo.cc.

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

Referenced by PFRootEventManager::readOptions().

271  {
272  postHFCleaning_ = postHFCleaning;
273  minHFCleaningPt_ = minHFCleaningPt;
274  minSignificance_ = minSignificance;
275  maxSignificance_ = maxSignificance;
276  minSignificanceReduction_= minSignificanceReduction;
277  maxDeltaPhiPt_ = maxDeltaPhiPt;
278  minDeltaMet_ = minDeltaMet;
279 }
double maxDeltaPhiPt_
Definition: PFAlgo.h:369
double maxSignificance_
Definition: PFAlgo.h:367
double minHFCleaningPt_
Definition: PFAlgo.h:365
double minDeltaMet_
Definition: PFAlgo.h:370
double minSignificance_
Definition: PFAlgo.h:366
double minSignificanceReduction_
Definition: PFAlgo.h:368
bool postHFCleaning_
Definition: PFAlgo.h:363
boost::shared_ptr<PFEnergyCalibration> PFAlgo::thePFEnergyCalibration ( )
inline

return the pointer to the calibration function

Definition at line 208 of file PFAlgo.h.

References calibration_.

208  {
209  return calibration_;
210  }
boost::shared_ptr< PFEnergyCalibration > calibration_
Definition: PFAlgo.h:304
std::auto_ptr< reco::PFCandidateCollection > PFAlgo::transferCandidates ( )
inline
Returns
auto_ptr to the collection of candidates (transfers ownership)

Definition at line 203 of file PFAlgo.h.

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

Referenced by PFRootEventManager::particleFlow().

203  {
205  }
std::auto_ptr< reco::PFCandidateCollection > connect(std::auto_ptr< reco::PFCandidateCollection > &pfCand)
PFCandConnector connector_
Definition: PFAlgo.h:352
std::auto_ptr< reco::PFCandidateCollection > pfCandidates_
Definition: PFAlgo.h:258
std::auto_ptr< reco::PFCandidateCollection >& PFAlgo::transferCleanedCandidates ( )
inline
Returns
collection of cleaned HF candidates

Definition at line 198 of file PFAlgo.h.

References pfCleanedCandidates_.

198  {
199  return pfCleanedCandidates_;
200  }
std::auto_ptr< reco::PFCandidateCollection > pfCleanedCandidates_
Definition: PFAlgo.h:264
std::auto_ptr< reco::PFCandidateCollection> PFAlgo::transferElectronCandidates ( )
inline
Returns
the unfiltered electron collection

Definition at line 175 of file PFAlgo.h.

References pfElectronCandidates_.

175  {
176  return pfElectronCandidates_;
177  }
std::auto_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
Definition: PFAlgo.h:260
std::auto_ptr< reco::PFCandidateElectronExtraCollection> PFAlgo::transferElectronExtra ( )
inline
Returns
the unfiltered electron extra collection

Definition at line 181 of file PFAlgo.h.

References pfElectronExtra_, and query::result.

Referenced by PFRootEventManager::particleFlow().

181  {
182  std::auto_ptr< reco::PFCandidateElectronExtraCollection> result(new reco::PFCandidateElectronExtraCollection);
183  result->insert(result->end(),pfElectronExtra_.begin(),pfElectronExtra_.end());
184  return result;
185  }
tuple result
Definition: query.py:137
std::vector< reco::PFCandidateElectronExtra > PFCandidateElectronExtraCollection
collection of PFCandidateElectronExtras
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
Definition: PFAlgo.h:267
std::auto_ptr< reco::PFCandidatePhotonExtraCollection> PFAlgo::transferPhotonExtra ( )
inline
Returns
the unfiltered photon extra collection

Definition at line 190 of file PFAlgo.h.

References pfPhotonExtra_, and query::result.

190  {
191  std::auto_ptr< reco::PFCandidatePhotonExtraCollection> result(new reco::PFCandidatePhotonExtraCollection);
192  result->insert(result->end(),pfPhotonExtra_.begin(),pfPhotonExtra_.end());
193  return result;
194  }
tuple result
Definition: query.py:137
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
Definition: PFAlgo.h:269
std::vector< reco::PFCandidatePhotonExtra > PFCandidatePhotonExtraCollection
collection of PFCandidatePhotonExtras

Friends And Related Function Documentation

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

Member Data Documentation

int PFAlgo::algo_
private

Definition at line 309 of file PFAlgo.h.

Referenced by setAlgo().

bool PFAlgo::applyCrackCorrectionsElectrons_
private

Definition at line 318 of file PFAlgo.h.

Referenced by setPFEleParameters().

reco::PFBlockHandle PFAlgo::blockHandle_
private

input block handle (full framework case)

Definition at line 296 of file PFAlgo.h.

Referenced by createBlockRef(), and reconstructParticles().

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

Definition at line 304 of file PFAlgo.h.

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

double PFAlgo::coneEcalIsoForEgammaSC_
private

Definition at line 324 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::coneTrackIsoForEgammaSC_
private

Definition at line 327 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 352 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 347 of file PFAlgo.h.

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

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

Definition at line 360 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

double PFAlgo::maxDeltaPhiPt_
private

Definition at line 369 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::maxSignificance_
private

Definition at line 367 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minDeltaMet_
private

Definition at line 370 of file PFAlgo.h.

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

double PFAlgo::minHFCleaningPt_
private

Definition at line 365 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minSignificance_
private

Definition at line 366 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

double PFAlgo::minSignificanceReduction_
private

Definition at line 368 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

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

Definition at line 356 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

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

Definition at line 377 of file PFAlgo.h.

Referenced by reconstructParticles(), and setMuonHandle().

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

Variables for muons and fakes.

Definition at line 355 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

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

Definition at line 357 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

double PFAlgo::mvaEleCut_
private

Definition at line 315 of file PFAlgo.h.

Referenced by setPFEleParameters().

std::string PFAlgo::mvaWeightFileEleID_
private

Variables for PFElectrons.

Definition at line 313 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::nSigmaECAL_
private

number of sigma to judge energy excess in ECAL

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

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

double PFAlgo::nSigmaTRACK_
private

Definition at line 358 of file PFAlgo.h.

Referenced by processBlock(), and setPFMuonAndFakeParameters().

unsigned int PFAlgo::nTrackIsoForEgammaSC_
private

Definition at line 328 of file PFAlgo.h.

Referenced by setPFEleParameters().

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

Definition at line 264 of file PFAlgo.h.

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

PFElectronAlgo* PFAlgo::pfele_
private

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

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

reco::PFCandidateElectronExtraCollection PFAlgo::pfElectronExtra_
protected

the unfiltered electron collection

Definition at line 267 of file PFAlgo.h.

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

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

the unfiltered photon collection

Definition at line 262 of file PFAlgo.h.

Referenced by processBlock(), and reconstructParticles().

reco::PFCandidatePhotonExtraCollection PFAlgo::pfPhotonExtra_
protected

the extra photon collection

Definition at line 269 of file PFAlgo.h.

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

bool PFAlgo::postHFCleaning_
private

Definition at line 363 of file PFAlgo.h.

Referenced by postCleaning(), and setPostHFCleaningParameters().

bool PFAlgo::postMuonCleaning_
private

Definition at line 364 of file PFAlgo.h.

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

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

Referenced by processBlock(), and setDisplacedVerticesParameters().

bool PFAlgo::rejectTracks_Step45_
private

Definition at line 339 of file PFAlgo.h.

Referenced by processBlock(), and setDisplacedVerticesParameters().

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

Definition at line 314 of file PFAlgo.h.

double PFAlgo::sumEtEcalIsoForEgammaSC_barrel_
private

Definition at line 322 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumEtEcalIsoForEgammaSC_endcap_
private

Definition at line 323 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumPtTrackIsoForEgammaSC_barrel_
private

Definition at line 325 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::sumPtTrackIsoForEgammaSC_endcap_
private

Definition at line 326 of file PFAlgo.h.

Referenced by setPFEleParameters().

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

Definition at line 305 of file PFAlgo.h.

Referenced by processBlock(), and setParameters().

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

Definition at line 306 of file PFAlgo.h.

Referenced by setPFEleParameters().

double PFAlgo::useBestMuonTrack_
private

Definition at line 371 of file PFAlgo.h.

bool PFAlgo::useEGammaSupercluster_
private

Definition at line 321 of file PFAlgo.h.

Referenced by setPFEleParameters().

bool PFAlgo::useEGElectrons_
private

Definition at line 320 of file PFAlgo.h.

Referenced by setEGElectronCollection(), and setPFEleParameters().

bool PFAlgo::useHO_
private

Definition at line 308 of file PFAlgo.h.

Referenced by processBlock(), and setHOTag().

bool PFAlgo::usePFConversions_
private

Definition at line 342 of file PFAlgo.h.

Referenced by processBlock(), and setDisplacedVerticesParameters().

bool PFAlgo::usePFDecays_
private

Definition at line 343 of file PFAlgo.h.

Referenced by isFromSecInt(), and setDisplacedVerticesParameters().

bool PFAlgo::usePFElectrons_
private

Definition at line 316 of file PFAlgo.h.

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

bool PFAlgo::usePFMuonMomAssign_
private

Definition at line 334 of file PFAlgo.h.

bool PFAlgo::usePFNuclearInteractions_
private

Definition at line 341 of file PFAlgo.h.

Referenced by isFromSecInt(), and setDisplacedVerticesParameters().

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

Definition at line 319 of file PFAlgo.h.

Referenced by setPFEleParameters().

bool PFAlgo::useVertices_
private

Definition at line 375 of file PFAlgo.h.

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