CMS 3D CMS Logo

List of all members | Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes
PFCandConnector Class Reference

Based on a class from : V. Roberfroid, February 2008. More...

#include <PFCandConnector.h>

Public Member Functions

reco::PFCandidateCollection connect (reco::PFCandidateCollection &pfCand) const
 
 PFCandConnector ()
 
void setParameters (const edm::ParameterSet &iCfgCandConnector)
 
void setParameters (bool bCorrect, bool bCalibPrimary, double dptRel_PrimaryTrack, double dptRel_MergedTrack, double ptErrorSecondary, const std::vector< double > &nuclCalibFactors)
 

Static Public Member Functions

static void fillPSetDescription (edm::ParameterSetDescription &iDesc)
 

Private Member Functions

void analyseNuclearWPrim (reco::PFCandidateCollection &, std::vector< bool > &, unsigned int) const
 Analyse nuclear interactions where a primary or merged track is present. More...
 
void analyseNuclearWSec (reco::PFCandidateCollection &, std::vector< bool > &, unsigned int) const
 Analyse nuclear interactions where a secondary track is present. More...
 
bool isPrimaryNucl (const reco::PFCandidate &pf) const
 
bool isSecondaryNucl (const reco::PFCandidate &pf) const
 
double rescaleFactor (const double pt, const double cFrac) const
 Return a calibration factor for a reconstructed nuclear interaction. More...
 

Private Attributes

bool bCalibPrimary_
 Calibration parameters for the reconstructed nuclear interactions. More...
 
bool bCorrect_
 Parameters. More...
 
double dptRel_MergedTrack_
 
double dptRel_PrimaryTrack_
 
std::vector< double > fConst_
 
std::vector< double > fExp_
 
std::vector< double > fNorm_
 
double ptErrorSecondary_
 

Static Private Attributes

static const reco::PFCandidate::Flags fT_FROM_DISP_ = PFCandidate::T_FROM_DISP
 
static const reco::PFCandidate::Flags fT_TO_DISP_ = PFCandidate::T_TO_DISP
 
static const double pion_mass2 = 0.0194
 Useful constants. More...
 

Detailed Description

Based on a class from : V. Roberfroid, February 2008.

Definition at line 15 of file PFCandConnector.h.

Constructor & Destructor Documentation

◆ PFCandConnector()

PFCandConnector::PFCandConnector ( )
inline

Definition at line 17 of file PFCandConnector.h.

References bCalibPrimary_, bCorrect_, dptRel_MergedTrack_, dptRel_PrimaryTrack_, fConst_, fExp_, fNorm_, and ptErrorSecondary_.

17  {
18  bCorrect_ = false;
19  bCalibPrimary_ = false;
20 
21  fConst_.push_back(1), fConst_.push_back(0);
22  fNorm_.push_back(0), fNorm_.push_back(0);
23  fExp_.push_back(0);
24 
27  ptErrorSecondary_ = 0.;
28  }
std::vector< double > fExp_
double ptErrorSecondary_
std::vector< double > fNorm_
std::vector< double > fConst_
double dptRel_PrimaryTrack_
bool bCalibPrimary_
Calibration parameters for the reconstructed nuclear interactions.
bool bCorrect_
Parameters.
double dptRel_MergedTrack_

Member Function Documentation

◆ analyseNuclearWPrim()

void PFCandConnector::analyseNuclearWPrim ( reco::PFCandidateCollection pfCand,
std::vector< bool > &  bMask,
unsigned int  ce1 
) const
private

Analyse nuclear interactions where a primary or merged track is present.

Definition at line 148 of file PFCandConnector.cc.

References reco::PFCandidate::displacedVertexRef(), MillePedeFileConverter_cfg::e, reco::PFCandidate::ecalEnergy(), dqmdumpme::first, reco::PFCandidate::hcalEnergy(), edm::Ref< C, T, F >::isNonnull(), LogTrace, reco::HitPattern::MISSING_OUTER_HITS, reco::LeafCandidate::p4(), multPhiCorr_741_25nsDY_cfi::px, multPhiCorr_741_25nsDY_cfi::py, edm::second(), and mathSSE::sqrt().

