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