BOSS 7.0.2
BESIII Offline Software System
Loading...
Searching...
No Matches
KalmanVertexFit.cxx
Go to the documentation of this file.
1//
2// Kalman Vertex fit
3// The algoritm is based on a paper by
4// R. Fruhwirth etc Computer Physics Communications 96(1996) 189-208
5// The formulism for BES3 can be find at BESIII Software Note: No. xx
6// Author: Kanglin He and Min Xu, Apr. 13, 2007 for created
7//
8
9
10#include "VertexFit/KalmanVertexFit.h"
11#include "VertexFit/HTrackParameter.h"
12#include "VertexFit/WTrackParameter.h"
13#include "math.h"
14
15using namespace std;
16
17KalmanVertexFit * KalmanVertexFit::m_pointer = 0;
18
20 if(m_pointer) return m_pointer;
21 m_pointer = new KalmanVertexFit();
22 return m_pointer;
23}
24
26
27KalmanVertexFit::KalmanVertexFit() {;}
28
30 m_x = HepVector(3, 0);
31 m_C0 = HepSymMatrix(3, 0);
32 m_C = HepSymMatrix(3, 0);
33 m_chisq = 0;
34 m_ndof = -3;
35
36 m_flag.clear();
37 m_p.clear();
38 m_hTrkOrigin.clear();
39 m_hTrkInfit.clear(); //xum
40 //m_wTrkInfit.clear();
41
42 m_G.clear();
43 m_A.clear();
44 m_B.clear();
45 m_c.clear();
46 m_W.clear();
47 m_GB.clear();
48 m_chiF.clear();
49
50 //
51 // chi-square cut, number of iteration etc
52 //
53 m_chisqCutforTrack = 50;
54 m_maxVertexIteration = 3;
55 m_maxTrackIteration = 5;
56 m_chisqCutforTrackIteration = 0.1;
57}
58
60 int ifail;
61 m_x = vtx.Vx();
62 m_C0 = (vtx.Evx()).inverse(ifail);
63 m_C = m_C0;
64}
65
67 int ifail;
69 v.setVx(m_x);
70
71 std::vector<int> trackid;
72 v.setEvx(m_C.inverse(ifail));
73 return v;
74}
75
76HepSymMatrix KalmanVertexFit::Ex() const {
77 int ifail;
78 return m_C.inverse(ifail);
79}
80
82
83 int ifail;
84
85 HepVector p(3, 0);
86 p = htrk.p();
87
88 m_p.push_back(p);
89 m_flag.push_back(0);
90 m_chiF.push_back(999.);
91
92 HepMatrix A(5, 3, 0);
93 HepMatrix B(5, 3, 0);
94 HepSymMatrix G(5, 0);
95
96 G = (htrk.eHel()).inverse(ifail);
97
98 m_hTrkOrigin.push_back(htrk);
99
100 //xum
101 m_hTrkInfit.push_back(htrk);
102 //m_wTrkInfit.push_back(htrk.wTrack());
103
104 m_G.push_back(G);
105 m_A.push_back(A);
106 m_B.push_back(B);
107
108 HepSymMatrix W(3, 0);
109 HepSymMatrix GB(5, 0);
110 HepVector c(5, 0);
111
112 m_W.push_back(W);
113 m_GB.push_back(GB);
114 m_c.push_back(c);
115
116}
117
119 int num = 0;
120 for(int k = 0; k < m_hTrkOrigin.size(); k++)
121 if(m_flag[k] == 0) num = num +1;
122
123 return num;
124}
125
126std::vector<int> KalmanVertexFit::trackIDList() const {
127 std::vector<int> trackid;
128 for(int k = 0; k < m_hTrkOrigin.size(); k++)
129 if(m_flag[k] == 0) trackid.push_back(trackID(k));
130
131 return trackid;
132}
133
134
135int KalmanVertexFit::filter(const int k) {
136 int ifail;
137 double chisq[10];
138 ////////////////////////////////////////////////
139 // start iteration
140 ///////////////////////////////////////////////
141 HepVector pp(3, 0);
142 HepVector xp(3, 0);
143 HepSymMatrix CP(3, 0);
144 xp = m_x;
145 CP = m_C;
146 pp = m_p[k];
147
148 for(int iter = 0; iter < m_maxTrackIteration; iter++) {
149 //
150 // calculate derivative matrices for track k
151 //
152 updateMatrices(k, pp, xp);
153 //
154 // vertex covariance matrix updated
155 //
156 HepSymMatrix CK(3, 0);
157 CK = CP + (m_GB[k].similarity(m_A[k].T()));
158 //
159 // state vector x and p updated
160 //
161 HepVector x(3, 0);
162 HepVector p(3, 0);
163 x = CK.inverse(ifail) * (CP * xp + m_A[k].T() * m_GB[k] *
164 (m_hTrkOrigin[k].hel() - m_c[k]));
165 p = m_W[k] * m_B[k].T() * m_G[k] *(m_hTrkOrigin[k].hel()- m_c[k]-
166 m_A[k]*x);
167 // chi-square of filter
168 HepSymMatrix chif(1, 0);
169 chif = CP.similarity((x-xp).T()) +
170 m_G[k].similarity((m_hTrkOrigin[k].hel()-
171 m_c[k]- m_A[k]*x - m_B[k]*p).T());
172
173 //
174 // save current 3-momentum and vertex for track k
175 //
176 // 3-momentum
177 pp = p;
178 // current vertex and its covaiance matrix
179 xp = x;
180 CP = CK;
181 chisq[iter] = chif[0][0];
182 m_chiF[k] = chif[0][0];
183 // std::cout << "chisq, iter = " <<m_chiF[k] << ", " << iter << ", " << k <<std::endl;
184 if(iter > 0) {
185 double delchi = (chisq[iter]-chisq[iter-1]);
186 if(fabs(delchi) < m_chisqCutforTrackIteration) break;
187 }
188 }
189
190 if(m_chiF[k] > m_chisqCutforTrack) {
191 // do not update vertex if failed
192 m_flag[k]=1;
193 return 1;
194 } else {
195 // update vertex if filter success
196 m_x = xp;
197 m_C = CP;
198 m_p[k] = pp;
199 return 0;
200 }
201}
202
203void KalmanVertexFit::inverse(const int k) {
204 //
205 // inverse kalman filter for track k
206 //
207
208 int ifail;
209 HepVector x(3, 0);
210 HepVector p(3, 0);
211 HepSymMatrix C(3, 0);
212 C = m_C - m_GB[k].similarity(m_A[k].T());
213 x = C.inverse(ifail)*(m_C*m_x-m_A[k].T() * m_GB[k] *
214 (m_hTrkOrigin[k].hel()-m_c[k]));
215 //
216 // update vertex position and its covariance matrix
217 //
218 m_x = x;
219 m_C = C;
220}
222
223 for(int iter = 0; iter < m_maxVertexIteration; iter++) {
224 //
225 // at start of each iteration,
226 // the covariance matrix take the initial values: m_C0
227 // the vertex position take the update value by the last iteration
228 //
229 m_C = m_C0; // covariance matrix of verter --> initial values
230 m_chisq = 0; // total chi-square of smooth
231 m_ndof = -3; // number of degrees of freedom
232
233 for(int k = 0; k < m_hTrkOrigin.size(); k++) {
234 if(m_flag[k]==1) continue;
235 if(filter(k)==0) // filter track k
236 m_ndof += 2;
237
238 }
239 //
240 // check the chi-square of smooth, make decision to remove bad tracks
241 // user may remove more bad track by tight chi-square cut
242 // through the following interface
243 // KalmanVertexFit::remove(k)
244 //
245 for(int k = 0; k < m_hTrkOrigin.size(); k++) {
246 if(m_flag[k]==1) continue;
247 double chi2 = chiS(k);
248 if(chi2 < 0) { // remove track k from vertex
249 remove(k);
250 continue;
251 }
252
253 if(chi2 > m_chisqCutforTrack) { // remove track k from vertex
254 remove(k);
255 continue;
256 }
257 m_chisq += chi2;
258
259 }
260 } // end of iteration
261}
262
263double KalmanVertexFit::chiS(const int k) const {
264 if(m_flag[k]==1) return 999;
265 int ifail;
266 HepVector x(3, 0);
267 HepVector p(3, 0);
268 HepSymMatrix C(3, 0);
269 C = m_C - m_GB[k].similarity(m_A[k].T());
270 x = C.inverse(ifail)*(m_C*m_x-m_A[k].T() * m_GB[k] *
271 (m_hTrkOrigin[k].hel()-m_c[k]));
272 p = m_W[k]* m_B[k].T()*m_G[k]*
273 (m_hTrkOrigin[k].hel()-m_c[k]-m_A[k]*m_x);
274 HepSymMatrix chis(1, 0);
275 chis = C.similarity((x-m_x).T())+
276 m_G[k].similarity((m_hTrkOrigin[k].hel()-m_c[k]-
277 m_A[k]*m_x-m_B[k]*p).T());
278 return chis[0][0];
279}
280
281void KalmanVertexFit::smooth(const int k) {
282 // xum
283 //
284 // update htrk and wtrk parameters
285 //
286 if(m_flag[k] == 1) return;
287 int ifail;
288
289 HepVector pp(3, 0);
290 HepVector xp(3, 0);
291 HepSymMatrix CP(3, 0);
292 xp = m_x;
293 CP = m_C;
294 pp = m_p[k];
295
296 updateMatrices(k, pp, xp);
297 pp = m_W[k] * m_B[k].T() * m_G[k] * (m_hTrkOrigin[k].hel() - m_c[k] - m_A[k] * xp);
298
299 updateMatrices(k, pp, xp);
300 //for htrk
301 HepVector helix(5, 0);
302 helix = m_c[k] + m_A[k] * xp + m_B[k] * pp;
303 HepMatrix E(3, 3, 0);
304 E = -CP.inverse(ifail) * m_A[k].T() * m_G[k] * m_B[k] * m_W[k];
305 HepSymMatrix D(3, 0);
306 D = m_W[k] + CP.similarity(E.T());
307
308 HepMatrix middle(5, 5, 0);
309 HepSymMatrix error(5, 0);
310 middle = (CP.inverse(ifail)).similarity(m_A[k]) + m_A[k] * E * m_B[k].T() +
311 (m_A[k] * E * m_B[k].T()).T() + D.similarity(m_B[k]);
312 error.assign(middle);
313
314 m_hTrkInfit[k].setHel(helix);
315 m_hTrkInfit[k].setEHel(error);
316
317 m_p[k] = pp;
318/*
319 //for wtrk
320 double mass = m_hTrkOrigin[k].xmass(m_hTrkOrigin[k].partID());
321 double Energy = sqrt(pp[0]*pp[0] + pp[1]*pp[1] + pp[2]*pp[2] + mass * mass);
322
323 HepMatrix Awtrk(7, 3, 0), Bwtrk(7, 3, 0);
324 Awtrk[4][0] = Awtrk[5][1] = Awtrk[6][2] = 1;
325 Bwtrk[0][0] = Bwtrk[1][1] = Bwtrk[2][2] = 1;
326 Bwtrk[3][0] = pp[0] / Energy;
327 Bwtrk[3][1] = pp[1] / Energy;
328 Bwtrk[3][2] = pp[2] / Energy;
329
330 HepVector w(7, 0);
331 HepSymMatrix Ew(7, 0);
332 w[0] = pp[0]; w[1] = pp[1]; w[2] = pp[2]; w[3] = Energy;
333 w[4] = xp[0]; w[5] = xp[1]; w[6] = xp[2];
334
335 HepSymMatrix Gwtrk(7, 0);
336 Gwtrk = m_hTrkOrigin[k].wTrack().Ew().inverse(ifail);
337 HepSymMatrix Wwtrk(3, 0);
338 Wwtrk = Gwtrk.similarity(Bwtrk.T()).inverse(ifail);
339
340 HepMatrix Ewtrk(3, 3, 0);
341 Ewtrk = -CP.inverse(ifail) * m_Awtrk[k].T() * m_Gwtrk[k] * m_Bwtrk[k] * m_Wwtrk[k];
342 HepSymMatrix Dwtrk(3, 0);
343 Dwtrk = m_Wwtrk[k] + CP.similarity(Ewtrk.T());
344
345 HepMatrix Ewmiddle(7, 7, 0);
346 Ewmiddle = (CP.inverse(ifail)).similarity(m_Awtrk[k]) + m_Awtrk[k] * Ewtrk * m_Bwtrk[k].T() +
347 (m_Awtrk[k] * Ewtrk * m_Bwtrk[k].T()).T() + Dwtrk.similarity(m_Bwtrk[k]);
348 Ew.assign(Ewmiddle);
349
350 m_wTrkInfit[k].setCharge(m_hTrkOrigin[k].charge());
351 m_wTrkInfit[k].setW(w);
352 m_wTrkInfit[k].setEw(Ew);*/
353}
354
355void KalmanVertexFit::remove(const int k) {
356 //
357 // remove track k from the vertex fit
358 //
359 /*
360 m_hTrkOrigin.erase(m_hTrkOrigin.begin()+k);
361 m_p.erase(m_p.begin()+k);
362 m_flag.erase(m_flag.begin()+k);
363 m_A.erase(m_A.begin()+k);
364 m_B.erase(m_B.begin()+k);
365 m_c.erase(m_c.begin()+k);
366 m_G.erase(m_G.begin()+k);
367 m_GB.erase(m_GB.begin()+k);
368 m_W.erase(m_W.begin()+k);
369 m_chiF.erase(m_chiF.begin()+k);
370 */
371
372 if(m_flag[k]==1) return; // track k already removed
373 inverse(k);
374 m_ndof -= 2;
375 m_flag[k]=1;
376 //xum
377 //m_chisq -=chiS(k);
378}
379
380
382 //add xum
383 //HTrackParameter htrk;
384 //return htrk;
385 return m_hTrkInfit[k];
386}
387
388WTrackParameter KalmanVertexFit::wTrack(const int k, const double mass) const {
389 if(m_flag[k] == 1) return m_hTrkOrigin[k].wTrack();
390 int ifail;
391
392 HepVector pp(3, 0);
393 HepVector xp(3, 0);
394 HepSymMatrix CP(3, 0);
395 xp = m_x;
396 CP = m_C;
397 pp = m_p[k];
398
399 WTrackParameter wtrk;
400 double Energy = sqrt(pp[0]*pp[0] + pp[1]*pp[1] + pp[2]*pp[2] + mass * mass);
401
402 HepMatrix Awtrk(7, 3, 0), Bwtrk(7, 3, 0);
403 Awtrk[4][0] = Awtrk[5][1] = Awtrk[6][2] = 1;
404 Bwtrk[0][0] = Bwtrk[1][1] = Bwtrk[2][2] = 1;
405 Bwtrk[3][0] = pp[0] / Energy;
406 Bwtrk[3][1] = pp[1] / Energy;
407 Bwtrk[3][2] = pp[2] / Energy;
408
409 HepVector w(7, 0);
410 HepSymMatrix Ew(7, 0);
411 w[0] = pp[0]; w[1] = pp[1]; w[2] = pp[2]; w[3] = Energy;
412 w[4] = xp[0]; w[5] = xp[1]; w[6] = xp[2];
413
414 HepSymMatrix Gwtrk(7, 0);
415 Gwtrk = m_hTrkOrigin[k].wTrack().Ew().inverse(ifail);
416 HepSymMatrix Wwtrk(3, 0);
417 Wwtrk = Gwtrk.similarity(Bwtrk.T()).inverse(ifail);
418
419 HepMatrix Ewtrk(3, 3, 0);
420 Ewtrk = -CP.inverse(ifail) * Awtrk.T() * Gwtrk * Bwtrk * Wwtrk;
421 HepSymMatrix Dwtrk(3, 0);
422 Dwtrk = Wwtrk + CP.similarity(Ewtrk.T());
423
424 HepMatrix Ewmiddle(7, 7, 0);
425 Ewmiddle = (CP.inverse(ifail)).similarity(Awtrk) + Awtrk * Ewtrk * Bwtrk.T() +
426 (Awtrk * Ewtrk * Bwtrk.T()).T() + Dwtrk.similarity(Bwtrk);
427 Ew.assign(Ewmiddle);
428
429 wtrk.setCharge(m_hTrkOrigin[k].charge());
430 wtrk.setW(w);
431 wtrk.setEw(Ew);
432
433 return wtrk;
434}
435
436//
437// private functions, update derivative matrices
438//
439void KalmanVertexFit::updateMatrices(const int k, const HepVector p, const HepVector x) {
440
441 int ifail;
442 //
443 // expand measurement equation at (x, p)
444 //
445 HTrackParameter he(m_hTrkOrigin[k].charge(), p, x);
446
447 // derivative matrix
448
449 m_A[k] = he.dHdx(p, x);
450 m_B[k] = he.dHdp(p, x);
451
452 // W, GB, c
453 m_W[k] = (m_G[k].similarity(m_B[k].T())).inverse(ifail);
454 m_GB[k] = m_G[k] - (m_W[k].similarity(m_B[k])).similarity(m_G[k]);
455 m_c[k] = he.hel() - m_A[k] * x - m_B[k] * p;
456}
457
458void KalmanVertexFit::updateMatrices(const int k) {
459
460 int ifail;
461 HepVector p(3, 0);
462 HepVector x(3, 0);
463 p = m_p[k];
464 x = m_x;
465 updateMatrices(k, p, x);
466}
467
468HepVector KalmanVertexFit::pull(const int k) {
469 HepVector n_pull(5, 0);
470 n_pull[0] = n_pull[1] = n_pull[2] = n_pull[3] = n_pull[4] = 999.;
471 if(m_flag[k] == 1) return n_pull;
472 for (int i = 0 ; i < 5; i++) {
473 double cov = m_hTrkOrigin[k].eHel()[i][i] - m_hTrkInfit[k].eHel()[i][i];
474 if (cov == 0.) continue;
475 n_pull[i] = (m_hTrkOrigin[k].hel()[i] - m_hTrkInfit[k].hel()[i]) / sqrt(cov);
476 }
477 return n_pull;
478}
479
480double KalmanVertexFit::pullmomentum(const int k) {
481 double pull = 999.;
482 if(m_flag[k] == 1) return pull;
483
484 double kappa_origin = m_hTrkOrigin[k].kappa();
485 double kappa_infit = m_hTrkInfit[k].kappa();
486 double lamb_origin = m_hTrkOrigin[k].lambda();
487 double lamb_infit = m_hTrkInfit[k].lambda();
488
489 double Vkappa_origin = m_hTrkOrigin[k].eHel()[2][2];
490 double Vkappa_infit = m_hTrkInfit[k].eHel()[2][2];
491 double Vlamb_origin = m_hTrkOrigin[k].eHel()[4][4];
492 double Vlamb_infit = m_hTrkInfit[k].eHel()[4][4];
493 double V_kappa_lamb_origin = m_hTrkOrigin[k].eHel()[4][2];
494 double V_kappa_lamb_infit = m_hTrkInfit[k].eHel()[4][2];
495
496 double P_origin = calculationP(kappa_origin, lamb_origin);
497 //cout << "P_origin = " << P_origin << endl;
498 //P_origin = m_hTrkOrigin[k].p()[0] * m_hTrkOrigin[k].p()[0]
499 // + m_hTrkOrigin[k].p()[1] * m_hTrkOrigin[k].p()[1]
500 // + m_hTrkOrigin[k].p()[2] * m_hTrkOrigin[k].p()[2];
501 //cout << "P = " << P_origin << endl;
502 double P_infit = calculationP(kappa_infit, lamb_infit);
503
504 double SigmaP_origin = calculationSigmaP(kappa_origin, lamb_origin, Vkappa_origin,
505 Vlamb_origin, V_kappa_lamb_origin);
506 double SigmaP_infit = calculationSigmaP(kappa_infit, lamb_infit, Vkappa_infit,
507 Vlamb_infit, V_kappa_lamb_infit);
508 if ((SigmaP_origin - SigmaP_infit) <= 0.) return pull;
509 pull = (P_origin - P_infit) / sqrt (SigmaP_origin - SigmaP_infit);
510
511 return pull;
512}
513
514//====================== sub routine ==================================
515double KalmanVertexFit::calculationP(const double kappa, const double lamb) {
516 double P = 0.0;
517 P = sqrt(1 + lamb * lamb) / kappa;
518 //cout << "P in calculationP = " << P << endl;
519 return P;
520}
521
522double KalmanVertexFit::calculationSigmaP(const double kappa, const double lamb,
523 const double Vkappa, const double Vlamb,
524 const double Vkappa_lamb) {
525 double SigmaP = 0.0;
526 double dp_dkappa = -sqrt(1 + lamb*lamb) /kappa/kappa;
527 double dp_dlamb = lamb / kappa / sqrt(1 + lamb*lamb);
528 SigmaP = dp_dkappa * dp_dkappa * Vkappa + dp_dlamb * dp_dlamb * Vlamb
529 + 2 * dp_dkappa * dp_dlamb * Vkappa_lamb;
530 return SigmaP;
531}
double P(RecMdcKalTrack *trk)
double mass
double w
EvtStreamInputIterator< typename Generator::result_type > iter(Generator gen, int N=0)
**********Class see also m_nmax DOUBLE PRECISION m_amel DOUBLE PRECISION m_x2 DOUBLE PRECISION m_alfinv DOUBLE PRECISION m_Xenph INTEGER m_KeyWtm INTEGER m_idyfs DOUBLE PRECISION m_zini DOUBLE PRECISION m_q2 DOUBLE PRECISION m_Wt_KF DOUBLE PRECISION m_WtCut INTEGER m_KFfin *COMMON c_KarLud $ !Input CMS energy[GeV] $ !CMS energy after beam spread beam strahlung[GeV] $ !Beam energy spread[GeV] $ !z boost due to beam spread $ !electron beam mass *ff pair spectrum $ !minimum v
Definition: KarLud.h:35
***************************************************************************************Pseudo Class RRes *****************************************************************************************Parameters and physical constants **Maarten sept ************************************************************************DOUBLE PRECISION xsmu **************************************************************************PARTICLE DATA all others are from PDG *Only resonances with known widths into electron pairs are sept ************************************************************************C Declarations C
Definition: RRes.h:29
double pullmomentum(const int k)
HepSymMatrix Ex() const
void addTrack(const HTrackParameter)
HTrackParameter hTrack(const int k) const
WTrackParameter wTrack(const int k, const double mass) const
VertexParameter vtx() const
std::vector< int > trackIDList() const
double chiS(const int k) const
void initVertex(const VertexParameter vtx)
int numTrack() const
HepVector pull(const int k)
static KalmanVertexFit * instance()
void inverse(const int k)
void remove(const int k)