150  {
151  PFDisplacedVertexRef ref1, ref2, ref1_bis;
152 
153  PFCandidate primaryCand = pfCand.at(ce1);
154 
155  // ------- look for the little friends -------- //
156 
157  const math::XYZTLorentzVectorD& momentumPrim = primaryCand.p4();
158 
159  math::XYZTLorentzVectorD momentumSec(0., 0., 0., 0.);
160 
161  if (momentumPrim.E() > 0)
162  momentumSec = momentumPrim / momentumPrim.E() * (primaryCand.ecalEnergy() + primaryCand.hcalEnergy());
163 
164  map<double, math::XYZTLorentzVectorD> candidatesWithTrackExcess;
165  map<double, math::XYZTLorentzVectorD> candidatesWithoutCalo;
166 
167  ref1 = primaryCand.displacedVertexRef(fT_TO_DISP_);
168 
169  for (unsigned int ce2 = 0; ce2 < pfCand.size(); ++ce2) {
170  if (ce2 != ce1 && isSecondaryNucl(pfCand.at(ce2))) {
171  ref2 = (pfCand.at(ce2)).displacedVertexRef(fT_FROM_DISP_);
172 
173  if (ref1 == ref2) {
174  LogTrace("PFCandConnector|analyseNuclearWPrim")
175  << "\t here is a Secondary Candidate " << ce2 << " " << pfCand.at(ce2) << endl
176  << "\t based on the Track " << pfCand.at(ce2).trackRef().key()
177  << " w p = " << pfCand.at(ce2).trackRef()->p() << " w pT = " << pfCand.at(ce2).trackRef()->pt() << " #pm "
178  << pfCand.at(ce2).trackRef()->ptError() << " %"
179  << " ECAL = " << pfCand.at(ce2).ecalEnergy() << " HCAL = " << pfCand.at(ce2).hcalEnergy()
180  << " dE(Trk-CALO) = "
181  << pfCand.at(ce2).trackRef()->p() - pfCand.at(ce2).ecalEnergy() - pfCand.at(ce2).hcalEnergy()
182  << " Nmissing hits = "
183  << pfCand.at(ce2).trackRef()->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS) << endl;
184 
185  if (isPrimaryNucl(pfCand.at(ce2))) {
186  LogTrace("PFCandConnector|analyseNuclearWPrim") << "\t\t but it is also a Primary Candidate " << ce2 << endl;
187 
188  ref1_bis = (pfCand.at(ce2)).displacedVertexRef(fT_TO_DISP_);
189  if (ref1_bis.isNonnull())
190  analyseNuclearWPrim(pfCand, bMask, ce2);
191  }
192 
193  // Take now the parameters of the secondary track that are relevant and use them to construct the NI candidate
194 
195  PFCandidate::ElementsInBlocks elementsInBlocks = pfCand.at(ce2).elementsInBlocks();
196  PFCandidate::ElementsInBlocks elementsAlreadyInBlocks = pfCand.at(ce1).elementsInBlocks();
197  for (unsigned blockElem = 0; blockElem < elementsInBlocks.size(); blockElem++) {
198  bool isAlreadyHere = false;
199  for (unsigned alreadyBlock = 0; alreadyBlock < elementsAlreadyInBlocks.size(); alreadyBlock++) {
200  if (elementsAlreadyInBlocks[alreadyBlock].second == elementsInBlocks[blockElem].second)
201  isAlreadyHere = true;
202  }
203  if (!isAlreadyHere)
204  pfCand.at(ce1).addElementInBlock(elementsInBlocks[blockElem].first, elementsInBlocks[blockElem].second);
205  }
206 
207  double candE = pfCand.at(ce2).p4().E();
208  double caloEn = pfCand.at(ce2).ecalEnergy() + pfCand.at(ce2).hcalEnergy();
209  double deltaEn = candE - caloEn;
210  int nMissOuterHits =
211  pfCand.at(ce2).trackRef()->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS);
212 
213  // Check if the difference Track Calo is not too large and if we can trust the track, ie it doesn't miss too much hits.
214  if (deltaEn > 1 && nMissOuterHits > 1 && candE > 0) {
215  math::XYZTLorentzVectorD momentumToAdd = pfCand.at(ce2).p4() * caloEn / candE;
216  momentumSec += momentumToAdd;
217  LogTrace("PFCandConnector|analyseNuclearWPrim")
218  << "The difference track-calo s really large and the track miss at least 2 hits. A secondary NI may "
219  "have happened. Let's trust the calo energy"
220  << endl
221  << "add " << momentumToAdd << endl;
222 
223  } else {
224  // Check if the difference Track Calo is not too large and if we can trust the track, ie it doesn't miss too much hits.
225  if (caloEn > 0.01 && deltaEn > 1 && nMissOuterHits > 0 && candE > 0) {
226  math::XYZTLorentzVectorD momentumExcess = pfCand.at(ce2).p4() * deltaEn / candE;
227  candidatesWithTrackExcess[pfCand.at(ce2).trackRef()->pt() / pfCand.at(ce2).trackRef()->ptError()] =
228  momentumExcess;
229  } else if (caloEn < 0.01)
230  candidatesWithoutCalo[pfCand.at(ce2).trackRef()->pt() / pfCand.at(ce2).trackRef()->ptError()] =
231  pfCand.at(ce2).p4();
232  momentumSec += (pfCand.at(ce2)).p4();
233  }
234 
235  bMask[ce2] = true;
236  }
237  }
238  }
239 
240  // We have more primary energy than secondary: reject all secondary tracks which have no calo energy attached.
241 
242  if (momentumPrim.E() < momentumSec.E()) {
243  LogTrace("PFCandConnector|analyseNuclearWPrim")
244  << "Size of 0 calo Energy secondary candidates" << candidatesWithoutCalo.size() << endl;
245  for (map<double, math::XYZTLorentzVectorD>::iterator iter = candidatesWithoutCalo.begin();
246  iter != candidatesWithoutCalo.end() && momentumPrim.E() < momentumSec.E();
247  iter++)
248  if (momentumSec.E() > iter->second.E() + 0.1) {
249  momentumSec -= iter->second;
250 
251  LogTrace("PFCandConnector|analyseNuclearWPrim")
252  << "\t Remove a SecondaryCandidate with 0 calo energy " << iter->second << endl;
253  LogTrace("PFCandConnector|analyseNuclearWPrim")
254  << "momentumPrim.E() = " << momentumPrim.E() << " and momentumSec.E() = " << momentumSec.E() << endl;
255  }
256  }
257 
258  if (momentumPrim.E() < momentumSec.E()) {
259  LogTrace("PFCandConnector|analyseNuclearWPrim")
260  << "0 Calo Energy rejected but still not sufficient. Size of not enough calo Energy secondary candidates"
261  << candidatesWithTrackExcess.size() << endl;
262  for (map<double, math::XYZTLorentzVectorD>::iterator iter = candidatesWithTrackExcess.begin();
263  iter != candidatesWithTrackExcess.end() && momentumPrim.E() < momentumSec.E();
264  iter++)
265  if (momentumSec.E() > iter->second.E() + 0.1)
266  momentumSec -= iter->second;
267  }
268 
269  double dpt = pfCand.at(ce1).trackRef()->ptError() / pfCand.at(ce1).trackRef()->pt() * 100;
270 
271  if (momentumSec.E() < 0.1) {
272  bMask[ce1] = true;
273  return;
274  }
275 
276  // Rescale the secondary candidates to account for the loss of energy, but only if we can trust the primary track:
277  // if it has more energy than secondaries and is precise enough and secondary exist and was not eaten or rejected during the PFAlgo step.
278 
279  if (((ref1->isTherePrimaryTracks() && dpt < dptRel_PrimaryTrack_) ||
280  (ref1->isThereMergedTracks() && dpt < dptRel_MergedTrack_)) &&
281  momentumPrim.E() > momentumSec.E() && momentumSec.E() > 0.1) {
282  if (bCalibPrimary_) {
283  double factor = momentumPrim.E() > 0 ? rescaleFactor(momentumPrim.Pt(), momentumSec.E() / momentumPrim.E()) : 1.;
284  LogTrace("PFCandConnector|analyseNuclearWPrim") << "factor = " << factor << endl;
285  if (factor * momentumPrim.Pt() < momentumSec.Pt())
286  momentumSec = momentumPrim;
287  else
288  momentumSec += (1 - factor) * momentumPrim;
289  }
290 
291  double px = 0, py = 0, pz = 0.;
292  if (momentumPrim.P() > 0) {
293  px = momentumPrim.Px() * momentumSec.P() / momentumPrim.P();
294  py = momentumPrim.Py() * momentumSec.P() / momentumPrim.P();
295  pz = momentumPrim.Pz() * momentumSec.P() / momentumPrim.P();
296  }
297  double E = sqrt(px * px + py * py + pz * pz + pion_mass2);
298  math::XYZTLorentzVectorD momentum(px, py, pz, E);
299  pfCand.at(ce1).setP4(momentum);
300 
301  return;
302 
303  } else {
304  math::XYZVector primDir = ref1->primaryDirection();
305 
306  if (primDir.Mag2() < 0.1) {
307  // It might be 0 but this situation should never happend. Throw a warning if it happens.
308  edm::LogWarning("PFCandConnector") << "A Nuclear Interaction do not have primary direction" << std::endl;
309  pfCand.at(ce1).setP4(momentumSec);
310  return;
311  } else {
312  // rescale the primary direction to the optimal momentum. But take care of the factthat it shall not be completly 0 to avoid a warning if Jet Area.
313  double momentumS = momentumSec.P();
314  if (momentumS < 1e-4)
315  momentumS = 1e-4;
316  double px = momentumS * primDir.x();
317  double py = momentumS * primDir.y();
318  double pz = momentumS * primDir.z();
319  double E = sqrt(px * px + py * py + pz * pz + pion_mass2);
320 
321  math::XYZTLorentzVectorD momentum(px, py, pz, E);
322  pfCand.at(ce1).setP4(momentum);
323  return;
324  }
325  }
326 }
reco::PFDisplacedVertexRef displacedVertexRef(Flags type) const
Definition: PFCandidate.cc:510
bool isPrimaryNucl(const reco::PFCandidate &pf) const
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzE4D< double > > XYZTLorentzVectorD
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:14
static const reco::PFCandidate::Flags fT_FROM_DISP_
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:238
static const reco::PFCandidate::Flags fT_TO_DISP_
const LorentzVector & p4() const final
four-momentum Lorentz vector
#define LogTrace(id)
std::vector< ElementInBlock > ElementsInBlocks
Definition: PFCandidate.h:404
U second(std::pair< T, U > const &p)
void analyseNuclearWPrim(reco::PFCandidateCollection &, std::vector< bool > &, unsigned int) const
Analyse nuclear interactions where a primary or merged track is present.
double hcalEnergy() const
return corrected Hcal energy
Definition: PFCandidate.h:233
T sqrt(T t)
Definition: SSEVec.h:23
static const double pion_mass2
Useful constants.
double ecalEnergy() const
return corrected Ecal energy
Definition: PFCandidate.h:221
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:31
bool bCalibPrimary_
Calibration parameters for the reconstructed nuclear interactions.
double dptRel_PrimaryTrack_
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:41
bool isSecondaryNucl(const reco::PFCandidate &pf) const
Log< level::Warning, false > LogWarning
double dptRel_MergedTrack_
double rescaleFactor(const double pt, const double cFrac) const
Return a calibration factor for a reconstructed nuclear interaction.

