00001 #include "PhysicsTools/RecoUtils/interface/CandCommonVertexFitter.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 using namespace reco; 00007 using namespace std; 00008 00009 void CandCommonVertexFitterBase::set(VertexCompositeCandidate & c) const { 00010 if(bField_ == 0) 00011 throw edm::Exception(edm::errors::InvalidReference) 00012 << "B-Field was not set up CandCommonVertexFitter.\n" 00013 << "the following method must be called before fitting a candidate:\n" 00014 << " CandCommonVertexFitter:.set( const MagneticField * )" << endl; 00015 vector<TransientTrack> tracks; 00016 vector<Candidate *> daughters; 00017 vector<RecoCandidate::TrackType> trackTypes; 00018 fill(tracks, daughters, trackTypes, c); 00019 assert(tracks.size() == daughters.size()); 00020 TransientVertex vertex; 00021 if(fit(vertex, tracks)) { 00022 tracks = vertex.refittedTracks(); 00023 Candidate::Point vtx(vertex.position()); 00024 c.setVertex(vtx); 00025 vector<TransientTrack>::const_iterator trackIt = tracks.begin(), tracksEnd = tracks.end(); 00026 vector<Candidate *>::const_iterator daughterIt = daughters.begin(); 00027 vector<RecoCandidate::TrackType>::const_iterator trackTypeIt = trackTypes.begin(); 00028 Candidate::LorentzVector mp4(0, 0, 0, 0); 00029 for(; trackIt != tracksEnd; ++ trackIt, ++ daughterIt, ++trackTypeIt) { 00030 const Track & track = trackIt->track(); 00031 Candidate & daughter = * * daughterIt; 00032 double px = track.px(), py = track.py(), pz = track.pz(), p = track.p(); 00033 double energy; 00034 daughter.setVertex( vtx ); 00035 if(*trackTypeIt == RecoCandidate::recoTrackType) { 00036 double mass = daughter.mass(); 00037 energy = sqrt(p*p + mass*mass); 00038 } else { 00039 energy = daughter.energy(); 00040 double scale = energy / p; 00041 px *= scale; py *= scale; pz *= scale; 00042 } 00043 Candidate::LorentzVector dp4(px, py, pz, energy); 00044 daughter.setP4(dp4); 00045 mp4 += dp4; 00046 } 00047 c.setP4(mp4); 00048 Vertex v = vertex; 00049 c.setChi2AndNdof(chi2_ = v.chi2(), ndof_ = v.ndof()); 00050 v.fill(cov_); 00051 c.setCovariance(cov_); 00052 } else { 00053 c.setChi2AndNdof(chi2_ = -1, ndof_ = 0); 00054 c.setCovariance(cov_ = CovarianceMatrix(ROOT::Math::SMatrixIdentity())); 00055 } 00056 } 00057 00058 void CandCommonVertexFitterBase::fill(vector<TransientTrack> & tracks, 00059 vector<Candidate *> & daughters, 00060 vector<RecoCandidate::TrackType> & trackTypes, 00061 Candidate & c) const { 00062 size_t nDau = c.numberOfDaughters(); 00063 for(unsigned int j = 0; j < nDau ; ++j) { 00064 Candidate * d = c.daughter(j); 00065 if(d == 0) { 00066 ostringstream message; 00067 message << "Can't access in write mode candidate daughters. " 00068 << "pdgId = " << c.pdgId() << ".\n"; 00069 const Candidate * d1 = c.daughter(j); 00070 if(d1 == 0) 00071 message << "Null daughter also found in read-only mode\n"; 00072 else 00073 message << "Daughter found in read-only mode with id: " << d1->pdgId() << "\n"; 00074 throw edm::Exception(edm::errors::InvalidReference) << message.str(); 00075 } 00076 if(d->numberOfDaughters() > 0) 00077 fill(tracks, daughters, trackTypes, * d); 00078 else { 00079 const Track * trk = d->get<const Track *>(); 00080 RecoCandidate::TrackType type = d->get<RecoCandidate::TrackType>(); 00081 if(trk != 0) { 00082 tracks.push_back(TransientTrack(* trk, bField_)); 00083 daughters.push_back(d); 00084 trackTypes.push_back(type); 00085 } else { 00086 cerr << ">>> warning: candidate of type " << d->pdgId() 00087 << " has no track reference." << endl; 00088 } 00089 } 00090 } 00091 }