Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DTrackFitterKalmanSIMD_ALT1.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DTrackFitterKalmanSIMD_ALT1.cc
4 // Created: Tue Mar 29 09:45:14 EDT 2011
5 // Creator: staylor (on Linux ifarml1 2.6.18-128.el5 x86_64)
6 //
7 
9 
10 // Kalman engine for forward tracks. For FDC hits only the position along
11 // the wire is used in the fit
12 kalman_error_t DTrackFitterKalmanSIMD_ALT1::KalmanForward(double fdc_anneal_factor, double cdc_anneal_factor,
13  DMatrix5x1 &S,
14  DMatrix5x5 &C,
15  double &chisq,
16  unsigned int &numdof){
17  DMatrix1x5 H; // Track projection matrix for cdc hits
18  DMatrix5x1 H_T; // Transpose of track projection matrix for cdc hits
19  DMatrix5x5 J; // State vector Jacobian matrix
20  DMatrix5x5 Q; // Process noise covariance matrix
21  DMatrix5x1 K; // Kalman gain matrix for cdc hits
22  DMatrix5x1 S0,S0_; //State vector
23  DMatrix5x5 Ctest; // Covariance matrix
24  // double Vc=0.2028; // covariance for cdc wires =1.56*1.56/12.;
25  double Vc=0.0507*1.15;
26 
27  // Vectors for cdc wires
28  DVector2 origin,dir,wirepos;
29  double z0w=0.; // origin in z for wire
30 
31  // Set used_in_fit flags to false for fdc and cdc hits
32  unsigned int num_cdc=cdc_updates.size();
33  unsigned int num_fdc=fdc_updates.size();
34  for (unsigned int i=0;i<num_cdc;i++) cdc_updates[i].used_in_fit=false;
35  for (unsigned int i=0;i<num_fdc;i++) fdc_updates[i].used_in_fit=false;
36  for (unsigned int i=0;i<forward_traj.size();i++){
37  if (forward_traj[i].h_id>999)
38  forward_traj[i].h_id=0;
39  }
40 
41  // Save the starting values for C and S in the deque
44 
45  // Initialize chi squared
46  chisq=0;
47 
48  // Initialize number of degrees of freedom
49  numdof=0;
50 
51  double my_cdc_anneal=cdc_anneal_factor*cdc_anneal_factor;
52  double my_fdc_anneal=fdc_anneal_factor*fdc_anneal_factor;
53 
54  double var_fdc_cut=NUM_FDC_SIGMA_CUT*NUM_FDC_SIGMA_CUT;
55  double fdc_chi2cut=my_fdc_anneal*var_fdc_cut;
56 
57  double var_cdc_cut=NUM_CDC_SIGMA_CUT*NUM_CDC_SIGMA_CUT;
58  double cdc_chi2cut=my_cdc_anneal*var_cdc_cut;
59 
60  // Variables for estimating t0 from tracking
61  //mInvVarT0=mT0wires=0.;
62 
63  unsigned int num_fdc_hits=break_point_fdc_index+1;
64  unsigned int max_num_fdc_used_in_fit=num_fdc_hits;
65  unsigned int num_cdc_hits=my_cdchits.size();
66  unsigned int cdc_index=0;
67  if (num_cdc_hits>0) cdc_index=num_cdc_hits-1;
68  bool more_cdc_measurements=(num_cdc_hits>0);
69  double old_doca2=1e6;
70 
71  if (num_fdc_hits+num_cdc_hits<MIN_HITS_FOR_REFIT){
72  cdc_chi2cut=1000.0;
73  fdc_chi2cut=1000.0;
74  }
75 
76  if (more_cdc_measurements){
77  origin=my_cdchits[cdc_index]->origin;
78  dir=my_cdchits[cdc_index]->dir;
79  z0w=my_cdchits[cdc_index]->z0wire;
80  wirepos=origin+(forward_traj[break_point_step_index].z-z0w)*dir;
81  }
82 
84 
85  if (DEBUG_LEVEL > 25){
86  jout << "Entering DTrackFitterKalmanSIMD_ALT1::KalmanForward ================================" << endl;
87  jout << " We have the following starting parameters for our fit. S = State vector, C = Covariance matrix" << endl;
88  S.Print();
89  C.Print();
90  jout << setprecision(6);
91  jout << " There are " << num_cdc << " CDC Updates and " << num_fdc << " FDC Updates on this track" << endl;
92  jout << " There are " << num_cdc_hits << " CDC Hits and " << num_fdc_hits << " FDC Hits on this track" << endl;
93  jout << " With NUM_FDC_SIGMA_CUT = " << NUM_FDC_SIGMA_CUT << " and NUM_CDC_SIGMA_CUT = " << NUM_CDC_SIGMA_CUT << endl;
94  jout << " fdc_anneal_factor = " << fdc_anneal_factor << " cdc_anneal_factor = " << cdc_anneal_factor << endl;
95  jout << " yields fdc_chi2cut = " << fdc_chi2cut << " cdc_chi2cut = " << cdc_chi2cut << endl;
96  jout << " Starting from break_point_step_index " << break_point_step_index << endl;
97  jout << " S0_ which is the state vector of the reference trajectory at the break point step:" << endl;
98  S0_.Print();
99  jout << " ===== Beginning pass over reference trajectory ======== " << endl;
100  }
101  for (unsigned int k=break_point_step_index+1;k<forward_traj.size();k++){
102  unsigned int k_minus_1=k-1;
103 
104  // Check that C matrix is positive definite
105  if (C(0,0)<0 || C(1,1)<0 || C(2,2)<0 || C(3,3)<0 || C(4,4)<0){
106  if (DEBUG_LEVEL>0) _DBG_ << "Broken covariance matrix!" <<endl;
108  }
109 
110  // Get the state vector, jacobian matrix, and multiple scattering matrix
111  // from reference trajectory
112  S0=(forward_traj[k].S);
113  J=(forward_traj[k].J);
114  Q=(forward_traj[k].Q);
115 
116  // State S is perturbation about a seed S0
117  //dS=S-S0_;
118 
119  // Update the actual state vector and covariance matrix
120  S=S0+J*(S-S0_);
121 
122  // Bail if the momentum has dropped below some minimum
123  if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX){
124  if (DEBUG_LEVEL>2)
125  {
126  _DBG_ << "Bailing: P = " << 1./fabs(S(state_q_over_p)) << endl;
127  }
128  break_point_fdc_index=(3*num_fdc)/4;
129  return MOMENTUM_OUT_OF_RANGE;
130  }
131 
132  //C=J*(C*J_T)+Q;
133  C=Q.AddSym(C.SandwichMultiply(J));
134 
135  // Save the current state and covariance matrix in the deque
136  forward_traj[k].Skk=S;
137  forward_traj[k].Ckk=C;
138 
139  // Save the current state of the reference trajectory
140  S0_=S0;
141 
142  // Z position along the trajectory
143  double z=forward_traj[k].z;
144 
145  if (DEBUG_LEVEL > 25){
146  jout << " At reference trajectory index " << k << " at z=" << z << endl;
147  jout << " The State vector from the reference trajectory" << endl;
148  S0.Print();
149  jout << " The Jacobian matrix " << endl;
150  J.Print();
151  jout << " The Q matrix "<< endl;
152  Q.Print();
153  jout << " The updated State vector S=S0+J*(S-S0_)" << endl;
154  S.Print();
155  jout << " The updated Covariance matrix C=J*(C*J_T)+Q;" << endl;
156  C.Print();
157  }
158 
159  // Add the hit
160  if (num_fdc_hits>0){
161  if (forward_traj[k].h_id>0 && forward_traj[k].h_id<1000){
162  unsigned int id=forward_traj[k].h_id-1;
163 
164  double cosa=my_fdchits[id]->cosa;
165  double sina=my_fdchits[id]->sina;
166  double u=my_fdchits[id]->uwire;
167  double v=my_fdchits[id]->vstrip;
168 
169  // Position and direction from state vector
170  double x=S(state_x);
171  double y=S(state_y);
172  double tx=S(state_tx);
173  double ty=S(state_ty);
174 
175  // Projected position along the wire without doca-dependent corrections
176  double vpred_uncorrected=x*sina+y*cosa;
177 
178  // Projected postion in the plane of the wires transverse to the wires
179  double upred=x*cosa-y*sina;
180 
181  // Direction tangent in the u-z plane
182  double tu=tx*cosa-ty*sina;
183  double alpha=atan(tu);
184  double cosalpha=cos(alpha);
185  double cosalpha2=cosalpha*cosalpha;
186  double sinalpha=sin(alpha);
187 
188  // (signed) distance of closest approach to wire
189  double doca=(upred-u)*cosalpha;
190 
191  // Correction for lorentz effect
192  double nz=my_fdchits[id]->nz;
193  double nr=my_fdchits[id]->nr;
194  double nz_sinalpha_plus_nr_cosalpha=nz*sinalpha+nr*cosalpha;
195 
196  // Variance in coordinate along wire
197  double V=my_fdchits[id]->vvar;
198 
199  // Difference between measurement and projection
200  double tv=tx*sina+ty*cosa;
201  double Mdiff=v-(vpred_uncorrected+doca*(nz_sinalpha_plus_nr_cosalpha
202  -tv*sinalpha
203  ));
204  // To transform from (x,y) to (u,v), need to do a rotation:
205  // u = x*cosa-y*sina
206  // v = y*cosa+x*sina
207  double temp2=nz_sinalpha_plus_nr_cosalpha
208  -tv*sinalpha
209  ;
210  H_T(state_x)=sina+cosa*cosalpha*temp2;
211  H_T(state_y)=cosa-sina*cosalpha*temp2;
212 
213  double cos2_minus_sin2=cosalpha2-sinalpha*sinalpha;
214  double fac=nz*cos2_minus_sin2-2.*nr*cosalpha*sinalpha;
215  double doca_cosalpha=doca*cosalpha;
216  double temp=doca_cosalpha*fac;
217  H_T(state_tx)=cosa*temp
218  -doca_cosalpha*(tu*sina+tv*cosa*cos2_minus_sin2)
219  ;
220  H_T(state_ty)=-sina*temp
221  -doca_cosalpha*(tu*cosa-tv*sina*cos2_minus_sin2)
222  ;
223 
224  // Matrix transpose H_T -> H
225  H(state_x)=H_T(state_x);
226  H(state_y)=H_T(state_y);
227  H(state_tx)=H_T(state_tx);
228  H(state_ty)=H_T(state_ty);
229 
230  // Check to see if we have multiple hits in the same plane
231  if (forward_traj[k].num_hits>1){
232  // If we do have multiple hits, then all of the hits within some
233  // validation region are included with weights determined by how
234  // close the hits are to the track projection of the state to the
235  // "hit space".
236  vector<DMatrix5x1> Klist;
237  vector<double> Mlist;
238  vector<DMatrix1x5> Hlist;
239  vector<double> Vlist;
240  vector<double>probs;
241  vector<unsigned int>used_ids;
242 
243  // Deal with the first hit:
244  //double Vtemp=V+H*C*H_T;
245  double Vtemp=V+C.SandwichMultiply(H_T);
246  double InvV=1./Vtemp;;
247 
248  //probability
249  double chi2_hit=Mdiff*Mdiff*InvV;
250  double prob_hit=exp(-0.5*chi2_hit)/sqrt(M_TWO_PI*Vtemp);
251 
252  if (DEBUG_LEVEL > 25) jout << " == There are multiple (" << forward_traj[k].num_hits << ") FDC hits" << endl;
253 
254  // Cut out outliers
255  if (chi2_hit<fdc_chi2cut && my_fdchits[id]->status==good_hit){
256  probs.push_back(prob_hit);
257  Vlist.push_back(V);
258  Hlist.push_back(H);
259  Mlist.push_back(Mdiff);
260  Klist.push_back(InvV*(C*H_T)); // Kalman gain
261 
262  used_ids.push_back(id);
263  fdc_used_in_fit[id]=true;
264  }
265 
266  // loop over the remaining hits
267  for (unsigned int m=1;m<forward_traj[k].num_hits;m++){
268  unsigned int my_id=id-m;
269  if (my_fdchits[my_id]->status==good_hit){
270  u=my_fdchits[my_id]->uwire;
271  v=my_fdchits[my_id]->vstrip;
272 
273  // Doca to this wire
274  doca=(upred-u)*cosalpha;
275 
276  // variance for coordinate along the wire
277  V=my_fdchits[my_id]->vvar;
278 
279  // Difference between measurement and projection
280  Mdiff=v-(vpred_uncorrected+doca*(nz_sinalpha_plus_nr_cosalpha
281  -tv*sinalpha
282  ));
283 
284  // Update the terms in H/H_T that depend on the particular hit
285  doca_cosalpha=doca*cosalpha;
286  temp=doca_cosalpha*fac;
287  H_T(state_tx)=cosa*temp
288  -doca_cosalpha*(tu*sina+tv*cosa*cos2_minus_sin2)
289  ;
290  H_T(state_ty)=-sina*temp
291  -doca_cosalpha*(tu*cosa-tv*sina*cos2_minus_sin2)
292  ;
293 
294  // Matrix transpose H_T -> H
295  H(state_tx)=H_T(state_tx);
296  H(state_ty)=H_T(state_ty);
297 
298  // Calculate the kalman gain for this hit
299  //Vtemp=V+H*C*H_T;
300  Vtemp=V+C.SandwichMultiply(H_T);
301  InvV=1./Vtemp;
302 
303  // probability
304  chi2_hit=Mdiff*Mdiff*InvV;
305  prob_hit=exp(-0.5*chi2_hit)/sqrt(M_TWO_PI*Vtemp);
306 
307  // Cut out outliers
308  if(chi2_hit<fdc_chi2cut){
309  probs.push_back(prob_hit);
310  Mlist.push_back(Mdiff);
311  Vlist.push_back(V);
312  Hlist.push_back(H);
313  Klist.push_back(InvV*(C*H_T));
314 
315  used_ids.push_back(my_id);
316  fdc_used_in_fit[my_id]=true;
317 
318  }
319  }
320  }
321  double prob_tot=1e-100;
322  for (unsigned int m=0;m<probs.size();m++){
323  prob_tot+=probs[m];
324  }
325 
326  // Adjust the state vector and the covariance using the hit
327  //information
328  bool skip_plane=(my_fdchits[id]->hit->wire->layer==PLANE_TO_SKIP);
329  if (skip_plane==false){
331  DMatrix5x5 sum2;
332  for (unsigned int m=0;m<Klist.size();m++){
333  double my_prob=probs[m]/prob_tot;
334  S+=my_prob*(Mlist[m]*Klist[m]);
335  sum-=my_prob*(Klist[m]*Hlist[m]);
336  sum2+=(my_prob*my_prob*Vlist[m])*MultiplyTranspose(Klist[m]);
337  if (DEBUG_LEVEL > 25) {
338  jout << " Adjusting state vector for FDC hit " << m << " with prob " << my_prob << " S:" << endl;
339  S.Print();
340  }
341  }
342  C=C.SandwichMultiply(sum)+sum2;
343  if (DEBUG_LEVEL > 25) { jout << " C: " << endl; C.Print();}
344  }
345 
346  for (unsigned int m=0;m<Hlist.size();m++){
347  unsigned int my_id=used_ids[m];
348  double scale=(skip_plane)?1.:(1.-Hlist[m]*Klist[m]);
349  fdc_updates[my_id].S=S;
350  fdc_updates[my_id].C=C;
351  fdc_updates[my_id].tdrift
353  fdc_updates[my_id].tcorr=fdc_updates[my_id].tdrift; // temporary!
354  fdc_updates[my_id].variance=scale*Vlist[m];
355  fdc_updates[my_id].doca=doca;
356 
357  // update chi2
358  if (skip_plane==false){
359  chisq+=(probs[m]/prob_tot)*(1.-Hlist[m]*Klist[m])*Mlist[m]*Mlist[m]/Vlist[m];
360  }
361  }
362 
363  // update number of degrees of freedom
364  if (skip_plane==false){
365  numdof++;
366  }
367  }
368  else{
369 
370  if (DEBUG_LEVEL > 25) jout << " == There is a single FDC hit on this plane" << endl;
371  // Variance for this hit
372  //double Vtemp=V+H*C*H_T;
373  double Vproj=C.SandwichMultiply(H_T);
374  double Vtemp=V+Vproj;
375  double InvV=1./Vtemp;
376 
377  // Check if this hit is an outlier
378  double chi2_hit=Mdiff*Mdiff*InvV;
379  if (chi2_hit<fdc_chi2cut){
380  // Compute Kalman gain matrix
381  K=InvV*(C*H_T);
382 
383  bool skip_plane=(my_fdchits[id]->hit->wire->layer==PLANE_TO_SKIP);
384  if (skip_plane==false){
385  // Update the state vector
386  S+=Mdiff*K;
387 
388  // Update state vector covariance matrix
389  //C=C-K*(H*C);
390  C=C.SubSym(K*(H*C));
391  if (DEBUG_LEVEL > 25) {
392  jout << "S Update: " << endl; S.Print();
393  jout << "C Uodate: " << endl; C.Print();
394  }
395  }
396 
397  // Store the "improved" values for the state vector and covariance
398  double scale=(skip_plane)?1.:(1.-H*K);
399  fdc_updates[id].S=S;
400  fdc_updates[id].C=C;
401  fdc_updates[id].tdrift
403  fdc_updates[id].tcorr=fdc_updates[id].tdrift; // temporary!
404  fdc_updates[id].variance=scale*V;
405  fdc_updates[id].doca=doca;
406  fdc_used_in_fit[id]=true;
407 
408  if (skip_plane==false){
409  // Update chi2 for this segment
410  chisq+=scale*Mdiff*Mdiff/V;
411  // update number of degrees of freedom
412  numdof++;
413  }
414 
415  if (DEBUG_LEVEL>10){
416  printf("hit %d p %5.2f t %f dm %5.2f sig %f chi2 %5.2f z %5.2f\n",
417  id,1./S(state_q_over_p),fdc_updates[id].tdrift,Mdiff,sqrt(V),(1.-H*K)*Mdiff*Mdiff/V,
418  forward_traj[k].z);
419 
420  }
421 
422 
423 
426  }
427  }
428  if (num_fdc_hits>=forward_traj[k].num_hits)
429  num_fdc_hits-=forward_traj[k].num_hits;
430  }
431  }
432  else if (more_cdc_measurements /* && z<endplate_z*/){
433  // new wire position
434  wirepos=origin;
435  wirepos+=(z-z0w)*dir;
436 
437  // doca variables
438  double dx=S(state_x)-wirepos.X();
439  double dy=S(state_y)-wirepos.Y();
440  double doca2=dx*dx+dy*dy;
441 
442  // Check if the doca is no longer decreasing
443  if (doca2>old_doca2 /* && z<endplate_z */){
444  if(my_cdchits[cdc_index]->status==good_hit){
445  double newz=z;
446 
447  // Get energy loss
448  double dedx=0.;
449  if (CORRECT_FOR_ELOSS){
450  dedx=GetdEdx(S(state_q_over_p),
451  forward_traj[k].K_rho_Z_over_A,
452  forward_traj[k].rho_Z_over_A,
453  forward_traj[k].LnI,forward_traj[k].Z);
454  }
455 
456  // track direction variables
457  double tx=S(state_tx);
458  double ty=S(state_ty);
459  double tanl=1./sqrt(tx*tx+ty*ty);
460  double sinl=sin(atan(tanl));
461 
462  // Wire direction variables
463  double ux=dir.X();
464  double uy=dir.Y();
465  // Variables relating wire direction and track direction
466  double my_ux=tx-ux;
467  double my_uy=ty-uy;
468  double denom=my_ux*my_ux+my_uy*my_uy;
469  double dz=0.;
470 
471  // if the path length increment is small relative to the radius
472  // of curvature, use a linear approximation to find dz
473  bool do_brent=false;
474  double step1=mStepSizeZ;
475  double step2=mStepSizeZ;
476  if (k>=2){
477  step1=-forward_traj[k].z+forward_traj[k_minus_1].z;
478  step2=-forward_traj[k_minus_1].z+forward_traj[k-2].z;
479  }
480  //printf("step1 %f step 2 %f \n",step1,step2);
481  double two_step=step1+step2;
482  if (fabs(qBr2p*S(state_q_over_p)
483  *bfield->GetBz(S(state_x),S(state_y),z)
484  *two_step/sinl)<0.01
485  && denom>EPS)
486  {
487  double dzw=z-z0w;
488  dz=-((S(state_x)-origin.X()-ux*dzw)*my_ux
489  +(S(state_y)-origin.Y()-uy*dzw)*my_uy)/denom;
490 
491  if (fabs(dz)>two_step || dz<0){
492  do_brent=true;
493  }
494  else{
495  newz=z+dz;
496  // Check for exiting the straw
497  if (newz>endplate_z){
498  newz=endplate_z;
499  dz=endplate_z-z;
500  }
501  // Step the state and covariance through the field
502  if (dz>mStepSizeZ){
503  double my_z=z;
504  int my_steps=int(dz/mStepSizeZ);
505  double dz2=dz-my_steps*mStepSizeZ;
506  for (int m=0;m<my_steps;m++){
507  newz=my_z+mStepSizeZ;
508 
509  // Bail if the momentum has dropped below some minimum
510  if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX){
511  if (DEBUG_LEVEL>2)
512  {
513  _DBG_ << "Bailing: P = " << 1./fabs(S(state_q_over_p)) << endl;
514  }
515  break_point_fdc_index=(3*num_fdc)/4;
516  return MOMENTUM_OUT_OF_RANGE;
517  }
518 
519  // Step current state by step size
520  Step(my_z,newz,dedx,S);
521 
522  my_z=newz;
523  }
524  newz=my_z+dz2;
525  // Bail if the momentum has dropped below some minimum
526  if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX){
527  if (DEBUG_LEVEL>2)
528  {
529  _DBG_ << "Bailing: P = " << 1./fabs(S(state_q_over_p)) << endl;
530  }
531  break_point_fdc_index=(3*num_fdc)/4;
532  return MOMENTUM_OUT_OF_RANGE;
533  }
534 
535  Step(my_z,newz,dedx,S);
536  }
537  else{
538  // Bail if the momentum has dropped below some minimum
539  if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX){
540  if (DEBUG_LEVEL>2)
541  {
542  _DBG_ << "Bailing: P = " << 1./fabs(S(state_q_over_p)) << endl;
543  }
544  break_point_fdc_index=(3*num_fdc)/4;
545  return MOMENTUM_OUT_OF_RANGE;
546  }
547 
548  Step(z,newz,dedx,S);
549  }
550  }
551  }
552  else do_brent=true;
553  if (do_brent){
554  // We have bracketed the minimum doca: use Brent's agorithm
555  if (BrentsAlgorithm(z,-mStepSizeZ,dedx,z0w,origin,dir,S,dz)!=NOERROR){
556  break_point_fdc_index=(3*num_fdc)/4;
557  return MOMENTUM_OUT_OF_RANGE;
558  }
559  newz=z+dz;
560 
561  if (fabs(dz)>2.*mStepSizeZ-EPS3){
562  // whoops, looks like we didn't actually bracket the minimum
563  // after all. Swim to make sure we pass the minimum doca.
564  double ztemp=newz;
565 
566  // new wire position
567  wirepos=origin;
568  wirepos+=(ztemp-z0w)*dir;
569 
570  // doca
571  old_doca2=doca2;
572 
573  dx=S(state_x)-wirepos.X();
574  dy=S(state_y)-wirepos.Y();
575  doca2=dx*dx+dy*dy;
576 
577  while(doca2<old_doca2){
578  newz=ztemp+mStepSizeZ;
579  old_doca2=doca2;
580 
581  // Step to the new z position
582  Step(ztemp,newz,dedx,S);
583 
584  // find the new distance to the wire
585  wirepos=origin;
586  wirepos+=(newz-z0w)*dir;
587 
588  dx=S(state_x)-wirepos.X();
589  dy=S(state_y)-wirepos.Y();
590  doca2=dx*dx+dy*dy;
591 
592  ztemp=newz;
593  }
594  // Find the true doca
595  double dz2=0.;
596  if (BrentsAlgorithm(newz,mStepSizeZ,dedx,z0w,origin,dir,S,dz2)!=NOERROR){
597  break_point_fdc_index=(3*num_fdc)/4;
598  return MOMENTUM_OUT_OF_RANGE;
599  }
600  newz=ztemp+dz2;
601 
602  // Change in z relative to where we started for this wire
603  dz=newz-z;
604  }
605 
606  }
607 
608  // Step the state and covariance through the field
609  int num_steps=0;
610  double dz3=0.;
611  double my_dz=0.;
612  if (fabs(dz)>mStepSizeZ){
613  my_dz=(dz>0?1.0:-1.)*mStepSizeZ;
614  num_steps=int(fabs(dz/my_dz));
615  dz3=dz-num_steps*my_dz;
616 
617  double my_z=z;
618  for (int m=0;m<num_steps;m++){
619  newz=my_z+my_dz;
620 
621  // Step current state by my_dz
622  //Step(z,newz,dedx,S);
623 
624  // propagate error matrix to z-position of hit
625  StepJacobian(z,newz,S0,dedx,J);
626  //C=J*C*J.Transpose();
627  C=C.SandwichMultiply(J);
628 
629  // Step reference trajectory by my_dz
630  Step(z,newz,dedx,S0);
631 
632  my_z=newz;
633  }
634 
635  newz=my_z+dz3;
636 
637  // Step current state by dz3
638  //Step(my_z,newz,dedx,S);
639 
640  // propagate error matrix to z-position of hit
641  StepJacobian(my_z,newz,S0,dedx,J);
642  //C=J*C*J.Transpose();
643  C=C.SandwichMultiply(J);
644 
645  // Step reference trajectory by dz3
646  Step(my_z,newz,dedx,S0);
647  }
648  else{
649  // Step current state by dz
650  //Step(z,newz,dedx,S);
651 
652  // propagate error matrix to z-position of hit
653  StepJacobian(z,newz,S0,dedx,J);
654  //C=J*C*J.Transpose();
655  C=C.SandwichMultiply(J);
656 
657  // Step reference trajectory by dz
658  Step(z,newz,dedx,S0);
659  }
660 
661  // Wire position at current z
662  wirepos=origin;
663  wirepos+=(newz-z0w)*dir;
664 
665  double xw=wirepos.X();
666  double yw=wirepos.Y();
667 
668  // predicted doca taking into account the orientation of the wire
669  dy=S(state_y)-yw;
670  dx=S(state_x)-xw;
671  double cosstereo=my_cdchits[cdc_index]->cosstereo;
672  double d=sqrt(dx*dx+dy*dy)*cosstereo+EPS;
673 
674  // Track projection
675  double cosstereo2_over_d=cosstereo*cosstereo/d;
676  H_T(state_x)=dx*cosstereo2_over_d;
677  H(state_x)=H_T(state_x);
678  H_T(state_y)=dy*cosstereo2_over_d;
679  H(state_y)=H_T(state_y);
680 
681  //H.Print();
682 
683  // The next measurement
684  double dm=0.39,tdrift=0.,tcorr=0.;
686  // Find offset of wire with respect to the center of the
687  // straw at this z position
688  const DCDCWire *mywire=my_cdchits[cdc_index]->hit->wire;
689  int ring_index=mywire->ring-1;
690  int straw_index=mywire->straw-1;
691  double dz=newz-z0w;
692  double phi_d=atan2(dy,dx);
693  double delta
694  =max_sag[ring_index][straw_index]*(1.-dz*dz/5625.)
695  *cos(phi_d + sag_phi_offset[ring_index][straw_index]);
696  double dphi=phi_d-mywire->origin.Phi();
697  while (dphi>M_PI) dphi-=2*M_PI;
698  while (dphi<-M_PI) dphi+=2*M_PI;
699  if (mywire->origin.Y()<0) dphi*=-1.;
700 
701  tdrift=my_cdchits[cdc_index]->tdrift-mT0
702  -forward_traj[k_minus_1].t*TIME_UNIT_CONVERSION;
703  double B=forward_traj[k_minus_1].B;
704  ComputeCDCDrift(dphi,delta,tdrift,B,dm,Vc,tcorr);
705 
706  //_DBG_ << "t " << tdrift << " d " << d << " delta " << delta << " dphi " << atan2(dy,dx)-mywire->origin.Phi() << endl;
707 
708  //_DBG_ << tcorr << " " << dphi << " " << dm << endl;
709 
710  }
711 
712  // Residual
713  double res=dm-d;
714 
715  // inverse variance including prediction
716  //double InvV1=1./(Vc+H*(C*H_T));
717  double Vproj=C.SandwichMultiply(H_T);
718  double InvV1=1./(Vc+Vproj);
719  if (InvV1<0.){
720  if (DEBUG_LEVEL>0)
721  _DBG_ << "Negative variance???" << endl;
722  return NEGATIVE_VARIANCE;
723  }
724 
725  // Check if this hit is an outlier
726  double chi2_hit=res*res*InvV1;
727  if (chi2_hit<cdc_chi2cut){
728  // Compute KalmanSIMD gain matrix
729  K=InvV1*(C*H_T);
730 
731 
732  // Update state vector covariance matrix
733  //C=C-K*(H*C);
734  Ctest=C.SubSym(K*(H*C));
735  //Ctest=C.SandwichMultiply(I5x5-K*H)+Vc*MultiplyTranspose(K);
736  // Check that Ctest is positive definite
737  if (Ctest(0,0)>0 && Ctest(1,1)>0 && Ctest(2,2)>0 && Ctest(3,3)>0
738  && Ctest(4,4)>0){
739  bool skip_ring
740  =(my_cdchits[cdc_index]->hit->wire->ring==RING_TO_SKIP);
741  // update covariance matrix and state vector
742  if (my_cdchits[cdc_index]->hit->wire->ring!=RING_TO_SKIP && tdrift >= 0.){
743  C=Ctest;
744  S+=res*K;
745  if (DEBUG_LEVEL > 25) {
746  jout << " == Adding CDC Hit in Ring " << my_cdchits[cdc_index]->hit->wire->ring << endl;
747  jout << " New S: " << endl; S.Print();
748  jout << " New C: " << endl; C.Print();
749  }
750  }
751 
752  // Flag the place along the reference trajectory with hit id
753  forward_traj[k].h_id=1000+cdc_index;
754 
755  // Store updated info related to this hit
756  double scale=(skip_ring)?1.:(1.-H*K);
757  cdc_updates[cdc_index].tdrift=tdrift;
758  cdc_updates[cdc_index].tcorr=tcorr;
759  cdc_updates[cdc_index].variance=Vc;
760  cdc_updates[cdc_index].doca=dm;
761  cdc_used_in_fit[cdc_index]=true;
762  if(tdrift < 0.) cdc_used_in_fit[cdc_index]=false;
763 
764  // Update chi2 and number of degrees of freedom for this hit
765  if (skip_ring==false && tdrift >= 0.){
766  chisq+=scale*res*res/Vc;
767  numdof++;
768  }
769 
770  if (DEBUG_LEVEL>10)
771  jout << "Ring " << my_cdchits[cdc_index]->hit->wire->ring
772  << " Straw " << my_cdchits[cdc_index]->hit->wire->straw
773  << " Pred " << d << " Meas " << dm
774  << " Sigma meas " << sqrt(Vc)
775  << " t " << tcorr
776  << " Chi2 " << (1.-H*K)*res*res/Vc << endl;
777 
778  break_point_cdc_index=cdc_index;
779  break_point_step_index=k_minus_1;
780  }
781  }
782 
783  if (num_steps==0){
784  // Step C back to the z-position on the reference trajectory
785  StepJacobian(newz,z,S0,dedx,J);
786  //C=J*C*J.Transpose();
787  C=C.SandwichMultiply(J);
788 
789  // Step S to current position on the reference trajectory
790  Step(newz,z,dedx,S);
791  }
792  else{
793  double my_z=newz;
794  for (int m=0;m<num_steps;m++){
795  z=my_z-my_dz;
796 
797  // Step C along z
798  StepJacobian(my_z,z,S0,dedx,J);
799  //C=J*C*J.Transpose();
800  C=C.SandwichMultiply(J);
801 
802  // Step S along z
803  Step(my_z,z,dedx,S);
804 
805  // Step S0 along z
806  Step(my_z,z,dedx,S0);
807 
808  my_z=z;
809  }
810  z=my_z-dz3;
811 
812  // Step C back to the z-position on the reference trajectory
813  StepJacobian(my_z,z,S0,dedx,J);
814  //C=J*C*J.Transpose();
815  C=C.SandwichMultiply(J);
816 
817  // Step S to current position on the reference trajectory
818  Step(my_z,z,dedx,S);
819  }
820 
821  cdc_updates[cdc_index].S=S;
822  cdc_updates[cdc_index].C=C;
823  }
824 
825  // new wire origin and direction
826  if (cdc_index>0){
827  cdc_index--;
828  origin=my_cdchits[cdc_index]->origin;
829  z0w=my_cdchits[cdc_index]->z0wire;
830  dir=my_cdchits[cdc_index]->dir;
831  }
832  else more_cdc_measurements=false;
833 
834  // Update the wire position
835  wirepos=origin+(z-z0w)*dir;
836 
837  // new doca
838  dx=S(state_x)-wirepos.X();
839  dy=S(state_y)-wirepos.Y();
840  doca2=dx*dx+dy*dy;
841  }
842  old_doca2=doca2;
843  }
844  }
845  // Save final z position
846  z_=forward_traj[forward_traj.size()-1].z;
847 
848  // The following code segment addes a fake point at a well-defined z position
849  // that would correspond to a thin foil target. It should not be turned on
850  // for an extended target.
851  if (ADD_VERTEX_POINT){
852  double dz_to_target=TARGET_Z-z_;
853  double my_dz=mStepSizeZ*(dz_to_target>0?1.:-1.);
854  int num_steps=int(fabs(dz_to_target/my_dz));
855 
856  for (int k=0;k<num_steps;k++){
857  double newz=z_+my_dz;
858  // Step C along z
859  StepJacobian(z_,newz,S,0.,J);
860 
861  //C=J*C*J.Transpose();
862  C=C.SandwichMultiply(J);
863 
864  // Step S along z
865  Step(z_,newz,0.,S);
866 
867  z_=newz;
868  }
869 
870  // Step C along z
871  StepJacobian(z_,TARGET_Z,S,0.,J);
872 
873  //C=J*C*J.Transpose();
874  C=C.SandwichMultiply(J);
875 
876  // Step S along z
877  Step(z_,TARGET_Z,0.,S);
878 
879  z_=TARGET_Z;
880 
881  // predicted doca taking into account the orientation of the wire
882  double dy=S(state_y);
883  double dx=S(state_x);
884  double d=sqrt(dx*dx+dy*dy);
885 
886  // Track projection
887  double one_over_d=1./d;
888  H_T(state_x)=dx*one_over_d;
889  H(state_x)=H_T(state_x);
890  H_T(state_y)=dy*one_over_d;
891  H(state_y)=H_T(state_y);
892 
893  // Variance of target point
894  // Variance is for average beam spot size assuming triangular distribution
895  // out to 2.2 mm from the beam line.
896  // sigma_r = 2.2 mm/ sqrt(18)
897  Vc=0.002689;
898 
899  // inverse variance including prediction
900  //double InvV1=1./(Vc+H*(C*H_T));
901  double InvV1=1./(Vc+C.SandwichMultiply(H_T));
902  if (InvV1<0.){
903  if (DEBUG_LEVEL>0)
904  _DBG_ << "Negative variance???" << endl;
905  return NEGATIVE_VARIANCE;
906  }
907  // Compute KalmanSIMD gain matrix
908  K=InvV1*(C*H_T);
909 
910  // Update the state vector with the target point
911  // "Measurement" is average of expected beam spot size
912  double res=0.1466666667-d;
913  S+=res*K;
914  // Update state vector covariance matrix
915  //C=C-K*(H*C);
916  C=C.SubSym(K*(H*C));
917 
918  // Update chi2 for this segment
919  chisq+=(1.-H*K)*res*res/Vc;
920  numdof++;
921  }
922 
923  // Check that there were enough hits to make this a valid fit
924  if (numdof<6){
925  chisq=MAX_CHI2;
926  numdof=0;
927 
928  if (num_cdc==0){
929  unsigned int new_index=(3*num_fdc)/4;
931  }
932  else{
933  unsigned int new_index=num_fdc/2;
934  if (new_index+num_cdc>=MIN_HITS_FOR_REFIT){
935  break_point_fdc_index=new_index;
936  }
937  else{
939  }
940  }
941  return PRUNED_TOO_MANY_HITS;
942  }
943 
944  // chisq*=anneal_factor;
945  numdof-=5;
946 
947  // Final positions in x and y for this leg
948  x_=S(state_x);
949  y_=S(state_y);
950 
951  if (DEBUG_LEVEL>1){
952  cout << "Position after forward filter: " << x_ << ", " << y_ << ", " << z_ <<endl;
953  cout << "Momentum " << 1./S(state_q_over_p) <<endl;
954  }
955 
956  // Check if we have a kink in the track or threw away too many hits
957  if (num_cdc>0 && break_point_fdc_index>0){
959  //_DBG_ << endl;
960  unsigned int new_index=num_fdc/2;
961  if (new_index+num_cdc>=MIN_HITS_FOR_REFIT){
962  break_point_fdc_index=new_index;
963  }
964  else{
966  }
967  }
968  return BREAK_POINT_FOUND;
969  }
970  if (num_cdc==0 && break_point_fdc_index>2){
971  //_DBG_ << endl;
972  if (break_point_fdc_index<num_fdc/2){
973  break_point_fdc_index=(3*num_fdc)/4;
974  }
977  }
978  return BREAK_POINT_FOUND;
979  }
980  if (num_cdc>5 && break_point_cdc_index>2){
981  //_DBG_ << endl;
982  unsigned int new_index=num_fdc/2;
983  if (new_index+num_cdc>=MIN_HITS_FOR_REFIT){
984  break_point_fdc_index=new_index;
985  }
986  else{
988  }
989  return BREAK_POINT_FOUND;
990  }
991  unsigned int num_good=0;
992  unsigned int num_hits=num_cdc+max_num_fdc_used_in_fit;
993  for (unsigned int j=0;j<num_cdc;j++){
994  if (cdc_used_in_fit[j]) num_good++;
995  }
996  for (unsigned int j=0;j<num_fdc;j++){
997  if (fdc_used_in_fit[j]) num_good++;
998  }
999  if (double(num_good)/double(num_hits)<MINIMUM_HIT_FRACTION){
1000  //_DBG_ <<endl;
1001  if (num_cdc==0){
1002  unsigned int new_index=(3*num_fdc)/4;
1003  break_point_fdc_index=(new_index>=MIN_HITS_FOR_REFIT)?new_index:(MIN_HITS_FOR_REFIT-1);
1004  }
1005  else{
1006  unsigned int new_index=num_fdc/2;
1007  if (new_index+num_cdc>=MIN_HITS_FOR_REFIT){
1008  break_point_fdc_index=new_index;
1009  }
1010  else{
1012  }
1013  }
1014  return PRUNED_TOO_MANY_HITS;
1015  }
1016 
1017  return FIT_SUCCEEDED;
1018 }
1019 
1020 // Smoothing algorithm for the forward trajectory. Updates the state vector
1021 // at each step (going in the reverse direction to the filter) based on the
1022 // information from all the steps and outputs the state vector at the
1023 // outermost step.
1025  if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE;
1026 
1027  unsigned int max=forward_traj.size()-1;
1028  DMatrix5x1 S=(forward_traj[max].Skk);
1029  DMatrix5x5 C=(forward_traj[max].Ckk);
1030  DMatrix5x5 JT=forward_traj[max].J.Transpose();
1031  DMatrix5x1 Ss=S;
1032  DMatrix5x5 Cs=C;
1033  DMatrix5x5 A,dC;
1034 
1035 
1036  if (DEBUG_LEVEL>19){
1037  jout << "---- Smoothed residuals ----" <<endl;
1038  jout << setprecision(4);
1039  }
1040 
1041  for (unsigned int m=max-1;m>0;m--){
1042  if (forward_traj[m].h_id>0){
1043  if (forward_traj[m].h_id<1000){
1044  unsigned int id=forward_traj[m].h_id-1;
1045  A=fdc_updates[id].C*JT*C.InvertSym();
1046  Ss=fdc_updates[id].S+A*(Ss-S);
1047 
1048  if (!isfinite(Ss(state_q_over_p))){
1049  if (DEBUG_LEVEL>5) _DBG_ << "Invalid values for smoothed parameters..." << endl;
1050  return VALUE_OUT_OF_RANGE;
1051  }
1052  dC=A*(Cs-C)*A.Transpose();
1053  Cs=fdc_updates[id].C+dC;
1054 
1055  double cosa=my_fdchits[id]->cosa;
1056  double sina=my_fdchits[id]->sina;
1057  double u=my_fdchits[id]->uwire;
1058  double v=my_fdchits[id]->vstrip;
1059 
1060  // Position and direction from state vector
1061  double x=Ss(state_x);
1062  double y=Ss(state_y);
1063  double tx=Ss(state_tx);
1064  double ty=Ss(state_ty);
1065 
1066  // Projected position along the wire without doca-dependent corrections
1067  double vpred_uncorrected=x*sina+y*cosa;
1068 
1069  // Projected position in the plane of the wires transverse to the wires
1070  double upred=x*cosa-y*sina;
1071 
1072  // Direction tangent in the u-z plane
1073  double tu=tx*cosa-ty*sina;
1074  double alpha=atan(tu);
1075  double cosalpha=cos(alpha);
1076  //double cosalpha2=cosalpha*cosalpha;
1077  double sinalpha=sin(alpha);
1078 
1079  // (signed) distance of closest approach to wire
1080  double doca=(upred-u)*cosalpha;
1081 
1082  // Correction for lorentz effect
1083  double nz=my_fdchits[id]->nz;
1084  double nr=my_fdchits[id]->nr;
1085  double nz_sinalpha_plus_nr_cosalpha=nz*sinalpha+nr*cosalpha;
1086 
1087  // Difference between measurement and projection
1088  double tv=tx*sina+ty*cosa;
1089  double resi=v-(vpred_uncorrected+doca*(nz_sinalpha_plus_nr_cosalpha
1090  -tv*sinalpha));
1091 
1092  if (DEBUG_LEVEL>19){
1093  jout << "Layer " << my_fdchits[id]->hit->wire->layer
1094  <<": x "<< x << " " << u*cosa+v*sina << " y " << y
1095  << " " << v*cosa-u*sina
1096  << " coordinate along wire " << v << " resi_c " <<resi
1097  << " wire position " << u
1098  <<endl;
1099  }
1100 
1101 
1102  // Variance from filter step
1103  double V=fdc_updates[id].variance;
1104  // Compute projection matrix and find the variance for the residual
1105  DMatrix5x1 H_T;
1106  double temp2=nz_sinalpha_plus_nr_cosalpha-tv*sinalpha;
1107  H_T(state_x)=sina+cosa*cosalpha*temp2;
1108  H_T(state_y)=cosa-sina*cosalpha*temp2;
1109 
1110  double cos2_minus_sin2=cosalpha*cosalpha-sinalpha*sinalpha;
1111  double fac=nz*cos2_minus_sin2-2.*nr*cosalpha*sinalpha;
1112  double doca_cosalpha=doca*cosalpha;
1113  double temp=doca_cosalpha*fac;
1114  H_T(state_tx)=cosa*temp
1115  -doca_cosalpha*(tu*sina+tv*cosa*cos2_minus_sin2)
1116  ;
1117  H_T(state_ty)=-sina*temp
1118  -doca_cosalpha*(tu*cosa-tv*sina*cos2_minus_sin2)
1119  ;
1120 
1121  if (my_fdchits[id]->hit->wire->layer==PLANE_TO_SKIP){
1122  V+=Cs.SandwichMultiply(H_T);
1123  }
1124  else{
1125  V-=dC.SandwichMultiply(H_T);
1126  }
1127 
1128  pulls.push_back(pull_t(resi,sqrt(V),
1129  forward_traj[m].s,
1130  fdc_updates[id].tdrift,
1131  fdc_updates[id].doca,
1132  NULL,my_fdchits[id]->hit,0.,
1133  forward_traj[m].z
1134  ));
1135  }
1136  else{
1137  unsigned int id=forward_traj[m].h_id-1000;
1138  A=cdc_updates[id].C*JT*C.InvertSym();
1139  Ss=cdc_updates[id].S+A*(Ss-S);
1140 
1141  if (!isfinite(Ss(state_q_over_p))){
1142  if (DEBUG_LEVEL>5) _DBG_ << "Invalid values for smoothed parameters..." << endl;
1143  return VALUE_OUT_OF_RANGE;
1144  }
1145 
1146  Cs=cdc_updates[id].C+A*(Cs-C)*A.Transpose();
1147 
1148  // Fill in pulls information for cdc hits
1149  if(cdc_used_in_fit[id] == false) continue;
1150 
1152  cdc_updates[id],pulls);
1153  }
1154  }
1155  else{
1156  A=forward_traj[m].Ckk*JT*C.InvertSym();
1157  Ss=forward_traj[m].Skk+A*(Ss-S);
1158  Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose();
1159  }
1160 
1161  S=forward_traj[m].Skk;
1162  C=forward_traj[m].Ckk;
1163  JT=forward_traj[m].J.Transpose();
1164  }
1165 
1166  return NOERROR;
1167 }
#define EPS3
vector< pull_t > pulls
Definition: DTrackFitter.h:237
jerror_t BrentsAlgorithm(double ds1, double ds2, double dedx, DVector2 &pos, const double z0wire, const DVector2 &origin, const DVector2 &dir, DMatrix5x1 &Sc, double &ds_out)
DMatrix5x5 Transpose()
Definition: DMatrix5x5.h:66
vector< vector< double > > max_sag
TVector2 DVector2
Definition: DVector2.h:9
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
#define EPS
fit_type_t fit_type
Definition: DTrackFitter.h:227
#define y
deque< DKalmanForwardTrajectory_t > forward_traj
#define qBr2p
Definition: DHelicalFit.cc:15
void Print()
Definition: DMatrix5x5.h:603
vector< DKalmanUpdate_t > fdc_updates
vector< DKalmanSIMDFDCHit_t * > my_fdchits
vector< vector< double > > sag_phi_offset
#define MAX_CHI2
const DMagneticFieldMap * bfield
Definition: DTrackFitter.h:228
TEllipse * e
const double alpha
#define H(x, y, z)
TLatex tx
bool CORRECT_FOR_ELOSS
Definition: DTrackFitter.h:250
DMatrix5x5 InvertSym()
Definition: DMatrix5x5.h:221
int straw
Definition: DCDCWire.h:81
void Print()
Definition: DMatrix5x1.h:65
DMatrix5x5 SubSym(const DMatrix5x5 &m2) const
Definition: DMatrix5x5.h:108
DMatrix5x5 SandwichMultiply(const DMatrix5x5 &A)
Definition: DMatrix5x5.h:237
#define TIME_UNIT_CONVERSION
#define _DBG_
Definition: HDEVIO.h:12
vector< DKalmanSIMDCDCHit_t * > my_cdchits
double sqrt(double)
virtual double GetBz(double x, double y, double z) const =0
double sin(double)
jerror_t StepJacobian(double oldz, double newz, const DMatrix5x1 &S, double dEdx, DMatrix5x5 &J)
#define S(str)
Definition: hddm-c.cpp:84
void ComputeCDCDrift(double dphi, double delta, double t, double B, double &d, double &V, double &tcorr)
#define M_TWO_PI
Definition: DGeometry.cc:20
int ring
Definition: DCDCWire.h:80
double Step(double oldz, double newz, double dEdx, DMatrix5x1 &S)
DMatrix5x5 MultiplyTranspose(const DMatrix5x1 &m1)
Definition: DMatrixSIMD.h:233
TDirectory * dir
Definition: bcal_hist_eff.C:31
jerror_t FillPullsVectorEntry(const DMatrix5x1 &Ss, const DMatrix5x5 &Cs, const DKalmanForwardTrajectory_t &traj, const DKalmanSIMDCDCHit_t *hit, const DKalmanUpdate_t &update, vector< pull_t > &mypulls)
printf("string=%s", string)
TH2F * temp
vector< DKalmanUpdate_t > cdc_updates
union @6::@8 u
DMatrix5x5 AddSym(const DMatrix5x5 &m2) const
Definition: DMatrix5x5.h:96
kalman_error_t KalmanForward(double fdc_anneal, double cdc_anneal, DMatrix5x1 &S, DMatrix5x5 &C, double &chisq, unsigned int &numdof)
double GetdEdx(double q_over_p, double K_rho_Z_over_A, double rho_Z_over_A, double rho_Z_over_A_LnI, double Z)