◆ analyseNuclearWSec()

void PFCandConnector::analyseNuclearWSec ( reco::PFCandidateCollection pfCand,
std::vector< bool > &  bMask,
unsigned int  ce1 
) const
private

Analyse nuclear interactions where a secondary track is present.

Definition at line 328 of file PFCandConnector.cc.

References MillePedeFileConverter_cfg::e, reco::PFCandidate::e, dqmdumpme::first, ALPAKA_ACCELERATOR_NAMESPACE::vertexFinder::it, LogTrace, reco::HitPattern::MISSING_OUTER_HITS, reco::PFCandidate::mu, reco::LeafCandidate::p4(), reco::TrackBase::pt(), multPhiCorr_741_25nsDY_cfi::px, multPhiCorr_741_25nsDY_cfi::py, tkAlTrackRefitSequence_cff::refittedTracks, edm::second(), and mathSSE::sqrt().

330  {
331  PFDisplacedVertexRef ref1, ref2;
332 
333  // Check if the track excess was not too large and track may miss some outer hits. This may point to a secondary NI.
334 
335  double caloEn = pfCand.at(ce1).ecalEnergy() + pfCand.at(ce1).hcalEnergy();
336  double deltaEn = pfCand.at(ce1).p4().E() - caloEn;
337  int nMissOuterHits = pfCand.at(ce1).trackRef()->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS);
338 
339  ref1 = pfCand.at(ce1).displacedVertexRef(fT_FROM_DISP_);
340 
341  // ------- check if an electron or a muon vas spotted as incoming track -------- //
342  // ------- this mean probably that the NI was fake thus we do not correct it -------- /
343 
344  if (ref1->isTherePrimaryTracks() || ref1->isThereMergedTracks()) {
345  std::vector<reco::Track> refittedTracks = ref1->refittedTracks();
346  for (unsigned it = 0; it < refittedTracks.size(); it++) {
347  reco::TrackBaseRef primaryBaseRef = ref1->originalTrack(refittedTracks[it]);
348  if (ref1->isIncomingTrack(primaryBaseRef))
349  LogTrace("PFCandConnector|analyseNuclearWSec")
350  << "There is a Primary track ref with pt = " << primaryBaseRef->pt() << endl;
351 
352  for (unsigned int ce = 0; ce < pfCand.size(); ++ce) {
353  // cout << "PFCand Id = " << (pfCand.at(ce)).particleId() << endl;
354  if ((pfCand.at(ce)).particleId() == reco::PFCandidate::e ||
355  (pfCand.at(ce)).particleId() == reco::PFCandidate::mu) {
356  LogTrace("PFCandConnector|analyseNuclearWSec")
357  << " It is an electron and it has a ref to a track " << (pfCand.at(ce)).trackRef().isNonnull() << endl;
358 
359  if ((pfCand.at(ce)).trackRef().isNonnull()) {
360  reco::TrackRef tRef = (pfCand.at(ce)).trackRef();
361  reco::TrackBaseRef bRef(tRef);
362  LogTrace("PFCandConnector|analyseNuclearWSec")
363  << "With Track Ref pt = " << (pfCand.at(ce)).trackRef()->pt() << endl;
364 
365  if (bRef == primaryBaseRef) {
366  if ((pfCand.at(ce)).particleId() == reco::PFCandidate::e)
367  LogTrace("PFCandConnector|analyseNuclearWSec")
368  << "It is a NI from electron. NI Discarded. Just release the candidate." << endl;
369  if ((pfCand.at(ce)).particleId() == reco::PFCandidate::mu)
370  LogTrace("PFCandConnector|analyseNuclearWSec")
371  << "It is a NI from muon. NI Discarded. Just release the candidate" << endl;
372 
373  // release the track but take care of not overcounting bad tracks. In fact those tracks was protected against destruction in
374  // PFAlgo. Now we treat them as if they was treated in PFAlgo
375 
376  if (caloEn < 0.1 && pfCand.at(ce1).trackRef()->ptError() > ptErrorSecondary_) {
377  edm::LogInfo("PFCandConnector|analyseNuclearWSec")
378  << "discarded track since no calo energy and ill measured" << endl;
379  bMask[ce1] = true;
380  }
381  if (caloEn > 0.1 && deltaEn > ptErrorSecondary_ &&
382  pfCand.at(ce1).trackRef()->ptError() > ptErrorSecondary_) {
383  edm::LogInfo("PFCandConnector|analyseNuclearWSec")
384  << "rescaled momentum of the track since no calo energy and ill measured" << endl;
385 
386  double factor = caloEn / pfCand.at(ce1).p4().E();
387  pfCand.at(ce1).rescaleMomentum(factor);
388  }
389 
390  return;
391  }
392  }
393  }
394  }
395  }
396  }
397 
398  PFCandidate secondaryCand = pfCand.at(ce1);
399 
400  math::XYZTLorentzVectorD momentumSec = secondaryCand.p4();
401 
402  if (deltaEn > ptErrorSecondary_ && nMissOuterHits > 1) {
403  math::XYZTLorentzVectorD momentumToAdd(0., 0., 0., 0.);
404  float candE = pfCand.at(ce1).p4().E();
405  if (candE > 0)
406  momentumToAdd = pfCand.at(ce1).p4() * caloEn / candE;
407  momentumSec = momentumToAdd;
408  LogTrace("PFCandConnector|analyseNuclearWSec")
409  << "The difference track-calo s really large and the track miss at least 2 hits. A secondary NI may have "
410  "happened. Let's trust the calo energy"
411  << endl
412  << "add " << momentumToAdd << endl;
413  }
414 
415  // ------- look for the little friends -------- //
416  for (unsigned int ce2 = ce1 + 1; ce2 < pfCand.size(); ++ce2) {
417  if (isSecondaryNucl(pfCand.at(ce2))) {
418  ref2 = (pfCand.at(ce2)).displacedVertexRef(fT_FROM_DISP_);
419 
420  if (ref1 == ref2) {
421  LogTrace("PFCandConnector|analyseNuclearWSec")
422  << "\t here is a Secondary Candidate " << ce2 << " " << pfCand.at(ce2) << endl
423  << "\t based on the Track " << pfCand.at(ce2).trackRef().key()
424  << " w pT = " << pfCand.at(ce2).trackRef()->pt() << " #pm " << pfCand.at(ce2).trackRef()->ptError() << " %"
425  << " ECAL = " << pfCand.at(ce2).ecalEnergy() << " HCAL = " << pfCand.at(ce2).hcalEnergy()
426  << " dE(Trk-CALO) = "
427  << pfCand.at(ce2).trackRef()->p() - pfCand.at(ce2).ecalEnergy() - pfCand.at(ce2).hcalEnergy()
428  << " Nmissing hits = "
429  << pfCand.at(ce2).trackRef()->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS) << endl;
430 
431  // Take now the parameters of the secondary track that are relevant and use them to construct the NI candidate
432  PFCandidate::ElementsInBlocks elementsInBlocks = pfCand.at(ce2).elementsInBlocks();
433  PFCandidate::ElementsInBlocks elementsAlreadyInBlocks = pfCand.at(ce1).elementsInBlocks();
434  for (unsigned blockElem = 0; blockElem < elementsInBlocks.size(); blockElem++) {
435  bool isAlreadyHere = false;
436  for (unsigned alreadyBlock = 0; alreadyBlock < elementsAlreadyInBlocks.size(); alreadyBlock++) {
437  if (elementsAlreadyInBlocks[alreadyBlock].second == elementsInBlocks[blockElem].second)
438  isAlreadyHere = true;
439  }
440  if (!isAlreadyHere)
441  pfCand.at(ce1).addElementInBlock(elementsInBlocks[blockElem].first, elementsInBlocks[blockElem].second);
442  }
443 
444  double candE = pfCand.at(ce2).p4().E();
445  double caloEn = pfCand.at(ce2).ecalEnergy() + pfCand.at(ce2).hcalEnergy();
446  double deltaEn = candE - caloEn;
447  int nMissOuterHits =
448  pfCand.at(ce2).trackRef()->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS);
449  if (deltaEn > ptErrorSecondary_ && nMissOuterHits > 1) {
450  math::XYZTLorentzVectorD momentumToAdd = pfCand.at(ce2).p4() * caloEn / candE;
451  momentumSec += momentumToAdd;
452  LogTrace("PFCandConnector|analyseNuclearWSec")
453  << "The difference track-calo s really large and the track miss at least 2 hits. A secondary NI may "
454  "have happened. Let's trust the calo energy"
455  << endl
456  << "add " << momentumToAdd << endl;
457  } else {
458  momentumSec += (pfCand.at(ce2)).p4();
459  }
460 
461  bMask[ce2] = true;
462  }
463  }
464  }
465 
466  math::XYZVector primDir = ref1->primaryDirection();
467 
468  if (primDir.Mag2() < 0.1) {
469  // It might be 0 but this situation should never happend. Throw a warning if it happens.
470  pfCand.at(ce1).setP4(momentumSec);
471  edm::LogWarning("PFCandConnector") << "A Nuclear Interaction do not have primary direction" << std::endl;
472  return;
473  } else {
474  // rescale the primary direction to the optimal momentum. But take care of the factthat it shall not be completly 0 to avoid a warning if Jet Area.
475  double momentumS = momentumSec.P();
476  if (momentumS < 1e-4)
477  momentumS = 1e-4;
478  double px = momentumS * primDir.x();
479  double py = momentumS * primDir.y();
480  double pz = momentumS * primDir.z();
481  double E = sqrt(px * px + py * py + pz * pz + pion_mass2);
482 
483  math::XYZTLorentzVectorD momentum(px, py, pz, E);
484 
485  pfCand.at(ce1).setP4(momentum);
486  return;
487  }
488 }
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzE4D< double > > XYZTLorentzVectorD
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:14
static const reco::PFCandidate::Flags fT_FROM_DISP_
const LorentzVector & p4() const final
four-momentum Lorentz vector
#define LogTrace(id)
std::vector< ElementInBlock > ElementsInBlocks
Definition: PFCandidate.h:404
U second(std::pair< T, U > const &p)
double pt() const
track transverse momentum
Definition: TrackBase.h:637
double ptErrorSecondary_
T sqrt(T t)
Definition: SSEVec.h:23
static const double pion_mass2
Useful constants.
Log< level::Info, false > LogInfo
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:31
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:41
bool isSecondaryNucl(const reco::PFCandidate &pf) const
Log< level::Warning, false > LogWarning

