00001 #include "RecoVertex/KinematicFit/interface/ConstrainedTreeBuilder.h"
00002 #include "DataFormats/CLHEP/interface/Migration.h"
00003 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00004
00005 ConstrainedTreeBuilder::ConstrainedTreeBuilder()
00006 {
00007 pFactory = new VirtualKinematicParticleFactory();
00008 vFactory = new KinematicVertexFactory();
00009 }
00010
00011 ConstrainedTreeBuilder::~ConstrainedTreeBuilder()
00012 {
00013 delete pFactory;
00014 delete vFactory;
00015 }
00016
00017
00018 RefCountedKinematicTree ConstrainedTreeBuilder::buildTree(const std::vector<RefCountedKinematicParticle> & initialParticles,
00019 const std::vector<KinematicState> & finalStates,
00020 const RefCountedKinematicVertex vertex, const AlgebraicMatrix& fullCov) const
00021 {
00022 if (!vertex->vertexIsValid()) {
00023 LogDebug("ConstrainedTreeBuilder")
00024 << "Vertex is invalid\n";
00025 return ReferenceCountingPointer<KinematicTree>(new KinematicTree());
00026 }
00027 AlgebraicVector3 vtx;
00028 vtx(0) = vertex->position().x();
00029 vtx(1) = vertex->position().y();
00030 vtx(2) = vertex->position().z();
00031 AlgebraicMatrix33 vertexCov = asSMatrix<3,3>(fullCov.sub(1,3,1,3));
00032
00033
00034
00035
00036 double ent = 0.;
00037 int charge = 0;
00038 AlgebraicVector7 virtualPartPar;
00039 virtualPartPar(0) = vertex->position().x();
00040 virtualPartPar(1) = vertex->position().y();
00041 virtualPartPar(2) = vertex->position().z();
00042
00043
00044
00045
00046 ROOT::Math::SMatrix<double,7,7,ROOT::Math::MatRepStd<double,7,7> > aMatrix;
00047 aMatrix(3,3) = 1;
00048 aMatrix(4,4) = 1;
00049 aMatrix(5,5) = 1;
00050 aMatrix(6,6) = 1;
00051 ROOT::Math::SMatrix<double,7,3,ROOT::Math::MatRepStd<double,7,3> > bMatrix;
00052 bMatrix(0,0) = 1;
00053 bMatrix(1,1) = 1;
00054 bMatrix(2,2) = 1;
00055 AlgebraicMatrix77 trackParCov;
00056 ROOT::Math::SMatrix<double,3,7,ROOT::Math::MatRepStd<double,3,7> > vtxTrackCov;
00057 AlgebraicMatrix77 nCovariance;
00058
00059 std::vector<RefCountedKinematicParticle>::const_iterator i = initialParticles.begin();
00060 std::vector<KinematicState>::const_iterator iStates = finalStates.begin();
00061 std::vector<RefCountedKinematicParticle> rParticles;
00062 int n=0;
00063 for( ; i != initialParticles.end(), iStates != finalStates.end(); ++i,++iStates)
00064 {
00065 AlgebraicVector7 p = iStates->kinematicParameters().vector();
00066 double a = - iStates->particleCharge() *
00067 iStates->magneticField()->inInverseGeV(iStates->globalPosition()).z();
00068
00069 aMatrix(4,0) = -a;
00070 aMatrix(3,1) = a;
00071 bMatrix(4,0) = a;
00072 bMatrix(3,1) = -a;
00073
00074 AlgebraicVector7 par = aMatrix*p + bMatrix * vtx;
00075
00076 trackParCov = asSMatrix<7,7>(fullCov.sub(4+n*7,10+n*7,4+n*7,10+n*7));
00077 vtxTrackCov = asSMatrix<3,7>(fullCov.sub(1,3,4+n*7,10+n*7));;
00078 nCovariance = aMatrix * trackParCov * ROOT::Math::Transpose(aMatrix) +
00079 aMatrix * ROOT::Math::Transpose(vtxTrackCov) * ROOT::Math::Transpose(bMatrix) +
00080 bMatrix * vtxTrackCov * ROOT::Math::Transpose(aMatrix)+
00081 bMatrix * vertexCov * ROOT::Math::Transpose(bMatrix);
00082
00083 KinematicState stateAtVertex(KinematicParameters(par),
00084 KinematicParametersError(AlgebraicSymMatrix77(nCovariance.LowerBlock())),
00085 iStates->particleCharge(), iStates->magneticField());
00086 rParticles.push_back((*i)->refittedParticle(stateAtVertex, vertex->chiSquared(), vertex->degreesOfFreedom()));
00087
00088 virtualPartPar(3) += par(3);
00089 virtualPartPar(4) += par(4);
00090 virtualPartPar(5) += par(5);
00091 ent += sqrt(par(6)*par(6) + par(3)*par(3)+par(4)*par(4)+par(5)*par(5) );
00092 charge += iStates->particleCharge();
00093
00094 ++n;
00095
00096 }
00097
00098
00099 double differ = ent*ent - (virtualPartPar(3)*virtualPartPar(3) + virtualPartPar(5)*virtualPartPar(5) + virtualPartPar(4)*virtualPartPar(4));
00100 if(differ>0.) {
00101 virtualPartPar(6) = sqrt(differ);
00102 } else {
00103 LogDebug("ConstrainedTreeBuilder")
00104 << "Fit failed: Current precision does not allow to calculate the mass\n";
00105 return ReferenceCountingPointer<KinematicTree>(new KinematicTree());
00106 }
00107
00108
00109
00110 AlgebraicMatrix77 cov = asSMatrix<7,7>(covarianceMatrix(rParticles,virtualPartPar,fullCov));
00111
00112 KinematicState nState(KinematicParameters(virtualPartPar),
00113 KinematicParametersError(AlgebraicSymMatrix77(cov.LowerBlock())),
00114 charge, initialParticles[0]->magneticField());
00115
00116
00117 float chi2 = vertex->chiSquared();
00118 float ndf = vertex->degreesOfFreedom();
00119 KinematicParticle * zp = 0;
00120 RefCountedKinematicParticle virtualParticle = pFactory->particle(nState,chi2,ndf,zp);
00121
00122 return buildTree(virtualParticle, vertex, rParticles);
00123 }
00124
00125
00126 RefCountedKinematicTree ConstrainedTreeBuilder::buildTree(const RefCountedKinematicParticle virtualParticle,
00127 const RefCountedKinematicVertex vtx, const std::vector<RefCountedKinematicParticle> & particles) const
00128 {
00129
00130
00131 RefCountedKinematicTree resTree = ReferenceCountingPointer<KinematicTree>(new KinematicTree());
00132
00133
00134 RefCountedKinematicVertex fVertex = vFactory->vertex();
00135 resTree->addParticle(fVertex, vtx, virtualParticle);
00136
00137
00138 for(std::vector<RefCountedKinematicParticle>::const_iterator il = particles.begin(); il != particles.end(); il++)
00139 {
00140 if((*il)->previousParticle()->correspondingTree() != 0)
00141 {
00142 KinematicTree * tree = (*il)->previousParticle()->correspondingTree();
00143 tree->movePointerToTheTop();
00144 tree->replaceCurrentParticle(*il);
00145 RefCountedKinematicVertex cdVertex = resTree->currentDecayVertex();
00146 resTree->addTree(cdVertex, tree);
00147 }else{
00148 RefCountedKinematicVertex ffVertex = vFactory->vertex();
00149 resTree->addParticle(vtx,ffVertex,*il);
00150 }
00151 }
00152 return resTree;
00153 }
00154
00155 AlgebraicMatrix ConstrainedTreeBuilder::covarianceMatrix(std::vector<RefCountedKinematicParticle> rPart,
00156 const AlgebraicVector7& newPar, const AlgebraicMatrix& fitCov)const
00157 {
00158
00159
00160
00161
00162 int size = rPart.size();
00163
00164
00165 AlgebraicMatrix jac(3+7*size,3+7*size,0);
00166 jac(1,1) = 1;
00167 jac(2,2) = 1;
00168 jac(3,3) = 1;
00169 int i_int=0;
00170 for(std::vector<RefCountedKinematicParticle>::iterator i = rPart.begin(); i != rPart.end(); i++)
00171 {
00172
00173
00174 double a_i = - (*i)->currentState().particleCharge() * (*i)->magneticField()->inInverseGeV((*i)->currentState().globalPosition()).z();
00175
00176 AlgebraicMatrix upper(3,7,0);
00177 AlgebraicMatrix diagonal(7,7,0);
00178 upper(1,1) = 1;
00179 upper(2,2) = 1;
00180 upper(3,3) = 1;
00181 upper(2,4) = -a_i;
00182 upper(1,5) = a_i;
00183 jac.sub(1,4+i_int*7,upper);
00184
00185 diagonal(4,4) = 1;
00186 diagonal(5,5) = 1;
00187 diagonal(6,6) = 1;
00188 diagonal(7,7) = 1;
00189 diagonal(2,4) = a_i;
00190 diagonal(1,5) = -a_i;
00191 jac.sub(4+i_int*7,4+i_int*7,diagonal);
00192 i_int++;
00193 }
00194
00195
00196
00197
00198
00199
00200
00201 int vSize = rPart.size();
00202 AlgebraicSymMatrix fit_cov_sym(7*vSize+3,0);
00203 for(int i = 1; i<7*vSize+4; ++i)
00204 {
00205 for(int j = 1; j<7*vSize+4; ++j)
00206 {if(i<=j) fit_cov_sym(i,j) = fitCov(i,j);}
00207 }
00208
00209
00210 AlgebraicMatrix reduced(3+4*size,3+4*size,0);
00211 AlgebraicMatrix transform = fit_cov_sym.similarityT(jac);
00212
00213
00214 AlgebraicMatrix jac_t(7,7+4*(size-1));
00215 jac_t(1,1) = 1.;
00216 jac_t(2,2) = 1.;
00217 jac_t(3,3) = 1.;
00218
00219
00220
00221
00222 AlgebraicMatrix reduced_tm(7,7,0);
00223 for(int i = 1; i<8;++i)
00224 {
00225 for(int j =1; j<8; ++j)
00226 {reduced_tm(i,j) = transform(i+3, j+3);}
00227 }
00228
00229
00230
00231
00232
00233
00234
00235 reduced.sub(1,1,reduced_tm);
00236
00237
00238 int il_int = 0;
00239 double energy_global = sqrt(newPar(3)*newPar(3)+newPar(4)*newPar(4) + newPar(5)*newPar(5)+newPar(6)*newPar(6));
00240 for(std::vector<RefCountedKinematicParticle>::const_iterator rs = rPart.begin();
00241 rs!=rPart.end();rs++)
00242 {
00243
00244 AlgebraicMatrix jc_el(4,4,0);
00245 jc_el(1,1) = 1.;
00246 jc_el(2,2) = 1.;
00247 jc_el(3,3) = 1.;
00248
00249
00250 AlgebraicVector7 l_Par = (*rs)->currentState().kinematicParameters().vector();
00251 double energy_local = sqrt(l_Par(6)*l_Par(6) + l_Par(3)*l_Par(3) + l_Par(4)*l_Par(4) + l_Par(5)*l_Par(5));
00252 jc_el(4,4) = energy_global*l_Par(6)/(newPar(6)*energy_local);
00253 jc_el(4,1) = ((energy_global*l_Par(3)/energy_local) - newPar(3))/newPar(6);
00254 jc_el(4,2) = ((energy_global*l_Par(4)/energy_local) - newPar(4))/newPar(6);
00255 jc_el(4,3) = ((energy_global*l_Par(5)/energy_local) - newPar(5))/newPar(6);
00256 jac_t.sub(4,il_int*4+4,jc_el);
00257 il_int++;
00258 }
00259
00260
00261
00262
00263
00264 for(int i = 1; i<size; i++)
00265 {
00266
00267
00268
00269 AlgebraicMatrix transform_sub1(3,4,0);
00270 AlgebraicMatrix transform_sub2(4,3,0);
00271 for(int l1 = 1; l1<4;++l1)
00272 {
00273 for(int l2 = 1; l2<5;++l2)
00274 {transform_sub1(l1,l2) = transform(3+l1,6+7*i +l2);}
00275 }
00276
00277 for(int l1 = 1; l1<5;++l1)
00278 {
00279 for(int l2 = 1; l2<4;++l2)
00280 {transform_sub2(l1,l2) = transform(6+7*i+l1,3+l2);}
00281 }
00282
00283 AlgebraicMatrix transform_sub3(4,4,0);
00284 for(int l1 = 1; l1<5;++l1)
00285 {
00286 for(int l2 = 1; l2<5;++l2)
00287 {transform_sub3(l1,l2) = transform(6+7*i+l1, 6+7*i+l2); }
00288 }
00289
00290 reduced.sub(1,4+4*i,transform_sub1);
00291 reduced.sub(4+4*i,1,transform_sub2);
00292
00293
00294 reduced.sub(4+4*i,4+4*i,transform_sub3);
00295
00296
00297 for(int j = 1; j<size; j++)
00298 {
00299 AlgebraicMatrix transform_sub4(4,4,0);
00300 AlgebraicMatrix transform_sub5(4,4,0);
00301 for(int l1 = 1; l1<5;++l1)
00302 {
00303 for(int l2 = 1; l2<5;++l2)
00304 {
00305 transform_sub4(l1,l2) = transform(6+7*(i-1)+l1,6+7*j+l2);
00306 transform_sub5(l1,l2) = transform(6+7*j+l1, 6+7*(i-1)+l2);
00307 }
00308 }
00309 reduced.sub(4+4*(i-1),4+4*j,transform_sub4);
00310 reduced.sub(4+4*j,4+4*(i-1),transform_sub5);
00311 }
00312 }
00313
00314 return jac_t*reduced*jac_t.T();
00315 }