File indexing completed on 2024-04-06 12:24:08
0001 #include "PhysicsTools/RecoUtils/interface/CandKinematicVertexFitter.h"
0002 #include "RecoVertex/KinematicFit/interface/KinematicParticleFitter.h"
0003 #include "RecoVertex/KinematicFit/interface/MassKinematicConstraint.h"
0004 #include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
0005 #include "DataFormats/Candidate/interface/VertexCompositeCandidate.h"
0006 #include "FWCore/Utilities/interface/EDMException.h"
0007 #include "SimGeneral/HepPDTRecord/interface/ParticleDataTable.h"
0008 #include "FWCore/Framework/interface/ESHandle.h"
0009 #include <sstream>
0010 #include <iostream>
0011 using namespace reco;
0012 using namespace std;
0013
0014
0015 bool CandKinematicVertexFitter::fit(const vector<RefCountedKinematicParticle> &particles) const {
0016 try {
0017 tree_ = fitter_.fit(particles);
0018 } catch (std::exception &err) {
0019 std::cerr << ">>> exception thrown by KinematicParticleVertexFitter:\n"
0020 << err.what() << "\n"
0021 << ">>> candidate not fitted to common vertex" << std::endl;
0022 return false;
0023 }
0024
0025 if (tree_->isValid())
0026 return true;
0027 else
0028 return false;
0029 }
0030
0031
0032 void CandKinematicVertexFitter::set(VertexCompositeCandidate &c) const {
0033 if (bField_ == nullptr)
0034 throw edm::Exception(edm::errors::InvalidReference)
0035 << "B-Field was not set up CandKinematicVertexFitter.\n"
0036 << "the following method must be called before fitting a candidate:\n"
0037 << " CandKinematicVertexFitter:.set( const MagneticField * )" << endl;
0038 vector<RefCountedKinematicParticle> particles;
0039 vector<Candidate *> daughters;
0040 vector<RecoCandidate::TrackType> trackTypes;
0041
0042 fill(particles, daughters, trackTypes, c);
0043 assert(particles.size() == daughters.size());
0044
0045
0046 if (fit(particles)) {
0047
0048 tree_->movePointerToTheTop();
0049
0050 RefCountedKinematicVertex vertex = tree_->currentDecayVertex();
0051 if (vertex->vertexIsValid()) {
0052 Candidate::Point vtx(vertex->position());
0053 c.setVertex(vtx);
0054 vector<RefCountedKinematicParticle> treeParticles = tree_->daughterParticles();
0055 vector<RefCountedKinematicParticle>::const_iterator particleIt = treeParticles.begin();
0056 vector<Candidate *>::const_iterator daughterIt = daughters.begin(), daughtersEnd = daughters.end();
0057 vector<RecoCandidate::TrackType>::const_iterator trackTypeIt = trackTypes.begin();
0058 Candidate::LorentzVector mp4(0, 0, 0, 0);
0059 for (; daughterIt != daughtersEnd; ++particleIt, ++daughterIt, ++trackTypeIt) {
0060 Candidate &daughter = **daughterIt;
0061 GlobalVector p3 = (*particleIt)->currentState().globalMomentum();
0062 double px = p3.x(), py = p3.y(), pz = p3.z(), p = p3.mag();
0063 double energy;
0064
0065 if (!daughter.longLived())
0066 daughter.setVertex(vtx);
0067 double scale;
0068 switch (*trackTypeIt) {
0069 case RecoCandidate::gsfTrackType:
0070
0071 energy = daughter.energy();
0072 scale = energy / p;
0073 px *= scale;
0074 py *= scale;
0075 pz *= scale;
0076 [[fallthrough]];
0077 default:
0078 double mass = (*particleIt)->currentState().mass();
0079 energy = sqrt(p * p + mass * mass);
0080 };
0081 Candidate::LorentzVector dp4(px, py, pz, energy);
0082 daughter.setP4(dp4);
0083 mp4 += dp4;
0084 }
0085 c.setP4(mp4);
0086 c.setChi2AndNdof(chi2_ = vertex->chiSquared(), ndof_ = vertex->degreesOfFreedom());
0087 GlobalError err = vertex->error();
0088 cov_(0, 0) = err.cxx();
0089 cov_(0, 1) = err.cyx();
0090 cov_(0, 2) = err.czx();
0091 cov_(1, 2) = err.czy();
0092 cov_(1, 1) = err.cyy();
0093 cov_(2, 2) = err.czz();
0094 c.setCovariance(cov_);
0095 }
0096 } else {
0097 c.setChi2AndNdof(chi2_ = -1, ndof_ = 0);
0098 c.setCovariance(cov_ = CovarianceMatrix(ROOT::Math::SMatrixIdentity()));
0099 }
0100 }
0101
0102
0103 void CandKinematicVertexFitter::fill(vector<RefCountedKinematicParticle> &particles,
0104 vector<Candidate *> &daughters,
0105 vector<RecoCandidate::TrackType> &trackTypes,
0106 Candidate &c) const {
0107 size_t nDau = c.numberOfDaughters();
0108
0109 for (unsigned int j = 0; j < nDau; ++j) {
0110 Candidate *d = c.daughter(j);
0111 if (d == nullptr) {
0112 ostringstream message;
0113 message << "Can't access in write mode candidate daughters. "
0114 << "pdgId = " << c.pdgId() << ".\n";
0115 const Candidate *d1 = c.daughter(j);
0116 if (d1 == nullptr)
0117 message << "Null daughter also found in read-only mode\n";
0118 else
0119 message << "Daughter found in read-only mode with id: " << d1->pdgId() << "\n";
0120 throw edm::Exception(edm::errors::InvalidReference) << message.str();
0121 }
0122
0123 if (d->numberOfDaughters() > 0) {
0124
0125 VertexCompositeCandidate *vtxDau = dynamic_cast<VertexCompositeCandidate *>(d);
0126 if (vtxDau != nullptr && vtxDau->vertexChi2() > 0) {
0127
0128 (*this).set(*vtxDau);
0129
0130 if (vtxDau->massConstraint()) {
0131 KinematicParticleFitter csFitter;
0132
0133 const ParticleData *data = pdt_->particle(vtxDau->pdgId());
0134 ParticleMass mass = data->mass();
0135 float mass_sigma = mass * 0.000001;
0136
0137
0138 MassKinematicConstraint mkc(mass, mass_sigma);
0139 KinematicConstraint *mass_c(&mkc);
0140 tree_ = csFitter.fit(mass_c, tree_);
0141
0142
0143 }
0144
0145 RefCountedKinematicParticle current = (*this).currentParticle();
0146 particles.push_back(current);
0147 daughters.push_back(d);
0148 trackTypes.push_back(RecoCandidate::noTrackType);
0149 } else {
0150 fill(particles, daughters, trackTypes, *d);
0151 }
0152 } else {
0153
0154 TrackRef trk = d->get<TrackRef>();
0155 RecoCandidate::TrackType type = d->get<RecoCandidate::TrackType>();
0156 if (!trk.isNull()) {
0157 TransientTrack trTrk(trk, bField_);
0158 float chi2 = 0, ndof = 0;
0159 ParticleMass mass = d->mass();
0160 float sigma = mass * 1.e-6;
0161 particles.push_back(factory_.particle(trTrk, mass, chi2, ndof, sigma));
0162 daughters.push_back(d);
0163 trackTypes.push_back(type);
0164 } else {
0165 cerr << ">>> warning: candidate of type " << d->pdgId() << " has no track reference." << endl;
0166 }
0167 }
0168 }
0169 }