◆ connect()

reco::PFCandidateCollection PFCandConnector::connect ( reco::PFCandidateCollection pfCand) const

Collection of primary PFCandidates to be transmitted to the Event

A mask to define the candidates which shall not be transmitted

Definition at line 63 of file PFCandConnector.cc.

References LogTrace, and reco::HitPattern::MISSING_OUTER_HITS.

Referenced by PFAlgo::makeConnectedCandidates(), and o2o_db_cfgmap.DbManagerDAQ::update_hashmap().

63  {
67  std::vector<bool> bMask;
68  bMask.resize(pfCand.size(), false);
69 
70  // loop on primary
71  if (bCorrect_) {
72  LogTrace("PFCandConnector|connect") << "pfCand.size()=" << pfCand.size() << "bCalibPrimary_=" << bCalibPrimary_;
73 
74  for (unsigned int ce1 = 0; ce1 < pfCand.size(); ++ce1) {
75  if (isPrimaryNucl(pfCand.at(ce1))) {
76  LogTrace("PFCandConnector|connect")
77  << "" << endl
78  << "Nuclear Interaction w Primary Candidate " << ce1 << " " << pfCand.at(ce1) << endl
79  << " based on the Track " << pfCand.at(ce1).trackRef().key()
80  << " w pT = " << pfCand.at(ce1).trackRef()->pt() << " #pm "
81  << pfCand.at(ce1).trackRef()->ptError() / pfCand.at(ce1).trackRef()->pt() * 100 << " %"
82  << " ECAL = " << pfCand.at(ce1).ecalEnergy() << " HCAL = " << pfCand.at(ce1).hcalEnergy() << endl;
83 
84 #ifdef EDM_ML_DEBUG
85  (pfCand.at(ce1)).displacedVertexRef(fT_TO_DISP_)->Dump();
86 #endif
87 
88  analyseNuclearWPrim(pfCand, bMask, ce1);
89 
90 #ifdef EDM_ML_DEBUG
91  LogTrace("PFCandConnector|connect")
92  << "After Connection the candidate " << ce1 << " is " << pfCand.at(ce1) << endl
93  << endl;
94 
95  PFCandidate::ElementsInBlocks elementsInBlocks = pfCand.at(ce1).elementsInBlocks();
96  for (unsigned blockElem = 0; blockElem < elementsInBlocks.size(); blockElem++) {
97  if (blockElem == 0)
98  LogTrace("PFCandConnector|connect") << *(elementsInBlocks[blockElem].first) << endl;
99  LogTrace("PFCandConnector|connect") << " position " << elementsInBlocks[blockElem].second;
100  }
101 #endif
102  }
103  }
104 
105  for (unsigned int ce1 = 0; ce1 < pfCand.size(); ++ce1) {
106  if (!bMask[ce1] && isSecondaryNucl(pfCand.at(ce1))) {
107  LogTrace("PFCandConnector|connect")
108  << "" << endl
109  << "Nuclear Interaction w no Primary Candidate " << ce1 << " " << pfCand.at(ce1) << endl
110  << " based on the Track " << pfCand.at(ce1).trackRef().key()
111  << " w pT = " << pfCand.at(ce1).trackRef()->pt() << " #pm " << pfCand.at(ce1).trackRef()->ptError() << " %"
112  << " ECAL = " << pfCand.at(ce1).ecalEnergy() << " HCAL = " << pfCand.at(ce1).hcalEnergy()
113  << " dE(Trk-CALO) = "
114  << pfCand.at(ce1).trackRef()->p() - pfCand.at(ce1).ecalEnergy() - pfCand.at(ce1).hcalEnergy()
115  << " Nmissing hits = "
116  << pfCand.at(ce1).trackRef()->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS) << endl;
117 
118 #ifdef EDM_ML_DEBUG
119  (pfCand.at(ce1)).displacedVertexRef(fT_FROM_DISP_)->Dump();
120 #endif
121 
122  analyseNuclearWSec(pfCand, bMask, ce1);
123 
124 #ifdef EDM_ML_DEBUG
125  LogTrace("PFCandConnector|connect") << "After Connection the candidate " << ce1 << " is " << pfCand.at(ce1)
126  << " and elements connected to it are: " << endl;
127 
128  PFCandidate::ElementsInBlocks elementsInBlocks = pfCand.at(ce1).elementsInBlocks();
129  for (unsigned blockElem = 0; blockElem < elementsInBlocks.size(); blockElem++) {
130  if (blockElem == 0)
131  LogTrace("PFCandConnector|connect") << *(elementsInBlocks[blockElem].first) << endl;
132  LogTrace("PFCandConnector|connect") << " position " << elementsInBlocks[blockElem].second;
133  }
134 #endif
135  }
136  }
137  }
138 
139  for (unsigned int ce1 = 0; ce1 < pfCand.size(); ++ce1)
140  if (!bMask[ce1])
141  pfC.push_back(pfCand.at(ce1));
142 
143  LogTrace("PFCandConnector|connect") << "end of function";
144 
145  return pfC;
146 }
bool isPrimaryNucl(const reco::PFCandidate &pf) const
static const reco::PFCandidate::Flags fT_FROM_DISP_
static const reco::PFCandidate::Flags fT_TO_DISP_
#define LogTrace(id)
std::vector< ElementInBlock > ElementsInBlocks
Definition: PFCandidate.h:404
void analyseNuclearWPrim(reco::PFCandidateCollection &, std::vector< bool > &, unsigned int) const
Analyse nuclear interactions where a primary or merged track is present.
void analyseNuclearWSec(reco::PFCandidateCollection &, std::vector< bool > &, unsigned int) const
Analyse nuclear interactions where a secondary track is present.
std::vector< reco::PFCandidate > PFCandidateCollection
collection of PFCandidates
bool bCalibPrimary_
Calibration parameters for the reconstructed nuclear interactions.
bool bCorrect_
Parameters.
bool isSecondaryNucl(const reco::PFCandidate &pf) const

