00001
00015 #include"StableChargedParticle.h"
00016 #include"cernlib.h"
00017 #include <cmath>
00018 #include <cassert>
00019
00020 using std::sqrt;
00021 using std::sin;
00022 using std::cos;
00023
00024
00025 StableChargedParticle::StableChargedParticle(double kappa, double phi0, double theta,
00026 double dca, double z0,
00027 double bfield_, double mass_)
00028 : bfield (bfield_), mass (mass_)
00029 {
00030 setParam (0, kappa, true);
00031 setParam (1, phi0, true);
00032 setParam (2, theta, true);
00033 setParam (3, dca, true);
00034 setParam (4, z0, true);
00035 setParam (5, 0, false);
00036 setMass (m);
00037 for (int ilocal = 0; ilocal < NPAR; ++ilocal) globalParNum[ilocal] = -1;
00038 invalidateCache();
00039 }
00040
00041
00042 StableChargedParticle::~StableChargedParticle() {}
00043
00044
00045
00046
00047
00048 void StableChargedParticle::addToDerivatives (double der[],
00049 int idim,
00050 double pxfact,
00051 double pyfact,
00052 double pzfact,
00053 double efact) const {
00054 assert (0);
00055 int i_E = globalParNum[0];
00056 int i_theta = globalParNum[1];
00057 int i_phi = globalParNum[2];
00058 assert (i_E >= 0 && i_E < idim);
00059 assert (i_theta >= 0 && i_theta < idim);
00060 assert (i_phi >= 0 && i_phi < idim);
00061
00062 if (!cachevalid) updateCache();
00063
00064
00065 double der_E = 0;
00066 double der_theta = 0;
00067 double der_phi = 0;
00068
00069 if (pxfact != 0) {
00070 der_E += pxfact*dpxdE;
00071 der_theta += pxfact*dpydtheta;
00072 der_phi -= pxfact*py;
00073 }
00074 if (pyfact != 0) {
00075 der_E += pyfact*dpydE;
00076 der_theta += pyfact*dpydtheta;
00077 der_phi += pyfact*px;
00078 }
00079 if (pzfact != 0) {
00080 der_E += pzfact*dpdE*ctheta;
00081 der_theta -= pzfact*pt;
00082 }
00083 der_E += efact;
00084
00085 der[i_E] += der_E;
00086 der[i_theta] += der_theta;
00087 der[i_phi] += der_phi;
00088 }
00089
00090 void StableChargedParticle::addTo2ndDerivatives (double der2[],
00091 int idim,
00092 double pxfact,
00093 double pyfact,
00094 double pzfact,
00095 double efact) const {
00096 int i_E = globalParNum[0];
00097 int i_th = globalParNum[1];
00098 int i_ph= globalParNum[2];
00099 assert (i_E >= 0 && i_E < idim);
00100 assert (i_th >= 0 && i_th < idim);
00101 assert (i_ph >= 0 && i_ph < idim);
00102
00103 if (!cachevalid) updateCache();
00104
00105
00106 double der_EE = 0;
00107 double der_Eth = 0;
00108 double der_Eph = 0;
00109 double der_thth = 0;
00110 double der_thph = 0;
00111 double der_phph = 0;
00112
00113 double d2pdE2 = (mass != 0) ? -mass*mass/(p*p*p) : 0;
00114 double d2ptdE2 = d2pdE2*stheta;
00115
00116 if (pxfact != 0) {
00117 der_EE += pxfact*d2ptdE2*cphi;
00118 der_Eth += pxfact*dpzdE*cphi;
00119 der_Eph -= pxfact*dpydE;
00120 der_thth -= pxfact*px;
00121 der_thph -= pxfact*dpydtheta;
00122 der_phph -= pxfact*px;
00123 }
00124 if (pyfact != 0) {
00125 der_EE += pyfact*d2ptdE2*sphi;
00126 der_Eth += pyfact*dpzdE*sphi;
00127 der_Eph += pyfact*dpxdE;
00128 der_thth -= pyfact*py;
00129 der_thph += pyfact*dpxdtheta;
00130 der_phph -= pyfact*py;
00131 }
00132 if (pzfact != 0) {
00133 der_EE += pzfact*d2pdE2*ctheta;
00134 der_Eth -= pzfact*dptdE;
00135 der_thth -= pzfact*pz;
00136 }
00137
00138 der2[idim*i_E+i_E] += der_EE;
00139 der2[idim*i_E+i_th] += der_Eth;
00140 der2[idim*i_E+i_ph] += der_Eph;
00141 der2[idim*i_th+i_E] += der_Eth;
00142 der2[idim*i_th+i_th] += der_thth;
00143 der2[idim*i_th+i_ph] += der_thph;
00144 der2[idim*i_ph+i_E] += der_Eph;
00145 der2[idim*i_ph+i_th] += der_thph;
00146 der2[idim*i_ph+i_ph] += der_phph;
00147 }
00148
00149
00150
00151 double StableChargedParticle::getChi2() const {
00152 if (!cachevalid) updateCache();
00153 return chi2;
00154 }
00155
00156 void StableChargedParticle::addToGlobalChi2DerMatrix (int idim, double *M) const {
00157 assert (0);
00158
00159 for (int ilocal = 0; ilocal < getNPar(); ++ilocal) {
00160 int iglobal = getGlobalParNum (ilocal);
00161 assert (iglobal >= 0 && iglobal < idim);
00162 M[(idim+1)*iglobal] += 2./std::pow (err[ilocal], 2);
00163 }
00164 }
00165
00166
00167 void StableChargedParticle::addToGlobalDerMatrix (int idim, double c, double *M) const {
00168 assert (0);
00169
00170 if (c == 0) return;
00171
00172
00173 }
00174
00175 double StableChargedParticle::getDChi2DParam(int ilocal) const {
00176 assert (ilocal >= 0 && ilocal < NPAR);
00177 if (ilocal >= NMEAS) return 0;
00178 if (!cachevalid) updateCache();
00179 double result = 0;
00180 for (int i = 0; i<NMEAS; i++) result += 2*covinv[ilocal][i]*resid[i];
00181 return ;
00182 }
00183
00184 double StableChargedParticle::getD2Chi2DParam2(int ilocal1, int ilocal2) const {
00185 assert (ilocal1 >= 0 && ilocal1 < NPAR);
00186 assert (ilocal2 >= 0 && ilocal2 < NPAR);
00187 if (ilocal1 >= NMEAS || ilocal2 >= NMEAS ) return 0;
00188 return 2*covinv[ilocal1][ilocal2];
00189 }
00190
00191 void StableChargedParticle::setCovMatrix(double values[NMEAS*(NMEAS+1)/2]) {
00192 for (int i = 0; i < NMEAS; ++i) {
00193 for (int j = 0; j < NMEAS; ++j) {
00194 covmatrix[i][j] = 0.;
00195 }
00196 }
00197 int k=0;
00198 for (int i = 0; i < NMEAS; ++i) {
00199 covinv[i][i] = covmatrix[i][i] = std::pow(values[k++], 2);
00200 }
00201 for (int i = 0; i < 4; ++i) {
00202 for (int j = i+1; j < NMEAS; ++j) {
00203 covinv[i][j] = covinv[j][i] = covmatrix[i][j] = covmatrix[j][i] = values[k++];
00204 }
00205 }
00206 int ifail = dsinv (NMEAS, covinv, NMEAS);
00207 assert (ifail == 0);
00208 }
00209
00210 void StableChargedParticle::addToGlobCov(double *cov, int idim) const {
00211 assert(0);
00212 for (int ilocal = 0; ilocal < NPAR; ilocal++) {
00213 int iglobal = getGlobalParNum(ilocal);
00214 if (iglobal >= 0) cov[iglobal*(1+idim)] += err[ilocal]*err[ilocal];
00215
00216
00217 }
00218 }
00219
00220 void StableChargedParticle::invalidateCache() const {
00221 cachevalid = false;
00222 }
00223
00224 void StableChargedParticle::updateCache() const {
00225 double& kappa = par[0];
00226 double& phi0 = par[1];
00227 double& theta = par[2];
00228 double& dca = par[3];
00229 double& z0 = par[4];
00230 double& s1 = par[5];
00231
00232 sphi0 = std::sin(phi0);
00233 cphi0 = std::cos(phi0);
00234 r = (kappa != 0) ? 1/kappa : 0;
00235 dcamir = dca - r;
00236 cottheta = 1/std::tan(theta);
00237 cos2theta = std::pow (std::cos(theta), 2);
00238
00239 setVertex (v1, dv1, 5, s1);
00240
00241 chi2 = 0;
00242 for (int i = 0; i < NMEAS; ++i) {
00243 resid[i] = par[i]-measured[i];
00244 chi2 += resid[i]*covinv[i][i]*resid[i];
00245 for (int j = 0; j < i; ++j) {
00246 chi2 += 2*(resid[i])*covinv[i][j]*(resid[j])
00247 }
00248 }
00249 cachevalid = true;
00250 }
00251 void StableChargedParticle::setVertex (FitThreeVector& v, FitThreeVector dv[NPAR],
00252 int n, double s) const {
00253 double& kappa = par[0];
00254 double& dca = par[3];
00255 double& z0 = par[4];
00256
00257 if (std::abs (kappa*s) < 1.e-6) {
00258 double ssq = s*s;
00259 double kssq = 0.5*kappa*ssq;
00260 v.setValues (sphi0*( dca + kssq) - cphi0*s,
00261 cphi0*(-dca + kssq) + sphi0*s,
00262 z0 + s*cottheta);
00263 dv[0].setValues (-0.5*sphi0*ssq,
00264 0.5*cphi0*ssq,
00265 0);
00266 }
00267 else {
00268 double kappas = kappa*s;
00269 double phi0plkappas = phi0 + kappas;
00270 double si = std::sin(phi0plkappas);
00271 double co = std::cos(phi0plkappas);
00272 v.setValues ( dcamir*sphi0 + r*si,
00273 -dcamir*cphi0 - r*co,
00274 z0 + s*cottheta);
00275 dv[0].setValues (co*kappas + sphi0 -si,
00276 si*kappas - cphi0 +co,
00277 0);
00278 }
00279 dv[1].setValues (-v.getY(),
00280 -v.getX(),
00281 0);
00282 dv[2].setValues (0, 0, - s/cos2theta);
00283 dv[3].setValues (sphi0, -cphi0, 0);
00284 dv[4].setValues (0, 0, 1);
00285 assert (n<NPAR);
00286 dv[n].setValues (co, si, cottheta);
00287 }