00001 #include "PhysicsTools/RecoUtils/interface/CandKinematicVertexFitter.h" 00002 #include "DataFormats/GsfTrackReco/interface/GsfTrack.h" 00003 #include "DataFormats/Candidate/interface/VertexCompositeCandidate.h" 00004 #include "FWCore/Utilities/interface/EDMException.h" 00005 #include <sstream> 00006 #include <iostream> 00007 using namespace reco; 00008 using namespace std; 00009 00010 bool CandKinematicVertexFitter::fit(const vector<RefCountedKinematicParticle> & particles) const { 00011 try { 00012 tree_ = fitter_.fit(particles); 00013 } catch (std::exception & err) { 00014 std::cerr << ">>> exception thrown by KinematicParticleVertexFitter:\n" 00015 << err.what() << "\n" 00016 << ">>> candidate not fitted to common vertex" << std::endl; 00017 return false; 00018 } 00019 return true; 00020 } 00021 00022 void CandKinematicVertexFitter::set(VertexCompositeCandidate & c) const { 00023 if(bField_ == 0) 00024 throw edm::Exception(edm::errors::InvalidReference) 00025 << "B-Field was not set up CandKinematicVertexFitter.\n" 00026 << "the following method must be called before fitting a candidate:\n" 00027 << " CandKinematicVertexFitter:.set( const MagneticField * )" << endl; 00028 vector<RefCountedKinematicParticle> particles; 00029 vector<Candidate *> daughters; 00030 vector<RecoCandidate::TrackType> trackTypes; 00031 fill(particles, daughters, trackTypes, c); 00032 assert(particles.size() == daughters.size()); 00033 if(fit(particles)) { 00034 tree_->movePointerToTheTop(); 00035 RefCountedKinematicVertex vertex = tree_->currentDecayVertex(); 00036 if(vertex->vertexIsValid()) { 00037 Candidate::Point vtx(vertex->position()); 00038 c.setVertex(vtx); 00039 vector<RefCountedKinematicParticle> treeParticles = tree_->daughterParticles(); 00040 vector<RefCountedKinematicParticle>::const_iterator particleIt = treeParticles.begin(); 00041 vector<Candidate *>::const_iterator daughterIt = daughters.begin(), daughtersEnd = daughters.end(); 00042 vector<RecoCandidate::TrackType>::const_iterator trackTypeIt = trackTypes.begin(); 00043 Candidate::LorentzVector mp4(0, 0, 0, 0); 00044 for(; daughterIt != daughtersEnd; ++ particleIt, ++ daughterIt, ++trackTypeIt) { 00045 GlobalVector p3 = (*particleIt)->currentState().globalMomentum(); 00046 double px = p3.x(), py = p3.y(), pz = p3.z(), p = p3.mag(); 00047 double energy; 00048 Candidate & daughter = * * daughterIt; 00049 if(!daughter.longLived()) daughter.setVertex(vtx); 00050 double scale; 00051 switch(*trackTypeIt) { 00052 case RecoCandidate::gsfTrackType : 00053 energy = daughter.energy(); 00054 scale = energy / p; 00055 px *= scale; py *= scale; pz *= scale; 00056 default: 00057 double mass = daughter.mass(); 00058 energy = sqrt(p*p + mass*mass); 00059 }; 00060 Candidate::LorentzVector dp4(px, py, pz, energy); 00061 daughter.setP4(dp4); 00062 mp4 += dp4; 00063 } 00064 c.setP4(mp4); 00065 c.setChi2AndNdof(chi2_ = vertex->chiSquared(), ndof_ = vertex->degreesOfFreedom()); 00066 GlobalError err = vertex->error(); 00067 cov_(0,0) = err.cxx(); 00068 cov_(0,1) = err.cyx(); 00069 cov_(0,2) = err.czx(); 00070 cov_(1,2) = err.czy(); 00071 cov_(1,1) = err.cyy(); 00072 cov_(2,2) = err.czz(); 00073 c.setCovariance(cov_); 00074 } 00075 } else { 00076 c.setChi2AndNdof(chi2_ = -1, ndof_ = 0); 00077 c.setCovariance(cov_ = CovarianceMatrix(ROOT::Math::SMatrixIdentity())); 00078 } 00079 } 00080 00081 void CandKinematicVertexFitter::fill(vector<RefCountedKinematicParticle> & particles, 00082 vector<Candidate *> & daughters, 00083 vector<RecoCandidate::TrackType> & trackTypes, 00084 Candidate & c) const { 00085 size_t nDau = c.numberOfDaughters(); 00086 for(unsigned int j = 0; j < nDau ; ++j) { 00087 Candidate * d = c.daughter(j); 00088 if(d == 0) { 00089 ostringstream message; 00090 message << "Can't access in write mode candidate daughters. " 00091 << "pdgId = " << c.pdgId() << ".\n"; 00092 const Candidate * d1 = c.daughter(j); 00093 if(d1 == 0) 00094 message << "Null daughter also found in read-only mode\n"; 00095 else 00096 message << "Daughter found in read-only mode with id: " << d1->pdgId() << "\n"; 00097 throw edm::Exception(edm::errors::InvalidReference) << message.str(); 00098 } 00099 if(d->numberOfDaughters() > 0) { 00100 VertexCompositeCandidate * vtxDau = dynamic_cast<VertexCompositeCandidate*>(d); 00101 if(vtxDau!=0 && vtxDau->longLived()) { 00102 fitters_->push_back(CandKinematicVertexFitter(*this)); 00103 CandKinematicVertexFitter & fitter = fitters_->back(); 00104 fitter.set(*vtxDau); 00105 RefCountedKinematicParticle current = fitter.currentParticle(); 00106 particles.push_back(current); 00107 daughters.push_back(d); 00108 trackTypes.push_back(RecoCandidate::noTrackType); 00109 } else 00110 fill(particles, daughters, trackTypes, *d); 00111 } 00112 else { 00113 const Track * trk = d->get<const Track *>(); 00114 RecoCandidate::TrackType type = d->get<RecoCandidate::TrackType>(); 00115 if(trk != 0) { 00116 TransientTrack trTrk(*trk, bField_); 00117 float chi2 = 0, ndof = 0; 00118 ParticleMass mass = d->mass(); 00119 float sigma = mass *1.e-6; 00120 particles.push_back(factory_.particle(trTrk, mass, chi2, ndof, sigma)); 00121 daughters.push_back(d); 00122 trackTypes.push_back(type); 00123 } else { 00124 cerr << ">>> warning: candidate of type " << d->pdgId() 00125 << " has no track reference." << endl; 00126 } 00127 } 00128 } 00129 }