◆ fillPSetDescription()

void PFCandConnector::fillPSetDescription ( edm::ParameterSetDescription iDesc)
static

Definition at line 563 of file PFCandConnector.cc.

References edm::ParameterSetDescription::add().

Referenced by PFProducer::fillDescriptions().

563  {
564  iDesc.add<bool>("bCorrect", true);
565  iDesc.add<bool>("bCalibPrimary", true);
566  iDesc.add<double>("dptRel_PrimaryTrack", 10.0);
567  iDesc.add<double>("dptRel_MergedTrack", 5.0);
568  iDesc.add<double>("ptErrorSecondary", 1.0);
569  iDesc.add<std::vector<double>>("nuclCalibFactors", {0.8, 0.15, 0.5, 0.5, 0.05});
570 }
ParameterDescriptionBase * add(U const &iLabel, T const &value)

◆ isPrimaryNucl()

bool PFCandConnector::isPrimaryNucl ( const reco::PFCandidate pf) const
private

Definition at line 505 of file PFCandConnector.cc.

References edm::Ref< C, T, F >::isNonnull(), and packedPFCandidateRefMixer_cfi::pf.

505  {
507 
508  // nuclear
509  if (pf.flag(fT_TO_DISP_)) {
510  ref1 = pf.displacedVertexRef(fT_TO_DISP_);
511  //ref1->Dump();
512 
513  if (!ref1.isNonnull())
514  return false;
515  else if (ref1->isNucl() || ref1->isNucl_Loose() || ref1->isNucl_Kink())
516  return true;
517  }
518 
519  return false;
520 }
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:238
static const reco::PFCandidate::Flags fT_TO_DISP_

