File indexing completed on 2024-04-06 12:29:11
0001 #include "RecoVertex/KinematicFit/interface/FinalTreeBuilder.h"
0002 #include "RecoVertex/KinematicFitPrimitives/interface/KinematicRefittedTrackState.h"
0003 #include "RecoVertex/KinematicFitPrimitives/interface/KinematicStatePropagator.h"
0004 #include "RecoVertex/KinematicFitPrimitives/interface/KinematicState.h"
0005
0006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0007
0008 FinalTreeBuilder::FinalTreeBuilder() {
0009 kvFactory = new KinematicVertexFactory();
0010 KinematicStatePropagator* ksp = nullptr;
0011 pFactory = new VirtualKinematicParticleFactory(ksp);
0012 }
0013
0014 FinalTreeBuilder::~FinalTreeBuilder() {
0015 delete kvFactory;
0016 delete pFactory;
0017 }
0018
0019 RefCountedKinematicTree FinalTreeBuilder::buildTree(const CachingVertex<6>& vtx,
0020 const std::vector<RefCountedKinematicParticle>& input) const {
0021
0022 AlgebraicVector7 par;
0023 AlgebraicMatrix cov(7, 7, 0);
0024 par(0) = vtx.position().x();
0025 par(1) = vtx.position().y();
0026 par(2) = vtx.position().z();
0027 double en = 0.;
0028 int ch = 0;
0029
0030
0031 std::vector<KinematicRefittedTrackState*> rStates;
0032 std::vector<RefCountedVertexTrack> refTracks = vtx.tracks();
0033 for (std::vector<RefCountedVertexTrack>::const_iterator i = refTracks.begin(); i != refTracks.end(); ++i) {
0034 KinematicRefittedTrackState* rs = dynamic_cast<KinematicRefittedTrackState*>(&(*((*i)->refittedState())));
0035 AlgebraicVector4 f_mom = rs->kinematicMomentumVector();
0036 par(3) += f_mom(0);
0037 par(4) += f_mom(1);
0038 par(5) += f_mom(2);
0039 en += sqrt(f_mom(1) * f_mom(1) + f_mom(2) * f_mom(2) + f_mom(3) * f_mom(3) + f_mom(0) * f_mom(0));
0040 ch += (*i)->linearizedTrack()->charge();
0041 rStates.push_back(rs);
0042 }
0043
0044
0045 double differ = en * en - (par(3) * par(3) + par(4) * par(4) + par(5) * par(5));
0046 if (differ > 0.) {
0047 par(6) = sqrt(differ);
0048 } else {
0049 LogDebug("FinalTreeBuilder") << "Fit failed: Current precision does not allow to calculate the mass\n";
0050 return ReferenceCountingPointer<KinematicTree>(new KinematicTree());
0051 }
0052
0053
0054
0055 AlgebraicMatrix m_all = momentumPart(vtx, par);
0056
0057
0058
0059
0060
0061 cov.sub(1, 1, m_all);
0062
0063
0064 AlgebraicSymMatrix77 sCov;
0065 for (int i = 1; i < 8; i++) {
0066 for (int j = 1; j < 8; j++) {
0067 if (i <= j)
0068 sCov(i - 1, j - 1) = cov(i, j);
0069 }
0070 }
0071
0072
0073 RefCountedKinematicVertex dVrt = kvFactory->vertex(vtx);
0074
0075
0076 RefCountedKinematicVertex pVrt = kvFactory->vertex();
0077
0078
0079 KinematicParameters kPar(par);
0080 KinematicParametersError kEr(sCov);
0081 const MagneticField* field = input.front()->magneticField();
0082 KinematicState nState(kPar, kEr, ch, field);
0083
0084
0085 KinematicParticle* zp = nullptr;
0086 RefCountedKinematicParticle pPart = ReferenceCountingPointer<KinematicParticle>(zp);
0087
0088 float vChi = vtx.totalChiSquared();
0089 float vNdf = vtx.degreesOfFreedom();
0090 RefCountedKinematicParticle nPart = pFactory->particle(nState, vChi, vNdf, pPart);
0091
0092
0093 RefCountedKinematicTree resTree = ReferenceCountingPointer<KinematicTree>(new KinematicTree());
0094 resTree->addParticle(pVrt, dVrt, nPart);
0095
0096
0097 std::vector<RefCountedKinematicParticle> rrP;
0098
0099 std::vector<RefCountedKinematicParticle>::const_iterator j;
0100 std::vector<RefCountedVertexTrack>::const_iterator i;
0101 for (j = input.begin(), i = refTracks.begin(); j != input.end() && i != refTracks.end(); ++j, ++i) {
0102 RefCountedLinearizedTrackState lT = (*i)->linearizedTrack();
0103 KinematicRefittedTrackState* rS = dynamic_cast<KinematicRefittedTrackState*>(&(*((*i)->refittedState())));
0104
0105
0106 AlgebraicVector7 lPar = rS->kinematicParameters();
0107 KinematicParameters lkPar(lPar);
0108 AlgebraicSymMatrix77 lCov = rS->kinematicParametersCovariance();
0109 KinematicParametersError lkCov(lCov);
0110 TrackCharge lch = lT->charge();
0111 KinematicState nState(lkPar, lkCov, lch, field);
0112 RefCountedKinematicParticle nPart = (*j)->refittedParticle(nState, vChi, vNdf);
0113 rrP.push_back(nPart);
0114 if ((*j)->correspondingTree() != nullptr) {
0115
0116 KinematicTree* tree = (*j)->correspondingTree();
0117 tree->movePointerToTheTop();
0118 tree->replaceCurrentParticle(nPart);
0119 RefCountedKinematicVertex cdVertex = resTree->currentDecayVertex();
0120 resTree->addTree(cdVertex, tree);
0121 } else {
0122
0123 RefCountedKinematicVertex nV = kvFactory->vertex();
0124 resTree->addParticle(dVrt, nV, nPart);
0125 }
0126 }
0127 return resTree;
0128 }
0129
0130
0131
0132 AlgebraicMatrix FinalTreeBuilder::momentumPart(const CachingVertex<6>& vtx, const AlgebraicVector7& par) const {
0133 std::vector<RefCountedVertexTrack> refTracks = vtx.tracks();
0134 int size = refTracks.size();
0135 AlgebraicMatrix cov(7 + 4 * (size - 1), 7 + 4 * (size - 1));
0136 AlgebraicMatrix jac(7, 7 + 4 * (size - 1));
0137 jac(1, 1) = 1.;
0138 jac(2, 2) = 1.;
0139 jac(3, 3) = 1.;
0140
0141 double energy_total = sqrt(par(3) * par(3) + par(6) * par(6) + par(5) * par(5) + par(4) * par(4));
0142
0143 std::vector<RefCountedVertexTrack>::const_iterator rt_i;
0144 int i_int = 0;
0145 for (rt_i = refTracks.begin(); rt_i != refTracks.end(); rt_i++) {
0146 double a;
0147 AlgebraicVector6 param = (**rt_i).refittedState()->parameters();
0148 double rho = param[0];
0149 double theta = param[1];
0150 double phi = param[2];
0151 double mass = param[5];
0152
0153 if ((**rt_i).linearizedTrack()->charge() != 0) {
0154 a = -(**rt_i).refittedState()->freeTrajectoryState().parameters().magneticFieldInInverseGeV(vtx.position()).z() *
0155 (**rt_i).refittedState()->freeTrajectoryState().parameters().charge();
0156 if (a == 0.)
0157 throw cms::Exception("FinalTreeBuilder", "Field is 0");
0158 } else {
0159 a = 1;
0160 }
0161
0162 AlgebraicMatrix jc_el(4, 4, 0);
0163 jc_el(1, 1) = -a * cos(phi) / (rho * rho);
0164 jc_el(2, 1) = -a * sin(phi) / (rho * rho);
0165 jc_el(3, 1) = -a / (rho * rho * tan(theta));
0166
0167 jc_el(3, 2) = -a / (rho * sin(theta) * sin(theta));
0168
0169 jc_el(1, 3) = -a * sin(phi) / rho;
0170 jc_el(2, 3) = a * cos(phi) / rho;
0171
0172
0173 double energy_local = sqrt(a * a / (rho * rho) * (1 + 1 / (tan(theta) * tan(theta))) + mass * mass);
0174
0175 jc_el(4, 4) = energy_total * mass / (par(6) * energy_local);
0176
0177 jc_el(4, 1) = (-(energy_total / energy_local * a * a / (rho * rho * rho * sin(theta) * sin(theta))) +
0178 par(3) * a / (rho * rho) * cos(phi) + par(4) * a / (rho * rho) * sin(phi) +
0179 par(5) * a / (rho * rho * tan(theta))) /
0180 par(6);
0181
0182 jc_el(4, 2) = (-(energy_total / energy_local * a * a / (rho * rho * sin(theta) * sin(theta) * tan(theta))) +
0183 par(5) * a / (rho * sin(theta) * sin(theta))) /
0184 par(6);
0185
0186 jc_el(4, 3) = (par(3) * sin(phi) - par(4) * cos(phi)) * a / (rho * par(6));
0187
0188 jac.sub(4, i_int * 4 + 4, jc_el);
0189
0190
0191 if (i_int == 0) {
0192 cov.sub(1, 1, asHepMatrix<7>((**rt_i).fullCovariance()));
0193 } else {
0194
0195 AlgebraicMatrix fullCovMatrix(asHepMatrix<7>((**rt_i).fullCovariance()));
0196 AlgebraicMatrix m_m_cov = fullCovMatrix.sub(4, 7, 4, 7);
0197 AlgebraicMatrix x_p_cov = fullCovMatrix.sub(1, 3, 4, 7);
0198 AlgebraicMatrix p_x_cov = fullCovMatrix.sub(4, 7, 1, 3);
0199
0200
0201
0202
0203
0204
0205
0206
0207 cov.sub(i_int * 4 + 4, i_int * 4 + 4, m_m_cov);
0208
0209
0210 cov.sub(1, i_int * 4 + 4, x_p_cov);
0211 cov.sub(i_int * 4 + 4, 1, p_x_cov);
0212
0213
0214
0215 }
0216 int j_int = 0;
0217 for (std::vector<RefCountedVertexTrack>::const_iterator rt_j = refTracks.begin(); rt_j != refTracks.end(); rt_j++) {
0218 if (i_int < j_int) {
0219 AlgebraicMatrix i_k_cov_m = asHepMatrix<4, 4>(vtx.tkToTkCovariance((*rt_i), (*rt_j)));
0220
0221 cov.sub(i_int * 4 + 4, j_int * 4 + 4, i_k_cov_m);
0222 cov.sub(j_int * 4 + 4, i_int * 4 + 4, i_k_cov_m.T());
0223 }
0224 j_int++;
0225 }
0226 i_int++;
0227 }
0228
0229
0230
0231
0232 return jac * cov * jac.T();
0233 }