CMS 3D CMS Logo

PFCandConnector.cc
Go to the documentation of this file.
7 
8 using namespace reco;
9 using namespace std;
10 
11 const double PFCandConnector::pion_mass2 = 0.0194;
12 
15 
17 
18  bCorrect_ = bCorrect;
19  bCalibPrimary_ = bCalibPrimary;
20  dptRel_PrimaryTrack_ = dptRel_PrimaryTrack;
21  dptRel_MergedTrack_ = dptRel_MergedTrack;
22  ptErrorSecondary_ = ptErrorSecondary;
23 
24  if (nuclCalibFactors.size() == 5) {
25  fConst_[0] = nuclCalibFactors[0];
26  fConst_[1] = nuclCalibFactors[1];
27 
28  fNorm_[0] = nuclCalibFactors[2];
29  fNorm_[1] = nuclCalibFactors[3];
30 
31  fExp_[0] = nuclCalibFactors[4];
32  } else {
33  edm::LogWarning("PFCandConnector") << "Wrong calibration factors for nuclear interactions. The calibration procedure would not be applyed." << std::endl;
34  bCalibPrimary_ = false;
35  }
36 
37  std::string sCorrect = bCorrect_ ? "On" : "Off";
38  edm::LogInfo("PFCandConnector") << " ====================== The PFCandConnector is switched " << sCorrect.c_str() << " ==================== " << std::endl;
39  std::string sCalibPrimary = bCalibPrimary_ ? "used for calibration" : "not used for calibration";
40  if (bCorrect_) edm::LogInfo("PFCandConnector") << "Primary Tracks are " << sCalibPrimary.c_str() << std::endl;
41  if (bCorrect_ && bCalibPrimary_) edm::LogInfo("PFCandConnector") << "Under the condition that the precision on the Primary track is better than " << dptRel_PrimaryTrack_ << " % "<< std::endl;
42  if (bCorrect_ && bCalibPrimary_) edm::LogInfo("PFCandConnector") << " and on merged tracks better than " << dptRel_MergedTrack_ << " % "<< std::endl;
43  if (bCorrect_ && bCalibPrimary_) edm::LogInfo("PFCandConnector") << " and secondary tracks in some cases more precise than " << ptErrorSecondary_ << " GeV"<< std::endl;
44  if (bCorrect_ && bCalibPrimary_) edm::LogInfo("PFCandConnector") << "factor = (" << fConst_[0] << " + " << fConst_[1] << "*cFrac) - ("
45  << fNorm_[0] << " - " << fNorm_[1] << "cFrac)*exp( "
46  << -1*fExp_[0] << "*pT )"<< std::endl;
47  edm::LogInfo("PFCandConnector") << " =========================================================== " << std::endl;
48 
49  }
50 
51 
52 
55 
59  std::vector<bool> bMask;
60  bMask.resize(pfCand.size(), false);
61 
62  // debug_ = true;
63 
64  // loop on primary
65  if (bCorrect_){
66  if(debug_){
67  cout << "" << endl;
68  cout << "==================== ------------------------------ ===============" << endl;
69  cout << "==================== Cand Connector ===============" << endl;
70  cout << "==================== ------------------------------ ===============" << endl;
71  cout << "==================== \tfor " << pfCand.size() << " Candidates\t =============" << endl;
72  cout << "==================== primary calibrated " << bCalibPrimary_ << " =============" << endl;
73  }
74 
75  for( unsigned int ce1=0; ce1 < pfCand.size(); ++ce1){
76  if ( isPrimaryNucl(pfCand.at(ce1)) ){
77 
78  if (debug_)
79  cout << "" << endl << "Nuclear Interaction w Primary Candidate " << ce1
80  << " " << pfCand.at(ce1) << endl
81  << " based on the Track " << pfCand.at(ce1).trackRef().key()
82  << " w pT = " << pfCand.at(ce1).trackRef()->pt()
83  << " #pm " << pfCand.at(ce1).trackRef()->ptError()/pfCand.at(ce1).trackRef()->pt()*100 << " %"
84  << " ECAL = " << pfCand.at(ce1).ecalEnergy()
85  << " HCAL = " << pfCand.at(ce1).hcalEnergy() << endl;
86 
87  if (debug_) (pfCand.at(ce1)).displacedVertexRef(fT_TO_DISP_)->Dump();
88 
89  analyseNuclearWPrim(pfCand, bMask, ce1);
90 
91  if (debug_){
92  cout << "After Connection the candidate " << ce1
93  << " is " << pfCand.at(ce1) << endl << endl;
94 
95  PFCandidate::ElementsInBlocks elementsInBlocks = pfCand.at(ce1).elementsInBlocks();
96  for (unsigned blockElem = 0; blockElem < elementsInBlocks.size(); blockElem++){
97  if (blockElem == 0) cout << *(elementsInBlocks[blockElem].first) << endl;
98  cout << " position " << elementsInBlocks[blockElem].second;
99  }
100  }
101 
102  }
103 
104  }
105 
106  for( unsigned int ce1=0; ce1 < pfCand.size(); ++ce1){
107  if ( !bMask[ce1] && isSecondaryNucl(pfCand.at(ce1)) ){
108  if (debug_)
109  cout << "" << endl << "Nuclear Interaction w no Primary Candidate " << ce1
110  << " " << pfCand.at(ce1) << endl
111  << " based on the Track " << pfCand.at(ce1).trackRef().key()
112  << " w pT = " << pfCand.at(ce1).trackRef()->pt()
113  << " #pm " << pfCand.at(ce1).trackRef()->ptError() << " %"
114  << " ECAL = " << pfCand.at(ce1).ecalEnergy()
115  << " HCAL = " << pfCand.at(ce1).hcalEnergy()
116  << " dE(Trk-CALO) = " << pfCand.at(ce1).trackRef()->p()-pfCand.at(ce1).ecalEnergy()-pfCand.at(ce1).hcalEnergy()
117  << " Nmissing hits = " << pfCand.at(ce1).trackRef()->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS) << endl;
118 
119  if (debug_) (pfCand.at(ce1)).displacedVertexRef(fT_FROM_DISP_)->Dump();
120 
121  analyseNuclearWSec(pfCand, bMask, ce1);
122 
123  if (debug_) {
124  cout << "After Connection the candidate " << ce1
125  << " 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) cout << *(elementsInBlocks[blockElem].first) << endl;
131  cout << " position " << elementsInBlocks[blockElem].second;
132  }
133  }
134 
135  }
136 
137 
138  }
139  }
140 
141 
142 
143 
144  for( unsigned int ce1=0; ce1 < pfCand.size(); ++ce1)
145  if (!bMask[ce1]) pfC.push_back(pfCand.at(ce1));
146 
147 
148  if(debug_ && bCorrect_) cout << "==================== ------------------------------ ===============" << endl<< endl << endl;
149 
150  return pfC;
151 
152 
153 }
154 
155 void
156 PFCandConnector::analyseNuclearWPrim(PFCandidateCollection& pfCand, std::vector<bool> & bMask, unsigned int ce1) const {
157 
158 
159  PFDisplacedVertexRef ref1, ref2, ref1_bis;
160 
161  PFCandidate primaryCand = pfCand.at(ce1);
162 
163  // ------- look for the little friends -------- //
164 
165  const math::XYZTLorentzVectorD& momentumPrim = primaryCand.p4();
166 
167  math::XYZTLorentzVectorD momentumSec;
168 
169  momentumSec = momentumPrim/momentumPrim.E()*(primaryCand.ecalEnergy() + primaryCand.hcalEnergy());
170 
171  map<double, math::XYZTLorentzVectorD> candidatesWithTrackExcess;
172  map<double, math::XYZTLorentzVectorD> candidatesWithoutCalo;
173 
174 
175  ref1 = primaryCand.displacedVertexRef(fT_TO_DISP_);
176 
177  for( unsigned int ce2=0; ce2 < pfCand.size(); ++ce2) {
178  if (ce2 != ce1 && isSecondaryNucl(pfCand.at(ce2))){
179 
180  ref2 = (pfCand.at(ce2)).displacedVertexRef(fT_FROM_DISP_);
181 
182  if (ref1 == ref2) {
183 
184  if (debug_) cout << "\t here is a Secondary Candidate " << ce2
185  << " " << pfCand.at(ce2) << endl
186  << "\t based on the Track " << pfCand.at(ce2).trackRef().key()
187  << " w p = " << pfCand.at(ce2).trackRef()->p()
188  << " w pT = " << pfCand.at(ce2).trackRef()->pt()
189  << " #pm " << pfCand.at(ce2).trackRef()->ptError() << " %"
190  << " ECAL = " << pfCand.at(ce2).ecalEnergy()
191  << " HCAL = " << pfCand.at(ce2).hcalEnergy()
192  << " dE(Trk-CALO) = " << pfCand.at(ce2).trackRef()->p()-pfCand.at(ce2).ecalEnergy()-pfCand.at(ce2).hcalEnergy()
193  << " Nmissing hits = " << pfCand.at(ce2).trackRef()->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS) << endl;
194 
195  if(isPrimaryNucl(pfCand.at(ce2))){
196  if (debug_) cout << "\t\t but it is also a Primary Candidate " << ce2 << endl;
197 
198  ref1_bis = (pfCand.at(ce2)).displacedVertexRef(fT_TO_DISP_);
199  if(ref1_bis.isNonnull()) analyseNuclearWPrim(pfCand, bMask, ce2);
200  }
201 
202  // Take now the parameters of the secondary track that are relevant and use them to construct the NI candidate
203 
204  PFCandidate::ElementsInBlocks elementsInBlocks = pfCand.at(ce2).elementsInBlocks();
205  PFCandidate::ElementsInBlocks elementsAlreadyInBlocks = pfCand.at(ce1).elementsInBlocks();
206  for (unsigned blockElem = 0; blockElem < elementsInBlocks.size(); blockElem++){
207  bool isAlreadyHere = false;
208  for (unsigned alreadyBlock = 0; alreadyBlock < elementsAlreadyInBlocks.size(); alreadyBlock++){
209  if (elementsAlreadyInBlocks[alreadyBlock].second == elementsInBlocks[blockElem].second) isAlreadyHere = true;
210  }
211  if (!isAlreadyHere) pfCand.at(ce1).addElementInBlock( elementsInBlocks[blockElem].first, elementsInBlocks[blockElem].second);
212  }
213 
214  double caloEn = pfCand.at(ce2).ecalEnergy() + pfCand.at(ce2).hcalEnergy();
215  double deltaEn = pfCand.at(ce2).p4().E() - caloEn;
216  int nMissOuterHits = pfCand.at(ce2).trackRef()->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS);
217 
218 
219  // 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.
220  if (deltaEn > 1 && nMissOuterHits > 1) {
221  math::XYZTLorentzVectorD momentumToAdd = pfCand.at(ce2).p4()*caloEn/pfCand.at(ce2).p4().E();
222  momentumSec += momentumToAdd;
223  if (debug_) cout << "The difference track-calo s really large and the track miss at least 2 hits. A secondary NI may have happened. Let's trust the calo energy" << endl << "add " << momentumToAdd << endl;
224 
225  } else {
226  // 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.
227  if (caloEn > 0.01 && deltaEn > 1 && nMissOuterHits > 0) {
228  math::XYZTLorentzVectorD momentumExcess = pfCand.at(ce2).p4()*deltaEn/pfCand.at(ce2).p4().E();
229  candidatesWithTrackExcess[pfCand.at(ce2).trackRef()->pt()/pfCand.at(ce2).trackRef()->ptError()] = momentumExcess;
230  }
231  else if(caloEn < 0.01) candidatesWithoutCalo[pfCand.at(ce2).trackRef()->pt()/pfCand.at(ce2).trackRef()->ptError()] = pfCand.at(ce2).p4();
232  momentumSec += (pfCand.at(ce2)).p4();
233  }
234 
235  bMask[ce2] = true;
236 
237 
238 
239  }
240  }
241  }
242 
243 
244  // We have more primary energy than secondary: reject all secondary tracks which have no calo energy attached.
245 
246 
247  if (momentumPrim.E() < momentumSec.E()){
248 
249  if(debug_) cout << "Size of 0 calo Energy secondary candidates" << candidatesWithoutCalo.size() << endl;
250  for( map<double, math::XYZTLorentzVectorD>::iterator iter = candidatesWithoutCalo.begin(); iter != candidatesWithoutCalo.end() && momentumPrim.E() < momentumSec.E(); iter++)
251  if (momentumSec.E() > iter->second.E()+0.1) {
252  momentumSec -= iter->second;
253 
254  if(debug_) cout << "\t Remove a SecondaryCandidate with 0 calo energy " << iter->second << endl;
255 
256  if(debug_) cout << "momentumPrim.E() = " << momentumPrim.E() << " and momentumSec.E() = " << momentumSec.E() << endl;
257 
258  }
259 
260  }
261 
262 
263  if (momentumPrim.E() < momentumSec.E()){
264  if(debug_) cout << "0 Calo Energy rejected but still not sufficient. Size of not enough calo Energy secondary candidates" << candidatesWithTrackExcess.size() << endl;
265  for( map<double, math::XYZTLorentzVectorD>::iterator iter = candidatesWithTrackExcess.begin(); iter != candidatesWithTrackExcess.end() && momentumPrim.E() < momentumSec.E(); iter++)
266  if (momentumSec.E() > iter->second.E()+0.1) momentumSec -= iter->second;
267 
268  }
269 
270 
271 
272 
273  double dpt = pfCand.at(ce1).trackRef()->ptError()/pfCand.at(ce1).trackRef()->pt()*100;
274 
275  if (momentumSec.E() < 0.1) {
276  bMask[ce1] = true;
277  return;
278  }
279 
280  // Rescale the secondary candidates to account for the loss of energy, but only if we can trust the primary track:
281  // if it has more energy than secondaries and is precise enough and secondary exist and was not eaten or rejected during the PFAlgo step.
282 
283  if( ( (ref1->isTherePrimaryTracks() && dpt<dptRel_PrimaryTrack_) || (ref1->isThereMergedTracks() && dpt<dptRel_MergedTrack_) ) && momentumPrim.E() > momentumSec.E() && momentumSec.E() > 0.1) {
284 
285  if (bCalibPrimary_){
286  double factor = rescaleFactor( momentumPrim.Pt(), momentumSec.E()/momentumPrim.E());
287  if (debug_) cout << "factor = " << factor << endl;
288  if (factor*momentumPrim.Pt() < momentumSec.Pt()) momentumSec = momentumPrim;
289  else momentumSec += (1-factor)*momentumPrim;
290  }
291 
292  double px = momentumPrim.Px()*momentumSec.P()/momentumPrim.P();
293  double py = momentumPrim.Py()*momentumSec.P()/momentumPrim.P();
294  double pz = momentumPrim.Pz()*momentumSec.P()/momentumPrim.P();
295  double E = sqrt(px*px + py*py + pz*pz + pion_mass2);
296  math::XYZTLorentzVectorD momentum(px, py, pz, E);
297  pfCand.at(ce1).setP4(momentum);
298 
299  return;
300 
301  } else {
302 
303  math::XYZVector primDir = ref1->primaryDirection();
304 
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) momentumS = 1e-4;
315  double px = momentumS*primDir.x();
316  double py = momentumS*primDir.y();
317  double pz = momentumS*primDir.z();
318  double E = sqrt(px*px + py*py + pz*pz + pion_mass2);
319 
320  math::XYZTLorentzVectorD momentum(px, py, pz, E);
321  pfCand.at(ce1).setP4(momentum);
322  return;
323  }
324  }
325 
326 
327 
328 }
329 
330 
331 
332 
333 void
334 PFCandConnector::analyseNuclearWSec(PFCandidateCollection& pfCand, std::vector<bool> & bMask, unsigned int ce1) const {
335 
336  PFDisplacedVertexRef ref1, ref2;
337 
338 
339  // Check if the track excess was not too large and track may miss some outer hits. This may point to a secondary NI.
340 
341  double caloEn = pfCand.at(ce1).ecalEnergy() + pfCand.at(ce1).hcalEnergy();
342  double deltaEn = pfCand.at(ce1).p4().E() - caloEn;
343  int nMissOuterHits = pfCand.at(ce1).trackRef()->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS);
344 
345 
346  ref1 = pfCand.at(ce1).displacedVertexRef(fT_FROM_DISP_);
347 
348  // ------- check if an electron or a muon vas spotted as incoming track -------- //
349  // ------- this mean probably that the NI was fake thus we do not correct it -------- /
350 
351  if (ref1->isTherePrimaryTracks() || ref1->isThereMergedTracks()){
352 
353  std::vector<reco::Track> refittedTracks = ref1->refittedTracks();
354  for(unsigned it = 0; it < refittedTracks.size(); it++){
355  reco::TrackBaseRef primaryBaseRef = ref1->originalTrack(refittedTracks[it]);
356  if (ref1->isIncomingTrack(primaryBaseRef))
357  if (debug_) cout << "There is a Primary track ref with pt = " << primaryBaseRef->pt()<< endl;
358 
359  for( unsigned int ce=0; ce < pfCand.size(); ++ce){
360  // cout << "PFCand Id = " << (pfCand.at(ce)).particleId() << endl;
361  if ((pfCand.at(ce)).particleId() == reco::PFCandidate::e || (pfCand.at(ce)).particleId() == reco::PFCandidate::mu) {
362 
363  if (debug_) cout << " It is an electron and it has a ref to a track " << (pfCand.at(ce)).trackRef().isNonnull() << endl;
364 
365 
366  if ( (pfCand.at(ce)).trackRef().isNonnull() ){
367  reco::TrackRef tRef = (pfCand.at(ce)).trackRef();
368  reco::TrackBaseRef bRef(tRef);
369  if (debug_) cout << "With Track Ref pt = " << (pfCand.at(ce)).trackRef()->pt() << endl;
370 
371  if (bRef == primaryBaseRef) {
372  if (debug_ && (pfCand.at(ce)).particleId() == reco::PFCandidate::e) cout << "It is a NI from electron. NI Discarded. Just release the candidate." << endl;
373  if (debug_ && (pfCand.at(ce)).particleId() == reco::PFCandidate::mu) cout << "It is a NI from muon. NI Discarded. Just release the candidate" << endl;
374 
375  // release the track but take care of not overcounting bad tracks. In fact those tracks was protected against destruction in
376  // PFAlgo. Now we treat them as if they was treated in PFAlgo
377 
378  if (caloEn < 0.1 && pfCand.at(ce1).trackRef()->ptError() > ptErrorSecondary_) {
379  cout << "discarded track since no calo energy and ill measured" << endl;
380  bMask[ce1] = true;
381  }
382  if (caloEn > 0.1 && deltaEn >ptErrorSecondary_ && pfCand.at(ce1).trackRef()->ptError() > ptErrorSecondary_) {
383  cout << "rescaled momentum of the track since no calo energy and ill measured" << endl;
384 
385  double factor = caloEn/pfCand.at(ce1).p4().E();
386  pfCand.at(ce1).rescaleMomentum(factor);
387  }
388 
389  return;
390  }
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 = pfCand.at(ce1).p4()*caloEn/pfCand.at(ce1).p4().E();
404  momentumSec = momentumToAdd;
405  if (debug_) cout << "The difference track-calo s really large and the track miss at least 2 hits. A secondary NI may have happened. Let's trust the calo energy" << endl << "add " << momentumToAdd << endl;
406  }
407 
408 
409  // ------- look for the little friends -------- //
410  for( unsigned int ce2=ce1+1; ce2 < pfCand.size(); ++ce2) {
411  if (isSecondaryNucl(pfCand.at(ce2))){
412  ref2 = (pfCand.at(ce2)).displacedVertexRef(fT_FROM_DISP_);
413 
414  if (ref1 == ref2) {
415 
416  if (debug_) cout << "\t here is a Secondary Candidate " << ce2
417  << " " << pfCand.at(ce2) << endl
418  << "\t based on the Track " << pfCand.at(ce2).trackRef().key()
419  << " w pT = " << pfCand.at(ce2).trackRef()->pt()
420  << " #pm " << pfCand.at(ce2).trackRef()->ptError() << " %"
421  << " ECAL = " << pfCand.at(ce2).ecalEnergy()
422  << " HCAL = " << pfCand.at(ce2).hcalEnergy()
423  << " dE(Trk-CALO) = " << pfCand.at(ce2).trackRef()->p()-pfCand.at(ce2).ecalEnergy()-pfCand.at(ce2).hcalEnergy()
424  << " Nmissing hits = " << pfCand.at(ce2).trackRef()->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS) << endl;
425 
426  // Take now the parameters of the secondary track that are relevant and use them to construct the NI candidate
427  PFCandidate::ElementsInBlocks elementsInBlocks = pfCand.at(ce2).elementsInBlocks();
428  PFCandidate::ElementsInBlocks elementsAlreadyInBlocks = pfCand.at(ce1).elementsInBlocks();
429  for (unsigned blockElem = 0; blockElem < elementsInBlocks.size(); blockElem++){
430  bool isAlreadyHere = false;
431  for (unsigned alreadyBlock = 0; alreadyBlock < elementsAlreadyInBlocks.size(); alreadyBlock++){
432  if (elementsAlreadyInBlocks[alreadyBlock].second == elementsInBlocks[blockElem].second) isAlreadyHere = true;
433  }
434  if (!isAlreadyHere) pfCand.at(ce1).addElementInBlock( elementsInBlocks[blockElem].first, elementsInBlocks[blockElem].second);
435  }
436 
437  double caloEn = pfCand.at(ce2).ecalEnergy() + pfCand.at(ce2).hcalEnergy();
438  double deltaEn = pfCand.at(ce2).p4().E() - caloEn;
439  int nMissOuterHits = pfCand.at(ce2).trackRef()->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS);
440  if (deltaEn > ptErrorSecondary_ && nMissOuterHits > 1) {
441  math::XYZTLorentzVectorD momentumToAdd = pfCand.at(ce2).p4()*caloEn/pfCand.at(ce2).p4().E();
442  momentumSec += momentumToAdd;
443  if (debug_) cout << "The difference track-calo s really large and the track miss at least 2 hits. A secondary NI may have happened. Let's trust the calo energy" << endl << "add " << momentumToAdd << endl;
444  } else {
445  momentumSec += (pfCand.at(ce2)).p4();
446  }
447 
448  bMask[ce2] = true;
449  }
450  }
451  }
452 
453 
454 
455 
456  math::XYZVector primDir = ref1->primaryDirection();
457 
458  if (primDir.Mag2() < 0.1){
459  // It might be 0 but this situation should never happend. Throw a warning if it happens.
460  pfCand.at(ce1).setP4(momentumSec);
461  edm::LogWarning("PFCandConnector") << "A Nuclear Interaction do not have primary direction" << std::endl;
462  return;
463  } else {
464  // 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.
465  double momentumS = momentumSec.P();
466  if (momentumS < 1e-4) momentumS = 1e-4;
467  double px = momentumS*primDir.x();
468  double py = momentumS*primDir.y();
469  double pz = momentumS*primDir.z();
470  double E = sqrt(px*px + py*py + pz*pz + pion_mass2);
471 
472  math::XYZTLorentzVectorD momentum(px, py, pz, E);
473 
474  pfCand.at(ce1).setP4(momentum);
475  return;
476  }
477 
478 }
479 
480 bool
482 
484  // nuclear
485  if( pf.flag( fT_FROM_DISP_ ) ) {
486  ref1 = pf.displacedVertexRef(fT_FROM_DISP_);
487  // ref1->Dump();
488  if (!ref1.isNonnull()) return false;
489  else if (ref1->isNucl() || ref1->isNucl_Loose() || ref1->isNucl_Kink())
490  return true;
491  }
492 
493  return false;
494 }
495 
496 bool
498 
500 
501  // nuclear
502  if( pf.flag( fT_TO_DISP_ ) ) {
503  ref1 = pf.displacedVertexRef(fT_TO_DISP_);
504  //ref1->Dump();
505 
506  if (!ref1.isNonnull()) return false;
507  else if (ref1->isNucl()|| ref1->isNucl_Loose() || ref1->isNucl_Kink())
508  return true;
509  }
510 
511  return false;
512 }
513 
514 
515 double
516 PFCandConnector::rescaleFactor( const double pt, const double cFrac ) const {
517 
518 
519  /*
520  LOG NORMAL FIT
521  FCN=35.8181 FROM MIGRAD STATUS=CONVERGED 257 CALLS 258 TOTAL
522  EDM=8.85763e-09 STRATEGY= 1 ERROR MATRIX ACCURATE
523  EXT PARAMETER STEP FIRST
524  NO. NAME VALUE ERROR SIZE DERIVATIVE
525  1 p0 7.99434e-01 2.77264e-02 6.59108e-06 9.80247e-03
526  2 p1 1.51303e-01 2.89981e-02 1.16775e-05 6.99035e-03
527  3 p2 -5.03829e-01 2.87929e-02 1.90070e-05 1.37015e-03
528  4 p3 4.54043e-01 5.00908e-02 3.17625e-05 3.86622e-03
529  5 p4 -4.61736e-02 8.07940e-03 3.25775e-06 -1.37247e-02
530  */
531 
532 
533  /*
534  FCN=34.4051 FROM MIGRAD STATUS=CONVERGED 221 CALLS 222 TOTAL
535  EDM=1.02201e-09 STRATEGY= 1 ERROR MATRIX UNCERTAINTY 2.3 per cent
536 
537  fConst
538  1 p0 7.99518e-01 2.23519e-02 1.41523e-06 4.05975e-04
539  2 p1 1.44619e-01 2.39398e-02 -7.68117e-07 -2.55775e-03
540 
541  fNorm
542  3 p2 -5.16571e-01 3.12362e-02 5.74932e-07 3.42292e-03
543  4 p3 4.69055e-01 5.09665e-02 1.94353e-07 1.69031e-03
544 
545  fExp
546  5 p4 -5.18044e-02 8.13458e-03 4.29815e-07 -1.07624e-02
547  */
548 
549  double fConst, fNorm, fExp;
550 
551  fConst = fConst_[0] + fConst_[1]*cFrac;
552  fNorm = fNorm_[0] - fNorm_[1]*cFrac;
553  fExp = fExp_[0];
554 
555  double factor = fConst - fNorm*exp( -fExp*pt );
556 
557  return factor;
558 
559 }
double ecalEnergy() const
return corrected Ecal energy
Definition: PFCandidate.h:222
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:251
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
bool isSecondaryNucl(const reco::PFCandidate &pf) const
void analyseNuclearWSec(reco::PFCandidateCollection &, std::vector< bool > &, unsigned int) const
Analyse nuclear interactions where a secondary track is present.
double rescaleFactor(const double pt, const double cFrac) const
Return a calibration factor for a reconstructed nuclear interaction.
static const reco::PFCandidate::Flags fT_FROM_DISP_
static const reco::PFCandidate::Flags fT_TO_DISP_
std::vector< ElementInBlock > ElementsInBlocks
Definition: PFCandidate.h:387
reco::PFDisplacedVertexRef displacedVertexRef(Flags type) const
Definition: PFCandidate.cc:528
U second(std::pair< T, U > const &p)
T sqrt(T t)
Definition: SSEVec.h:18
double p4[4]
Definition: TauolaWrapper.h:92
double pt() const
track transverse momentum
Definition: TrackBase.h:660
bool flag(Flags theFlag) const
return a given flag
Definition: PFCandidate.cc:304
const LorentzVector & p4() const final
four-momentum Lorentz vector
Definition: LeafCandidate.h:99
reco::PFCandidateCollection connect(reco::PFCandidateCollection &pfCand) const
void analyseNuclearWPrim(reco::PFCandidateCollection &, std::vector< bool > &, unsigned int) const
Analyse nuclear interactions where a primary or merged track is present.
static const double pion_mass2
Useful constants.
std::vector< reco::PFCandidate > PFCandidateCollection
collection of PFCandidates
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:30
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:40
fixed size matrix
double hcalEnergy() const
return corrected Hcal energy
Definition: PFCandidate.h:232
void setParameters(const edm::ParameterSet &iCfgCandConnector)