◆ isSecondaryNucl()

bool PFCandConnector::isSecondaryNucl ( const reco::PFCandidate pf) const
private

Definition at line 490 of file PFCandConnector.cc.

References edm::Ref< C, T, F >::isNonnull(), and packedPFCandidateRefMixer_cfi::pf.

490  {
492  // nuclear
493  if (pf.flag(fT_FROM_DISP_)) {
494  ref1 = pf.displacedVertexRef(fT_FROM_DISP_);
495  // ref1->Dump();
496  if (!ref1.isNonnull())
497  return false;
498  else if (ref1->isNucl() || ref1->isNucl_Loose() || ref1->isNucl_Kink())
499  return true;
500  }
501 
502  return false;
503 }
static const reco::PFCandidate::Flags fT_FROM_DISP_
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:238

◆ rescaleFactor()

double PFCandConnector::rescaleFactor ( const double  pt,
const double  cFrac 
) const
private

Return a calibration factor for a reconstructed nuclear interaction.

Definition at line 522 of file PFCandConnector.cc.

References JetChargeProducer_cfi::exp, and DiDispStaMuonMonitor_cfi::pt.

522  {
523  /*
524  LOG NORMAL FIT
525  FCN=35.8181 FROM MIGRAD STATUS=CONVERGED 257 CALLS 258 TOTAL
526  EDM=8.85763e-09 STRATEGY= 1 ERROR MATRIX ACCURATE
527  EXT PARAMETER STEP FIRST
528  NO. NAME VALUE ERROR SIZE DERIVATIVE
529  1 p0 7.99434e-01 2.77264e-02 6.59108e-06 9.80247e-03
530  2 p1 1.51303e-01 2.89981e-02 1.16775e-05 6.99035e-03
531  3 p2 -5.03829e-01 2.87929e-02 1.90070e-05 1.37015e-03
532  4 p3 4.54043e-01 5.00908e-02 3.17625e-05 3.86622e-03
533  5 p4 -4.61736e-02 8.07940e-03 3.25775e-06 -1.37247e-02
534  */
535 
536  /*
537  FCN=34.4051 FROM MIGRAD STATUS=CONVERGED 221 CALLS 222 TOTAL
538  EDM=1.02201e-09 STRATEGY= 1 ERROR MATRIX UNCERTAINTY 2.3 per cent
539 
540  fConst
541  1 p0 7.99518e-01 2.23519e-02 1.41523e-06 4.05975e-04
542  2 p1 1.44619e-01 2.39398e-02 -7.68117e-07 -2.55775e-03
543 
544  fNorm
545  3 p2 -5.16571e-01 3.12362e-02 5.74932e-07 3.42292e-03
546  4 p3 4.69055e-01 5.09665e-02 1.94353e-07 1.69031e-03
547 
548  fExp
549  5 p4 -5.18044e-02 8.13458e-03 4.29815e-07 -1.07624e-02
550  */
551 
552  double fConst, fNorm, fExp;
553 
554  fConst = fConst_[0] + fConst_[1] * cFrac;
555  fNorm = fNorm_[0] - fNorm_[1] * cFrac;
556  fExp = fExp_[0];
557 
558  double factor = fConst - fNorm * exp(-fExp * pt);
559 
560  return factor;
561 }
std::vector< double > fExp_
std::vector< double > fNorm_
std::vector< double > fConst_

