Go to the documentation of this file.00001 #include "RecoParticleFlow/PFProducer/interface/PFCandConnector.h"
00002 #include "DataFormats/ParticleFlowReco/interface/PFDisplacedVertexFwd.h"
00003 #include "DataFormats/ParticleFlowReco/interface/PFDisplacedVertex.h"
00004 #include "DataFormats/ParticleFlowReco/interface/PFBlock.h"
00005 #include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
00006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00007
00008 using namespace reco;
00009 using namespace std;
00010
00011 const double PFCandConnector::pion_mass2 = 0.0194;
00012
00013 const reco::PFCandidate::Flags PFCandConnector::fT_TO_DISP_ = PFCandidate::T_TO_DISP;
00014 const reco::PFCandidate::Flags PFCandConnector::fT_FROM_DISP_ = PFCandidate::T_FROM_DISP;
00015
00016 void PFCandConnector::setParameters(bool bCorrect, bool bCalibPrimary, double dptRel_PrimaryTrack, double dptRel_MergedTrack, double ptErrorSecondary, std::vector<double> nuclCalibFactors){
00017
00018 bCorrect_ = bCorrect;
00019 bCalibPrimary_ = bCalibPrimary;
00020 dptRel_PrimaryTrack_ = dptRel_PrimaryTrack;
00021 dptRel_MergedTrack_ = dptRel_MergedTrack;
00022 ptErrorSecondary_ = ptErrorSecondary;
00023
00024 if (nuclCalibFactors.size() == 5) {
00025 fConst_[0] = nuclCalibFactors[0];
00026 fConst_[1] = nuclCalibFactors[1];
00027
00028 fNorm_[0] = nuclCalibFactors[2];
00029 fNorm_[1] = nuclCalibFactors[3];
00030
00031 fExp_[0] = nuclCalibFactors[4];
00032 } else {
00033 edm::LogWarning("PFCandConnector") << "Wrong calibration factors for nuclear interactions. The calibration procedure would not be applyed." << std::endl;
00034 bCalibPrimary_ = false;
00035 }
00036
00037 std::string sCorrect = bCorrect_ ? "On" : "Off";
00038 edm::LogInfo("PFCandConnector") << " ====================== The PFCandConnector is switched " << sCorrect.c_str() << " ==================== " << std::endl;
00039 std::string sCalibPrimary = bCalibPrimary_ ? "used for calibration" : "not used for calibration";
00040 if (bCorrect_) edm::LogInfo("PFCandConnector") << "Primary Tracks are " << sCalibPrimary.c_str() << std::endl;
00041 if (bCorrect_ && bCalibPrimary_) edm::LogInfo("PFCandConnector") << "Under the condition that the precision on the Primary track is better than " << dptRel_PrimaryTrack_ << " % "<< std::endl;
00042 if (bCorrect_ && bCalibPrimary_) edm::LogInfo("PFCandConnector") << " and on merged tracks better than " << dptRel_MergedTrack_ << " % "<< std::endl;
00043 if (bCorrect_ && bCalibPrimary_) edm::LogInfo("PFCandConnector") << " and secondary tracks in some cases more precise than " << ptErrorSecondary_ << " GeV"<< std::endl;
00044 if (bCorrect_ && bCalibPrimary_) edm::LogInfo("PFCandConnector") << "factor = (" << fConst_[0] << " + " << fConst_[1] << "*cFrac) - ("
00045 << fNorm_[0] << " - " << fNorm_[1] << "cFrac)*exp( "
00046 << -1*fExp_[0] << "*pT )"<< std::endl;
00047 edm::LogInfo("PFCandConnector") << " =========================================================== " << std::endl;
00048
00049 }
00050
00051
00052
00053 std::auto_ptr<reco::PFCandidateCollection>
00054 PFCandConnector::connect(std::auto_ptr<PFCandidateCollection>& pfCand) {
00055
00056 if(pfC_.get() ) pfC_->clear();
00057 else
00058 pfC_.reset( new PFCandidateCollection );
00059
00060 bMask_.clear();
00061 bMask_.resize(pfCand->size(), false);
00062
00063
00064
00065
00066 if (bCorrect_){
00067 if(debug_){
00068 cout << "" << endl;
00069 cout << "==================== ------------------------------ ===============" << endl;
00070 cout << "==================== Cand Connector ===============" << endl;
00071 cout << "==================== ------------------------------ ===============" << endl;
00072 cout << "==================== \tfor " << pfCand->size() << " Candidates\t =============" << endl;
00073 cout << "==================== primary calibrated " << bCalibPrimary_ << " =============" << endl;
00074 }
00075
00076 for( unsigned int ce1=0; ce1 < pfCand->size(); ++ce1){
00077 if ( isPrimaryNucl(pfCand->at(ce1)) ){
00078
00079 if (debug_)
00080 cout << "" << endl << "Nuclear Interaction w Primary Candidate " << ce1
00081 << " " << pfCand->at(ce1) << endl
00082 << " based on the Track " << pfCand->at(ce1).trackRef().key()
00083 << " w pT = " << pfCand->at(ce1).trackRef()->pt()
00084 << " #pm " << pfCand->at(ce1).trackRef()->ptError()/pfCand->at(ce1).trackRef()->pt()*100 << " %"
00085 << " ECAL = " << pfCand->at(ce1).ecalEnergy()
00086 << " HCAL = " << pfCand->at(ce1).hcalEnergy() << endl;
00087
00088 if (debug_) (pfCand->at(ce1)).displacedVertexRef(fT_TO_DISP_)->Dump();
00089
00090 analyseNuclearWPrim(pfCand, ce1);
00091
00092 if (debug_){
00093 cout << "After Connection the candidate " << ce1
00094 << " is " << pfCand->at(ce1) << endl << endl;
00095
00096 PFCandidate::ElementsInBlocks elementsInBlocks = pfCand->at(ce1).elementsInBlocks();
00097 for (unsigned blockElem = 0; blockElem < elementsInBlocks.size(); blockElem++){
00098 if (blockElem == 0) cout << *(elementsInBlocks[blockElem].first) << endl;
00099 cout << " position " << elementsInBlocks[blockElem].second;
00100 }
00101 }
00102
00103 }
00104
00105 }
00106
00107 for( unsigned int ce1=0; ce1 < pfCand->size(); ++ce1){
00108 if ( !bMask_[ce1] && isSecondaryNucl(pfCand->at(ce1)) ){
00109 if (debug_)
00110 cout << "" << endl << "Nuclear Interaction w no Primary Candidate " << ce1
00111 << " " << pfCand->at(ce1) << endl
00112 << " based on the Track " << pfCand->at(ce1).trackRef().key()
00113 << " w pT = " << pfCand->at(ce1).trackRef()->pt()
00114 << " #pm " << pfCand->at(ce1).trackRef()->ptError() << " %"
00115 << " ECAL = " << pfCand->at(ce1).ecalEnergy()
00116 << " HCAL = " << pfCand->at(ce1).hcalEnergy()
00117 << " dE(Trk-CALO) = " << pfCand->at(ce1).trackRef()->p()-pfCand->at(ce1).ecalEnergy()-pfCand->at(ce1).hcalEnergy()
00118 << " Nmissing hits = " << pfCand->at(ce1).trackRef()->trackerExpectedHitsOuter().numberOfHits() << endl;
00119
00120 if (debug_) (pfCand->at(ce1)).displacedVertexRef(fT_FROM_DISP_)->Dump();
00121
00122 analyseNuclearWSec(pfCand, ce1);
00123
00124 if (debug_) {
00125 cout << "After Connection the candidate " << ce1
00126 << " is " << pfCand->at(ce1)
00127 << " and elements connected to it are: " << endl;
00128
00129 PFCandidate::ElementsInBlocks elementsInBlocks = pfCand->at(ce1).elementsInBlocks();
00130 for (unsigned blockElem = 0; blockElem < elementsInBlocks.size(); blockElem++){
00131 if (blockElem == 0) cout << *(elementsInBlocks[blockElem].first) << endl;
00132 cout << " position " << elementsInBlocks[blockElem].second;
00133 }
00134 }
00135
00136 }
00137
00138
00139 }
00140 }
00141
00142
00143
00144
00145 for( unsigned int ce1=0; ce1 < pfCand->size(); ++ce1)
00146 if (!bMask_[ce1]) pfC_->push_back(pfCand->at(ce1));
00147
00148
00149 if(debug_ && bCorrect_) cout << "==================== ------------------------------ ===============" << endl<< endl << endl;
00150
00151 return pfC_;
00152
00153
00154 }
00155
00156 void
00157 PFCandConnector::analyseNuclearWPrim(std::auto_ptr<PFCandidateCollection>& pfCand, unsigned int ce1) {
00158
00159
00160 PFDisplacedVertexRef ref1, ref2, ref1_bis;
00161
00162 PFCandidate primaryCand = pfCand->at(ce1);
00163
00164
00165
00166 math::XYZTLorentzVectorD momentumPrim = primaryCand.p4();
00167
00168 math::XYZTLorentzVectorD momentumSec;
00169
00170 momentumSec = momentumPrim/momentumPrim.E()*(primaryCand.ecalEnergy() + primaryCand.hcalEnergy());
00171
00172 map<double, math::XYZTLorentzVectorD> candidatesWithTrackExcess;
00173 map<double, math::XYZTLorentzVectorD> candidatesWithoutCalo;
00174
00175
00176 ref1 = primaryCand.displacedVertexRef(fT_TO_DISP_);
00177
00178 for( unsigned int ce2=0; ce2 < pfCand->size(); ++ce2) {
00179 if (ce2 != ce1 && isSecondaryNucl(pfCand->at(ce2))){
00180
00181 ref2 = (pfCand->at(ce2)).displacedVertexRef(fT_FROM_DISP_);
00182
00183 if (ref1 == ref2) {
00184
00185 if (debug_) cout << "\t here is a Secondary Candidate " << ce2
00186 << " " << pfCand->at(ce2) << endl
00187 << "\t based on the Track " << pfCand->at(ce2).trackRef().key()
00188 << " w p = " << pfCand->at(ce2).trackRef()->p()
00189 << " w pT = " << pfCand->at(ce2).trackRef()->pt()
00190 << " #pm " << pfCand->at(ce2).trackRef()->ptError() << " %"
00191 << " ECAL = " << pfCand->at(ce2).ecalEnergy()
00192 << " HCAL = " << pfCand->at(ce2).hcalEnergy()
00193 << " dE(Trk-CALO) = " << pfCand->at(ce2).trackRef()->p()-pfCand->at(ce2).ecalEnergy()-pfCand->at(ce2).hcalEnergy()
00194 << " Nmissing hits = " << pfCand->at(ce2).trackRef()->trackerExpectedHitsOuter().numberOfHits() << endl;
00195
00196 if(isPrimaryNucl(pfCand->at(ce2))){
00197 if (debug_) cout << "\t\t but it is also a Primary Candidate " << ce2 << endl;
00198
00199 ref1_bis = (pfCand->at(ce2)).displacedVertexRef(fT_TO_DISP_);
00200 if(ref1_bis.isNonnull()) analyseNuclearWPrim(pfCand, ce2);
00201 }
00202
00203
00204
00205 PFCandidate::ElementsInBlocks elementsInBlocks = pfCand->at(ce2).elementsInBlocks();
00206 PFCandidate::ElementsInBlocks elementsAlreadyInBlocks = pfCand->at(ce1).elementsInBlocks();
00207 for (unsigned blockElem = 0; blockElem < elementsInBlocks.size(); blockElem++){
00208 bool isAlreadyHere = false;
00209 for (unsigned alreadyBlock = 0; alreadyBlock < elementsAlreadyInBlocks.size(); alreadyBlock++){
00210 if (elementsAlreadyInBlocks[alreadyBlock].second == elementsInBlocks[blockElem].second) isAlreadyHere = true;
00211 }
00212 if (!isAlreadyHere) pfCand->at(ce1).addElementInBlock( elementsInBlocks[blockElem].first, elementsInBlocks[blockElem].second);
00213 }
00214
00215 double caloEn = pfCand->at(ce2).ecalEnergy() + pfCand->at(ce2).hcalEnergy();
00216 double deltaEn = pfCand->at(ce2).p4().E() - caloEn;
00217 int nMissOuterHits = pfCand->at(ce2).trackRef()->trackerExpectedHitsOuter().numberOfHits();
00218
00219
00220
00221 if (deltaEn > 1 && nMissOuterHits > 1) {
00222 math::XYZTLorentzVectorD momentumToAdd = pfCand->at(ce2).p4()*caloEn/pfCand->at(ce2).p4().E();
00223 momentumSec += momentumToAdd;
00224 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;
00225
00226 } else {
00227
00228 if (caloEn > 0.01 && deltaEn > 1 && nMissOuterHits > 0) {
00229 math::XYZTLorentzVectorD momentumExcess = pfCand->at(ce2).p4()*deltaEn/pfCand->at(ce2).p4().E();
00230 candidatesWithTrackExcess[pfCand->at(ce2).trackRef()->pt()/pfCand->at(ce2).trackRef()->ptError()] = momentumExcess;
00231 }
00232 else if(caloEn < 0.01) candidatesWithoutCalo[pfCand->at(ce2).trackRef()->pt()/pfCand->at(ce2).trackRef()->ptError()] = pfCand->at(ce2).p4();
00233 momentumSec += (pfCand->at(ce2)).p4();
00234 }
00235
00236 bMask_[ce2] = true;
00237
00238
00239
00240 }
00241 }
00242 }
00243
00244
00245
00246
00247
00248 if (momentumPrim.E() < momentumSec.E()){
00249
00250 if(debug_) cout << "Size of 0 calo Energy secondary candidates" << candidatesWithoutCalo.size() << endl;
00251 for( map<double, math::XYZTLorentzVectorD>::iterator iter = candidatesWithoutCalo.begin(); iter != candidatesWithoutCalo.end() && momentumPrim.E() < momentumSec.E(); iter++)
00252 if (momentumSec.E() > iter->second.E()+0.1) {
00253 momentumSec -= iter->second;
00254
00255 if(debug_) cout << "\t Remove a SecondaryCandidate with 0 calo energy " << iter->second << endl;
00256
00257 if(debug_) cout << "momentumPrim.E() = " << momentumPrim.E() << " and momentumSec.E() = " << momentumSec.E() << endl;
00258
00259 }
00260
00261 }
00262
00263
00264 if (momentumPrim.E() < momentumSec.E()){
00265 if(debug_) cout << "0 Calo Energy rejected but still not sufficient. Size of not enough calo Energy secondary candidates" << candidatesWithTrackExcess.size() << endl;
00266 for( map<double, math::XYZTLorentzVectorD>::iterator iter = candidatesWithTrackExcess.begin(); iter != candidatesWithTrackExcess.end() && momentumPrim.E() < momentumSec.E(); iter++)
00267 if (momentumSec.E() > iter->second.E()+0.1) momentumSec -= iter->second;
00268
00269 }
00270
00271
00272
00273
00274 double dpt = pfCand->at(ce1).trackRef()->ptError()/pfCand->at(ce1).trackRef()->pt()*100;
00275
00276 if (momentumSec.E() < 0.1) {
00277 bMask_[ce1] = true;
00278 return;
00279 }
00280
00281
00282
00283
00284 if( ( (ref1->isTherePrimaryTracks() && dpt<dptRel_PrimaryTrack_) || (ref1->isThereMergedTracks() && dpt<dptRel_MergedTrack_) ) && momentumPrim.E() > momentumSec.E() && momentumSec.E() > 0.1) {
00285
00286 if (bCalibPrimary_){
00287 double factor = rescaleFactor( momentumPrim.Pt(), momentumSec.E()/momentumPrim.E());
00288 if (debug_) cout << "factor = " << factor << endl;
00289 if (factor*momentumPrim.Pt() < momentumSec.Pt()) momentumSec = momentumPrim;
00290 else momentumSec += (1-factor)*momentumPrim;
00291 }
00292
00293 double px = momentumPrim.Px()*momentumSec.P()/momentumPrim.P();
00294 double py = momentumPrim.Py()*momentumSec.P()/momentumPrim.P();
00295 double pz = momentumPrim.Pz()*momentumSec.P()/momentumPrim.P();
00296 double E = sqrt(px*px + py*py + pz*pz + pion_mass2);
00297 math::XYZTLorentzVectorD momentum(px, py, pz, E);
00298 pfCand->at(ce1).setP4(momentum);
00299
00300 return;
00301
00302 } else {
00303
00304 math::XYZVector primDir = ref1->primaryDirection();
00305
00306
00307 if (primDir.Mag2() < 0.1){
00308
00309 edm::LogWarning("PFCandConnector") << "A Nuclear Interaction do not have primary direction" << std::endl;
00310 pfCand->at(ce1).setP4(momentumSec);
00311 return;
00312 } else {
00313
00314 double momentumS = momentumSec.P();
00315 if (momentumS < 1e-4) momentumS = 1e-4;
00316 double px = momentumS*primDir.x();
00317 double py = momentumS*primDir.y();
00318 double pz = momentumS*primDir.z();
00319 double E = sqrt(px*px + py*py + pz*pz + pion_mass2);
00320
00321 math::XYZTLorentzVectorD momentum(px, py, pz, E);
00322 pfCand->at(ce1).setP4(momentum);
00323 return;
00324 }
00325 }
00326
00327
00328
00329 }
00330
00331
00332
00333
00334 void
00335 PFCandConnector::analyseNuclearWSec(std::auto_ptr<PFCandidateCollection>& pfCand, unsigned int ce1){
00336
00337 PFDisplacedVertexRef ref1, ref2;
00338
00339
00340
00341
00342 double caloEn = pfCand->at(ce1).ecalEnergy() + pfCand->at(ce1).hcalEnergy();
00343 double deltaEn = pfCand->at(ce1).p4().E() - caloEn;
00344 int nMissOuterHits = pfCand->at(ce1).trackRef()->trackerExpectedHitsOuter().numberOfHits();
00345
00346
00347 ref1 = pfCand->at(ce1).displacedVertexRef(fT_FROM_DISP_);
00348
00349
00350
00351
00352 if (ref1->isTherePrimaryTracks() || ref1->isThereMergedTracks()){
00353
00354 std::vector<reco::Track> refittedTracks = ref1->refittedTracks();
00355 for(unsigned it = 0; it < refittedTracks.size(); it++){
00356 reco::TrackBaseRef primaryBaseRef = ref1->originalTrack(refittedTracks[it]);
00357 if (ref1->isIncomingTrack(primaryBaseRef))
00358 if (debug_) cout << "There is a Primary track ref with pt = " << primaryBaseRef->pt()<< endl;
00359
00360 for( unsigned int ce=0; ce < pfCand->size(); ++ce){
00361
00362 if ((pfCand->at(ce)).particleId() == reco::PFCandidate::e || (pfCand->at(ce)).particleId() == reco::PFCandidate::mu) {
00363
00364 if (debug_) cout << " It is an electron and it has a ref to a track " << (pfCand->at(ce)).trackRef().isNonnull() << endl;
00365
00366
00367 if ( (pfCand->at(ce)).trackRef().isNonnull() ){
00368 reco::TrackRef tRef = (pfCand->at(ce)).trackRef();
00369 reco::TrackBaseRef bRef(tRef);
00370 if (debug_) cout << "With Track Ref pt = " << (pfCand->at(ce)).trackRef()->pt() << endl;
00371
00372 if (bRef == primaryBaseRef) {
00373 if (debug_ && (pfCand->at(ce)).particleId() == reco::PFCandidate::e) cout << "It is a NI from electron. NI Discarded. Just release the candidate." << endl;
00374 if (debug_ && (pfCand->at(ce)).particleId() == reco::PFCandidate::mu) cout << "It is a NI from muon. NI Discarded. Just release the candidate" << endl;
00375
00376
00377
00378
00379 if (caloEn < 0.1 && pfCand->at(ce1).trackRef()->ptError() > ptErrorSecondary_) {
00380 cout << "discarded track since no calo energy and ill measured" << endl;
00381 bMask_[ce1] = true;
00382 }
00383 if (caloEn > 0.1 && deltaEn >ptErrorSecondary_ && pfCand->at(ce1).trackRef()->ptError() > ptErrorSecondary_) {
00384 cout << "rescaled momentum of the track since no calo energy and ill measured" << endl;
00385
00386 double factor = caloEn/pfCand->at(ce1).p4().E();
00387 pfCand->at(ce1).rescaleMomentum(factor);
00388 }
00389
00390 return;
00391 }
00392 }
00393 }
00394 }
00395 }
00396 }
00397
00398
00399 PFCandidate secondaryCand = pfCand->at(ce1);
00400
00401 math::XYZTLorentzVectorD momentumSec = secondaryCand.p4();
00402
00403 if (deltaEn > ptErrorSecondary_ && nMissOuterHits > 1) {
00404 math::XYZTLorentzVectorD momentumToAdd = pfCand->at(ce1).p4()*caloEn/pfCand->at(ce1).p4().E();
00405 momentumSec = momentumToAdd;
00406 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;
00407 }
00408
00409
00410
00411 for( unsigned int ce2=ce1+1; ce2 < pfCand->size(); ++ce2) {
00412 if (isSecondaryNucl(pfCand->at(ce2))){
00413 ref2 = (pfCand->at(ce2)).displacedVertexRef(fT_FROM_DISP_);
00414
00415 if (ref1 == ref2) {
00416
00417 if (debug_) cout << "\t here is a Secondary Candidate " << ce2
00418 << " " << pfCand->at(ce2) << endl
00419 << "\t based on the Track " << pfCand->at(ce2).trackRef().key()
00420 << " w pT = " << pfCand->at(ce2).trackRef()->pt()
00421 << " #pm " << pfCand->at(ce2).trackRef()->ptError() << " %"
00422 << " ECAL = " << pfCand->at(ce2).ecalEnergy()
00423 << " HCAL = " << pfCand->at(ce2).hcalEnergy()
00424 << " dE(Trk-CALO) = " << pfCand->at(ce2).trackRef()->p()-pfCand->at(ce2).ecalEnergy()-pfCand->at(ce2).hcalEnergy()
00425 << " Nmissing hits = " << pfCand->at(ce2).trackRef()->trackerExpectedHitsOuter().numberOfHits() << endl;
00426
00427
00428 PFCandidate::ElementsInBlocks elementsInBlocks = pfCand->at(ce2).elementsInBlocks();
00429 PFCandidate::ElementsInBlocks elementsAlreadyInBlocks = pfCand->at(ce1).elementsInBlocks();
00430 for (unsigned blockElem = 0; blockElem < elementsInBlocks.size(); blockElem++){
00431 bool isAlreadyHere = false;
00432 for (unsigned alreadyBlock = 0; alreadyBlock < elementsAlreadyInBlocks.size(); alreadyBlock++){
00433 if (elementsAlreadyInBlocks[alreadyBlock].second == elementsInBlocks[blockElem].second) isAlreadyHere = true;
00434 }
00435 if (!isAlreadyHere) pfCand->at(ce1).addElementInBlock( elementsInBlocks[blockElem].first, elementsInBlocks[blockElem].second);
00436 }
00437
00438 double caloEn = pfCand->at(ce2).ecalEnergy() + pfCand->at(ce2).hcalEnergy();
00439 double deltaEn = pfCand->at(ce2).p4().E() - caloEn;
00440 int nMissOuterHits = pfCand->at(ce2).trackRef()->trackerExpectedHitsOuter().numberOfHits();
00441 if (deltaEn > ptErrorSecondary_ && nMissOuterHits > 1) {
00442 math::XYZTLorentzVectorD momentumToAdd = pfCand->at(ce2).p4()*caloEn/pfCand->at(ce2).p4().E();
00443 momentumSec += momentumToAdd;
00444 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;
00445 } else {
00446 momentumSec += (pfCand->at(ce2)).p4();
00447 }
00448
00449 bMask_[ce2] = true;
00450 }
00451 }
00452 }
00453
00454
00455
00456
00457 math::XYZVector primDir = ref1->primaryDirection();
00458
00459 if (primDir.Mag2() < 0.1){
00460
00461 pfCand->at(ce1).setP4(momentumSec);
00462 edm::LogWarning("PFCandConnector") << "A Nuclear Interaction do not have primary direction" << std::endl;
00463 return;
00464 } else {
00465
00466 double momentumS = momentumSec.P();
00467 if (momentumS < 1e-4) momentumS = 1e-4;
00468 double px = momentumS*primDir.x();
00469 double py = momentumS*primDir.y();
00470 double pz = momentumS*primDir.z();
00471 double E = sqrt(px*px + py*py + pz*pz + pion_mass2);
00472
00473 math::XYZTLorentzVectorD momentum(px, py, pz, E);
00474
00475 pfCand->at(ce1).setP4(momentum);
00476 return;
00477 }
00478
00479 }
00480
00481 bool
00482 PFCandConnector::isSecondaryNucl( const PFCandidate& pf ) const {
00483
00484 PFDisplacedVertexRef ref1;
00485
00486 if( pf.flag( fT_FROM_DISP_ ) ) {
00487 ref1 = pf.displacedVertexRef(fT_FROM_DISP_);
00488
00489 if (!ref1.isNonnull()) return false;
00490 else if (ref1->isNucl() || ref1->isNucl_Loose() || ref1->isNucl_Kink())
00491 return true;
00492 }
00493
00494 return false;
00495 }
00496
00497 bool
00498 PFCandConnector::isPrimaryNucl( const PFCandidate& pf ) const {
00499
00500 PFDisplacedVertexRef ref1;
00501
00502
00503 if( pf.flag( fT_TO_DISP_ ) ) {
00504 ref1 = pf.displacedVertexRef(fT_TO_DISP_);
00505
00506
00507 if (!ref1.isNonnull()) return false;
00508 else if (ref1->isNucl()|| ref1->isNucl_Loose() || ref1->isNucl_Kink())
00509 return true;
00510 }
00511
00512 return false;
00513 }
00514
00515
00516 double
00517 PFCandConnector::rescaleFactor( const double pt, const double cFrac ) const {
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550 double fConst, fNorm, fExp;
00551
00552 fConst = fConst_[0] + fConst_[1]*cFrac;
00553 fNorm = fNorm_[0] - fNorm_[1]*cFrac;
00554 fExp = fExp_[0];
00555
00556 double factor = fConst - fNorm*exp( -fExp*pt );
00557
00558 return factor;
00559
00560 }