◆ setParameters() [1/2]

void PFCandConnector::setParameters ( const edm::ParameterSet iCfgCandConnector)
inline

Flag to apply the correction procedure for nuclear interactions

Flag to calibrate the reconstructed nuclear interactions with primary or merged tracks

Definition at line 30 of file PFCandConnector.h.

References HLT_2024v14_cff::bCalibPrimary, HLT_2024v14_cff::bCorrect, hltParticleFlowTmpBarrel_cfi::dptRel_MergedTrack, hltParticleFlowTmpBarrel_cfi::dptRel_PrimaryTrack, HLT_2024v14_cff::iCfgCandConnector, HLT_2024v14_cff::nuclCalibFactors, and hltParticleFlowTmpBarrel_cfi::ptErrorSecondary.

Referenced by PFAlgo::setCandConnectorParameters().

30  {
32  const auto& bCorrect = iCfgCandConnector.getParameter<bool>("bCorrect");
34  const auto& bCalibPrimary = iCfgCandConnector.getParameter<bool>("bCalibPrimary");
35  const auto& dptRel_PrimaryTrack = iCfgCandConnector.getParameter<double>("dptRel_PrimaryTrack");
36  const auto& dptRel_MergedTrack = iCfgCandConnector.getParameter<double>("dptRel_MergedTrack");
37  const auto& ptErrorSecondary = iCfgCandConnector.getParameter<double>("ptErrorSecondary");
38  const auto& nuclCalibFactors = iCfgCandConnector.getParameter<std::vector<double> >("nuclCalibFactors");
39 
41  }
void setParameters(const edm::ParameterSet &iCfgCandConnector)

◆ setParameters() [2/2]

void PFCandConnector::setParameters ( bool  bCorrect,
bool  bCalibPrimary,
double  dptRel_PrimaryTrack,
double  dptRel_MergedTrack,
double  ptErrorSecondary,
const std::vector< double > &  nuclCalibFactors 
)

Definition at line 15 of file PFCandConnector.cc.

References HLT_2024v14_cff::bCalibPrimary, HLT_2024v14_cff::bCorrect, hltParticleFlowTmpBarrel_cfi::dptRel_MergedTrack, hltParticleFlowTmpBarrel_cfi::dptRel_PrimaryTrack, HLT_2024v14_cff::nuclCalibFactors, hltParticleFlowTmpBarrel_cfi::ptErrorSecondary, and AlCaHLTBitMon_QueryRunRegistry::string.

20  {
26 
27  if (nuclCalibFactors.size() == 5) {
28  fConst_[0] = nuclCalibFactors[0];
29  fConst_[1] = nuclCalibFactors[1];
30 
31  fNorm_[0] = nuclCalibFactors[2];
32  fNorm_[1] = nuclCalibFactors[3];
33 
34  fExp_[0] = nuclCalibFactors[4];
35  } else {
36  edm::LogWarning("PFCandConnector")
37  << "Wrong calibration factors for nuclear interactions. The calibration procedure would not be applyed."
38  << std::endl;
39  bCalibPrimary_ = false;
40  }
41 
42  std::string sCorrect = bCorrect_ ? "On" : "Off";
43  edm::LogInfo("PFCandConnector") << " ====================== The PFCandConnector is switched " << sCorrect.c_str()
44  << " ==================== " << std::endl;
45  std::string sCalibPrimary = bCalibPrimary_ ? "used for calibration" : "not used for calibration";
46  if (bCorrect_)
47  edm::LogInfo("PFCandConnector") << "Primary Tracks are " << sCalibPrimary.c_str() << std::endl;
49  edm::LogInfo("PFCandConnector") << "Under the condition that the precision on the Primary track is better than "
50  << dptRel_PrimaryTrack_ << " % " << std::endl;
52  edm::LogInfo("PFCandConnector") << " and on merged tracks better than " << dptRel_MergedTrack_ << " % "
53  << std::endl;
55  edm::LogInfo("PFCandConnector") << " and secondary tracks in some cases more precise than "
56  << ptErrorSecondary_ << " GeV" << std::endl;
58  edm::LogInfo("PFCandConnector") << "factor = (" << fConst_[0] << " + " << fConst_[1] << "*cFrac) - (" << fNorm_[0]
59  << " - " << fNorm_[1] << "cFrac)*exp( " << -1 * fExp_[0] << "*pT )" << std::endl;
60  edm::LogInfo("PFCandConnector") << " =========================================================== " << std::endl;
61 }
std::vector< double > fExp_
double ptErrorSecondary_
std::vector< double > fNorm_
std::vector< double > fConst_
Log< level::Info, false > LogInfo
double dptRel_PrimaryTrack_
bool bCalibPrimary_
Calibration parameters for the reconstructed nuclear interactions.
bool bCorrect_
Parameters.
Log< level::Warning, false > LogWarning
double dptRel_MergedTrack_

Member Data Documentation

◆ bCalibPrimary_

bool PFCandConnector::bCalibPrimary_
private

Calibration parameters for the reconstructed nuclear interactions.

Definition at line 72 of file PFCandConnector.h.

Referenced by PFCandConnector().

◆ bCorrect_

bool PFCandConnector::bCorrect_
private

Parameters.

Definition at line 69 of file PFCandConnector.h.

Referenced by PFCandConnector().

◆ dptRel_MergedTrack_

double PFCandConnector::dptRel_MergedTrack_
private

Definition at line 79 of file PFCandConnector.h.

Referenced by PFCandConnector().

◆ dptRel_PrimaryTrack_

double PFCandConnector::dptRel_PrimaryTrack_
private

Definition at line 78 of file PFCandConnector.h.

Referenced by PFCandConnector().

◆ fConst_

std::vector<double> PFCandConnector::fConst_
private

Definition at line 73 of file PFCandConnector.h.

Referenced by PFCandConnector().

◆ fExp_

std::vector<double> PFCandConnector::fExp_
private

Definition at line 75 of file PFCandConnector.h.

Referenced by PFCandConnector().

◆ fNorm_

std::vector<double> PFCandConnector::fNorm_
private

Definition at line 74 of file PFCandConnector.h.

Referenced by PFCandConnector().

◆ fT_FROM_DISP_

const reco::PFCandidate::Flags PFCandConnector::fT_FROM_DISP_ = PFCandidate::T_FROM_DISP
staticprivate

Definition at line 85 of file PFCandConnector.h.

◆ fT_TO_DISP_

const reco::PFCandidate::Flags PFCandConnector::fT_TO_DISP_ = PFCandidate::T_TO_DISP
staticprivate

Definition at line 84 of file PFCandConnector.h.

◆ pion_mass2

const double PFCandConnector::pion_mass2 = 0.0194
staticprivate

Useful constants.

Definition at line 83 of file PFCandConnector.h.

◆ ptErrorSecondary_

double PFCandConnector::ptErrorSecondary_
private

Definition at line 80 of file PFCandConnector.h.

Referenced by PFCandConnector().