Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DTrackFitterKalmanSIMD.cc
Go to the documentation of this file.
1 //************************************************************************
2 // DTrackFitterKalmanSIMD.cc
3 //************************************************************************
4 
6 #include "CDC/DCDCTrackHit.h"
9 #include "HDGEOMETRY/DRootGeom.h"
10 #include "DANA/DApplication.h"
11 #include <JANA/JCalibration.h>
12 #include "PID/DParticleID.h"
13 
14 #include <TH2F.h>
15 #include <TH1I.h>
16 #include <TROOT.h>
17 #include <TMath.h>
18 #include <DMatrix.h>
19 
20 #include <iomanip>
21 #include <math.h>
22 
23 #define MAX_TB_PASSES 20
24 #define MAX_WB_PASSES 20
25 #define MAX_P 12.0
26 #define ALPHA 1./137.
27 #define CHISQ_DELTA 0.01
28 #define MIN_ITER 3
29 
30 
31 // Local boolean routines for sorting
32 //bool static DKalmanSIMDHit_cmp(DKalmanSIMDHit_t *a, DKalmanSIMDHit_t *b){
33 // return a->z<b->z;
34 //}
35 
37  if (fabs(a->z-b->z)<EPS){
38  if (fabs(a->t-b->t)<EPS){
39  double tsum_1=a->hit->t_u+a->hit->t_v;
40  double tsum_2=b->hit->t_u+b->hit->t_v;
41  if (fabs(tsum_1-tsum_2)<EPS){
42  return (a->dE>b->dE);
43  }
44  return (tsum_1<tsum_2);
45  }
46  return(a->t<b->t);
47  }
48  return a->z<b->z;
49 }
51  if (a==NULL || b==NULL){
52  cout << "Null pointer in CDC hit list??" << endl;
53  return false;
54  }
55  const DCDCWire *wire_a= a->hit->wire;
56  const DCDCWire *wire_b= b->hit->wire;
57  if(wire_b->ring == wire_a->ring){
58  return wire_b->straw < wire_a->straw;
59  }
60 
61  return (wire_b->ring>wire_a->ring);
62 }
63 
64 
65 // Locate a position in array xx given x
66 void DTrackFitterKalmanSIMD::locate(const double *xx,int n,double x,int *j){
67  int jl=-1;
68  int ju=n;
69  int ascnd=(xx[n-1]>=xx[0]);
70  while(ju-jl>1){
71  int jm=(ju+jl)>>1;
72  if ( (x>=xx[jm])==ascnd)
73  jl=jm;
74  else
75  ju=jm;
76  }
77  if (x==xx[0]) *j=0;
78  else if (x==xx[n-1]) *j=n-2;
79  else *j=jl;
80 }
81 
82 
83 
84 // Locate a position in vector xx given x
85 unsigned int DTrackFitterKalmanSIMD::locate(vector<double>&xx,double x){
86  int n=xx.size();
87  if (x==xx[0]) return 0;
88  else if (x==xx[n-1]) return n-2;
89 
90  int jl=-1;
91  int ju=n;
92  int ascnd=(xx[n-1]>=xx[0]);
93  while(ju-jl>1){
94  int jm=(ju+jl)>>1;
95  if ( (x>=xx[jm])==ascnd)
96  jl=jm;
97  else
98  ju=jm;
99  }
100  return jl;
101 }
102 
103 // Crude approximation for the variance in drift distance due to smearing
105  //return FDC_ANODE_VARIANCE;
106  if (t<5.) t=5.;
107  double sigma=DRIFT_RES_PARMS[0]/(t+1.)+DRIFT_RES_PARMS[1]+DRIFT_RES_PARMS[2]*t*t;
108 
109  return sigma*sigma;
110 }
111 
112 // Convert time to distance for the cdc and compute variance
113 void DTrackFitterKalmanSIMD::ComputeCDCDrift(double dphi,double delta,double t,
114  double B,
115  double &d, double &V, double &tcorr){
116  //d=0.39; // initialize at half-cell
117  //V=0.0507; // initialize with (cell size)/12.
118  tcorr = t; // Need this value even when t is negative for calibration
119  if (t>0){
120  //double dtc =(CDC_DRIFT_BSCALE_PAR1 + CDC_DRIFT_BSCALE_PAR2 * B)* t;
121  //tcorr=t-dtc;
122 
123  // CDC_RES_PAR2=0.005;
124  double sigma=CDC_RES_PAR1/(tcorr+1.) + CDC_RES_PAR2 + CDC_RES_PAR3*tcorr;
125 
126  // Variables to store values for time-to-distance functions for delta=0
127  // and delta!=0
128  double f_0=0.;
129  double f_delta=0.;
130  // Derivative of d with respect to t, needed to add t0 variance
131  // dependence to sigma
132  double dd_dt=0;
133  // Scale factor to account for affect of B-field on maximum drift time
135  tcorr=t*Bscale;
136 
137  // if (delta>0)
138  if (delta>-EPS2){
139  double a1=long_drift_func[0][0];
140  double a2=long_drift_func[0][1];
141  double b1=long_drift_func[1][0];
142  double b2=long_drift_func[1][1];
143  double c1=long_drift_func[2][0];
144  double c2=long_drift_func[2][1];
145  double c3=long_drift_func[2][2];
146 
147  // use "long side" functional form
148  double my_t=0.001*tcorr;
149  double sqrt_t=sqrt(my_t);
150  double t3=my_t*my_t*my_t;
151  double delta_mag=fabs(delta);
152  double a=a1+a2*delta_mag;
153  double b=b1+b2*delta_mag;
154  double c=c1+c2*delta_mag+c3*delta*delta;
155  f_delta=a*sqrt_t+b*my_t+c*t3;
156  f_0=a1*sqrt_t+b1*my_t+c1*t3;
157 
158  dd_dt=0.001*(0.5*a/sqrt_t+b+3.*c*my_t*my_t);
159  }
160  else{
161  double my_t=0.001*tcorr;
162  double sqrt_t=sqrt(my_t);
163  double delta_mag=fabs(delta);
164 
165  // use "short side" functional form
166  double a1=short_drift_func[0][0];
167  double a2=short_drift_func[0][1];
168  double a3=short_drift_func[0][2];
169  double b1=short_drift_func[1][0];
170  double b2=short_drift_func[1][1];
171  double b3=short_drift_func[1][2];
172 
173  double delta_sq=delta*delta;
174  double a=a1+a2*delta_mag+a3*delta_sq;
175  double b=b1+b2*delta_mag+b3*delta_sq;
176  f_delta=a*sqrt_t+b*my_t;
177  f_0=a1*sqrt_t+b1*my_t;
178 
179  dd_dt=0.001*(0.5*a/sqrt_t+b);
180  }
181 
182  unsigned int max_index=cdc_drift_table.size()-1;
183  if (tcorr>cdc_drift_table[max_index]){
184  //_DBG_ << "t: " << tcorr <<" d " << f_delta <<endl;
185  d=f_delta;
186  V=sigma*sigma+mVarT0*dd_dt*dd_dt;
187 
188  return;
189  }
190 
191  // Drift time is within range of table -- interpolate...
192  unsigned int index=0;
193  index=locate(cdc_drift_table,tcorr);
194  double dt=cdc_drift_table[index+1]-cdc_drift_table[index];
195  double frac=(tcorr-cdc_drift_table[index])/dt;
196  double d_0=0.01*(double(index)+frac);
197 
198  if (fabs(delta) < EPS2){
199  d=d_0;
200  V=sigma*sigma+mVarT0*dd_dt*dd_dt;
201  }
202  else{
203  double P=0.;
204  double tcut=250.0; // ns
205  if (tcorr<tcut) {
206  P=(tcut-tcorr)/tcut;
207  }
208  d=f_delta*(d_0/f_0*P+1.-P);
209  V=sigma*sigma+mVarT0*dd_dt*dd_dt;
210  }
211  }
212  else { // Time is negative, or exactly zero, choose position at wire, with error of t=0 hit
213  d=0.;
215  double dt=cdc_drift_table[1]-cdc_drift_table[0];
216  V=sigma*sigma+mVarT0*0.0001/(dt*dt);
217  //V=0.0507; // straw radius^2 / 12
218  }
219 
220 }
221 
222 #define FDC_T0_OFFSET 17.6
223 // Interpolate on a table to convert time to distance for the fdc
224 /*
225  double DTrackFitterKalmanSIMD::fdc_drift_distance(double t,double Bz) const {
226  double a=93.31,b=4.614,Bref=2.143;
227  t*=(a+b*Bref)/(a+b*Bz);
228  int id=int((t+FDC_T0_OFFSET)/2.);
229  if (id<0) id=0;
230  if (id>138) id=138;
231  double d=fdc_drift_table[id];
232  if (id!=138){
233  double frac=0.5*(t+FDC_T0_OFFSET-2.*double(id));
234  double dd=fdc_drift_table[id+1]-fdc_drift_table[id];
235  d+=frac*dd;
236  }
237 
238  return d;
239  }
240  */
241 
242 // parametrization of time-to-distance for FDC
243 double DTrackFitterKalmanSIMD::fdc_drift_distance(double time,double Bz) const {
244  if (time<0.) return 0.;
245  double d=0.;
247  double tsq=time*time;
248  double t_high=DRIFT_FUNC_PARMS[4];
249 
250  if (time<t_high){
251  d=DRIFT_FUNC_PARMS[0]*sqrt(time)+DRIFT_FUNC_PARMS[1]*time
252  +DRIFT_FUNC_PARMS[2]*tsq+DRIFT_FUNC_PARMS[3]*tsq*time;
253  }
254  else{
255  double t_high_sq=t_high*t_high;
256  d=DRIFT_FUNC_PARMS[0]*sqrt(t_high)+DRIFT_FUNC_PARMS[1]*t_high
257  +DRIFT_FUNC_PARMS[2]*t_high_sq+DRIFT_FUNC_PARMS[3]*t_high_sq*t_high;
258  d+=DRIFT_FUNC_PARMS[5]*(time-t_high);
259  }
260 
261  return d;
262 }
263 
264 
266  FactorForSenseOfRotation=(bfield->GetBz(0.,0.,65.)>0.)?-1.:1.;
267 
268  // Some useful values
271 
272  // Get the position of the CDC downstream endplate from DGeometry
273  double endplate_rmin,endplate_rmax;
274  geom->GetCDCEndplate(endplate_z,endplate_dz,endplate_rmin,endplate_rmax);
275  endplate_z-=0.5*endplate_dz;
277  endplate_rmin+=0.1; // put just inside CDC
278  endplate_r2min=endplate_rmin*endplate_rmin;
279  endplate_r2max=endplate_rmax*endplate_rmax;
280 
281  // Beginning of the cdc
282  vector<double>cdc_center;
283  vector<double>cdc_upstream_endplate_pos;
284  vector<double>cdc_endplate_dim;
285  geom->Get("//posXYZ[@volume='CentralDC'/@X_Y_Z",cdc_origin);
286  geom->Get("//posXYZ[@volume='centralDC']/@X_Y_Z",cdc_center);
287  geom->Get("//posXYZ[@volume='CDPU']/@X_Y_Z",cdc_upstream_endplate_pos);
288  geom->Get("//tubs[@name='CDPU']/@Rio_Z",cdc_endplate_dim);
289  cdc_origin[2]+=cdc_center[2]+cdc_upstream_endplate_pos[2]
290  +0.5*cdc_endplate_dim[2];
291 
293  // geom->GetCDCRmid(cdc_rmid); // THIS ISN'T IMPLEMENTED!!
294  // extract the "mean" radius of each ring from the wire data
295  for(uint ring=0; ring<cdcwires.size(); ring++)
296  cdc_rmid.push_back( cdcwires[ring][0]->origin.Perp() );
297 
298  // Outer detector geometry parameters
299  geom->GetFCALZ(dFCALz);
300  if (geom->GetDIRCZ(dDIRCz)==false) dDIRCz=1000.;
301  vector<double>tof_face;
302  geom->Get("//section/composition/posXYZ[@volume='ForwardTOF']/@X_Y_Z",
303  tof_face);
304  vector<double>tof_plane;
305  geom->Get("//composition[@name='ForwardTOF']/posXYZ[@volume='forwardTOF']/@X_Y_Z/plane[@value='0']", tof_plane);
306  dTOFz=tof_face[2]+tof_plane[2];
307  geom->Get("//composition[@name='ForwardTOF']/posXYZ[@volume='forwardTOF']/@X_Y_Z/plane[@value='1']", tof_plane);
308  dTOFz+=tof_face[2]+tof_plane[2];
309  dTOFz*=0.5; // mid plane between tof planes
310 
311 
312 
313  // Get start counter geometry;
315  // Create vector of direction vectors in scintillator planes
316  for (int i=0;i<30;i++){
317  vector<DVector3>temp;
318  for (unsigned int j=0;j<sc_pos[i].size()-1;j++){
319  double dx=sc_pos[i][j+1].x()-sc_pos[i][j].x();
320  double dy=sc_pos[i][j+1].y()-sc_pos[i][j].y();
321  double dz=sc_pos[i][j+1].z()-sc_pos[i][j].z();
322  temp.push_back(DVector3(dx/dz,dy/dz,1.));
323  }
324  sc_dir.push_back(temp);
325  }
326  SC_END_NOSE_Z=sc_pos[0][12].z();
327  SC_BARREL_R2=sc_pos[0][0].Perp2();
328  SC_PHI_SECTOR1=sc_pos[0][0].Phi();
329  }
330 
331  // Get z positions of fdc wire planes
333  // for now, assume the z extent of a package is the difference between the positions
334  // of the two wire planes. save half of this distance
338 
339  ADD_VERTEX_POINT=false;
340  gPARMS->SetDefaultParameter("KALMAN:ADD_VERTEX_POINT", ADD_VERTEX_POINT);
341 
342  THETA_CUT=60.0;
343  gPARMS->SetDefaultParameter("KALMAN:THETA_CUT", THETA_CUT);
344 
345  RING_TO_SKIP=0;
346  gPARMS->SetDefaultParameter("KALMAN:RING_TO_SKIP",RING_TO_SKIP);
347 
348  PLANE_TO_SKIP=0;
349  gPARMS->SetDefaultParameter("KALMAN:PLANE_TO_SKIP",PLANE_TO_SKIP);
350 
352  gPARMS->SetDefaultParameter("KALMAN:MINIMUM_HIT_FRACTION",MINIMUM_HIT_FRACTION);
354  gPARMS->SetDefaultParameter("KALMAN:MIN_HITS_FOR_REFIT", MIN_HITS_FOR_REFIT);
355  PHOTON_ENERGY_CUTOFF=0.125;
356  gPARMS->SetDefaultParameter("KALMAN:PHOTON_ENERGY_CUTOFF",
358 
359  USE_FDC_HITS=true;
360  gPARMS->SetDefaultParameter("TRKFIT:USE_FDC_HITS",USE_FDC_HITS);
361  USE_CDC_HITS=true;
362  gPARMS->SetDefaultParameter("TRKFIT:USE_CDC_HITS",USE_CDC_HITS);
363 
364  // Flag to enable calculation of alignment derivatives
365  ALIGNMENT=false;
366  gPARMS->SetDefaultParameter("TRKFIT:ALIGNMENT",ALIGNMENT);
367 
368  ALIGNMENT_FORWARD=false;
369  gPARMS->SetDefaultParameter("TRKFIT:ALIGNMENT_FORWARD",ALIGNMENT_FORWARD);
370 
371  ALIGNMENT_CENTRAL=false;
372  gPARMS->SetDefaultParameter("TRKFIT:ALIGNMENT_CENTRAL",ALIGNMENT_CENTRAL);
373 
375 
376  DEBUG_HISTS=false;
377  gPARMS->SetDefaultParameter("KALMAN:DEBUG_HISTS", DEBUG_HISTS);
378 
379  DEBUG_LEVEL=0;
380  gPARMS->SetDefaultParameter("KALMAN:DEBUG_LEVEL", DEBUG_LEVEL);
381 
383  gPARMS->SetDefaultParameter("KALMAN:USE_T0_FROM_WIRES", USE_T0_FROM_WIRES);
384 
385  ESTIMATE_T0_TB=false;
386  gPARMS->SetDefaultParameter("KALMAN:ESTIMATE_T0_TB",ESTIMATE_T0_TB);
387 
389  gPARMS->SetDefaultParameter("GEOM:ENABLE_BOUNDARY_CHECK",
391 
392  USE_MULS_COVARIANCE=true;
393  gPARMS->SetDefaultParameter("TRKFIT:USE_MULS_COVARIANCE",
395 
396  USE_PASS1_TIME_MODE=false;
397  gPARMS->SetDefaultParameter("KALMAN:USE_PASS1_TIME_MODE",USE_PASS1_TIME_MODE);
398 
399  USE_FDC_DRIFT_TIMES=true;
400  gPARMS->SetDefaultParameter("TRKFIT:USE_FDC_DRIFT_TIMES",
402 
404  gPARMS->SetDefaultParameter("KALMAN:RECOVER_BROKEN_TRACKS",RECOVER_BROKEN_TRACKS);
405 
406  NUM_CDC_SIGMA_CUT=5.0;
407  NUM_FDC_SIGMA_CUT=5.0;
408  gPARMS->SetDefaultParameter("KALMAN:NUM_CDC_SIGMA_CUT",NUM_CDC_SIGMA_CUT,
409  "maximum distance in number of sigmas away from projection to accept cdc hit");
410  gPARMS->SetDefaultParameter("KALMAN:NUM_FDC_SIGMA_CUT",NUM_FDC_SIGMA_CUT,
411  "maximum distance in number of sigmas away from projection to accept fdc hit");
412 
413  ANNEAL_SCALE=9.0;
414  ANNEAL_POW_CONST=1.5;
415  gPARMS->SetDefaultParameter("KALMAN:ANNEAL_SCALE",ANNEAL_SCALE,
416  "Scale factor for annealing");
417  gPARMS->SetDefaultParameter("KALMAN:ANNEAL_POW_CONST",ANNEAL_POW_CONST,
418  "Annealing parameter");
421  gPARMS->SetDefaultParameter("KALMAN:FORWARD_ANNEAL_SCALE",
423  "Scale factor for annealing");
424  gPARMS->SetDefaultParameter("KALMAN:FORWARD_ANNEAL_POW_CONST",
426  "Annealing parameter");
427 
428  FORWARD_PARMS_COV=false;
429  gPARMS->SetDefaultParameter("KALMAN:FORWARD_PARMS_COV",FORWARD_PARMS_COV);
430 
432  gPARMS->SetDefaultParameter("KALMAN:CDC_VAR_SCALE_FACTOR",CDC_VAR_SCALE_FACTOR);
433  CDC_T_DRIFT_MIN=-12.; // One f125 clock = 8 ns
434  gPARMS->SetDefaultParameter("KALMAN:CDC_T_DRIFT_MIN",CDC_T_DRIFT_MIN);
435 
436  MOLIERE_FRACTION=0.9;
437  gPARMS->SetDefaultParameter("KALMAN:MOLIERE_FRACTION",MOLIERE_FRACTION);
438  MS_SCALE_FACTOR=2.0;
439  gPARMS->SetDefaultParameter("KALMAN:MS_SCALE_FACTOR",MS_SCALE_FACTOR);
441  MOLIERE_RATIO2=MS_SCALE_FACTOR*1.e-6/(1.+MOLIERE_FRACTION*MOLIERE_FRACTION); //scale_factor/(1+F*F)
442 
444  gPARMS->SetDefaultParameter("KALMAN:COVARIANCE_SCALE_FACTOR_CENTRAL",
446 
448  gPARMS->SetDefaultParameter("KALMAN:COVARIANCE_SCALE_FACTOR_FORWARD",
450 
452  gPARMS->SetDefaultParameter("KALMAN:WRITE_ML_TRAINING_OUTPUT",
454 
456  mlfile.open("mltraining.dat");
457  }
458 
459 
460  DApplication* dapp = dynamic_cast<DApplication*>(loop->GetJApplication());
461  JCalibration *jcalib = dapp->GetJCalibration((loop->GetJEvent()).GetRunNumber());
462  vector< map<string, double> > tvals;
463  cdc_drift_table.clear();
464  if (jcalib->Get("CDC/cdc_drift_table", tvals)==false){
465  for(unsigned int i=0; i<tvals.size(); i++){
466  map<string, double> &row = tvals[i];
467  cdc_drift_table.push_back(1000.*row["t"]);
468  }
469  }
470  else{
471  jerr << " CDC time-to-distance table not available... bailing..." << endl;
472  exit(0);
473  }
474 
475  int straw_number[28]={42,42,54,54,66,66,80,80,93,93,106,106,
476  123,123,135,135,146,146,158,158,170,170,
477  182,182,197,197,209,209};
478  max_sag.clear();
479  sag_phi_offset.clear();
480  int straw_count=0,ring_count=0;
481  if (jcalib->Get("CDC/sag_parameters", tvals)==false){
482  vector<double>temp,temp2;
483  for(unsigned int i=0; i<tvals.size(); i++){
484  map<string, double> &row = tvals[i];
485 
486  temp.push_back(row["offset"]);
487  temp2.push_back(row["phi"]);
488 
489  straw_count++;
490  if (straw_count==straw_number[ring_count]){
491  max_sag.push_back(temp);
492  sag_phi_offset.push_back(temp2);
493  temp.clear();
494  temp2.clear();
495  straw_count=0;
496  ring_count++;
497  }
498  }
499  }
500 
501  if (jcalib->Get("CDC/drift_parameters", tvals)==false){
502  map<string, double> &row = tvals[0]; // long drift side
503  long_drift_func[0][0]=row["a1"];
504  long_drift_func[0][1]=row["a2"];
505  long_drift_func[0][2]=row["a3"];
506  long_drift_func[1][0]=row["b1"];
507  long_drift_func[1][1]=row["b2"];
508  long_drift_func[1][2]=row["b3"];
509  long_drift_func[2][0]=row["c1"];
510  long_drift_func[2][1]=row["c2"];
511  long_drift_func[2][2]=row["c3"];
512  long_drift_Bscale_par1=row["B1"];
513  long_drift_Bscale_par2=row["B2"];
514 
515  row = tvals[1]; // short drift side
516  short_drift_func[0][0]=row["a1"];
517  short_drift_func[0][1]=row["a2"];
518  short_drift_func[0][2]=row["a3"];
519  short_drift_func[1][0]=row["b1"];
520  short_drift_func[1][1]=row["b2"];
521  short_drift_func[1][2]=row["b3"];
522  short_drift_func[2][0]=row["c1"];
523  short_drift_func[2][1]=row["c2"];
524  short_drift_func[2][2]=row["c3"];
525  short_drift_Bscale_par1=row["B1"];
526  short_drift_Bscale_par2=row["B2"];
527  }
528 
529  map<string, double> cdc_drift_parms;
530  jcalib->Get("CDC/cdc_drift_parms", cdc_drift_parms);
531  CDC_DRIFT_BSCALE_PAR1 = cdc_drift_parms["bscale_par1"];
532  CDC_DRIFT_BSCALE_PAR2 = cdc_drift_parms["bscale_par2"];
533 
534  map<string, double> cdc_res_parms;
535  jcalib->Get("CDC/cdc_resolution_parms_v2", cdc_res_parms);
536  CDC_RES_PAR1 = cdc_res_parms["res_par1"];
537  CDC_RES_PAR2 = cdc_res_parms["res_par2"];
538  CDC_RES_PAR3 = cdc_res_parms["res_par3"];
539 
540  // Parameters for correcting for deflection due to Lorentz force
541  map<string,double>lorentz_parms;
542  jcalib->Get("FDC/lorentz_deflection_parms",lorentz_parms);
543  LORENTZ_NR_PAR1=lorentz_parms["nr_par1"];
544  LORENTZ_NR_PAR2=lorentz_parms["nr_par2"];
545  LORENTZ_NZ_PAR1=lorentz_parms["nz_par1"];
546  LORENTZ_NZ_PAR2=lorentz_parms["nz_par2"];
547 
548  // Parameters for accounting for variation in drift distance from FDC
549  map<string,double>drift_res_parms;
550  jcalib->Get("FDC/drift_resolution_parms",drift_res_parms);
551  DRIFT_RES_PARMS[0]=drift_res_parms["p0"];
552  DRIFT_RES_PARMS[1]=drift_res_parms["p1"];
553  DRIFT_RES_PARMS[2]=drift_res_parms["p2"];
554 
555  // Time-to-distance function parameters for FDC
556  map<string,double>drift_func_parms;
557  jcalib->Get("FDC/drift_function_parms",drift_func_parms);
558  DRIFT_FUNC_PARMS[0]=drift_func_parms["p0"];
559  DRIFT_FUNC_PARMS[1]=drift_func_parms["p1"];
560  DRIFT_FUNC_PARMS[2]=drift_func_parms["p2"];
561  DRIFT_FUNC_PARMS[3]=drift_func_parms["p3"];
562  DRIFT_FUNC_PARMS[4]=1000.;
563  DRIFT_FUNC_PARMS[5]=0.;
564  map<string,double>drift_func_ext;
565  if (jcalib->Get("FDC/drift_function_ext",drift_func_ext)==false){
566  DRIFT_FUNC_PARMS[4]=drift_func_ext["p4"];
567  DRIFT_FUNC_PARMS[5]=drift_func_ext["p5"];
568  }
569  // Factors for taking care of B-dependence of drift time for FDC
570  map<string, double> fdc_drift_parms;
571  jcalib->Get("FDC/fdc_drift_parms", fdc_drift_parms);
572  FDC_DRIFT_BSCALE_PAR1 = fdc_drift_parms["bscale_par1"];
573  FDC_DRIFT_BSCALE_PAR2 = fdc_drift_parms["bscale_par2"];
574 
575 
576  /*
577  if (jcalib->Get("FDC/fdc_drift2", tvals)==false){
578  for(unsigned int i=0; i<tvals.size(); i++){
579  map<string, float> &row = tvals[i];
580  iter_float iter = row.begin();
581  fdc_drift_table[i] = iter->second;
582  }
583  }
584  else{
585  jerr << " FDC time-to-distance table not available... bailing..." << endl;
586  exit(0);
587  }
588  */
589 
590  for (unsigned int i=0;i<5;i++)I5x5(i,i)=1.;
591 
592 
593  // center of the target
594  map<string, double> targetparms;
595  if (jcalib->Get("TARGET/target_parms",targetparms)==false){
596  TARGET_Z = targetparms["TARGET_Z_POSITION"];
597  }
598  else{
600  }
601  if (ADD_VERTEX_POINT){
602  gPARMS->SetDefaultParameter("KALMAN:VERTEX_POSITION",TARGET_Z);
603  }
604 
605  // Beam position and direction
606  map<string, double> beam_vals;
607  jcalib->Get("PHOTON_BEAM/beam_spot",beam_vals);
608  beam_center.Set(beam_vals["x"],beam_vals["y"]);
609  beam_dir.Set(beam_vals["dxdz"],beam_vals["dydz"]);
610  jout << " Beam spot: x=" << beam_center.X() << " y=" << beam_center.Y()
611  << " z=" << beam_vals["z"]
612  << " dx/dz=" << beam_dir.X() << " dy/dz=" << beam_dir.Y() << endl;
613  beam_z0=beam_vals["z"];
614 
615  // Inform user of some configuration settings
616  static bool config_printed = false;
617  if(!config_printed){
618  config_printed = true;
619  stringstream ss;
620  ss << "vertex constraint: " ;
621  if(ADD_VERTEX_POINT){
622  ss << "z = " << TARGET_Z << "cm" << endl;
623  }else{
624  ss << "<none>" << endl;
625  }
626  jout << ss.str();
627  } // config_printed
628 
629  if(DEBUG_HISTS){
630  for (auto i=0; i < 46; i++){
631  double min = -10., max=10.;
632  if(i%23<12) {min=-5; max=5;}
633  if(i<23)alignDerivHists[i]=new TH1I(Form("CentralDeriv%i",i),Form("CentralDeriv%i",i),200, min, max);
634  else alignDerivHists[i]=new TH1I(Form("ForwardDeriv%i",i%23),Form("ForwardDeriv%i",i%23),200, min, max);
635  }
636  brentCheckHists[0]=new TH2I("ForwardBrentCheck","DOCA vs ds", 100, -5., 5., 100, 0.0, 1.5);
637  brentCheckHists[1]=new TH2I("CentralBrentCheck","DOCA vs ds", 100, -5., 5., 100, 0.0, 1.5);
638  }
639 
640  dResourcePool_TMatrixFSym = std::make_shared<DResourcePool<TMatrixFSym>>();
641  dResourcePool_TMatrixFSym->Set_ControlParams(20, 20, 50);
642 
643  my_fdchits.reserve(24);
644  my_cdchits.reserve(28);
645  fdc_updates.reserve(24);
646  cdc_updates.reserve(28);
647  cdc_used_in_fit.reserve(28);
648  fdc_used_in_fit.reserve(24);
649 }
650 
651 //-----------------
652 // ResetKalmanSIMD
653 //-----------------
655 {
657 
658  for (unsigned int i=0;i<my_cdchits.size();i++){
659  delete my_cdchits[i];
660  }
661  for (unsigned int i=0;i<my_fdchits.size();i++){
662  delete my_fdchits[i];
663  }
664  central_traj.clear();
665  forward_traj.clear();
666  my_fdchits.clear();
667  my_cdchits.clear();
668  fdc_updates.clear();
669  cdc_updates.clear();
670  fdc_used_in_fit.clear();
671  cdc_used_in_fit.clear();
672 
673  cov.clear();
674  fcov.clear();
675 
676  len = 0.0;
677  ftime=0.0;
678  var_ftime=0.0;
679  x_=0.,y_=0.,tx_=0.,ty_=0.,q_over_p_ = 0.0;
680  z_=0.,phi_=0.,tanl_=0.,q_over_pt_ =0, D_= 0.0;
681  chisq_ = 0.0;
682  ndf_ = 0;
683  MASS=0.13957;
684  mass2=MASS*MASS;
685  Bx=By=0.;
686  Bz=2.;
687  dBxdx=0.,dBxdy=0.,dBxdz=0.,dBydx=0.,dBydy=0.,dBydy=0.,dBzdx=0.,dBzdy=0.,dBzdz=0.;
688  // Step sizes
689  mStepSizeS=2.0;
690  mStepSizeZ=2.0;
691  //mStepSizeZ=0.5;
692 
693  //if (fit_type==kTimeBased){
694  // mStepSizeS=0.5;
695  // mStepSizeZ=0.5;
696  // }
697 
698 
699  mT0=0.,mT0MinimumDriftTime=1e6;
700  mVarT0=25.;
701 
703  //mCDCInternalStepSize=1.0;
704  //mCentralStepSize=0.75;
705  mCentralStepSize=0.75;
706 
708 
709  IsHadron=true;
710  IsElectron=false;
711  IsPositron=false;
712 
713  PT_MIN=0.01;
714  Q_OVER_P_MAX=100.;
715 
716  // These variables provide the approximate location along the trajectory
717  // where there is an indication of a kink in the track
721 
722 }
723 
724 //-----------------
725 // FitTrack
726 //-----------------
728 {
729  // Reset member data and free an memory associated with the last fit,
730  // but some of which only for wire-based fits
731  ResetKalmanSIMD();
732 
733  // Check that we have enough FDC and CDC hits to proceed
734  if (cdchits.size()==0 && fdchits.size()<4) return kFitNotDone;
735  if (cdchits.size()+fdchits.size() < 6) return kFitNotDone;
736 
737  // Copy hits from base class into structures specific to DTrackFitterKalmanSIMD
738  if (USE_CDC_HITS)
739  for(unsigned int i=0; i<cdchits.size(); i++)AddCDCHit(cdchits[i]);
740  if (USE_FDC_HITS)
741  for(unsigned int i=0; i<fdchits.size(); i++)AddFDCHit(fdchits[i]);
742 
743  unsigned int num_good_cdchits=my_cdchits.size();
744  unsigned int num_good_fdchits=my_fdchits.size();
745 
746  // keep track of the range of detector elements that could be hit
747  // for calculating the number of expected hits later on
748  //int min_cdc_ring=-1, max_cdc_ring=-1;
749 
750  // Order the cdc hits by ring number
751  if (num_good_cdchits>0){
752  stable_sort(my_cdchits.begin(),my_cdchits.end(),DKalmanSIMDCDCHit_cmp);
753 
754  //min_cdc_ring = my_cdchits[0]->hit->wire->ring;
755  //max_cdc_ring = my_cdchits[my_cdchits.size()-1]->hit->wire->ring;
756 
757  // Look for multiple hits on the same wire
758  for (unsigned int i=0;i<my_cdchits.size()-1;i++){
759  if (my_cdchits[i]->hit->wire->ring==my_cdchits[i+1]->hit->wire->ring &&
760  my_cdchits[i]->hit->wire->straw==my_cdchits[i+1]->hit->wire->straw){
761  num_good_cdchits--;
762  if (my_cdchits[i]->tdrift<my_cdchits[i+1]->tdrift){
763  my_cdchits[i+1]->status=late_hit;
764  }
765  else{
766  my_cdchits[i]->status=late_hit;
767  }
768  }
769  }
770 
771  }
772  // Order the fdc hits by z
773  if (num_good_fdchits>0){
774  stable_sort(my_fdchits.begin(),my_fdchits.end(),DKalmanSIMDFDCHit_cmp);
775 
776  // Look for multiple hits on the same wire
777  for (unsigned int i=0;i<my_fdchits.size()-1;i++){
778  if (my_fdchits[i]->hit->wire->layer==my_fdchits[i+1]->hit->wire->layer &&
779  my_fdchits[i]->hit->wire->wire==my_fdchits[i+1]->hit->wire->wire){
780  num_good_fdchits--;
781  if (fabs(my_fdchits[i]->t-my_fdchits[i+1]->t)<EPS){
782  double tsum_1=my_fdchits[i]->hit->t_u+my_fdchits[i]->hit->t_v;
783  double tsum_2=my_fdchits[i+1]->hit->t_u+my_fdchits[i+1]->hit->t_v;
784  if (tsum_1<tsum_2){
785  my_fdchits[i+1]->status=late_hit;
786  }
787  else{
788  my_fdchits[i]->status=late_hit;
789  }
790  }
791  else if (my_fdchits[i]->t<my_fdchits[i+1]->t){
792  my_fdchits[i+1]->status=late_hit;
793  }
794  else{
795  my_fdchits[i]->status=late_hit;
796  }
797  }
798  }
799  }
800  if (num_good_cdchits==0 && num_good_fdchits<4) return kFitNotDone;
801  if(num_good_cdchits+num_good_fdchits < 6) return kFitNotDone;
802 
803  // Create vectors of updates (from hits) to S and C
804  if (my_cdchits.size()>0){
805  cdc_updates=vector<DKalmanUpdate_t>(my_cdchits.size());
806  // Initialize vector to keep track of whether or not a hit is used in
807  // the fit
808  cdc_used_in_fit=vector<bool>(my_cdchits.size());
809  }
810  if (my_fdchits.size()>0){
811  fdc_updates=vector<DKalmanUpdate_t>(my_fdchits.size());
812  // Initialize vector to keep track of whether or not a hit is used in
813  // the fit
814  fdc_used_in_fit=vector<bool>(my_fdchits.size());
815  }
816 
817  // start time and variance
818  if (fit_type==kTimeBased){
819  mT0=input_params.t0();
820  switch(input_params.t0_detector()){
821  case SYS_TOF:
822  mVarT0=0.01;
823  break;
824  case SYS_CDC:
825  mVarT0=7.5;
826  break;
827  case SYS_FDC:
828  mVarT0=7.5;
829  break;
830  case SYS_BCAL:
831  mVarT0=0.25;
832  break;
833  default:
834  mVarT0=0.09;
835  break;
836  }
837  }
838 
839  //_DBG_ << SystemName(input_params.t0_detector()) << " " << mT0 <<endl;
840 
841  //Set the mass
843  mass2=MASS*MASS;
846 
847  // Is this particle an electron or positron?
848  if (MASS<0.001){
849  IsHadron=false;
850  if (input_params.charge()<0.) IsElectron=true;
851  else IsPositron=true;
852  }
853  if (DEBUG_LEVEL>0)
854  {
855  _DBG_ << "------Starting "
856  <<(fit_type==kTimeBased?"Time-based":"Wire-based")
857  << " Fit with " << my_fdchits.size() << " FDC hits and "
858  << my_cdchits.size() << " CDC hits.-------" <<endl;
859  if (fit_type==kTimeBased){
860  _DBG_ << " Using t0=" << mT0 << " from DET="
861  << input_params.t0_detector() <<endl;
862  }
863  }
864  // Do the fit
865  jerror_t error = KalmanLoop();
866  if (error!=NOERROR){
867  if (DEBUG_LEVEL>0)
868  _DBG_ << "Fit failed with Error = " << error <<endl;
869  return kFitFailed;
870  }
871 
872  // Copy fit results into DTrackFitter base-class data members
873  DVector3 mom,pos;
874  GetPosition(pos);
875  GetMomentum(mom);
876  double charge = GetCharge();
877  fit_params.setPosition(pos);
878  fit_params.setMomentum(mom);
880  fit_params.setPID(IDTrack(charge, MASS));
882 
883  if (DEBUG_LEVEL>0){
884  _DBG_ << "----- Pass: "
885  << (fit_type==kTimeBased?"Time-based ---":"Wire-based ---")
886  << " Mass: " << MASS
887  << " p=" << mom.Mag()
888  << " theta=" << 90.0-180./M_PI*atan(tanl_)
889  << " vertex=(" << x_ << "," << y_ << "," << z_<<")"
890  << " chi2=" << chisq_
891  <<endl;
892  if(DEBUG_LEVEL>3){
893  //Dump pulls
894  for (unsigned int iPull = 0; iPull < pulls.size(); iPull++){
895  if (pulls[iPull].cdc_hit != NULL){
896  _DBG_ << " ring: " << pulls[iPull].cdc_hit->wire->ring
897  << " straw: " << pulls[iPull].cdc_hit->wire->straw
898  << " Residual: " << pulls[iPull].resi
899  << " Err: " << pulls[iPull].err
900  << " tdrift: " << pulls[iPull].tdrift
901  << " doca: " << pulls[iPull].d
902  << " docaphi: " << pulls[iPull].docaphi
903  << " z: " << pulls[iPull].z
904  << " cos(theta_rel): " << pulls[iPull].cosThetaRel
905  << " tcorr: " << pulls[iPull].tcorr
906  << endl;
907  }
908  }
909  }
910  }
911 
912  DMatrixDSym errMatrix(5);
913  // Fill the tracking error matrix and the one needed for kinematic fitting
914  if (fcov.size()!=0){
915  // We MUST fill the entire matrix (not just upper right) even though
916  // this is a DMatrixDSym
917  for (unsigned int i=0;i<5;i++){
918  for (unsigned int j=0;j<5;j++){
919  errMatrix(i,j)=fcov[i][j];
920  }
921  }
922  if (FORWARD_PARMS_COV){
925 
926  // Compute and fill the error matrix needed for kinematic fitting
928  }
929  else {
932 
933  // Compute and fill the error matrix needed for kinematic fitting
935  }
936  }
937  else if (cov.size()!=0){
939 
940  // We MUST fill the entire matrix (not just upper right) even though
941  // this is a DMatrixDSym
942  for (unsigned int i=0;i<5;i++){
943  for (unsigned int j=0;j<5;j++){
944  errMatrix(i,j)=cov[i][j];
945  }
946  }
948 
949  // Compute and fill the error matrix needed for kinematic fitting
951  }
952  auto locTrackingCovarianceMatrix = dResourcePool_TMatrixFSym->Get_SharedResource();
953  locTrackingCovarianceMatrix->ResizeTo(5, 5);
954  for(unsigned int loc_i = 0; loc_i < 5; ++loc_i)
955  {
956  for(unsigned int loc_j = 0; loc_j < 5; ++loc_j)
957  (*locTrackingCovarianceMatrix)(loc_i, loc_j) = errMatrix(loc_i, loc_j);
958 
959  }
960  fit_params.setTrackingErrorMatrix(locTrackingCovarianceMatrix);
961  this->chisq = GetChiSq();
962  this->Ndof = GetNDF();
964 
965  // figure out the number of expected hits for this track based on the final fit
966  set<const DCDCWire *> expected_hit_straws;
967  set<int> expected_hit_fdc_planes;
968 
969  for(uint i=0; i<extrapolations[SYS_CDC].size(); i++) {
970  // figure out the radial position of the point to see which ring it's in
971  double r = extrapolations[SYS_CDC][i].position.Perp();
972  uint ring=0;
973  for(; ring<cdc_rmid.size(); ring++) {
974  //_DBG_ << "Rs = " << r << " " << cdc_rmid[ring] << endl;
975  if( (r<cdc_rmid[ring]-0.78) || (fabs(r-cdc_rmid[ring])<0.78) )
976  break;
977  }
978  if(ring == cdc_rmid.size()) ring--;
979  //_DBG_ << "ring = " << ring << endl;
980  //_DBG_ << "ring = " << ring << " stereo = " << cdcwires[ring][0]->stereo << endl;
981  int best_straw=0;
982  double best_dist_diff=fabs((extrapolations[SYS_CDC][i].position
983  - cdcwires[ring][0]->origin).Mag());
984  // match based on straw center
985  for(uint straw=1; straw<cdcwires[ring].size(); straw++) {
986  DVector3 wire_position = cdcwires[ring][straw]->origin; // start with the nominal wire center
987  // now take into account the z dependence due to the stereo angle
988  double dz = extrapolations[SYS_CDC][i].position.Z() - cdcwires[ring][straw]->origin.Z();
989  double ds = dz*tan(cdcwires[ring][straw]->stereo);
990  wire_position += DVector3(-ds*sin(cdcwires[ring][straw]->origin.Phi()), ds*cos(cdcwires[ring][straw]->origin.Phi()), dz);
991  double diff = fabs((extrapolations[SYS_CDC][i].position
992  - wire_position).Mag());
993  if( diff < best_dist_diff )
994  best_straw = straw;
995  }
996 
997  expected_hit_straws.insert(cdcwires[ring][best_straw]);
998  }
999 
1000  for(uint i=0; i<extrapolations[SYS_FDC].size(); i++) {
1001  // check to make sure that the track goes through the sensitive region of the FDC
1002  // assume one hit per plane
1003  double z = extrapolations[SYS_FDC][i].position.Z();
1004  double r = extrapolations[SYS_FDC][i].position.Perp();
1005 
1006  // see if we're in the "sensitive area" of a package
1007  for(uint plane=0; plane<fdc_z_wires.size(); plane++) {
1008  int package = plane/6;
1009  if(fabs(z-fdc_z_wires[plane]) < fdc_package_size) {
1010  if( r<fdc_rmax && r>fdc_rmin_packages[package]) {
1011  expected_hit_fdc_planes.insert(plane);
1012  }
1013  break; // found the right plane
1014  }
1015  }
1016  }
1017 
1018  potential_cdc_hits_on_track = expected_hit_straws.size();
1019  potential_fdc_hits_on_track = expected_hit_fdc_planes.size();
1020 
1021  if(DEBUG_LEVEL>0) {
1022  _DBG_ << " CDC hits/potential hits " << my_cdchits.size() << "/" << potential_cdc_hits_on_track
1023  << " FDC hits/potential hits " << my_fdchits.size() << "/" << potential_fdc_hits_on_track << endl;
1024  }
1025 
1026  //_DBG_ << "========= done!" << endl;
1027 
1028  return fit_status;
1029 }
1030 
1031 //-----------------
1032 // ChiSq
1033 //-----------------
1034 double DTrackFitterKalmanSIMD::ChiSq(fit_type_t fit_type, DReferenceTrajectory *rt, double *chisq_ptr, int *dof_ptr, vector<pull_t> *pulls_ptr)
1035 {
1036  // This simply returns whatever was left in for the chisq/NDF from the last fit.
1037  // Using a DReferenceTrajectory is not really appropriate here so the base class'
1038  // requirement of it should be reviewed.
1039  double chisq = GetChiSq();
1040  unsigned int ndf = GetNDF();
1041 
1042  if(chisq_ptr)*chisq_ptr = chisq;
1043  if(dof_ptr)*dof_ptr = int(ndf);
1044  if(pulls_ptr)*pulls_ptr = pulls;
1045 
1046  return chisq/double(ndf);
1047 }
1048 
1049 // Return the momentum at the distance of closest approach to the origin.
1051  double pt=1./fabs(q_over_pt_);
1052  mom.SetXYZ(pt*cos(phi_),pt*sin(phi_),pt*tanl_);
1053 }
1054 
1055 // Return the "vertex" position (position at which track crosses beam line)
1057  pos.SetXYZ(x_,y_,z_);
1058 }
1059 
1060 // Add FDC hits
1063 
1064  hit->t=fdchit->time;
1065  hit->uwire=fdchit->w;
1066  hit->vstrip=fdchit->s;
1067  hit->vvar=fdchit->ds*fdchit->ds;
1068  hit->z=fdchit->wire->origin.z();
1069  hit->cosa=cos(fdchit->wire->angle);
1070  hit->sina=sin(fdchit->wire->angle);
1071  hit->phiX=fdchit->wire->angles.X();
1072  hit->phiY=fdchit->wire->angles.Y();
1073  hit->phiZ=fdchit->wire->angles.Z();
1074 
1075  hit->nr=0.;
1076  hit->nz=0.;
1077  hit->dE=1e6*fdchit->dE;
1078  hit->hit=fdchit;
1079  hit->status=good_hit;
1080 
1081  my_fdchits.push_back(hit);
1082 
1083  return NOERROR;
1084 }
1085 
1086 // Add CDC hits
1089 
1090  hit->hit=cdchit;
1091  hit->status=good_hit;
1092  hit->origin.Set(cdchit->wire->origin.x(),cdchit->wire->origin.y());
1093  double one_over_uz=1./cdchit->wire->udir.z();
1094  hit->dir.Set(one_over_uz*cdchit->wire->udir.x(),
1095  one_over_uz*cdchit->wire->udir.y());
1096  hit->z0wire=cdchit->wire->origin.z();
1097  hit->cosstereo=cos(cdchit->wire->stereo);
1098  hit->tdrift=cdchit->tdrift;
1099  my_cdchits.push_back(hit);
1100 
1101  return NOERROR;
1102 }
1103 
1104 // Calculate the derivative of the state vector with respect to z
1106  const DMatrix5x1 &S,
1107  double dEdx,
1108  DMatrix5x1 &D){
1109  double tx=S(state_tx),ty=S(state_ty);
1110  double q_over_p=S(state_q_over_p);
1111 
1112  // Turn off dEdx if the magnitude of the momentum drops below some cutoff
1113  if (fabs(q_over_p)>Q_OVER_P_MAX){
1114  dEdx=0.;
1115  }
1116  // Try to keep the direction tangents from heading towards 90 degrees
1117  if (fabs(tx)>TAN_MAX) tx=TAN_MAX*(tx>0.0?1.:-1.);
1118  if (fabs(ty)>TAN_MAX) ty=TAN_MAX*(ty>0.0?1.:-1.);
1119 
1120  // useful combinations of terms
1121  double kq_over_p=qBr2p*q_over_p;
1122  double tx2=tx*tx;
1123  double ty2=ty*ty;
1124  double txty=tx*ty;
1125  double one_plus_tx2=1.+tx2;
1126  double dsdz=sqrt(one_plus_tx2+ty2);
1127  double dtx_Bfac=ty*Bz+txty*Bx-one_plus_tx2*By;
1128  double dty_Bfac=Bx*(1.+ty2)-txty*By-tx*Bz;
1129  double kq_over_p_dsdz=kq_over_p*dsdz;
1130 
1131  // Derivative of S with respect to z
1132  D(state_x)=tx;
1133  D(state_y)=ty;
1134  D(state_tx)=kq_over_p_dsdz*dtx_Bfac;
1135  D(state_ty)=kq_over_p_dsdz*dty_Bfac;
1136 
1137  D(state_q_over_p)=0.;
1138  if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS){
1139  double q_over_p_sq=q_over_p*q_over_p;
1140  double E=sqrt(1./q_over_p_sq+mass2);
1141  D(state_q_over_p)=-q_over_p_sq*q_over_p*E*dEdx*dsdz;
1142  }
1143  return NOERROR;
1144 }
1145 
1146 // Reference trajectory for forward tracks in CDC region
1147 // At each point we store the state vector and the Jacobian needed to get to
1148 //this state along z from the previous state.
1150  int i=0,forward_traj_length=forward_traj.size();
1151  double z=z_;
1152  double r2=0.;
1153  bool stepped_to_boundary=false;
1154 
1155  // Magnetic field and gradient at beginning of trajectory
1156  //bfield->GetField(x_,y_,z_,Bx,By,Bz);
1160 
1161  // Reset cdc status flags
1162  for (unsigned int i=0;i<my_cdchits.size();i++){
1163  if (my_cdchits[i]->status!=late_hit) my_cdchits[i]->status=good_hit;
1164  }
1165 
1166  // Continue adding to the trajectory until we have reached the endplate
1167  // or the maximum radius
1168  while(z<endplate_z_downstream && z>cdc_origin[2] &&
1170  && fabs(S(state_tx))<TAN_MAX
1171  && fabs(S(state_ty))<TAN_MAX
1172  ){
1173  if (PropagateForwardCDC(forward_traj_length,i,z,r2,S,stepped_to_boundary)
1174  !=NOERROR) return UNRECOVERABLE_ERROR;
1175  }
1176 
1177  // Only use hits that would fall within the range of the reference trajectory
1178  /*
1179  for (unsigned int i=0;i<my_cdchits.size();i++){
1180  DKalmanSIMDCDCHit_t *hit=my_cdchits[i];
1181  double my_r2=(hit->origin+(z-hit->z0wire)*hit->dir).Mod2();
1182  if (my_r2>r2) hit->status=bad_hit;
1183  }
1184  */
1185 
1186  // If the current length of the trajectory deque is less than the previous
1187  // trajectory deque, remove the extra elements and shrink the deque
1188  if (i<(int)forward_traj.size()){
1189  forward_traj_length=forward_traj.size();
1190  for (int j=0;j<forward_traj_length-i;j++){
1191  forward_traj.pop_front();
1192  }
1193  }
1194 
1195  // return an error if there are not enough entries in the trajectory
1196  if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE;
1197 
1198  if (DEBUG_LEVEL>20)
1199  {
1200  cout << "--- Forward cdc trajectory ---" <<endl;
1201  for (unsigned int m=0;m<forward_traj.size();m++){
1202  // DMatrix5x1 S=*(forward_traj[m].S);
1203  DMatrix5x1 S=(forward_traj[m].S);
1204  double tx=S(state_tx),ty=S(state_ty);
1205  double phi=atan2(ty,tx);
1206  double cosphi=cos(phi);
1207  double sinphi=sin(phi);
1208  double p=fabs(1./S(state_q_over_p));
1209  double tanl=1./sqrt(tx*tx+ty*ty);
1210  double sinl=sin(atan(tanl));
1211  double cosl=cos(atan(tanl));
1212  cout
1213  << setiosflags(ios::fixed)<< "pos: " << setprecision(4)
1214  << forward_traj[m].S(state_x) << ", "
1215  << forward_traj[m].S(state_y) << ", "
1216  << forward_traj[m].z << " mom: "
1217  << p*cosphi*cosl<< ", " << p*sinphi*cosl << ", "
1218  << p*sinl << " -> " << p
1219  <<" s: " << setprecision(3)
1220  << forward_traj[m].s
1221  <<" t: " << setprecision(3)
1222  << forward_traj[m].t/SPEED_OF_LIGHT
1223  <<" B: " << forward_traj[m].B
1224  << endl;
1225  }
1226  }
1227 
1228  // Current state vector
1229  S=forward_traj[0].S;
1230 
1231  // position at the end of the swim
1232  x_=forward_traj[0].S(state_x);
1233  y_=forward_traj[0].S(state_y);
1234  z_=forward_traj[0].z;
1235 
1236  return NOERROR;
1237 }
1238 
1239 // Routine that extracts the state vector propagation part out of the reference
1240 // trajectory loop
1242  double &z,double &r2,
1243  DMatrix5x1 &S,
1244  bool &stepped_to_boundary){
1245  DMatrix5x5 J,Q;
1247  int my_i=0;
1248  temp.h_id=0;
1249  temp.num_hits=0;
1250  double dEdx=0.;
1251  double s_to_boundary=1e6;
1252  double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
1253 
1254  // current position
1255  DVector3 pos(S(state_x),S(state_y),z);
1256  temp.z=z;
1257  // squared radius
1258  r2=pos.Perp2();
1259 
1260  temp.s=len;
1261  temp.t=ftime;
1262  temp.S=S;
1263 
1264  // Kinematic variables
1265  double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
1266  double one_over_beta2=1.+mass2*q_over_p_sq;
1267  if (one_over_beta2>BIG) one_over_beta2=BIG;
1268 
1269  // get material properties from the Root Geometry
1271  DVector3 mom(S(state_tx),S(state_ty),1.);
1272  if(geom->FindMatKalman(pos,mom,temp.K_rho_Z_over_A,
1273  temp.rho_Z_over_A,temp.LnI,temp.Z,
1274  temp.chi2c_factor,temp.chi2a_factor,
1275  temp.chi2a_corr,
1277  &s_to_boundary)!=NOERROR){
1278  return UNRECOVERABLE_ERROR;
1279  }
1280  }
1281  else
1282  {
1283  if(geom->FindMatKalman(pos,temp.K_rho_Z_over_A,
1284  temp.rho_Z_over_A,temp.LnI,temp.Z,
1285  temp.chi2c_factor,temp.chi2a_factor,
1286  temp.chi2a_corr,
1287  last_material_map)!=NOERROR){
1288  return UNRECOVERABLE_ERROR;
1289  }
1290  }
1291 
1292  // Get dEdx for the upcoming step
1293  if (CORRECT_FOR_ELOSS){
1295  temp.LnI,temp.Z);
1296  }
1297 
1298  index++;
1299  if (index<=length){
1300  my_i=length-index;
1301  forward_traj[my_i].s=temp.s;
1302  forward_traj[my_i].t=temp.t;
1303  forward_traj[my_i].h_id=temp.h_id;
1304  forward_traj[my_i].num_hits=0;
1305  forward_traj[my_i].z=temp.z;
1306  forward_traj[my_i].rho_Z_over_A=temp.rho_Z_over_A;
1307  forward_traj[my_i].K_rho_Z_over_A=temp.K_rho_Z_over_A;
1308  forward_traj[my_i].LnI=temp.LnI;
1309  forward_traj[my_i].Z=temp.Z;
1310  forward_traj[my_i].S=S;
1311  }
1312 
1313  // Determine the step size based on energy loss
1314  //double step=mStepSizeS*dz_ds;
1315  double max_step_size
1316  =(z<endplate_z&& r2>endplate_r2min)?mCDCInternalStepSize:mStepSizeS;
1317  double ds=mStepSizeS;
1318  if (z<endplate_z && r2<endplate_r2max && z>cdc_origin[2]){
1319  if (!stepped_to_boundary){
1320  stepped_to_boundary=false;
1321  if (fabs(dEdx)>EPS){
1322  ds=DE_PER_STEP/fabs(dEdx);
1323  }
1324  if (ds>max_step_size) ds=max_step_size;
1325  if (s_to_boundary<ds){
1326  ds=s_to_boundary+EPS3;
1327  stepped_to_boundary=true;
1328  }
1329  if(ds<MIN_STEP_SIZE)ds=MIN_STEP_SIZE;
1330  }
1331  else{
1332  ds=MIN_STEP_SIZE;
1333  stepped_to_boundary=false;
1334  }
1335  }
1336  double newz=z+ds*dz_ds; // new z position
1337 
1338  // Store magnetic field
1339  temp.B=sqrt(Bx*Bx+By*By+Bz*Bz);
1340 
1341  // Step through field
1342  ds=FasterStep(z,newz,dEdx,S);
1343 
1344  // update path length
1345  len+=fabs(ds);
1346 
1347  // Update flight time
1348  ftime+=ds*sqrt(one_over_beta2);// in units where c=1
1349 
1350  // Get the contribution to the covariance matrix due to multiple
1351  // scattering
1353  temp.S,Q);
1354 
1355  // Energy loss straggling
1356  if (CORRECT_FOR_ELOSS){
1357  double varE=GetEnergyVariance(ds,one_over_beta2,temp.K_rho_Z_over_A);
1358  Q(state_q_over_p,state_q_over_p)=varE*q_over_p_sq*q_over_p_sq*one_over_beta2;
1359  }
1360 
1361  // Compute the Jacobian matrix and its transpose
1362  StepJacobian(newz,z,S,dEdx,J);
1363 
1364  // update the trajectory
1365  if (index<=length){
1366  forward_traj[my_i].B=temp.B;
1367  forward_traj[my_i].Q=Q;
1368  forward_traj[my_i].J=J;
1369  }
1370  else{
1371  temp.Q=Q;
1372  temp.J=J;
1373  temp.Ckk=Zero5x5;
1374  temp.Skk=Zero5x1;
1375  forward_traj.push_front(temp);
1376  }
1377 
1378  //update z
1379  z=newz;
1380 
1381  return NOERROR;
1382 }
1383 
1384 // Routine that extracts the state vector propagation part out of the reference
1385 // trajectory loop
1387  DVector2 &my_xy,
1388  double &var_t_factor,
1389  DMatrix5x1 &Sc,
1390  bool &stepped_to_boundary){
1392  DMatrix5x5 J; // State vector Jacobian matrix
1393  DMatrix5x5 Q; // Process noise covariance matrix
1394 
1395  //Initialize some variables needed later
1396  double dEdx=0.;
1397  double s_to_boundary=1e6;
1398  int my_i=0;
1399  // Kinematic variables
1400  double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl)));
1401  double q_over_p_sq=q_over_p*q_over_p;
1402  double one_over_beta2=1.+mass2*q_over_p_sq;
1403  if (one_over_beta2>BIG) one_over_beta2=BIG;
1404 
1405  // Reset D to zero
1406  Sc(state_D)=0.;
1407 
1408  temp.xy=my_xy;
1409  temp.s=len;
1410  temp.t=ftime;
1411  temp.h_id=0;
1412  temp.S=Sc;
1413 
1414  // Store magnitude of magnetic field
1415  temp.B=sqrt(Bx*Bx+By*By+Bz*Bz);
1416 
1417  // get material properties from the Root Geometry
1418  DVector3 pos3d(my_xy.X(),my_xy.Y(),Sc(state_z));
1420  DVector3 mom(cos(Sc(state_phi)),sin(Sc(state_phi)),Sc(state_tanl));
1421  if(geom->FindMatKalman(pos3d,mom,temp.K_rho_Z_over_A,
1422  temp.rho_Z_over_A,temp.LnI,temp.Z,
1423  temp.chi2c_factor,temp.chi2a_factor,
1424  temp.chi2a_corr,
1426  &s_to_boundary)
1427  !=NOERROR){
1428  return UNRECOVERABLE_ERROR;
1429  }
1430  }
1431  else if(geom->FindMatKalman(pos3d,temp.K_rho_Z_over_A,
1432  temp.rho_Z_over_A,temp.LnI,temp.Z,
1433  temp.chi2c_factor,temp.chi2a_factor,
1434  temp.chi2a_corr,
1435  last_material_map)!=NOERROR){
1436  return UNRECOVERABLE_ERROR;
1437  }
1438 
1439  if (CORRECT_FOR_ELOSS){
1440  dEdx=GetdEdx(q_over_p,temp.K_rho_Z_over_A,temp.rho_Z_over_A,temp.LnI,
1441  temp.Z);
1442  }
1443 
1444  // If the deque already exists, update it
1445  index++;
1446  if (index<=length){
1447  my_i=length-index;
1448  central_traj[my_i].B=temp.B;
1449  central_traj[my_i].s=temp.s;
1450  central_traj[my_i].t=temp.t;
1451  central_traj[my_i].h_id=0;
1452  central_traj[my_i].xy=temp.xy;
1453  central_traj[my_i].rho_Z_over_A=temp.rho_Z_over_A;
1454  central_traj[my_i].K_rho_Z_over_A=temp.K_rho_Z_over_A;
1455  central_traj[my_i].LnI=temp.LnI;
1456  central_traj[my_i].Z=temp.Z;
1457  central_traj[my_i].S=Sc;
1458  }
1459 
1460  // Adjust the step size
1461  double step_size=mStepSizeS;
1462  if (stepped_to_boundary){
1463  step_size=MIN_STEP_SIZE;
1464  stepped_to_boundary=false;
1465  }
1466  else{
1467  if (fabs(dEdx)>EPS){
1468  step_size=DE_PER_STEP/fabs(dEdx);
1469  }
1470  if(step_size>mStepSizeS) step_size=mStepSizeS;
1471  if (s_to_boundary<step_size){
1472  step_size=s_to_boundary+EPS3;
1473  stepped_to_boundary=true;
1474  }
1475  if(step_size<MIN_STEP_SIZE)step_size=MIN_STEP_SIZE;
1476  }
1477  double r2=my_xy.Mod2();
1478  if (r2>endplate_r2min
1479  && step_size>mCDCInternalStepSize) step_size=mCDCInternalStepSize;
1480  // Propagate the state through the field
1481  FasterStep(my_xy,step_size,Sc,dEdx);
1482 
1483  // update path length
1484  len+=step_size;
1485 
1486  // Update flight time
1487  double dt=step_size*sqrt(one_over_beta2); // in units of c=1
1488  double one_minus_beta2=1.-1./one_over_beta2;
1489  ftime+=dt;
1490  var_ftime+=dt*dt*one_minus_beta2*one_minus_beta2*0.0004;
1491  var_t_factor=dt*dt*one_minus_beta2*one_minus_beta2;
1492 
1493  //printf("t %f sigt %f\n",TIME_UNIT_CONVERSION*ftime,TIME_UNIT_CONVERSION*sqrt(var_ftime));
1494 
1495  // Multiple scattering
1496  GetProcessNoiseCentral(step_size,temp.chi2c_factor,temp.chi2a_factor,
1497  temp.chi2a_corr,temp.S,Q);
1498 
1499  // Energy loss straggling in the approximation of thick absorbers
1500  if (CORRECT_FOR_ELOSS){
1501  double varE
1502  =GetEnergyVariance(step_size,one_over_beta2,temp.K_rho_Z_over_A);
1504  +=varE*temp.S(state_q_over_pt)*temp.S(state_q_over_pt)*one_over_beta2
1505  *q_over_p_sq;
1506  }
1507 
1508  // B-field and gradient at current (x,y,z)
1509  bfield->GetFieldAndGradient(my_xy.X(),my_xy.Y(),Sc(state_z),Bx,By,Bz,
1512 
1513  // Compute the Jacobian matrix and its transpose
1514  StepJacobian(my_xy,temp.xy-my_xy,-step_size,Sc,dEdx,J);
1515 
1516  // Update the trajectory info
1517  if (index<=length){
1518  central_traj[my_i].Q=Q;
1519  central_traj[my_i].J=J;
1520  }
1521  else{
1522  temp.Q=Q;
1523  temp.J=J;
1524  temp.Ckk=Zero5x5;
1525  temp.Skk=Zero5x1;
1526  central_traj.push_front(temp);
1527  }
1528 
1529  return NOERROR;
1530 }
1531 
1532 
1533 
1534 // Reference trajectory for central tracks
1535 // At each point we store the state vector and the Jacobian needed to get to this state
1536 // along s from the previous state.
1537 // The tricky part is that we swim out from the target to find Sc and pos along the trajectory
1538 // but we need the Jacobians for the opposite direction, because the filter proceeds from
1539 // the outer hits toward the target.
1541  DMatrix5x1 &Sc){
1542  bool stepped_to_boundary=false;
1543  int i=0,central_traj_length=central_traj.size();
1544  // factor for scaling momentum resolution to propagate variance in flight
1545  // time
1546  double var_t_factor=0;
1547 
1548  // Magnetic field and gradient at beginning of trajectory
1549  //bfield->GetField(x_,y_,z_,Bx,By,Bz);
1553 
1554  // Copy of initial position in xy
1555  DVector2 my_xy=xy;
1556  double r2=xy.Mod2(),z=z_;
1557 
1558  // Reset cdc status flags
1559  for (unsigned int j=0;j<my_cdchits.size();j++){
1560  if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
1561  }
1562 
1563  // Continue adding to the trajectory until we have reached the endplate
1564  // or the maximum radius
1565  while(z<endplate_z && z>=Z_MIN && r2<endplate_r2max
1566  && fabs(Sc(state_q_over_pt))<Q_OVER_PT_MAX
1567  ){
1568  if (PropagateCentral(central_traj_length,i,my_xy,var_t_factor,Sc,stepped_to_boundary)
1569  !=NOERROR) return UNRECOVERABLE_ERROR;
1570  z=Sc(state_z);
1571  r2=my_xy.Mod2();
1572  }
1573 
1574  // If the current length of the trajectory deque is less than the previous
1575  // trajectory deque, remove the extra elements and shrink the deque
1576  if (i<(int)central_traj.size()){
1577  int central_traj_length=central_traj.size();
1578  for (int j=0;j<central_traj_length-i;j++){
1579  central_traj.pop_front();
1580  }
1581  }
1582 
1583  // Only use hits that would fall within the range of the reference trajectory
1584  /*for (unsigned int j=0;j<my_cdchits.size();j++){
1585  DKalmanSIMDCDCHit_t *hit=my_cdchits[j];
1586  double my_r2=(hit->origin+(z-hit->z0wire)*hit->dir).Mod2();
1587  if (my_r2>r2) hit->status=bad_hit;
1588  }
1589  */
1590 
1591  // return an error if there are not enough entries in the trajectory
1592  if (central_traj.size()<2) return RESOURCE_UNAVAILABLE;
1593 
1594  if (DEBUG_LEVEL>20)
1595  {
1596  cout << "---------" << central_traj.size() <<" entries------" <<endl;
1597  for (unsigned int m=0;m<central_traj.size();m++){
1598  DMatrix5x1 S=central_traj[m].S;
1599  double cosphi=cos(S(state_phi));
1600  double sinphi=sin(S(state_phi));
1601  double pt=fabs(1./S(state_q_over_pt));
1602  double tanl=S(state_tanl);
1603 
1604  cout
1605  << m << "::"
1606  << setiosflags(ios::fixed)<< "pos: " << setprecision(4)
1607  << central_traj[m].xy.X() << ", "
1608  << central_traj[m].xy.Y() << ", "
1609  << central_traj[m].S(state_z) << " mom: "
1610  << pt*cosphi << ", " << pt*sinphi << ", "
1611  << pt*tanl << " -> " << pt/cos(atan(tanl))
1612  <<" s: " << setprecision(3)
1613  << central_traj[m].s
1614  <<" t: " << setprecision(3)
1615  << central_traj[m].t/SPEED_OF_LIGHT
1616  <<" B: " << central_traj[m].B
1617  << endl;
1618  }
1619  }
1620 
1621  // State at end of swim
1622  Sc=central_traj[0].S;
1623 
1624  return NOERROR;
1625 }
1626 
1627 // Routine that extracts the state vector propagation part out of the reference
1628 // trajectory loop
1629 jerror_t DTrackFitterKalmanSIMD::PropagateForward(int length,int &i,
1630  double &z,double zhit,
1631  DMatrix5x1 &S, bool &done,
1632  bool &stepped_to_boundary,
1633  bool &stepped_to_endplate){
1634  DMatrix5x5 J,Q;
1636 
1637  // Initialize some variables
1638  temp.h_id=0;
1639  temp.num_hits=0;
1640  int my_i=0;
1641  double s_to_boundary=1e6;
1642  double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
1643 
1644  // current position
1645  DVector3 pos(S(state_x),S(state_y),z);
1646  double r2=pos.Perp2();
1647 
1648  temp.s=len;
1649  temp.t=ftime;
1650  temp.z=z;
1651  temp.S=S;
1652 
1653  // Kinematic variables
1654  double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
1655  double one_over_beta2=1.+mass2*q_over_p_sq;
1656  if (one_over_beta2>BIG) one_over_beta2=BIG;
1657 
1658  // get material properties from the Root Geometry
1660  DVector3 mom(S(state_tx),S(state_ty),1.);
1661  if (geom->FindMatKalman(pos,mom,temp.K_rho_Z_over_A,
1662  temp.rho_Z_over_A,temp.LnI,temp.Z,
1663  temp.chi2c_factor,temp.chi2a_factor,
1664  temp.chi2a_corr,
1666  &s_to_boundary)
1667  !=NOERROR){
1668  return UNRECOVERABLE_ERROR;
1669  }
1670  }
1671  else
1672  {
1673  if (geom->FindMatKalman(pos,temp.K_rho_Z_over_A,
1674  temp.rho_Z_over_A,temp.LnI,temp.Z,
1675  temp.chi2c_factor,temp.chi2a_factor,
1676  temp.chi2a_corr,
1677  last_material_map)!=NOERROR){
1678  return UNRECOVERABLE_ERROR;
1679  }
1680  }
1681 
1682  // Get dEdx for the upcoming step
1683  double dEdx=0.;
1684  if (CORRECT_FOR_ELOSS){
1686  temp.rho_Z_over_A,temp.LnI,temp.Z);
1687  }
1688  i++;
1689  my_i=length-i;
1690  if (i<=length){
1691  forward_traj[my_i].s=temp.s;
1692  forward_traj[my_i].t=temp.t;
1693  forward_traj[my_i].h_id=temp.h_id;
1694  forward_traj[my_i].num_hits=temp.num_hits;
1695  forward_traj[my_i].z=temp.z;
1696  forward_traj[my_i].rho_Z_over_A=temp.rho_Z_over_A;
1697  forward_traj[my_i].K_rho_Z_over_A=temp.K_rho_Z_over_A;
1698  forward_traj[my_i].LnI=temp.LnI;
1699  forward_traj[my_i].S=S;
1700  }
1701  else{
1702  temp.S=S;
1703  }
1704 
1705  // Determine the step size based on energy loss
1706  // step=mStepSizeS*dz_ds;
1707  double max_step_size
1708  =(z<endplate_z&& r2>endplate_r2min)?mCentralStepSize:mStepSizeS;
1709  double ds=mStepSizeS;
1710  if (z>cdc_origin[2]){
1711  if (!stepped_to_boundary){
1712  stepped_to_boundary=false;
1713  if (fabs(dEdx)>EPS){
1714  ds=DE_PER_STEP/fabs(dEdx);
1715  }
1716  if (ds>max_step_size) ds=max_step_size;
1717  if (s_to_boundary<ds){
1718  ds=s_to_boundary+EPS3;
1719  stepped_to_boundary=true;
1720  }
1721  if(ds<MIN_STEP_SIZE)ds=MIN_STEP_SIZE;
1722 
1723  }
1724  else{
1725  ds=MIN_STEP_SIZE;
1726  stepped_to_boundary=false;
1727  }
1728  }
1729 
1730  double dz=stepped_to_endplate ? endplate_dz : ds*dz_ds;
1731  double newz=z+dz; // new z position
1732  // Check if we are stepping through the CDC endplate
1733  if (newz>endplate_z && z<endplate_z){
1734  // _DBG_ << endl;
1735  newz=endplate_z+EPS3;
1736  stepped_to_endplate=true;
1737  }
1738 
1739  // Check if we are about to step to one of the wire planes
1740  done=false;
1741  if (newz>zhit){
1742  newz=zhit;
1743  done=true;
1744  }
1745 
1746  // Store magnitude of magnetic field
1747  temp.B=sqrt(Bx*Bx+By*By+Bz*Bz);
1748 
1749  // Step through field
1750  ds=FasterStep(z,newz,dEdx,S);
1751 
1752  // update path length
1753  len+=ds;
1754 
1755  // update flight time
1756  ftime+=ds*sqrt(one_over_beta2); // in units where c=1
1757 
1758  // Get the contribution to the covariance matrix due to multiple
1759  // scattering
1761  temp.S,Q);
1762 
1763  // Energy loss straggling
1764  if (CORRECT_FOR_ELOSS){
1765  double varE=GetEnergyVariance(ds,one_over_beta2,temp.K_rho_Z_over_A);
1766  Q(state_q_over_p,state_q_over_p)=varE*q_over_p_sq*q_over_p_sq*one_over_beta2;
1767  }
1768 
1769  // Compute the Jacobian matrix and its transpose
1770  StepJacobian(newz,z,S,dEdx,J);
1771 
1772  // update the trajectory data
1773  if (i<=length){
1774  forward_traj[my_i].B=temp.B;
1775  forward_traj[my_i].Q=Q;
1776  forward_traj[my_i].J=J;
1777  }
1778  else{
1779  temp.Q=Q;
1780  temp.J=J;
1781  temp.Ckk=Zero5x5;
1782  temp.Skk=Zero5x1;
1783  forward_traj.push_front(temp);
1784  }
1785 
1786  // update z
1787  z=newz;
1788 
1789  return NOERROR;
1790 }
1791 
1792 // Reference trajectory for trajectories with hits in the forward direction
1793 // At each point we store the state vector and the Jacobian needed to get to this state
1794 // along z from the previous state.
1796 
1797  // Magnetic field and gradient at beginning of trajectory
1798  //bfield->GetField(x_,y_,z_,Bx,By,Bz);
1802 
1803  // progress in z from hit to hit
1804  double z=z_;
1805  int i=0;
1806 
1807  int forward_traj_length=forward_traj.size();
1808  // loop over the fdc hits
1809  double zhit=0.,old_zhit=0.;
1810  bool stepped_to_boundary=false;
1811  bool stepped_to_endplate=false;
1812  unsigned int m=0;
1813  for (m=0;m<my_fdchits.size();m++){
1814  if (fabs(S(state_q_over_p))>Q_OVER_P_MAX
1815  || fabs(S(state_tx))>TAN_MAX
1816  || fabs(S(state_ty))>TAN_MAX
1817  || S(state_x)*S(state_x)+S(state_y)*S(state_y)>50.*50.
1818  || z>400. || z<Z_MIN
1819  ){
1820  break;
1821  }
1822 
1823  zhit=my_fdchits[m]->z;
1824  if (fabs(old_zhit-zhit)>EPS){
1825  bool done=false;
1826  while (!done){
1827  if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX
1828  || fabs(S(state_tx))>TAN_MAX
1829  || fabs(S(state_ty))>TAN_MAX
1830  || S(state_x)*S(state_x)+S(state_y)*S(state_y)>50.*50.
1831  || z>400. || z< Z_MIN
1832  ){
1833  break;
1834  }
1835 
1836  if (PropagateForward(forward_traj_length,i,z,zhit,S,done,
1837  stepped_to_boundary,stepped_to_endplate)
1838  !=NOERROR)
1839  return UNRECOVERABLE_ERROR;
1840  }
1841  }
1842  old_zhit=zhit;
1843  }
1844 
1845  // If m<2 then no useable FDC hits survived the check on the magnitude on the
1846  // momentum
1847  if (m<2) return UNRECOVERABLE_ERROR;
1848 
1849  // Make sure the reference trajectory goes one step beyond the most
1850  // downstream hit plane
1851  if (m==my_fdchits.size()){
1852  bool done=false;
1853  if (PropagateForward(forward_traj_length,i,z,400.,S,done,
1854  stepped_to_boundary,stepped_to_endplate)
1855  !=NOERROR)
1856  return UNRECOVERABLE_ERROR;
1857  if (PropagateForward(forward_traj_length,i,z,400.,S,done,
1858  stepped_to_boundary,stepped_to_endplate)
1859  !=NOERROR)
1860  return UNRECOVERABLE_ERROR;
1861  }
1862 
1863  // Shrink the deque if the new trajectory has less points in it than the
1864  // old trajectory
1865  if (i<(int)forward_traj.size()){
1866  int mylen=forward_traj.size();
1867  //_DBG_ << "Shrinking: " << mylen << " to " << i << endl;
1868  for (int j=0;j<mylen-i;j++){
1869  forward_traj.pop_front();
1870  }
1871  // _DBG_ << " Now " << forward_traj.size() << endl;
1872  }
1873 
1874  // If we lopped off some hits on the downstream end, truncate the trajectory to
1875  // the point in z just beyond the last valid hit
1876  unsigned int my_id=my_fdchits.size();
1877  if (m<my_id){
1878  if (zhit<z) my_id=m;
1879  else my_id=m-1;
1880  zhit=my_fdchits[my_id-1]->z;
1881  //_DBG_ << "Shrinking: " << forward_traj.size()<< endl;
1882  for (;;){
1883  z=forward_traj[0].z;
1884  if (z<zhit+EPS2) break;
1885  forward_traj.pop_front();
1886  }
1887  //_DBG_ << " Now " << forward_traj.size() << endl;
1888 
1889  // Temporory structure keeping state and trajectory information
1891  temp.h_id=0;
1892  temp.num_hits=0;
1893  temp.B=0.;
1894  temp.K_rho_Z_over_A=temp.rho_Z_over_A=temp.LnI=0.;
1895  temp.Q=Zero5x5;
1896 
1897  // last S vector
1898  S=forward_traj[0].S;
1899 
1900  // Step just beyond the last hit
1901  double newz=z+0.01;
1902  double ds=Step(z,newz,0.,S); // ignore energy loss for this small step
1903  temp.s=forward_traj[0].s+ds;
1904  temp.z=newz;
1905  temp.S=S;
1906 
1907  // Flight time
1908  double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
1909  double one_over_beta2=1.+mass2*q_over_p_sq;
1910  if (one_over_beta2>BIG) one_over_beta2=BIG;
1911  temp.t=forward_traj[0].t+ds*sqrt(one_over_beta2); // in units where c=1
1912 
1913  // Covariance and state vector needed for smoothing code
1914  temp.Ckk=Zero5x5;
1915  temp.Skk=Zero5x1;
1916 
1917  // Jacobian matrices
1918  temp.J=I5x5;
1919 
1920  forward_traj.push_front(temp);
1921  }
1922 
1923  // return an error if there are not enough entries in the trajectory
1924  if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE;
1925 
1926  // Fill in Lorentz deflection parameters
1927  for (unsigned int m=0;m<forward_traj.size();m++){
1928  if (my_id>0){
1929  unsigned int hit_id=my_id-1;
1930  double z=forward_traj[m].z;
1931  if (fabs(z-my_fdchits[hit_id]->z)<EPS2){
1932  forward_traj[m].h_id=my_id;
1933 
1934  // Get the magnetic field at this position along the trajectory
1936  z,Bx,By,Bz);
1937  double Br=sqrt(Bx*Bx+By*By);
1938 
1939  // Angle between B and wire
1940  double my_phi=0.;
1941  if (Br>0.) my_phi=acos((Bx*my_fdchits[hit_id]->sina
1942  +By*my_fdchits[hit_id]->cosa)/Br);
1943  /*
1944  lorentz_def->GetLorentzCorrectionParameters(forward_traj[m].pos.x(),
1945  forward_traj[m].pos.y(),
1946  forward_traj[m].pos.z(),
1947  tanz,tanr);
1948  my_fdchits[hit_id]->nr=tanr;
1949  my_fdchits[hit_id]->nz=tanz;
1950  */
1951 
1952  my_fdchits[hit_id]->nr=LORENTZ_NR_PAR1*Bz*(1.+LORENTZ_NR_PAR2*Br);
1953  my_fdchits[hit_id]->nz=(LORENTZ_NZ_PAR1+LORENTZ_NZ_PAR2*Bz)*(Br*cos(my_phi));
1954 
1955 
1956  my_id--;
1957 
1958  unsigned int num=1;
1959  while (hit_id>0
1960  && fabs(my_fdchits[hit_id]->z-my_fdchits[hit_id-1]->z)<EPS){
1961  hit_id=my_id-1;
1962  num++;
1963  my_id--;
1964  }
1965  forward_traj[m].num_hits=num;
1966  }
1967 
1968  }
1969  }
1970 
1971  if (DEBUG_LEVEL>20)
1972  {
1973  cout << "--- Forward fdc trajectory ---" <<endl;
1974  for (unsigned int m=0;m<forward_traj.size();m++){
1975  DMatrix5x1 S=(forward_traj[m].S);
1976  double tx=S(state_tx),ty=S(state_ty);
1977  double phi=atan2(ty,tx);
1978  double cosphi=cos(phi);
1979  double sinphi=sin(phi);
1980  double p=fabs(1./S(state_q_over_p));
1981  double tanl=1./sqrt(tx*tx+ty*ty);
1982  double sinl=sin(atan(tanl));
1983  double cosl=cos(atan(tanl));
1984  cout
1985  << setiosflags(ios::fixed)<< "pos: " << setprecision(4)
1986  << forward_traj[m].S(state_x) << ", "
1987  << forward_traj[m].S(state_y) << ", "
1988  << forward_traj[m].z << " mom: "
1989  << p*cosphi*cosl<< ", " << p*sinphi*cosl << ", "
1990  << p*sinl << " -> " << p
1991  <<" s: " << setprecision(3)
1992  << forward_traj[m].s
1993  <<" t: " << setprecision(3)
1994  << forward_traj[m].t/SPEED_OF_LIGHT
1995  <<" id: " << forward_traj[m].h_id
1996  << endl;
1997  }
1998  }
1999 
2000 
2001  // position at the end of the swim
2002  z_=z;
2003  x_=S(state_x);
2004  y_=S(state_y);
2005 
2006  return NOERROR;
2007 }
2008 
2009 // Step the state vector through the field from oldz to newz.
2010 // Uses the 4th-order Runga-Kutte algorithm.
2011 double DTrackFitterKalmanSIMD::Step(double oldz,double newz, double dEdx,
2012  DMatrix5x1 &S){
2013  double delta_z=newz-oldz;
2014  if (fabs(delta_z)<EPS) return 0.; // skip if the step is too small
2015 
2016  // Direction tangents
2017  double tx=S(state_tx);
2018  double ty=S(state_ty);
2019  double ds=sqrt(1.+tx*tx+ty*ty)*delta_z;
2020 
2021  double delta_z_over_2=0.5*delta_z;
2022  double midz=oldz+delta_z_over_2;
2023  DMatrix5x1 D1,D2,D3,D4;
2024 
2025  //B-field and gradient at at (x,y,z)
2029  double Bx0=Bx,By0=By,Bz0=Bz;
2030 
2031  // Calculate the derivative and propagate the state to the next point
2032  CalcDeriv(oldz,S,dEdx,D1);
2033  DMatrix5x1 S1=S+delta_z_over_2*D1;
2034 
2035  // Calculate the field at the first intermediate point
2036  double dx=S1(state_x)-S(state_x);
2037  double dy=S1(state_y)-S(state_y);
2038  Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z_over_2;
2039  By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z_over_2;
2040  Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z_over_2;
2041 
2042  // Calculate the derivative and propagate the state to the next point
2043  CalcDeriv(midz,S1,dEdx,D2);
2044  S1=S+delta_z_over_2*D2;
2045 
2046  // Calculate the field at the second intermediate point
2047  dx=S1(state_x)-S(state_x);
2048  dy=S1(state_y)-S(state_y);
2049  Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z_over_2;
2050  By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z_over_2;
2051  Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z_over_2;
2052 
2053  // Calculate the derivative and propagate the state to the next point
2054  CalcDeriv(midz,S1,dEdx,D3);
2055  S1=S+delta_z*D3;
2056 
2057  // Calculate the field at the final point
2058  dx=S1(state_x)-S(state_x);
2059  dy=S1(state_y)-S(state_y);
2060  Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z;
2061  By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z;
2062  Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z;
2063 
2064  // Final derivative
2065  CalcDeriv(newz,S1,dEdx,D4);
2066 
2067  // S+=delta_z*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4);
2068  double dz_over_6=delta_z*ONE_SIXTH;
2069  double dz_over_3=delta_z*ONE_THIRD;
2070  S+=dz_over_6*D1;
2071  S+=dz_over_3*D2;
2072  S+=dz_over_3*D3;
2073  S+=dz_over_6*D4;
2074 
2075  // Don't let the magnitude of the momentum drop below some cutoff
2076  //if (fabs(S(state_q_over_p))>Q_OVER_P_MAX)
2077  // S(state_q_over_p)=Q_OVER_P_MAX*(S(state_q_over_p)>0.0?1.:-1.);
2078  // Try to keep the direction tangents from heading towards 90 degrees
2079  //if (fabs(S(state_tx))>TAN_MAX)
2080  // S(state_tx)=TAN_MAX*(S(state_tx)>0.0?1.:-1.);
2081  //if (fabs(S(state_ty))>TAN_MAX)
2082  // S(state_ty)=TAN_MAX*(S(state_ty)>0.0?1.:-1.);
2083 
2084  return ds;
2085 }
2086 // Step the state vector through the field from oldz to newz.
2087 // Uses the 4th-order Runga-Kutte algorithm.
2088 // Uses the gradient to compute the field at the intermediate and last
2089 // points.
2090 double DTrackFitterKalmanSIMD::FasterStep(double oldz,double newz, double dEdx,
2091  DMatrix5x1 &S){
2092  double delta_z=newz-oldz;
2093  if (fabs(delta_z)<EPS) return 0.; // skip if the step is too small
2094 
2095  // Direction tangents
2096  double tx=S(state_tx);
2097  double ty=S(state_ty);
2098  double ds=sqrt(1.+tx*tx+ty*ty)*delta_z;
2099 
2100  double delta_z_over_2=0.5*delta_z;
2101  double midz=oldz+delta_z_over_2;
2102  DMatrix5x1 D1,D2,D3,D4;
2103  double Bx0=Bx,By0=By,Bz0=Bz;
2104 
2105  // The magnetic field at the beginning of the step is assumed to be
2106  // obtained at the end of the previous step through StepJacobian
2107 
2108  // Calculate the derivative and propagate the state to the next point
2109  CalcDeriv(oldz,S,dEdx,D1);
2110  DMatrix5x1 S1=S+delta_z_over_2*D1;
2111 
2112  // Calculate the field at the first intermediate point
2113  double dx=S1(state_x)-S(state_x);
2114  double dy=S1(state_y)-S(state_y);
2115  Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z_over_2;
2116  By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z_over_2;
2117  Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z_over_2;
2118 
2119  // Calculate the derivative and propagate the state to the next point
2120  CalcDeriv(midz,S1,dEdx,D2);
2121  S1=S+delta_z_over_2*D2;
2122 
2123  // Calculate the field at the second intermediate point
2124  dx=S1(state_x)-S(state_x);
2125  dy=S1(state_y)-S(state_y);
2126  Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z_over_2;
2127  By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z_over_2;
2128  Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z_over_2;
2129 
2130  // Calculate the derivative and propagate the state to the next point
2131  CalcDeriv(midz,S1,dEdx,D3);
2132  S1=S+delta_z*D3;
2133 
2134  // Calculate the field at the final point
2135  dx=S1(state_x)-S(state_x);
2136  dy=S1(state_y)-S(state_y);
2137  Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z;
2138  By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z;
2139  Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z;
2140 
2141  // Final derivative
2142  CalcDeriv(newz,S1,dEdx,D4);
2143 
2144  // S+=delta_z*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4);
2145  double dz_over_6=delta_z*ONE_SIXTH;
2146  double dz_over_3=delta_z*ONE_THIRD;
2147  S+=dz_over_6*D1;
2148  S+=dz_over_3*D2;
2149  S+=dz_over_3*D3;
2150  S+=dz_over_6*D4;
2151 
2152  // Don't let the magnitude of the momentum drop below some cutoff
2153  //if (fabs(S(state_q_over_p))>Q_OVER_P_MAX)
2154  // S(state_q_over_p)=Q_OVER_P_MAX*(S(state_q_over_p)>0.0?1.:-1.);
2155  // Try to keep the direction tangents from heading towards 90 degrees
2156  //if (fabs(S(state_tx))>TAN_MAX)
2157  // S(state_tx)=TAN_MAX*(S(state_tx)>0.0?1.:-1.);
2158  //if (fabs(S(state_ty))>TAN_MAX)
2159  // S(state_ty)=TAN_MAX*(S(state_ty)>0.0?1.:-1.);
2160 
2161  return ds;
2162 }
2163 
2164 
2165 
2166 // Compute the Jacobian matrix for the forward parametrization.
2167 jerror_t DTrackFitterKalmanSIMD::StepJacobian(double oldz,double newz,
2168  const DMatrix5x1 &S,
2169  double dEdx,DMatrix5x5 &J){
2170  // Initialize the Jacobian matrix
2171  //J.Zero();
2172  //for (int i=0;i<5;i++) J(i,i)=1.;
2173  J=I5x5;
2174 
2175  // Step in z
2176  double delta_z=newz-oldz;
2177  if (fabs(delta_z)<EPS) return NOERROR; //skip if the step is too small
2178 
2179  // Current values of state vector variables
2180  double x=S(state_x), y=S(state_y),tx=S(state_tx),ty=S(state_ty);
2181  double q_over_p=S(state_q_over_p);
2182 
2183  //B-field and field gradient at (x,y,z)
2184  //if (get_field)
2186  dBxdz,dBydx,dBydy,
2188 
2189  // Don't let the magnitude of the momentum drop below some cutoff
2190  if (fabs(q_over_p)>Q_OVER_P_MAX){
2191  q_over_p=Q_OVER_P_MAX*(q_over_p>0.0?1.:-1.);
2192  dEdx=0.;
2193  }
2194  // Try to keep the direction tangents from heading towards 90 degrees
2195  if (fabs(tx)>TAN_MAX) tx=TAN_MAX*(tx>0.0?1.:-1.);
2196  if (fabs(ty)>TAN_MAX) ty=TAN_MAX*(ty>0.0?1.:-1.);
2197  // useful combinations of terms
2198  double kq_over_p=qBr2p*q_over_p;
2199  double tx2=tx*tx;
2200  double twotx2=2.*tx2;
2201  double ty2=ty*ty;
2202  double twoty2=2.*ty2;
2203  double txty=tx*ty;
2204  double one_plus_tx2=1.+tx2;
2205  double one_plus_ty2=1.+ty2;
2206  double one_plus_twotx2_plus_ty2=one_plus_ty2+twotx2;
2207  double one_plus_twoty2_plus_tx2=one_plus_tx2+twoty2;
2208  double dsdz=sqrt(1.+tx2+ty2);
2209  double ds=dsdz*delta_z;
2210  double kds=qBr2p*ds;
2211  double kqdz_over_p_over_dsdz=kq_over_p*delta_z/dsdz;
2212  double kq_over_p_ds=kq_over_p*ds;
2213  double dtx_Bdep=ty*Bz+txty*Bx-one_plus_tx2*By;
2214  double dty_Bdep=Bx*one_plus_ty2-txty*By-tx*Bz;
2215  double Bxty=Bx*ty;
2216  double Bytx=By*tx;
2217  double Bztxty=Bz*txty;
2218  double Byty=By*ty;
2219  double Bxtx=Bx*tx;
2220 
2221  // Jacobian
2222  J(state_x,state_tx)=J(state_y,state_ty)=delta_z;
2223  J(state_tx,state_q_over_p)=kds*dtx_Bdep;
2224  J(state_ty,state_q_over_p)=kds*dty_Bdep;
2225  J(state_tx,state_tx)+=kqdz_over_p_over_dsdz*(Bxty*(one_plus_twotx2_plus_ty2)
2226  -Bytx*(3.*one_plus_tx2+twoty2)
2227  +Bztxty);
2228  J(state_tx,state_x)=kq_over_p_ds*(ty*dBzdx+txty*dBxdx-one_plus_tx2*dBydx);
2229  J(state_ty,state_ty)+=kqdz_over_p_over_dsdz*(Bxty*(3.*one_plus_ty2+twotx2)
2230  -Bytx*(one_plus_twoty2_plus_tx2)
2231  -Bztxty);
2232  J(state_ty,state_y)= kq_over_p_ds*(one_plus_ty2*dBxdy-txty*dBydy-tx*dBzdy);
2233  J(state_tx,state_ty)=kqdz_over_p_over_dsdz
2234  *((Bxtx+Bz)*(one_plus_twoty2_plus_tx2)-Byty*one_plus_tx2);
2235  J(state_tx,state_y)= kq_over_p_ds*(tx*dBzdy+txty*dBxdy-one_plus_tx2*dBydy);
2236  J(state_ty,state_tx)=-kqdz_over_p_over_dsdz*((Byty+Bz)*(one_plus_twotx2_plus_ty2)
2237  -Bxtx*one_plus_ty2);
2238  J(state_ty,state_x)=kq_over_p_ds*(one_plus_ty2*dBxdx-txty*dBydx-tx*dBzdx);
2239  if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS){
2240  double one_over_p_sq=q_over_p*q_over_p;
2241  double E=sqrt(1./one_over_p_sq+mass2);
2242  J(state_q_over_p,state_q_over_p)-=dEdx*ds/E*(2.+3.*mass2*one_over_p_sq);
2243  double temp=-(q_over_p*one_over_p_sq/dsdz)*E*dEdx*delta_z;
2246  }
2247 
2248  return NOERROR;
2249 }
2250 
2251 // Calculate the derivative for the alternate set of parameters {q/pT, phi,
2252 // tan(lambda),D,z}
2254  double dEdx,DMatrix5x1 &D1){
2255  //Direction at current point
2256  double tanl=S(state_tanl);
2257  // Don't let tanl exceed some maximum
2258  if (fabs(tanl)>TAN_MAX) tanl=TAN_MAX*(tanl>0.0?1.:-1.);
2259 
2260  double phi=S(state_phi);
2261  double cosphi=cos(phi);
2262  double sinphi=sin(phi);
2263  double lambda=atan(tanl);
2264  double sinl=sin(lambda);
2265  double cosl=cos(lambda);
2266  // Other parameters
2267  double q_over_pt=S(state_q_over_pt);
2268  double pt=fabs(1./q_over_pt);
2269 
2270  // Turn off dEdx if the pt drops below some minimum
2271  if (pt<PT_MIN) {
2272  dEdx=0.;
2273  }
2274  double kq_over_pt=qBr2p*q_over_pt;
2275 
2276  // Derivative of S with respect to s
2277  double By_cosphi_minus_Bx_sinphi=By*cosphi-Bx*sinphi;
2278  D1(state_q_over_pt)
2279  =kq_over_pt*q_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2280  double one_over_cosl=1./cosl;
2281  if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS){
2282  double p=pt*one_over_cosl;
2283  double p_sq=p*p;
2284  double E=sqrt(p_sq+mass2);
2285  D1(state_q_over_pt)-=q_over_pt*E*dEdx/p_sq;
2286  }
2287  // D1(state_phi)
2288  // =kq_over_pt*(Bx*cosphi*sinl+By*sinphi*sinl-Bz*cosl);
2289  D1(state_phi)=kq_over_pt*((Bx*cosphi+By*sinphi)*sinl-Bz*cosl);
2290  D1(state_tanl)=kq_over_pt*By_cosphi_minus_Bx_sinphi*one_over_cosl;
2291  D1(state_z)=sinl;
2292 
2293  // New direction
2294  dpos.Set(cosl*cosphi,cosl*sinphi);
2295 
2296  return NOERROR;
2297 }
2298 
2299 // Calculate the derivative and Jacobian matrices for the alternate set of
2300 // parameters {q/pT, phi, tan(lambda),D,z}
2302  DVector2 &dxy,
2303  const DMatrix5x1 &S,
2304  double dEdx,
2305  DMatrix5x5 &J1,
2306  DMatrix5x1 &D1){
2307  //Direction at current point
2308  double tanl=S(state_tanl);
2309  // Don't let tanl exceed some maximum
2310  if (fabs(tanl)>TAN_MAX) tanl=TAN_MAX*(tanl>0.0?1.:-1.);
2311 
2312  double phi=S(state_phi);
2313  double cosphi=cos(phi);
2314  double sinphi=sin(phi);
2315  double lambda=atan(tanl);
2316  double sinl=sin(lambda);
2317  double cosl=cos(lambda);
2318  double cosl2=cosl*cosl;
2319  double cosl3=cosl*cosl2;
2320  double one_over_cosl=1./cosl;
2321  // Other parameters
2322  double q_over_pt=S(state_q_over_pt);
2323  double pt=fabs(1./q_over_pt);
2324  double q=pt*q_over_pt;
2325 
2326  // Turn off dEdx if pt drops below some minimum
2327  if (pt<PT_MIN) {
2328  dEdx=0.;
2329  }
2330  double kq_over_pt=qBr2p*q_over_pt;
2331 
2332  // B-field and gradient at (x,y,z)
2333  bfield->GetFieldAndGradient(xy.X(),xy.Y(),S(state_z),Bx,By,Bz,
2336 
2337  // Derivative of S with respect to s
2338  double By_cosphi_minus_Bx_sinphi=By*cosphi-Bx*sinphi;
2339  double By_sinphi_plus_Bx_cosphi=By*sinphi+Bx*cosphi;
2340  D1(state_q_over_pt)=kq_over_pt*q_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2341  D1(state_phi)=kq_over_pt*(By_sinphi_plus_Bx_cosphi*sinl-Bz*cosl);
2342  D1(state_tanl)=kq_over_pt*By_cosphi_minus_Bx_sinphi*one_over_cosl;
2343  D1(state_z)=sinl;
2344 
2345  // New direction
2346  dxy.Set(cosl*cosphi,cosl*sinphi);
2347 
2348  // Jacobian matrix elements
2349  J1(state_phi,state_phi)=kq_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2351  =qBr2p*(By_sinphi_plus_Bx_cosphi*sinl-Bz*cosl);
2352  J1(state_phi,state_tanl)=kq_over_pt*(By_sinphi_plus_Bx_cosphi*cosl
2353  +Bz*sinl)*cosl2;
2354  J1(state_phi,state_z)
2355  =kq_over_pt*(dBxdz*cosphi*sinl+dBydz*sinphi*sinl-dBzdz*cosl);
2356 
2357  J1(state_tanl,state_phi)=-kq_over_pt*By_sinphi_plus_Bx_cosphi*one_over_cosl;
2358  J1(state_tanl,state_q_over_pt)=qBr2p*By_cosphi_minus_Bx_sinphi*one_over_cosl;
2359  J1(state_tanl,state_tanl)=kq_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2360  J1(state_tanl,state_z)=kq_over_pt*(dBydz*cosphi-dBxdz*sinphi)*one_over_cosl;
2362  =-kq_over_pt*q_over_pt*sinl*By_sinphi_plus_Bx_cosphi;
2364  =2.*kq_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2366  =kq_over_pt*q_over_pt*cosl3*By_cosphi_minus_Bx_sinphi;
2367  if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS){
2368  double p=pt*one_over_cosl;
2369  double p_sq=p*p;
2370  double m2_over_p2=mass2/p_sq;
2371  double E=sqrt(p_sq+mass2);
2372 
2373  D1(state_q_over_pt)-=q_over_pt*E/p_sq*dEdx;
2374  J1(state_q_over_pt,state_q_over_pt)-=dEdx*(2.+3.*m2_over_p2)/E;
2375  J1(state_q_over_pt,state_tanl)+=q*dEdx*sinl*(1.+2.*m2_over_p2)/(p*E);
2376  }
2378  =kq_over_pt*q_over_pt*sinl*(dBydz*cosphi-dBxdz*sinphi);
2379  J1(state_z,state_tanl)=cosl3;
2380 
2381  return NOERROR;
2382 }
2383 
2384 // Step the state and the covariance matrix through the field
2386  double ds,
2387  double dEdx,
2388  DMatrix5x1 &S,
2389  DMatrix5x5 &J,
2390  DMatrix5x5 &C){
2391  //Initialize the Jacobian matrix
2392  J=I5x5;
2393  if (fabs(ds)<EPS) return NOERROR; // break out if ds is too small
2394 
2395  // B-field and gradient at current (x,y,z)
2396  bfield->GetFieldAndGradient(xy.X(),xy.Y(),S(state_z),Bx,By,Bz,
2399  double Bx0=Bx,By0=By,Bz0=Bz;
2400 
2401  // Matrices for intermediate steps
2402  DMatrix5x1 D1,D2,D3,D4;
2403  DMatrix5x1 S1;
2404  DMatrix5x5 J1;
2405  DVector2 dxy1,dxy2,dxy3,dxy4;
2406  double ds_2=0.5*ds;
2407 
2408  // Find the derivative at the first point, propagate the state to the
2409  // first intermediate point and start filling the Jacobian matrix
2410  CalcDerivAndJacobian(xy,dxy1,S,dEdx,J1,D1);
2411  S1=S+ds_2*D1;
2412 
2413  // Calculate the field at the first intermediate point
2414  double dz=S1(state_z)-S(state_z);
2415  double dx=ds_2*dxy1.X();
2416  double dy=ds_2*dxy1.Y();
2417  Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2418  By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2419  Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2420 
2421  // Calculate the derivative and propagate the state to the next point
2422  CalcDeriv(dxy2,S1,dEdx,D2);
2423  S1=S+ds_2*D2;
2424 
2425  // Calculate the field at the second intermediate point
2426  dz=S1(state_z)-S(state_z);
2427  dx=ds_2*dxy2.X();
2428  dy=ds_2*dxy2.Y();
2429  Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2430  By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2431  Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2432 
2433  // Calculate the derivative and propagate the state to the next point
2434  CalcDeriv(dxy3,S1,dEdx,D3);
2435  S1=S+ds*D3;
2436 
2437  // Calculate the field at the final point
2438  dz=S1(state_z)-S(state_z);
2439  dx=ds*dxy3.X();
2440  dy=ds*dxy3.Y();
2441  Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2442  By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2443  Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2444 
2445  // Final derivative
2446  CalcDeriv(dxy4,S1,dEdx,D4);
2447 
2448  // Position vector increment
2449  //DVector3 dpos
2450  // =ds*(ONE_SIXTH*dpos1+ONE_THIRD*dpos2+ONE_THIRD*dpos3+ONE_SIXTH*dpos4);
2451  double ds_over_6=ds*ONE_SIXTH;
2452  double ds_over_3=ds*ONE_THIRD;
2453  DVector2 dxy=ds_over_6*dxy1;
2454  dxy+=ds_over_3*dxy2;
2455  dxy+=ds_over_3*dxy3;
2456  dxy+=ds_over_6*dxy4;
2457 
2458  // New Jacobian matrix
2459  J+=ds*J1;
2460 
2461  // Deal with changes in D
2462  double B=sqrt(Bx0*Bx0+By0*By0+Bz0*Bz0);
2463  //double qrc_old=qpt/(qBr2p*Bz_);
2464  double qpt=1./S(state_q_over_pt);
2465  double q=(qpt>0.)?1.:-1.;
2466  double qrc_old=qpt/(qBr2p*B);
2467  double sinphi=sin(S(state_phi));
2468  double cosphi=cos(S(state_phi));
2469  double qrc_plus_D=S(state_D)+qrc_old;
2470  dx=dxy.X();
2471  dy=dxy.Y();
2472  double dx_sinphi_minus_dy_cosphi=dx*sinphi-dy*cosphi;
2473  double rc=sqrt(dxy.Mod2()
2474  +2.*qrc_plus_D*(dx_sinphi_minus_dy_cosphi)
2475  +qrc_plus_D*qrc_plus_D);
2476  double q_over_rc=q/rc;
2477 
2478  J(state_D,state_D)=q_over_rc*(dx_sinphi_minus_dy_cosphi+qrc_plus_D);
2479  J(state_D,state_q_over_pt)=qpt*qrc_old*(J(state_D,state_D)-1.);
2480  J(state_D,state_phi)=q_over_rc*qrc_plus_D*(dx*cosphi+dy*sinphi);
2481 
2482  // New xy vector
2483  xy+=dxy;
2484 
2485  // New state vector
2486  //S+=ds*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4);
2487  S+=ds_over_6*D1;
2488  S+=ds_over_3*D2;
2489  S+=ds_over_3*D3;
2490  S+=ds_over_6*D4;
2491 
2492  // Don't let the pt drop below some minimum
2493  //if (fabs(1./S(state_q_over_pt))<PT_MIN) {
2494  // S(state_q_over_pt)=(1./PT_MIN)*(S(state_q_over_pt)>0.0?1.:-1.);
2495  // }
2496  // Don't let tanl exceed some maximum
2497  if (fabs(S(state_tanl))>TAN_MAX){
2498  S(state_tanl)=TAN_MAX*(S(state_tanl)>0.0?1.:-1.);
2499  }
2500 
2501  // New covariance matrix
2502  // C=J C J^T
2503  //C=C.SandwichMultiply(J);
2504  C=J*C*J.Transpose();
2505 
2506  return NOERROR;
2507 }
2508 
2509 // Runga-Kutte for alternate parameter set {q/pT,phi,tanl(lambda),D,z}
2510 // Uses the gradient to compute the field at the intermediate and last
2511 // points.
2513  DMatrix5x1 &S,
2514  double dEdx){
2515  if (fabs(ds)<EPS) return NOERROR; // break out if ds is too small
2516 
2517  // Matrices for intermediate steps
2518  DMatrix5x1 D1,D2,D3,D4;
2519  DMatrix5x1 S1;
2520  DVector2 dxy1,dxy2,dxy3,dxy4;
2521  double ds_2=0.5*ds;
2522  double Bx0=Bx,By0=By,Bz0=Bz;
2523 
2524  // The magnetic field at the beginning of the step is assumed to be
2525  // obtained at the end of the previous step through StepJacobian
2526 
2527  // Calculate the derivative and propagate the state to the next point
2528  CalcDeriv(dxy1,S,dEdx,D1);
2529  S1=S+ds_2*D1;
2530 
2531  // Calculate the field at the first intermediate point
2532  double dz=S1(state_z)-S(state_z);
2533  double dx=ds_2*dxy1.X();
2534  double dy=ds_2*dxy1.Y();
2535  Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2536  By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2537  Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2538 
2539  // Calculate the derivative and propagate the state to the next point
2540  CalcDeriv(dxy2,S1,dEdx,D2);
2541  S1=S+ds_2*D2;
2542 
2543  // Calculate the field at the second intermediate point
2544  dz=S1(state_z)-S(state_z);
2545  dx=ds_2*dxy2.X();
2546  dy=ds_2*dxy2.Y();
2547  Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2548  By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2549  Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2550 
2551  // Calculate the derivative and propagate the state to the next point
2552  CalcDeriv(dxy3,S1,dEdx,D3);
2553  S1=S+ds*D3;
2554 
2555  // Calculate the field at the final point
2556  dz=S1(state_z)-S(state_z);
2557  dx=ds*dxy3.X();
2558  dy=ds*dxy3.Y();
2559  Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2560  By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2561  Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2562 
2563  // Final derivative
2564  CalcDeriv(dxy4,S1,dEdx,D4);
2565 
2566  // New state vector
2567  // S+=ds*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4);
2568  double ds_over_6=ds*ONE_SIXTH;
2569  double ds_over_3=ds*ONE_THIRD;
2570  S+=ds_over_6*D1;
2571  S+=ds_over_3*D2;
2572  S+=ds_over_3*D3;
2573  S+=ds_over_6*D4;
2574 
2575  // New position
2576  //pos+=ds*(ONE_SIXTH*dpos1+ONE_THIRD*dpos2+ONE_THIRD*dpos3+ONE_SIXTH*dpos4);
2577  xy+=ds_over_6*dxy1;
2578  xy+=ds_over_3*dxy2;
2579  xy+=ds_over_3*dxy3;
2580  xy+=ds_over_6*dxy4;
2581 
2582  // Don't let the pt drop below some minimum
2583  //if (fabs(1./S(state_q_over_pt))<PT_MIN) {
2584  // S(state_q_over_pt)=(1./PT_MIN)*(S(state_q_over_pt)>0.0?1.:-1.);
2585  //}
2586  // Don't let tanl exceed some maximum
2587  if (fabs(S(state_tanl))>TAN_MAX){
2588  S(state_tanl)=TAN_MAX*(S(state_tanl)>0.0?1.:-1.);
2589  }
2590 
2591  return NOERROR;
2592 }
2593 
2594 // Runga-Kutte for alternate parameter set {q/pT,phi,tanl(lambda),D,z}
2596  DMatrix5x1 &S,
2597  double dEdx){
2598  if (fabs(ds)<EPS) return NOERROR; // break out if ds is too small
2599 
2600  // B-field and gradient at current (x,y,z)
2601  bfield->GetFieldAndGradient(xy.X(),xy.Y(),S(state_z),Bx,By,Bz,
2604  double Bx0=Bx,By0=By,Bz0=Bz;
2605 
2606  // Matrices for intermediate steps
2607  DMatrix5x1 D1,D2,D3,D4;
2608  DMatrix5x1 S1;
2609  DVector2 dxy1,dxy2,dxy3,dxy4;
2610  double ds_2=0.5*ds;
2611 
2612  // Find the derivative at the first point, propagate the state to the
2613  // first intermediate point
2614  CalcDeriv(dxy1,S,dEdx,D1);
2615  S1=S+ds_2*D1;
2616 
2617  // Calculate the field at the first intermediate point
2618  double dz=S1(state_z)-S(state_z);
2619  double dx=ds_2*dxy1.X();
2620  double dy=ds_2*dxy1.Y();
2621  Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2622  By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2623  Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2624 
2625  // Calculate the derivative and propagate the state to the next point
2626  CalcDeriv(dxy2,S1,dEdx,D2);
2627  S1=S+ds_2*D2;
2628 
2629  // Calculate the field at the second intermediate point
2630  dz=S1(state_z)-S(state_z);
2631  dx=ds_2*dxy2.X();
2632  dy=ds_2*dxy2.Y();
2633  Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2634  By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2635  Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2636 
2637  // Calculate the derivative and propagate the state to the next point
2638  CalcDeriv(dxy3,S1,dEdx,D3);
2639  S1=S+ds*D3;
2640 
2641  // Calculate the field at the final point
2642  dz=S1(state_z)-S(state_z);
2643  dx=ds*dxy3.X();
2644  dy=ds*dxy3.Y();
2645  Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2646  By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2647  Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2648 
2649  // Final derivative
2650  CalcDeriv(dxy4,S1,dEdx,D4);
2651 
2652  // New state vector
2653  // S+=ds*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4);
2654  double ds_over_6=ds*ONE_SIXTH;
2655  double ds_over_3=ds*ONE_THIRD;
2656  S+=ds_over_6*D1;
2657  S+=ds_over_3*D2;
2658  S+=ds_over_3*D3;
2659  S+=ds_over_6*D4;
2660 
2661  // New position
2662  //pos+=ds*(ONE_SIXTH*dpos1+ONE_THIRD*dpos2+ONE_THIRD*dpos3+ONE_SIXTH*dpos4);
2663  xy+=ds_over_6*dxy1;
2664  xy+=ds_over_3*dxy2;
2665  xy+=ds_over_3*dxy3;
2666  xy+=ds_over_6*dxy4;
2667 
2668  // Don't let the pt drop below some minimum
2669  //if (fabs(1./S(state_q_over_pt))<PT_MIN) {
2670  // S(state_q_over_pt)=(1./PT_MIN)*(S(state_q_over_pt)>0.0?1.:-1.);
2671  //}
2672  // Don't let tanl exceed some maximum
2673  if (fabs(S(state_tanl))>TAN_MAX){
2674  S(state_tanl)=TAN_MAX*(S(state_tanl)>0.0?1.:-1.);
2675  }
2676 
2677  return NOERROR;
2678 }
2679 
2680 // Assuming that the magnetic field is constant over the step, use a helical
2681 // model to step directly to the next point along the trajectory.
2682 void DTrackFitterKalmanSIMD::FastStep(double &z,double ds, double dEdx,
2683  DMatrix5x1 &S){
2684 
2685  // Compute convenience terms involving Bx, By, Bz
2686  double one_over_p=fabs(S(state_q_over_p));
2687  double p=1./one_over_p;
2688  double tx=S(state_tx),ty=S(state_ty);
2689  double denom=sqrt(1.+tx*tx+ty*ty);
2690  double px=p*tx/denom;
2691  double py=p*ty/denom;
2692  double pz=p/denom;
2693  double q=S(state_q_over_p)>0?1.:-1.;
2694  double k_q=qBr2p*q;
2695  double ds_over_p=ds*one_over_p;
2696  double factor=k_q*(0.25*ds_over_p);
2697  double Ax=factor*Bx,Ay=factor*By,Az=factor*Bz;
2698  double Ax2=Ax*Ax,Ay2=Ay*Ay,Az2=Az*Az;
2699  double AxAy=Ax*Ay,AxAz=Ax*Az,AyAz=Ay*Az;
2700  double one_plus_Ax2=1.+Ax2;
2701  double scale=ds_over_p/(one_plus_Ax2+Ay2+Az2);
2702 
2703  // Compute new position
2704  double dx=scale*(px*one_plus_Ax2+py*(AxAy+Az)+pz*(AxAz-Ay));
2705  double dy=scale*(px*(AxAy-Az)+py*(1.+Ay2)+pz*(AyAz+Ax));
2706  double dz=scale*(px*(AxAz+Ay)+py*(AyAz-Ax)+pz*(1.+Az2));
2707  S(state_x)+=dx;
2708  S(state_y)+=dy;
2709  z+=dz;
2710 
2711  // Compute new momentum
2712  px+=k_q*(Bz*dy-By*dz);
2713  py+=k_q*(Bx*dz-Bz*dx);
2714  pz+=k_q*(By*dx-Bx*dy);
2715  S(state_tx)=px/pz;
2716  S(state_ty)=py/pz;
2717  if (fabs(dEdx)>EPS){
2718  double one_over_p_sq=one_over_p*one_over_p;
2719  double E=sqrt(1./one_over_p_sq+mass2);
2720  S(state_q_over_p)-=S(state_q_over_p)*one_over_p_sq*E*dEdx*ds;
2721  }
2722 }
2723 // Assuming that the magnetic field is constant over the step, use a helical
2724 // model to step directly to the next point along the trajectory.
2725 void DTrackFitterKalmanSIMD::FastStep(DVector2 &xy,double ds, double dEdx,
2726  DMatrix5x1 &S){
2727 
2728  // Compute convenience terms involving Bx, By, Bz
2729  double pt=fabs(1./S(state_q_over_pt));
2730  double one_over_p=cos(atan(S(state_tanl)))/pt;
2731  double px=pt*cos(S(state_phi));
2732  double py=pt*sin(S(state_phi));
2733  double pz=pt*S(state_tanl);
2734  double q=S(state_q_over_pt)>0?1.:-1.;
2735  double k_q=qBr2p*q;
2736  double ds_over_p=ds*one_over_p;
2737  double factor=k_q*(0.25*ds_over_p);
2738  double Ax=factor*Bx,Ay=factor*By,Az=factor*Bz;
2739  double Ax2=Ax*Ax,Ay2=Ay*Ay,Az2=Az*Az;
2740  double AxAy=Ax*Ay,AxAz=Ax*Az,AyAz=Ay*Az;
2741  double one_plus_Ax2=1.+Ax2;
2742  double scale=ds_over_p/(one_plus_Ax2+Ay2+Az2);
2743 
2744  // Compute new position
2745  double dx=scale*(px*one_plus_Ax2+py*(AxAy+Az)+pz*(AxAz-Ay));
2746  double dy=scale*(px*(AxAy-Az)+py*(1.+Ay2)+pz*(AyAz+Ax));
2747  double dz=scale*(px*(AxAz+Ay)+py*(AyAz-Ax)+pz*(1.+Az2));
2748  xy.Set(xy.X()+dx,xy.Y()+dy);
2749  S(state_z)+=dz;
2750 
2751  // Compute new momentum
2752  px+=k_q*(Bz*dy-By*dz);
2753  py+=k_q*(Bx*dz-Bz*dx);
2754  pz+=k_q*(By*dx-Bx*dy);
2755  pt=sqrt(px*px+py*py);
2756  S(state_q_over_pt)=q/pt;
2757  S(state_phi)=atan2(py,px);
2758  S(state_tanl)=pz/pt;
2759  if (fabs(dEdx)>EPS){
2760  double one_over_p_sq=one_over_p*one_over_p;
2761  double E=sqrt(1./one_over_p_sq+mass2);
2762  S(state_q_over_p)-=S(state_q_over_pt)*one_over_p_sq*E*dEdx*ds;
2763  }
2764 }
2765 
2766 // Calculate the jacobian matrix for the alternate parameter set
2767 // {q/pT,phi,tanl(lambda),D,z}
2769  const DVector2 &dxy,
2770  double ds,const DMatrix5x1 &S,
2771  double dEdx,DMatrix5x5 &J){
2772  // Initialize the Jacobian matrix
2773  //J.Zero();
2774  //for (int i=0;i<5;i++) J(i,i)=1.;
2775  J=I5x5;
2776 
2777  if (fabs(ds)<EPS) return NOERROR; // break out if ds is too small
2778  // B-field and gradient at current (x,y,z)
2779  //bfield->GetFieldAndGradient(xy.X(),xy.Y(),S(state_z),Bx,By,Bz,
2780  //dBxdx,dBxdy,dBxdz,dBydx,
2781  //dBydy,dBydz,dBzdx,dBzdy,dBzdz);
2782 
2783  // Charge
2784  double q=(S(state_q_over_pt)>0.0)?1.:-1.;
2785 
2786  //kinematic quantities
2787  double q_over_pt=S(state_q_over_pt);
2788  double sinphi=sin(S(state_phi));
2789  double cosphi=cos(S(state_phi));
2790  double D=S(state_D);
2791  double lambda=atan(S(state_tanl));
2792  double sinl=sin(lambda);
2793  double cosl=cos(lambda);
2794  double cosl2=cosl*cosl;
2795  double cosl3=cosl*cosl2;
2796  double one_over_cosl=1./cosl;
2797  double pt=fabs(1./q_over_pt);
2798 
2799  // Turn off dEdx if pt drops below some minimum
2800  if (pt<PT_MIN) {
2801  dEdx=0.;
2802  }
2803  double kds=qBr2p*ds;
2804  double kq_ds_over_pt=kds*q_over_pt;
2805  double By_cosphi_minus_Bx_sinphi=By*cosphi-Bx*sinphi;
2806  double By_sinphi_plus_Bx_cosphi=By*sinphi+Bx*cosphi;
2807 
2808  // Jacobian matrix elements
2809  J(state_phi,state_phi)+=kq_ds_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2810  J(state_phi,state_q_over_pt)=kds*(By_sinphi_plus_Bx_cosphi*sinl-Bz*cosl);
2811  J(state_phi,state_tanl)=kq_ds_over_pt*(By_sinphi_plus_Bx_cosphi*cosl
2812  +Bz*sinl)*cosl2;
2813  J(state_phi,state_z)
2814  =kq_ds_over_pt*(dBxdz*cosphi*sinl+dBydz*sinphi*sinl-dBzdz*cosl);
2815 
2816  J(state_tanl,state_phi)=-kq_ds_over_pt*By_sinphi_plus_Bx_cosphi*one_over_cosl;
2817  J(state_tanl,state_q_over_pt)=kds*By_cosphi_minus_Bx_sinphi*one_over_cosl;
2818  J(state_tanl,state_tanl)+=kq_ds_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2819  J(state_tanl,state_z)=kq_ds_over_pt*(dBydz*cosphi-dBxdz*sinphi)*one_over_cosl;
2821  =-kq_ds_over_pt*q_over_pt*sinl*By_sinphi_plus_Bx_cosphi;
2823  +=2.*kq_ds_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2825  =kq_ds_over_pt*q_over_pt*cosl3*By_cosphi_minus_Bx_sinphi;
2826  if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS){
2827  double p=pt*one_over_cosl;
2828  double p_sq=p*p;
2829  double m2_over_p2=mass2/p_sq;
2830  double E=sqrt(p_sq+mass2);
2831  double dE_over_E=dEdx*ds/E;
2832 
2833  J(state_q_over_pt,state_q_over_pt)-=dE_over_E*(2.+3.*m2_over_p2);
2834  J(state_q_over_pt,state_tanl)+=q*dE_over_E*sinl*(1.+2.*m2_over_p2)/p;
2835  }
2837  =kq_ds_over_pt*q_over_pt*sinl*(dBydz*cosphi-dBxdz*sinphi);
2838  J(state_z,state_tanl)=cosl3*ds;
2839 
2840  // Deal with changes in D
2841  double B=sqrt(Bx*Bx+By*By+Bz*Bz);
2842  //double qrc_old=qpt/(qBr2p*fabs(Bz));
2843  double qpt=FactorForSenseOfRotation/q_over_pt;
2844  double qrc_old=qpt/(qBr2p*B);
2845  double qrc_plus_D=D+qrc_old;
2846  double dx=dxy.X();
2847  double dy=dxy.Y();
2848  double dx_sinphi_minus_dy_cosphi=dx*sinphi-dy*cosphi;
2849  double rc=sqrt(dxy.Mod2()
2850  +2.*qrc_plus_D*(dx_sinphi_minus_dy_cosphi)
2851  +qrc_plus_D*qrc_plus_D);
2852  double q_over_rc=FactorForSenseOfRotation*q/rc;
2853 
2854  J(state_D,state_D)=q_over_rc*(dx_sinphi_minus_dy_cosphi+qrc_plus_D);
2855  J(state_D,state_q_over_pt)=qpt*qrc_old*(J(state_D,state_D)-1.);
2856  J(state_D,state_phi)=q_over_rc*qrc_plus_D*(dx*cosphi+dy*sinphi);
2857 
2858  return NOERROR;
2859 }
2860 
2861 
2862 
2863 
2864 // Runga-Kutte for alternate parameter set {q/pT,phi,tanl(lambda),D,z}
2866  double ds,const DMatrix5x1 &S,
2867  double dEdx,DMatrix5x5 &J){
2868  // Initialize the Jacobian matrix
2869  //J.Zero();
2870  //for (int i=0;i<5;i++) J(i,i)=1.;
2871  J=I5x5;
2872 
2873  if (fabs(ds)<EPS) return NOERROR; // break out if ds is too small
2874 
2875  // Matrices for intermediate steps
2876  DMatrix5x5 J1;
2877  DMatrix5x1 D1;
2878  DVector2 dxy1;
2879 
2880  // charge
2881  double q=(S(state_q_over_pt)>0.0)?1.:-1.;
2883 
2884  //kinematic quantities
2885  double qpt=1./S(state_q_over_pt) * FactorForSenseOfRotation;
2886  double sinphi=sin(S(state_phi));
2887  double cosphi=cos(S(state_phi));
2888  double D=S(state_D);
2889 
2890  CalcDerivAndJacobian(xy,dxy1,S,dEdx,J1,D1);
2891  // double Bz_=fabs(Bz); // needed for computing D
2892 
2893  // New Jacobian matrix
2894  J+=ds*J1;
2895 
2896  // change in position
2897  DVector2 dxy =ds*dxy1;
2898 
2899  // Deal with changes in D
2900  double B=sqrt(Bx*Bx+By*By+Bz*Bz);
2901  //double qrc_old=qpt/(qBr2p*Bz_);
2902  double qrc_old=qpt/(qBr2p*B);
2903  double qrc_plus_D=D+qrc_old;
2904  double dx=dxy.X();
2905  double dy=dxy.Y();
2906  double dx_sinphi_minus_dy_cosphi=dx*sinphi-dy*cosphi;
2907  double rc=sqrt(dxy.Mod2()
2908  +2.*qrc_plus_D*(dx_sinphi_minus_dy_cosphi)
2909  +qrc_plus_D*qrc_plus_D);
2910  double q_over_rc=q/rc;
2911 
2912  J(state_D,state_D)=q_over_rc*(dx_sinphi_minus_dy_cosphi+qrc_plus_D);
2913  J(state_D,state_q_over_pt)=qpt*qrc_old*(J(state_D,state_D)-1.);
2914  J(state_D,state_phi)=q_over_rc*qrc_plus_D*(dx*cosphi+dy*sinphi);
2915 
2916  return NOERROR;
2917 }
2918 
2919 // Compute contributions to the covariance matrix due to multiple scattering
2920 // using the Lynch/Dahl empirical formulas
2922  double chi2c_factor,
2923  double chi2a_factor,
2924  double chi2a_corr,
2925  const DMatrix5x1 &Sc,
2926  DMatrix5x5 &Q){
2927  Q.Zero();
2928  //return NOERROR;
2929  if (USE_MULS_COVARIANCE && chi2c_factor>0. && fabs(ds)>EPS){
2930  double tanl=Sc(state_tanl);
2931  double tanl2=tanl*tanl;
2932  double one_plus_tanl2=1.+tanl2;
2933  double one_over_pt=fabs(Sc(state_q_over_pt));
2934  double my_ds=fabs(ds);
2935  double my_ds_2=0.5*my_ds;
2936 
2937  Q(state_phi,state_phi)=one_plus_tanl2;
2938  Q(state_tanl,state_tanl)=one_plus_tanl2*one_plus_tanl2;
2939  Q(state_q_over_pt,state_q_over_pt)=one_over_pt*one_over_pt*tanl2;
2941  =Sc(state_q_over_pt)*tanl*one_plus_tanl2;
2942  Q(state_D,state_D)=ONE_THIRD*ds*ds;
2943 
2944  // I am not sure the following is correct...
2945  double sign_D=(Sc(state_D)>0.0)?1.:-1.;
2946  Q(state_D,state_phi)=Q(state_phi,state_D)=sign_D*my_ds_2*sqrt(one_plus_tanl2);
2947  Q(state_D,state_tanl)=Q(state_tanl,state_D)=sign_D*my_ds_2*one_plus_tanl2;
2948  Q(state_D,state_q_over_pt)=Q(state_q_over_pt,state_D)=sign_D*my_ds_2*tanl*Sc(state_q_over_pt);
2949 
2950  double one_over_p_sq=one_over_pt*one_over_pt/one_plus_tanl2;
2951  double one_over_beta2=1.+mass2*one_over_p_sq;
2952  double chi2c_p_sq=chi2c_factor*my_ds*one_over_beta2;
2953  double chi2a_p_sq=chi2a_factor*(1.+chi2a_corr*one_over_beta2);
2954  // F=Fraction of Moliere distribution to be taken into account
2955  // nu=0.5*chi2c/(chi2a*(1.-F));
2956  double nu=MOLIERE_RATIO1*chi2c_p_sq/chi2a_p_sq;
2957  double one_plus_nu=1.+nu;
2958  // sig2_ms=chi2c*1e-6/(1.+F*F)*((one_plus_nu)/nu*log(one_plus_nu)-1.);
2959  double sig2_ms=chi2c_p_sq*one_over_p_sq*MOLIERE_RATIO2
2960  *(one_plus_nu/nu*log(one_plus_nu)-1.);
2961 
2962  Q*=sig2_ms;
2963  }
2964 
2965  return NOERROR;
2966 }
2967 
2968 // Compute contributions to the covariance matrix due to multiple scattering
2969 // using the Lynch/Dahl empirical formulas
2970 jerror_t DTrackFitterKalmanSIMD::GetProcessNoise(double z, double ds,
2971  double chi2c_factor,
2972  double chi2a_factor,
2973  double chi2a_corr,
2974  const DMatrix5x1 &S,
2975  DMatrix5x5 &Q){
2976 
2977  Q.Zero();
2978  //return NOERROR;
2979  if (USE_MULS_COVARIANCE && chi2c_factor>0. && fabs(ds)>EPS){
2980  double tx=S(state_tx),ty=S(state_ty);
2981  double one_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
2982  double my_ds=fabs(ds);
2983  double my_ds_2=0.5*my_ds;
2984  double tx2=tx*tx;
2985  double ty2=ty*ty;
2986  double one_plus_tx2=1.+tx2;
2987  double one_plus_ty2=1.+ty2;
2988  double tsquare=tx2+ty2;
2989  double one_plus_tsquare=1.+tsquare;
2990 
2991  Q(state_tx,state_tx)=one_plus_tx2*one_plus_tsquare;
2992  Q(state_ty,state_ty)=one_plus_ty2*one_plus_tsquare;
2993  Q(state_tx,state_ty)=Q(state_ty,state_tx)=tx*ty*one_plus_tsquare;
2994 
2995  Q(state_x,state_x)=ONE_THIRD*ds*ds;
2998  = my_ds_2*sqrt(one_plus_tsquare*one_plus_ty2);
3000  = my_ds_2*sqrt(one_plus_tsquare*one_plus_tx2);
3001 
3002  double one_over_beta2=1.+one_over_p_sq*mass2;
3003  double chi2c_p_sq=chi2c_factor*my_ds*one_over_beta2;
3004  double chi2a_p_sq=chi2a_factor*(1.+chi2a_corr*one_over_beta2);
3005  // F=MOLIERE_FRACTION =Fraction of Moliere distribution to be taken into account
3006  // nu=0.5*chi2c/(chi2a*(1.-F));
3007  double nu=MOLIERE_RATIO1*chi2c_p_sq/chi2a_p_sq;
3008  double one_plus_nu=1.+nu;
3009  double sig2_ms=chi2c_p_sq*one_over_p_sq*MOLIERE_RATIO2
3010  *(one_plus_nu/nu*log(one_plus_nu)-1.);
3011 
3012  // printf("fac %f %f %f\n",chi2c_factor,chi2a_factor,chi2a_corr);
3013  //printf("omega %f\n",chi2c/chi2a);
3014 
3015 
3016  Q*=sig2_ms;
3017  }
3018 
3019  return NOERROR;
3020 }
3021 
3022 // Calculate the energy loss per unit length given properties of the material
3023 // through which a particle of momentum p is passing
3024 double DTrackFitterKalmanSIMD::GetdEdx(double q_over_p,double K_rho_Z_over_A,
3025  double rho_Z_over_A,double LnI,double Z){
3026  if (rho_Z_over_A<=0.) return 0.;
3027  //return 0.;
3028 
3029  double p=fabs(1./q_over_p);
3030  double betagamma=p/MASS;
3031  double betagamma2=betagamma*betagamma;
3032  double gamma2=1.+betagamma2;
3033  double beta2=betagamma2/gamma2;
3034  if (beta2<EPS) beta2=EPS;
3035 
3036  // density effect
3037  double delta=CalcDensityEffect(betagamma,rho_Z_over_A,LnI);
3038 
3039  double dEdx=0.;
3040  // For particles heavier than electrons:
3041  if (IsHadron){
3042  double two_Me_betagamma_sq=two_m_e*betagamma2;
3043  double Tmax
3044  =two_Me_betagamma_sq/(1.+2.*sqrt(gamma2)*m_ratio+m_ratio_sq);
3045 
3046  dEdx=K_rho_Z_over_A/beta2*(-log(two_Me_betagamma_sq*Tmax)
3047  +2.*(LnI + beta2)+delta);
3048  }
3049  else{
3050  // relativistic kinetic energy in units of M_e c^2
3051  double tau=sqrt(gamma2)-1.;
3052  double tau_sq=tau*tau;
3053  double tau_plus_1=tau+1.;
3054  double tau_plus_2=tau+2.;
3055  double tau_plus_2_sq=tau_plus_2*tau_plus_2;
3056  double f=0.; // function that depends on tau; see Leo (2nd ed.), p. 38.
3057  if (IsElectron){
3058  f=1.-beta2+(0.125*tau_sq-(2.*tau+1.)*log(2.))/(tau_plus_1*tau_plus_1);
3059  }
3060  else{
3061  f=2.*log(2.)-(beta2/12.)*(23.+14./tau_plus_2+10./tau_plus_2_sq
3062  +4./(tau_plus_2*tau_plus_2_sq));
3063  }
3064 
3065  // collision loss (Leo eq. 2.66)
3066  double dEdx_coll
3067  =-K_rho_Z_over_A/beta2*(log(0.5*tau_sq*tau_plus_2*m_e_sq)-LnI+f-delta);
3068 
3069  // radiation loss (Leo eqs. 2.74, 2.76 with Z^2 -> Z(Z+1)
3070  double a=Z*ALPHA;
3071  double a2=a*a;
3072  double a4=a2*a2;
3073  double epsilon=1.-PHOTON_ENERGY_CUTOFF;
3074  double epsilon2=epsilon*epsilon;
3075  double f_Z=a2*(1./(1.+a2)+0.20206-0.0369*a2+0.0083*a4-0.002*a2*a4);
3076  // The expression below is the integral of the photon energy weighted
3077  // by the bremsstrahlung cross section up to a maximum photon energy
3078  // expressed as a fraction of the incident electron energy.
3079  double dEdx_rad=-K_rho_Z_over_A*tau_plus_1*(2.*ALPHA/M_PI)*(Z+1.)
3080  *((log(183.*pow(Z,-1./3.))-f_Z)
3081  *(1.-epsilon-(1./3.)*(epsilon2-epsilon*epsilon2))
3082  +1./18.*(1.-epsilon2));
3083 
3084 
3085  // dEdx_rad=0.;
3086 
3087  dEdx=dEdx_coll+dEdx_rad;
3088  }
3089 
3090  return dEdx;
3091 }
3092 
3093 // Calculate the variance in the energy loss in a Gaussian approximation.
3094 // The standard deviation of the energy loss distribution is
3095 // var=0.1535*density*(Z/A)*x*(1-0.5*beta^2)*Tmax [MeV]
3096 // where Tmax is the maximum energy transfer.
3097 // (derived from Leo (2nd ed.), eq. 2.100. Note that I think there is a typo
3098 // in this formula in the text...)
3100  double one_over_beta2,
3101  double K_rho_Z_over_A){
3102  if (K_rho_Z_over_A<=0.) return 0.;
3103 
3104  double betagamma2=1./(one_over_beta2-1.);
3105  double gamma2=betagamma2*one_over_beta2;
3106  double two_Me_betagamma_sq=two_m_e*betagamma2;
3107  double Tmax=two_Me_betagamma_sq/(1.+2.*sqrt(gamma2)*m_ratio+m_ratio_sq);
3108  double var=K_rho_Z_over_A*one_over_beta2*fabs(ds)*Tmax*(1.-0.5/one_over_beta2);
3109  return var;
3110 }
3111 
3112 // Interface routine for Kalman filter
3114  if (z_<Z_MIN) return VALUE_OUT_OF_RANGE;
3115 
3116  // Vector to store the list of hits used in the fit for the forward parametrization
3117  vector<const DCDCTrackHit*>forward_cdc_used_in_fit;
3118 
3119  // State vector and initial guess for covariance matrix
3120  DMatrix5x1 S0;
3121  DMatrix5x5 C0;
3122 
3123  chisq_=-1.;
3124 
3125  // Angle with respect to beam line
3126  double theta_deg=(180/M_PI)*input_params.momentum().Theta();
3127  //double theta_deg_sq=theta_deg*theta_deg;
3128  double tanl0=tanl_=tan(M_PI_2-input_params.momentum().Theta());
3129 
3130  // Azimuthal angle
3131  double phi0=phi_=input_params.momentum().Phi();
3132 
3133  // Guess for momentum error
3134  double dpt_over_pt=0.1;
3135  /*
3136  if (theta_deg<15){
3137  dpt_over_pt=0.107-0.0178*theta_deg+0.000966*theta_deg_sq;
3138  }
3139  else {
3140  dpt_over_pt=0.0288+0.00579*theta_deg-2.77e-5*theta_deg_sq;
3141  }
3142  */
3143  /*
3144  if (theta_deg<28.){
3145  theta_deg=28.;
3146  theta_deg_sq=theta_deg*theta_deg;
3147  }
3148  else if (theta_deg>125.){
3149  theta_deg=125.;
3150  theta_deg_sq=theta_deg*theta_deg;
3151  }
3152  */
3153  double sig_lambda=0.02;
3154  double dp_over_p_sq
3155  =dpt_over_pt*dpt_over_pt+tanl_*tanl_*sig_lambda*sig_lambda;
3156 
3157  // Input charge
3158  double q=input_params.charge();
3159 
3160  // Input momentum
3162  double p_mag=pvec.Mag();
3163  double px=pvec.x();
3164  double py=pvec.y();
3165  double pz=pvec.z();
3166  double q_over_p0=q_over_p_=q/p_mag;
3167  double q_over_pt0=q_over_pt_=q/pvec.Perp();
3168 
3169  // Initial position
3170  double x0=x_=input_params.position().x();
3171  double y0=y_=input_params.position().y();
3172  double z0=z_=input_params.position().z();
3173 
3174  if (fit_type==kWireBased && theta_deg>10.){
3175  double Bz=fabs(bfield->GetBz(x0,y0,z0));
3176  double sperp=25.; // empirical guess
3177  if (my_fdchits.size()>0){
3178  double my_z=my_fdchits[0]->z;
3179  double my_x=my_fdchits[0]->hit->xy.X();
3180  double my_y=my_fdchits[0]->hit->xy.Y();
3181  Bz+=fabs(bfield->GetBz(my_x,my_y,my_z));
3182  Bz*=0.5; // crude average
3183  sperp=(my_z-z0)/tanl_;
3184  }
3185  double twokappa=qBr2p*Bz*q_over_pt0*FactorForSenseOfRotation;
3186  double one_over_2k=1./twokappa;
3187  if (my_fdchits.size()==0){
3188  for (unsigned int i=my_cdchits.size()-1;i>1;i--){
3189  // Use outermost axial straw to estimate a resonable arc length
3190  if (my_cdchits[i]->hit->is_stereo==false){
3191  double tworc=2.*fabs(one_over_2k);
3192  double ratio=(my_cdchits[i]->hit->wire->origin
3193  -input_params.position()).Perp()/tworc;
3194  sperp=(ratio<1.)?tworc*asin(ratio):tworc*M_PI_2;
3195  if (sperp<25.) sperp=25.;
3196  break;
3197  }
3198  }
3199  }
3200  double twoks=twokappa*sperp;
3201  double cosphi=cos(phi0);
3202  double sinphi=sin(phi0);
3203  double sin2ks=sin(twoks);
3204  double cos2ks=cos(twoks);
3205  double one_minus_cos2ks=1.-cos2ks;
3206  double myx=x0+one_over_2k*(cosphi*sin2ks-sinphi*one_minus_cos2ks);
3207  double myy=y0+one_over_2k*(sinphi*sin2ks+cosphi*one_minus_cos2ks);
3208  double mypx=px*cos2ks-py*sin2ks;
3209  double mypy=py*cos2ks+px*sin2ks;
3210  double myphi=atan2(mypy,mypx);
3211  phi0=phi_=myphi;
3212  px=mypx;
3213  py=mypy;
3214  x0=x_=myx;
3215  y0=y_=myy;
3216  z0+=tanl_*sperp;
3217  z_=z0;
3218  }
3219 
3220  // Check integrity of input parameters
3221  if (!isfinite(x0) || !isfinite(y0) || !isfinite(q_over_p0)){
3222  if (DEBUG_LEVEL>0) _DBG_ << "Invalid input parameters!" <<endl;
3223  return UNRECOVERABLE_ERROR;
3224  }
3225 
3226  // Initial direction tangents
3227  double tx0=tx_=px/pz;
3228  double ty0=ty_=py/pz;
3229  double one_plus_tsquare=1.+tx_*tx_+ty_*ty_;
3230 
3231  // deal with hits in FDC
3232  double fdc_prob=0.,fdc_chisq=-1.;
3233  unsigned int fdc_ndf=0;
3234  if (my_fdchits.size()>0
3235  && // Make sure that these parameters are valid for forward-going tracks
3236  (isfinite(tx0) && isfinite(ty0))
3237  ){
3238  if (DEBUG_LEVEL>0){
3239  _DBG_ << "Using forward parameterization." <<endl;
3240  }
3241 
3242  // Initial guess for the state vector
3243  S0(state_x)=x_;
3244  S0(state_y)=y_;
3245  S0(state_tx)=tx_;
3246  S0(state_ty)=ty_;
3248 
3249  // Initial guess for forward representation covariance matrix
3250  C0(state_x,state_x)=2.0;
3251  C0(state_y,state_y)=2.0;
3252  double temp=sig_lambda*one_plus_tsquare;
3256 
3257  if (my_cdchits.size()>0){
3258  mCDCInternalStepSize=0.25;
3259  }
3260 
3261  // The position from the track candidate is reported just outside the
3262  // start counter for tracks containing cdc hits. Propagate to the distance
3263  // of closest approach to the beam line
3265 
3266  kalman_error_t error=ForwardFit(S0,C0);
3267  if (error==FIT_SUCCEEDED) return NOERROR;
3268  if ((error==FIT_FAILED || ndf_==0) && my_cdchits.size()<6){
3269  return UNRECOVERABLE_ERROR;
3270  }
3271 
3272  fdc_prob=TMath::Prob(chisq_,ndf_);
3273  fdc_ndf=ndf_;
3274  fdc_chisq=chisq_;
3275  }
3276 
3277  // Deal with hits in the CDC
3278  if (my_cdchits.size()>5){
3280  kalman_error_t cdc_error=FIT_NOT_DONE;
3281 
3282  // Save the current state of the extrapolation vector if it exists
3283  map<DetectorSystem_t,vector<Extrapolation_t> >saved_extrapolations;
3284  if (!extrapolations.empty()){
3285  saved_extrapolations=extrapolations;
3287  }
3288  bool save_IsSmoothed=IsSmoothed;
3289 
3290  // Chi-squared, degrees of freedom, and probability
3291  double forward_prob=0.;
3292  double chisq_forward=-1.;
3293  unsigned int ndof_forward=0;
3294 
3295  // Parameters at "vertex"
3296  double phi=phi_,q_over_pt=q_over_pt_,tanl=tanl_,x=x_,y=y_,z=z_;
3297  vector< vector <double> > fcov_save;
3298  vector<pull_t>pulls_save;
3299  pulls_save.assign(pulls.begin(),pulls.end());
3300  if (!fcov.empty()){
3301  fcov_save.assign(fcov.begin(),fcov.end());
3302  }
3303  if (my_fdchits.size()>0){
3304  if (error==INVALID_FIT) _DBG_<< "Invalid fit " << fcov.size() << " " << fdc_ndf <<endl;
3305  }
3306 
3307  // Use forward parameters for CDC-only tracks with theta<THETA_CUT degrees
3308  if (theta_deg<THETA_CUT){
3309  if (DEBUG_LEVEL>0){
3310  _DBG_ << "Using forward parameterization." <<endl;
3311  }
3312 
3313  // Step size
3315 
3316  // Initialize the state vector
3317  S0(state_x)=x_=x0;
3318  S0(state_y)=y_=y0;
3319  S0(state_tx)=tx_=tx0;
3320  S0(state_ty)=ty_=ty0;
3321  S0(state_q_over_p)=q_over_p_=q_over_p0;
3322  z_=z0;
3323 
3324  // Initial guess for forward representation covariance matrix
3325  double temp=sig_lambda*one_plus_tsquare;
3326  C0(state_x,state_x)=2.0;
3327  C0(state_y,state_y)=2.0;
3331 
3332  //C0*=1.+1./tsquare;
3333 
3334  // The position from the track candidate is reported just outside the
3335  // start counter for tracks containing cdc hits. Propagate to the
3336  // distance of closest approach to the beam line
3338 
3339  error=ForwardCDCFit(S0,C0);
3340  if (error==FIT_SUCCEEDED) return NOERROR;
3341 
3342  // Find the CL of the fit
3343  forward_prob=TMath::Prob(chisq_,ndf_);
3344  if (my_fdchits.size()>0){
3345  if (fdc_ndf==0 || forward_prob>fdc_prob){
3346  // We did not end up using the fdc hits after all...
3347  fdchits_used_in_fit.clear();
3348  }
3349  else{
3350  chisq_=fdc_chisq;
3351  ndf_=fdc_ndf;
3352  x_=x;
3353  y_=y;
3354  z_=z;
3355  phi_=phi;
3356  tanl_=tanl;
3357  q_over_pt_=q_over_pt;
3358  if (!fcov_save.empty()){
3359  fcov.assign(fcov_save.begin(),fcov_save.end());
3360  }
3361  if (!saved_extrapolations.empty()){
3362  extrapolations=saved_extrapolations;
3363  }
3364  IsSmoothed=save_IsSmoothed;
3365  pulls.assign(pulls_save.begin(),pulls_save.end());
3366 
3367  // _DBG_ << endl;
3368  return NOERROR;
3369  }
3370 
3371  // Save the best values for the parameters and chi2 for now
3372  chisq_forward=chisq_;
3373  ndof_forward=ndf_;
3374  x=x_;
3375  y=y_;
3376  z=z_;
3377  phi=phi_;
3378  tanl=tanl_;
3379  q_over_pt=q_over_pt_;
3380  fcov_save.assign(fcov.begin(),fcov.end());
3381  pulls_save.assign(pulls.begin(),pulls.end());
3382  save_IsSmoothed=IsSmoothed;
3383  if (!extrapolations.empty()){
3384  saved_extrapolations=extrapolations;
3386  }
3387 
3388  // Save the list of hits used in the fit
3389  forward_cdc_used_in_fit.assign(cdchits_used_in_fit.begin(),cdchits_used_in_fit.end());
3390 
3391  }
3392  }
3393 
3394  // Attempt to fit the track using the central parametrization.
3395  if (DEBUG_LEVEL>0){
3396  _DBG_ << "Using central parameterization." <<endl;
3397  }
3398 
3399  // Step size
3401 
3402  // Initialize the state vector
3403  S0(state_q_over_pt)=q_over_pt_=q_over_pt0;
3404  S0(state_phi)=phi_=phi0;
3405  S0(state_tanl)=tanl_=tanl0;
3406  S0(state_z)=z_=z0;
3407  S0(state_D)=0.;
3408 
3409  // Initialize the covariance matrix
3410  double dz=1.0;
3411  C0(state_z,state_z)=dz*dz;
3413  =q_over_pt_*q_over_pt_*dpt_over_pt*dpt_over_pt;
3414  double dphi=0.02;
3415  C0(state_phi,state_phi)=dphi*dphi;
3416  C0(state_D,state_D)=1.0;
3417  double tanl2=tanl_*tanl_;
3418  double one_plus_tanl2=1.+tanl2;
3419  C0(state_tanl,state_tanl)=(one_plus_tanl2)*(one_plus_tanl2)
3420  *sig_lambda*sig_lambda;
3422 
3423  //if (theta_deg>90.) C0*=1.+5.*tanl2;
3424  //else C0*=1.+5.*tanl2*tanl2;
3425 
3426  mCentralStepSize=0.4;
3428 
3429  // The position from the track candidate is reported just outside the
3430  // start counter for tracks containing cdc hits. Propagate to the
3431  // distance of closest approach to the beam line
3432  DVector2 xy(x0,y0);
3433  if (fit_type==kWireBased){
3434  ExtrapolateToVertex(xy,S0);
3435  }
3436 
3437  cdc_error=CentralFit(xy,S0,C0);
3438  if (cdc_error==FIT_SUCCEEDED){
3439  // if the result of the fit using the forward parameterization succeeded
3440  // but the chi2 was too high, it still may provide the best estimate
3441  // for the track parameters...
3442  double central_prob=TMath::Prob(chisq_,ndf_);
3443 
3444  if (central_prob<forward_prob){
3445  phi_=phi;
3446  q_over_pt_=q_over_pt;
3447  tanl_=tanl;
3448  x_=x;
3449  y_=y;
3450  z_=z;
3451  chisq_=chisq_forward;
3452  ndf_= ndof_forward;
3453  fcov.assign(fcov_save.begin(),fcov_save.end());
3454  pulls.assign(pulls_save.begin(),pulls_save.end());
3455  IsSmoothed=save_IsSmoothed;
3456  if (!saved_extrapolations.empty()){
3457  extrapolations=saved_extrapolations;
3458  }
3459 
3460  cdchits_used_in_fit.assign(forward_cdc_used_in_fit.begin(),forward_cdc_used_in_fit.end());
3461 
3462  // We did not end up using any fdc hits...
3463  fdchits_used_in_fit.clear();
3464 
3465  }
3466  return NOERROR;
3467 
3468  }
3469  // otherwise if the fit using the forward parametrization worked, return that
3470  else if (error!=FIT_FAILED){
3471  phi_=phi;
3472  q_over_pt_=q_over_pt;
3473  tanl_=tanl;
3474  x_=x;
3475  y_=y;
3476  z_=z;
3477  chisq_=chisq_forward;
3478  ndf_= ndof_forward;
3479 
3480  if (!saved_extrapolations.empty()){
3481  extrapolations=saved_extrapolations;
3482  }
3483  IsSmoothed=save_IsSmoothed;
3484  fcov.assign(fcov_save.begin(),fcov_save.end());
3485  pulls.assign(pulls_save.begin(),pulls_save.end());
3486  cdchits_used_in_fit.assign(forward_cdc_used_in_fit.begin(),forward_cdc_used_in_fit.end());
3487 
3488  // We did not end up using any fdc hits...
3489  fdchits_used_in_fit.clear();
3490 
3491  return NOERROR;
3492  }
3493  else return UNRECOVERABLE_ERROR;
3494  }
3495 
3496  if (ndf_==0) return UNRECOVERABLE_ERROR;
3497 
3498  return NOERROR;
3499 }
3500 
3501 #define ITMAX 20
3502 #define CGOLD 0.3819660
3503 #define ZEPS 1.0e-10
3504 #define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
3505 #define SIGN(a,b) ((b)>=0.0?fabs(a):-fabs(a))
3506 // Routine for finding the minimum of a function bracketed between two values
3507 // (see Numerical Recipes in C, pp. 404-405).
3508 jerror_t DTrackFitterKalmanSIMD::BrentsAlgorithm(double ds1,double ds2,
3509  double dedx,DVector2 &pos,
3510  const double z0wire,
3511  const DVector2 &origin,
3512  const DVector2 &dir,
3513  DMatrix5x1 &Sc,
3514  double &ds_out){
3515  double d=0.;
3516  double e=0.0; // will be distance moved on step before last
3517  double ax=0.;
3518  double bx=-ds1;
3519  double cx=-ds1-ds2;
3520 
3521  double a=(ax<cx?ax:cx);
3522  double b=(ax>cx?ax:cx);
3523  double x=bx,w=bx,v=bx;
3524 
3525  // printf("ds1 %f ds2 %f\n",ds1,ds2);
3526  // Initialize return step size
3527  ds_out=0.;
3528 
3529  // Save the starting position
3530  // DVector3 pos0=pos;
3531  // DMatrix S0(Sc);
3532 
3533  // Step to intermediate point
3534  Step(pos,x,Sc,dedx);
3535  // Bail if the transverse momentum has dropped below some minimum
3536  if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX){
3537  if (DEBUG_LEVEL>2)
3538  {
3539  _DBG_ << "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3540  << endl;
3541  }
3542  return VALUE_OUT_OF_RANGE;
3543  }
3544 
3545  DVector2 wirepos=origin+(Sc(state_z)-z0wire)*dir;
3546  double u_old=x;
3547  double u=0.;
3548 
3549  // initialization
3550  double fw=(pos-wirepos).Mod2();
3551  double fv=fw,fx=fw;
3552 
3553  // main loop
3554  for (unsigned int iter=1;iter<=ITMAX;iter++){
3555  double xm=0.5*(a+b);
3556  double tol1=EPS2*fabs(x)+ZEPS;
3557  double tol2=2.0*tol1;
3558 
3559  if (fabs(x-xm)<=(tol2-0.5*(b-a))){
3560  if (Sc(state_z)<=cdc_origin[2]){
3561  unsigned int iter2=0;
3562  double ds_temp=0.;
3563  while (fabs(Sc(state_z)-cdc_origin[2])>EPS2 && iter2<20){
3564  u=x-(cdc_origin[2]-Sc(state_z))*sin(atan(Sc(state_tanl)));
3565  x=u;
3566  ds_temp+=u_old-u;
3567  // Bail if the transverse momentum has dropped below some minimum
3568  if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX){
3569  if (DEBUG_LEVEL>2)
3570  {
3571  _DBG_ << "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3572  << endl;
3573  }
3574  return VALUE_OUT_OF_RANGE;
3575  }
3576 
3577  // Function evaluation
3578  Step(pos,u_old-u,Sc,dedx);
3579  u_old=u;
3580  iter2++;
3581  }
3582  //printf("new z %f ds %f \n",pos.z(),x);
3583  ds_out=ds_temp;
3584  return NOERROR;
3585  }
3586  else if (Sc(state_z)>=endplate_z){
3587  unsigned int iter2=0;
3588  double ds_temp=0.;
3589  while (fabs(Sc(state_z)-endplate_z)>EPS2 && iter2<20){
3590  u=x-(endplate_z-Sc(state_z))*sin(atan(Sc(state_tanl)));
3591  x=u;
3592  ds_temp+=u_old-u;
3593 
3594  // Bail if the transverse momentum has dropped below some minimum
3595  if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX){
3596  if (DEBUG_LEVEL>2)
3597  {
3598  _DBG_ << "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3599  << endl;
3600  }
3601  return VALUE_OUT_OF_RANGE;
3602  }
3603 
3604  // Function evaluation
3605  Step(pos,u_old-u,Sc,dedx);
3606  u_old=u;
3607  iter2++;
3608  }
3609  //printf("new z %f ds %f \n",pos.z(),x);
3610  ds_out=ds_temp;
3611  return NOERROR;
3612  }
3613  ds_out=cx-x;
3614  return NOERROR;
3615  }
3616  // trial parabolic fit
3617  if (fabs(e)>tol1){
3618  double x_minus_w=x-w;
3619  double x_minus_v=x-v;
3620  double r=x_minus_w*(fx-fv);
3621  double q=x_minus_v*(fx-fw);
3622  double p=x_minus_v*q-x_minus_w*r;
3623  q=2.0*(q-r);
3624  if (q>0.0) p=-p;
3625  q=fabs(q);
3626  double etemp=e;
3627  e=d;
3628  if (fabs(p)>=fabs(0.5*q*etemp) || p<=q*(a-x) || p>=q*(b-x))
3629  // fall back on the Golden Section technique
3630  d=CGOLD*(e=(x>=xm?a-x:b-x));
3631  else{
3632  // parabolic step
3633  d=p/q;
3634  u=x+d;
3635  if (u-a<tol2 || b-u <tol2)
3636  d=SIGN(tol1,xm-x);
3637  }
3638  } else{
3639  d=CGOLD*(e=(x>=xm?a-x:b-x));
3640  }
3641  u=(fabs(d)>=tol1 ? x+d: x+SIGN(tol1,d));
3642 
3643  // Bail if the transverse momentum has dropped below some minimum
3644  if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX){
3645  if (DEBUG_LEVEL>2)
3646  {
3647  _DBG_ << "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3648  << endl;
3649  }
3650  return VALUE_OUT_OF_RANGE;
3651  }
3652 
3653  // Function evaluation
3654  Step(pos,u_old-u,Sc,dedx);
3655  u_old=u;
3656 
3657  wirepos=origin;
3658  wirepos+=(Sc(state_z)-z0wire)*dir;
3659  double fu=(pos-wirepos).Mod2();
3660 
3661  //cout << "Brent: z="<<Sc(state_z) << " d="<<sqrt(fu) << endl;
3662 
3663  if (fu<=fx){
3664  if (u>=x) a=x; else b=x;
3665  SHFT(v,w,x,u);
3666  SHFT(fv,fw,fx,fu);
3667  }
3668  else {
3669  if (u<x) a=u; else b=u;
3670  if (fu<=fw || w==x){
3671  v=w;
3672  w=u;
3673  fv=fw;
3674  fw=fu;
3675  }
3676  else if (fu<=fv || v==x || v==w){
3677  v=u;
3678  fv=fu;
3679  }
3680  }
3681  }
3682  ds_out=cx-x;
3683 
3684  return NOERROR;
3685 }
3686 
3687 // Routine for finding the minimum of a function bracketed between two values
3688 // (see Numerical Recipes in C, pp. 404-405).
3689 jerror_t DTrackFitterKalmanSIMD::BrentsAlgorithm(double z,double dz,
3690  double dedx,
3691  const double z0wire,
3692  const DVector2 &origin,
3693  const DVector2 &dir,
3694  DMatrix5x1 &S,
3695  double &dz_out){
3696  double d=0.,u=0.;
3697  double e=0.0; // will be distance moved on step before last
3698  double ax=0.;
3699  double bx=-dz;
3700  double cx=-2.*dz;
3701 
3702  double a=(ax<cx?ax:cx);
3703  double b=(ax>cx?ax:cx);
3704  double x=bx,w=bx,v=bx;
3705 
3706  // Initialize dz_out
3707  dz_out=0.;
3708 
3709  // Step to intermediate point
3710  double z_new=z+x;
3711  Step(z,z_new,dedx,S);
3712  // Bail if the momentum has dropped below some minimum
3713  if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){
3714  if (DEBUG_LEVEL>2)
3715  {
3716  _DBG_ << "Bailing: P = " << 1./fabs(S(state_q_over_p))
3717  << endl;
3718  }
3719  return VALUE_OUT_OF_RANGE;
3720  }
3721 
3722  double dz0wire=z-z0wire;
3723  DVector2 wirepos=origin+(dz0wire+x)*dir;
3724  DVector2 pos(S(state_x),S(state_y));
3725  double z_old=z_new;
3726 
3727  // initialization
3728  double fw=(pos-wirepos).Mod2();
3729  double fv=fw;
3730  double fx=fw;
3731 
3732  // main loop
3733  for (unsigned int iter=1;iter<=ITMAX;iter++){
3734  double xm=0.5*(a+b);
3735  double tol1=EPS2*fabs(x)+ZEPS;
3736  double tol2=2.0*tol1;
3737  if (fabs(x-xm)<=(tol2-0.5*(b-a))){
3738  if (z_new>=endplate_z){
3739  x=endplate_z-z_new;
3740 
3741  // Bail if the momentum has dropped below some minimum
3742  if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){
3743  if (DEBUG_LEVEL>2)
3744  {
3745  _DBG_ << "Bailing: P = " << 1./fabs(S(state_q_over_p))
3746  << endl;
3747  }
3748  return VALUE_OUT_OF_RANGE;
3749  }
3750  if (!isfinite(S(state_x)) || !isfinite(S(state_y))){
3751  _DBG_ <<endl;
3752  return VALUE_OUT_OF_RANGE;
3753  }
3754  Step(z_new,endplate_z,dedx,S);
3755  }
3756  dz_out=x;
3757  return NOERROR;
3758  }
3759  // trial parabolic fit
3760  if (fabs(e)>tol1){
3761  double x_minus_w=x-w;
3762  double x_minus_v=x-v;
3763  double r=x_minus_w*(fx-fv);
3764  double q=x_minus_v*(fx-fw);
3765  double p=x_minus_v*q-x_minus_w*r;
3766  q=2.0*(q-r);
3767  if (q>0.0) p=-p;
3768  q=fabs(q);
3769  double etemp=e;
3770  e=d;
3771  if (fabs(p)>=fabs(0.5*q*etemp) || p<=q*(a-x) || p>=q*(b-x))
3772  // fall back on the Golden Section technique
3773  d=CGOLD*(e=(x>=xm?a-x:b-x));
3774  else{
3775  // parabolic step
3776  d=p/q;
3777  u=x+d;
3778  if (u-a<tol2 || b-u <tol2)
3779  d=SIGN(tol1,xm-x);
3780  }
3781  } else{
3782  d=CGOLD*(e=(x>=xm?a-x:b-x));
3783  }
3784  u=(fabs(d)>=tol1 ? x+d: x+SIGN(tol1,d));
3785 
3786  // Function evaluation
3787  //S=S0;
3788  z_new=z+u;
3789  // Bail if the momentum has dropped below some minimum
3790  if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){
3791  if (DEBUG_LEVEL>2)
3792  {
3793  _DBG_ << "Bailing: P = " << 1./fabs(S(state_q_over_p))
3794  << endl;
3795  }
3796  return VALUE_OUT_OF_RANGE;
3797  }
3798 
3799  Step(z_old,z_new,dedx,S);
3800  z_old=z_new;
3801 
3802  wirepos=origin;
3803  wirepos+=(dz0wire+u)*dir;
3804  pos.Set(S(state_x),S(state_y));
3805  double fu=(pos-wirepos).Mod2();
3806 
3807  // _DBG_ << "Brent: z="<< z+u << " d^2="<<fu << endl;
3808 
3809  if (fu<=fx){
3810  if (u>=x) a=x; else b=x;
3811  SHFT(v,w,x,u);
3812  SHFT(fv,fw,fx,fu);
3813  }
3814  else {
3815  if (u<x) a=u; else b=u;
3816  if (fu<=fw || w==x){
3817  v=w;
3818  w=u;
3819  fv=fw;
3820  fw=fu;
3821  }
3822  else if (fu<=fv || v==x || v==w){
3823  v=u;
3824  fv=fu;
3825  }
3826  }
3827  }
3828  dz_out=x;
3829  return NOERROR;
3830 }
3831 
3832 // Kalman engine for Central tracks; updates the position on the trajectory
3833 // after the last hit (closest to the target) is added
3835  DMatrix5x1 &Sc,
3836  DMatrix5x5 &Cc,
3837  DVector2 &xy,double &chisq,
3838  unsigned int &my_ndf
3839  ){
3840  DMatrix1x5 H; // Track projection matrix
3841  DMatrix5x1 H_T; // Transpose of track projection matrix
3842  DMatrix5x5 J; // State vector Jacobian matrix
3843  DMatrix5x5 Q; // Process noise covariance matrix
3844  DMatrix5x1 K; // KalmanSIMD gain matrix
3845  DMatrix5x5 Ctest; // covariance matrix
3846  // double V=0.2028; //1.56*1.56/12.; // Measurement variance
3847  double V=0.0507;
3848  double InvV; // inverse of variance
3849  //DMatrix5x1 dS; // perturbation in state vector
3850  DMatrix5x1 S0,S0_; // state vector
3851 
3852  // set the used_in_fit flags to false for cdc hits
3853  unsigned int num_cdc=cdc_used_in_fit.size();
3854  for (unsigned int i=0;i<num_cdc;i++) cdc_used_in_fit[i]=false;
3855  for (unsigned int i=0;i<central_traj.size();i++){
3856  central_traj[i].h_id=0;
3857  }
3858 
3859  // Initialize the chi2 for this part of the track
3860  chisq=0.;
3861  my_ndf=0;
3862 
3863  double chi2cut=NUM_CDC_SIGMA_CUT*NUM_CDC_SIGMA_CUT;
3864 
3865  // path length increment
3866  double ds2=0.;
3867 
3868  //printf(">>>>>>>>>>>>>>>>\n");
3869 
3870  // beginning position
3871  double phi=Sc(state_phi);
3872  xy.Set(central_traj[break_point_step_index].xy.X()-Sc(state_D)*sin(phi),
3873  central_traj[break_point_step_index].xy.Y()+Sc(state_D)*cos(phi));
3874 
3875  // Wire origin and direction
3876  // unsigned int cdc_index=my_cdchits.size()-1;
3877  unsigned int cdc_index=break_point_cdc_index;
3878  if (break_point_cdc_index<num_cdc-1){
3879  num_cdc=break_point_cdc_index+1;
3880  }
3881 
3882  if (num_cdc<MIN_HITS_FOR_REFIT) chi2cut=BIG;
3883 
3884  // Wire origin and direction
3885  DVector2 origin=my_cdchits[cdc_index]->origin;
3886  double z0w=my_cdchits[cdc_index]->z0wire;
3887  DVector2 dir=my_cdchits[cdc_index]->dir;
3888  DVector2 wirexy=origin+(Sc(state_z)-z0w)*dir;
3889 
3890  // Save the starting values for C and S in the deque
3893 
3894  // doca variables
3895  double doca2,old_doca2=(xy-wirexy).Mod2();
3896 
3897  // energy loss
3898  double dedx=0.;
3899 
3900  // Boolean for flagging when we are done with measurements
3901  bool more_measurements=true;
3902 
3903  // Initialize S0_ and perform the loop over the trajectory
3905 
3906  for (unsigned int k=break_point_step_index+1;k<central_traj.size();k++){
3907  unsigned int k_minus_1=k-1;
3908 
3909  // Check that C matrix is positive definite
3910  if (!Cc.IsPosDef()){
3911  if (DEBUG_LEVEL>0) _DBG_ << "Broken covariance matrix!" <<endl;
3912  return BROKEN_COVARIANCE_MATRIX;
3913  }
3914 
3915  // Get the state vector, jacobian matrix, and multiple scattering matrix
3916  // from reference trajectory
3917  S0=central_traj[k].S;
3918  J=central_traj[k].J;
3919  Q=central_traj[k].Q;
3920 
3921  //Q.Print();
3922  //J.Print();
3923 
3924  // State S is perturbation about a seed S0
3925  //dS=Sc-S0_;
3926  //dS.Zero();
3927 
3928  // Update the actual state vector and covariance matrix
3929  Sc=S0+J*(Sc-S0_);
3930  // Cc=J*(Cc*JT)+Q;
3931  // Cc=Q.AddSym(Cc.SandwichMultiply(J));
3932  Cc=Q.AddSym(J*Cc*J.Transpose());
3933 
3934  // Save the current state and covariance matrix in the deque
3935  if (fit_type==kTimeBased){
3936  central_traj[k].Skk=Sc;
3937  central_traj[k].Ckk=Cc;
3938  }
3939 
3940  // update position based on new doca to reference trajectory
3941  xy.Set(central_traj[k].xy.X()-Sc(state_D)*sin(Sc(state_phi)),
3942  central_traj[k].xy.Y()+Sc(state_D)*cos(Sc(state_phi)));
3943 
3944  // Bail if the position is grossly outside of the tracking volume
3945  if (xy.Mod2()>R2_MAX || Sc(state_z)<Z_MIN || Sc(state_z)>Z_MAX){
3946  if (DEBUG_LEVEL>2)
3947  {
3948  _DBG_<< "Went outside of tracking volume at z="<<Sc(state_z)
3949  << " r="<<xy.Mod()<<endl;
3950  _DBG_ << " Break indexes: " << break_point_cdc_index <<","
3951  << break_point_step_index << endl;
3952  }
3953  return POSITION_OUT_OF_RANGE;
3954  }
3955  // Bail if the transverse momentum has dropped below some minimum
3956  if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX){
3957  if (DEBUG_LEVEL>2)
3958  {
3959  _DBG_ << "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3960  << " at step " << k
3961  << endl;
3962  }
3963  return MOMENTUM_OUT_OF_RANGE;
3964  }
3965 
3966 
3967  // Save the current state of the reference trajectory
3968  S0_=S0;
3969 
3970  // new wire position
3971  wirexy=origin;
3972  wirexy+=(Sc(state_z)-z0w)*dir;
3973 
3974  // new doca
3975  doca2=(xy-wirexy).Mod2();
3976 
3977  // Check if the doca is no longer decreasing
3978  if (more_measurements && (doca2>old_doca2 && Sc(state_z)>cdc_origin[2])){
3979  if (my_cdchits[cdc_index]->status==good_hit){
3980  if (DEBUG_LEVEL>9) {
3981  _DBG_ << " Good Hit Ring " << my_cdchits[cdc_index]->hit->wire->ring << " Straw " << my_cdchits[cdc_index]->hit->wire->straw << endl;
3982  _DBG_ << " doca " << sqrt(doca2) << endl;
3983  }
3984 
3985  // Save values at end of current step
3986  DVector2 xy0=central_traj[k].xy;
3987 
3988  // Variables for the computation of D at the doca to the wire
3989  double D=Sc(state_D);
3990  double q=(Sc(state_q_over_pt)>0.0)?1.:-1.;
3991 
3993 
3994  double qpt=1./Sc(state_q_over_pt) * FactorForSenseOfRotation;
3995  double sinphi=sin(Sc(state_phi));
3996  double cosphi=cos(Sc(state_phi));
3997  //double qrc_old=qpt/fabs(qBr2p*bfield->GetBz(pos.x(),pos.y(),pos.z()));
3998  double qrc_old=qpt/fabs(qBr2p*central_traj[k].B);
3999  double qrc_plus_D=D+qrc_old;
4000 
4001  // wire direction variable
4002  double ux=dir.X();
4003  double uy=dir.Y();
4004  double cosstereo=my_cdchits[cdc_index]->cosstereo;
4005  // Variables relating wire direction and track direction
4006  //double my_ux=ux*sinl-cosl*cosphi;
4007  //double my_uy=uy*sinl-cosl*sinphi;
4008  //double denom=my_ux*my_ux+my_uy*my_uy;
4009  // distance variables
4010  DVector2 diff,dxy1;
4011 
4012  // use Brent's algorithm to find the poca to the wire
4013  // See Numerical Recipes in C, pp 404-405
4014 
4015  // dEdx for current position along trajectory
4016  double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl)));
4017  if (CORRECT_FOR_ELOSS){
4018  dedx=GetdEdx(q_over_p, central_traj[k].K_rho_Z_over_A,
4019  central_traj[k].rho_Z_over_A,
4020  central_traj[k].LnI,central_traj[k].Z);
4021  }
4022 
4023  if (BrentCentral(dedx,xy,z0w,origin,dir,Sc,ds2)!=NOERROR) return MOMENTUM_OUT_OF_RANGE;
4024 
4025  //Step along the reference trajectory and compute the new covariance matrix
4026  StepStateAndCovariance(xy0,ds2,dedx,S0,J,Cc);
4027 
4028  // Compute the value of D (signed distance to the reference trajectory)
4029  // at the doca to the wire
4030  dxy1=xy0-central_traj[k].xy;
4031  double rc=sqrt(dxy1.Mod2()
4032  +2.*qrc_plus_D*(dxy1.X()*sinphi-dxy1.Y()*cosphi)
4033  +qrc_plus_D*qrc_plus_D);
4034  Sc(state_D)=q*rc-qrc_old;
4035 
4036  // wire position
4037  wirexy=origin;
4038  wirexy+=(Sc(state_z)-z0w)*dir;
4039  diff=xy-wirexy;
4040 
4041  // prediction for measurement
4042  double doca=diff.Mod()+EPS;
4043  double prediction=doca*cosstereo;
4044 
4045  // Measurement
4046  double measurement=0.39,tdrift=0.,tcorr=0.,dDdt0=0.;
4048  // Find offset of wire with respect to the center of the
4049  // straw at this z position
4050  const DCDCWire *mywire=my_cdchits[cdc_index]->hit->wire;
4051  int ring_index=mywire->ring-1;
4052  int straw_index=mywire->straw-1;
4053  double dz=Sc(state_z)-z0w;
4054  double phi_d=diff.Phi();
4055  double delta
4056  =max_sag[ring_index][straw_index]*(1.-dz*dz/5625.)
4057  *cos(phi_d + sag_phi_offset[ring_index][straw_index]);
4058  double dphi=phi_d-mywire->origin.Phi();
4059  while (dphi>M_PI) dphi-=2*M_PI;
4060  while (dphi<-M_PI) dphi+=2*M_PI;
4061  if (mywire->origin.Y()<0) dphi*=-1.;
4062 
4063  tdrift=my_cdchits[cdc_index]->tdrift-mT0
4064  -central_traj[k_minus_1].t*TIME_UNIT_CONVERSION;
4065  double B=central_traj[k_minus_1].B;
4066  ComputeCDCDrift(dphi,delta,tdrift,B,measurement,V,tcorr);
4067  V*=anneal_factor;
4068  if (ALIGNMENT_CENTRAL){
4069  double myV=0.;
4070  double mytcorr=0.;
4071  double d_shifted;
4072  double dt=2.0;
4073  ComputeCDCDrift(dphi,delta,tdrift+dt,B,d_shifted,myV,mytcorr);
4074  dDdt0=(d_shifted-measurement)/dt;
4075  }
4076 
4077  //_DBG_ << tcorr << " " << dphi << " " << dm << endl;
4078 
4079  }
4080 
4081  // Projection matrix
4082  sinphi=sin(Sc(state_phi));
4083  cosphi=cos(Sc(state_phi));
4084  double dx=diff.X();
4085  double dy=diff.Y();
4086  double cosstereo_over_doca=cosstereo/doca;
4087  H_T(state_D)=(dy*cosphi-dx*sinphi)*cosstereo_over_doca;
4088  H_T(state_phi)
4089  =-Sc(state_D)*cosstereo_over_doca*(dx*cosphi+dy*sinphi);
4090  H_T(state_z)=-cosstereo_over_doca*(dx*ux+dy*uy);
4091  H(state_tanl)=0.;
4092  H_T(state_tanl)=0.;
4093  H(state_D)=H_T(state_D);
4094  H(state_z)=H_T(state_z);
4095  H(state_phi)=H_T(state_phi);
4096 
4097  // Difference and inverse of variance
4098  //InvV=1./(V+H*(Cc*H_T));
4099  //double Vproj=Cc.SandwichMultiply(H_T);
4100  double Vproj=H*Cc*H_T;
4101  InvV=1./(V+Vproj);
4102  double dm=measurement-prediction;
4103 
4104  if (InvV<0.){
4105  if (DEBUG_LEVEL>1)
4106  _DBG_ << k <<" "<< central_traj.size()-1<<" Negative variance??? " << V << " " << H*(Cc*H_T) <<endl;
4107 
4108  break_point_cdc_index=(3*num_cdc)/4;
4109  return NEGATIVE_VARIANCE;
4110  }
4111  /*
4112  if (fabs(cosstereo)<1.){
4113  printf("t %f delta %f sigma %f V %f chi2 %f\n",my_cdchits[cdc_index]->hit->tdrift-mT0,dm,sqrt(V),1./InvV,dm*dm*InvV);
4114  }
4115  */
4116 
4117  // Check how far this hit is from the expected position
4118  double chi2check=dm*dm*InvV;
4119  if (DEBUG_LEVEL>9) _DBG_ << " Prediction " << prediction << " Measurement " << measurement << " Chi2 " << chi2check << endl;
4120  if (chi2check<chi2cut)
4121  {
4122  if (DEBUG_LEVEL>9) _DBG_ << " Passed Chi^2 check Ring " << my_cdchits[cdc_index]->hit->wire->ring << " Straw " << my_cdchits[cdc_index]->hit->wire->straw << endl;
4123 
4124  // Compute Kalman gain matrix
4125  K=InvV*(Cc*H_T);
4126 
4127  // Update state vector covariance matrix
4128  //Cc=Cc-(K*(H*Cc));
4129  Ctest=Cc.SubSym(K*(H*Cc));
4130  // Joseph form
4131  // C = (I-KH)C(I-KH)^T + KVK^T
4132  //Ctest=Cc.SandwichMultiply(I5x5-K*H)+V*MultiplyTranspose(K);
4133  // Check that Ctest is positive definite
4134  if (!Ctest.IsPosDef()){
4135  if (DEBUG_LEVEL>0) _DBG_ << "Broken covariance matrix!" <<endl;
4136  return BROKEN_COVARIANCE_MATRIX;
4137  }
4138  bool skip_ring
4139  =(my_cdchits[cdc_index]->hit->wire->ring==RING_TO_SKIP);
4140  //Update covariance matrix and state vector
4141  if (skip_ring==false && tdrift >= CDC_T_DRIFT_MIN){
4142  Cc=Ctest;
4143  Sc+=dm*K;
4144  }
4145 
4146  // Mark point on ref trajectory with a hit id for the straw
4147  central_traj[k].h_id=cdc_index+1;
4148  if (DEBUG_LEVEL>9) _DBG_ << " Marked Trajectory central_traj[k].h_id=cdc_index+1 (k cdc_index)" << k << " " << cdc_index << endl;
4149 
4150  // Save some updated information for this hit
4151  double scale=(skip_ring)?1.:(1.-H*K);
4152  cdc_updates[cdc_index].tcorr=tcorr;
4153  cdc_updates[cdc_index].tdrift=tdrift;
4154  cdc_updates[cdc_index].doca=measurement;
4155  cdc_updates[cdc_index].variance=V;
4156  cdc_updates[cdc_index].dDdt0=dDdt0;
4157  cdc_used_in_fit[cdc_index]=true;
4158  if (tdrift < CDC_T_DRIFT_MIN) cdc_used_in_fit[cdc_index]=false;
4159 
4160  // Update chi2 for this hit
4161  if (skip_ring==false && tdrift >= CDC_T_DRIFT_MIN){
4162  chisq+=scale*dm*dm/V;
4163  my_ndf++;
4164  }
4165  if (DEBUG_LEVEL>10)
4166  cout
4167  << "ring " << my_cdchits[cdc_index]->hit->wire->ring
4168  << " t " << my_cdchits[cdc_index]->hit->tdrift
4169  << " Dm-Dpred " << dm
4170  << " chi2 " << (1.-H*K)*dm*dm/V
4171  << endl;
4172 
4173  break_point_cdc_index=cdc_index;
4174  break_point_step_index=k_minus_1;
4175 
4176  //else printf("Negative variance!!!\n");
4177 
4178 
4179  }
4180 
4181  // Move back to the right step along the reference trajectory.
4182  StepStateAndCovariance(xy,-ds2,dedx,Sc,J,Cc);
4183 
4184  // Save state and covariance matrix to update vector
4185  cdc_updates[cdc_index].S=Sc;
4186  cdc_updates[cdc_index].C=Cc;
4187 
4188  //Sc.Print();
4189  //Cc.Print();
4190 
4191  // update position on current trajectory based on corrected doca to
4192  // reference trajectory
4193  xy.Set(central_traj[k].xy.X()-Sc(state_D)*sin(Sc(state_phi)),
4194  central_traj[k].xy.Y()+Sc(state_D)*cos(Sc(state_phi)));
4195 
4196  }
4197 
4198  // new wire origin and direction
4199  if (cdc_index>0){
4200  cdc_index--;
4201  origin=my_cdchits[cdc_index]->origin;
4202  z0w=my_cdchits[cdc_index]->z0wire;
4203  dir=my_cdchits[cdc_index]->dir;
4204  }
4205  else{
4206  more_measurements=false;
4207  }
4208 
4209  // Update the wire position
4210  wirexy=origin+(Sc(state_z)-z0w)*dir;
4211 
4212  //s+=ds2;
4213  // new doca
4214  doca2=(xy-wirexy).Mod2();
4215  }
4216 
4217  old_doca2=doca2;
4218 
4219  }
4220 
4221  // If there are not enough degrees of freedom, something went wrong...
4222  if (my_ndf<6){
4223  chisq=-1.;
4224  my_ndf=0;
4225  return PRUNED_TOO_MANY_HITS;
4226  }
4227  else my_ndf-=5;
4228 
4229  // Check if the momentum is unphysically large
4230  double p=cos(atan(Sc(state_tanl)))/fabs(Sc(state_q_over_pt));
4231  if (p>12.0){
4232  if (DEBUG_LEVEL>2)
4233  {
4234  _DBG_ << "Unphysical momentum: P = " << p <<endl;
4235  }
4236  return MOMENTUM_OUT_OF_RANGE;
4237  }
4238 
4239  // Check if we have a kink in the track or threw away too many cdc hits
4240  if (num_cdc>=MIN_HITS_FOR_REFIT){
4241  if (break_point_cdc_index>1){
4242  if (break_point_cdc_index<num_cdc/2){
4243  break_point_cdc_index=(3*num_cdc)/4;
4244  }
4245  return BREAK_POINT_FOUND;
4246  }
4247 
4248  unsigned int num_good=0;
4249  for (unsigned int j=0;j<num_cdc;j++){
4250  if (cdc_used_in_fit[j]) num_good++;
4251  }
4252  if (double(num_good)/double(num_cdc)<MINIMUM_HIT_FRACTION){
4253  return PRUNED_TOO_MANY_HITS;
4254  }
4255  }
4256 
4257  return FIT_SUCCEEDED;
4258 }
4259 
4260 // Kalman engine for forward tracks
4262  double cdc_anneal_factor,
4263  DMatrix5x1 &S,
4264  DMatrix5x5 &C,
4265  double &chisq,
4266  unsigned int &numdof){
4267  DMatrix2x1 Mdiff; // difference between measurement and prediction
4268  DMatrix2x5 H; // Track projection matrix
4269  DMatrix5x2 H_T; // Transpose of track projection matrix
4270  DMatrix1x5 Hc; // Track projection matrix for cdc hits
4271  DMatrix5x1 Hc_T; // Transpose of track projection matrix for cdc hits
4272  DMatrix5x5 J; // State vector Jacobian matrix
4273  //DMatrix5x5 J_T; // transpose of this matrix
4274  DMatrix5x5 Q; // Process noise covariance matrix
4275  DMatrix5x2 K; // Kalman gain matrix
4276  DMatrix5x1 Kc; // Kalman gain matrix for cdc hits
4277  DMatrix2x2 V(0.0833,0.,0.,FDC_CATHODE_VARIANCE); // Measurement covariance matrix
4278  DMatrix2x1 R; // Filtered residual
4279  DMatrix2x2 RC; // Covariance of filtered residual
4280  DMatrix5x1 S0,S0_; //State vector
4281  DMatrix5x5 Ctest; // Covariance matrix
4282  DMatrix2x2 InvV; // Inverse of error matrix
4283 
4284  double Vc=0.0507;
4285 
4286  // Vectors for cdc wires
4287  DVector2 origin,dir,wirepos;
4288  double z0w=0.; // origin in z for wire
4289 
4290  // Set used_in_fit flags to false for fdc and cdc hits
4291  unsigned int num_cdc=cdc_used_in_fit.size();
4292  unsigned int num_fdc=fdc_used_in_fit.size();
4293  for (unsigned int i=0;i<num_cdc;i++) cdc_used_in_fit[i]=false;
4294  for (unsigned int i=0;i<num_fdc;i++) fdc_used_in_fit[i]=false;
4295  for (unsigned int i=0;i<forward_traj.size();i++){
4296  if (forward_traj[i].h_id>999)
4297  forward_traj[i].h_id=0;
4298  }
4299 
4300  // Save the starting values for C and S in the deque
4303 
4304  // Initialize chi squared
4305  chisq=0;
4306 
4307  // Initialize number of degrees of freedom
4308  numdof=0;
4309 
4310  double fdc_chi2cut=NUM_FDC_SIGMA_CUT*NUM_FDC_SIGMA_CUT;
4311  double cdc_chi2cut=NUM_CDC_SIGMA_CUT*NUM_CDC_SIGMA_CUT;
4312 
4313  unsigned int num_fdc_hits=break_point_fdc_index+1;
4314  unsigned int max_num_fdc_used_in_fit=num_fdc_hits;
4315  unsigned int num_cdc_hits=my_cdchits.size();
4316  unsigned int cdc_index=0;
4317  if (num_cdc_hits>0) cdc_index=num_cdc_hits-1;
4318  bool more_cdc_measurements=(num_cdc_hits>0);
4319  double old_doca2=1e6;
4320 
4321  if (num_fdc_hits+num_cdc_hits<MIN_HITS_FOR_REFIT){
4322  cdc_chi2cut=BIG;
4323  fdc_chi2cut=BIG;
4324  }
4325 
4326  if (more_cdc_measurements){
4327  origin=my_cdchits[cdc_index]->origin;
4328  dir=my_cdchits[cdc_index]->dir;
4329  z0w=my_cdchits[cdc_index]->z0wire;
4330  wirepos=origin+(forward_traj[break_point_step_index].z-z0w)*dir;
4331  }
4332 
4334 
4335  if (DEBUG_LEVEL > 25){
4336  jout << "Entering DTrackFitterKalmanSIMD::KalmanForward ================================" << endl;
4337  jout << " We have the following starting parameters for our fit. S = State vector, C = Covariance matrix" << endl;
4338  S.Print();
4339  C.Print();
4340  jout << setprecision(6);
4341  jout << " There are " << num_cdc << " CDC Updates and " << num_fdc << " FDC Updates on this track" << endl;
4342  jout << " There are " << num_cdc_hits << " CDC Hits and " << num_fdc_hits << " FDC Hits on this track" << endl;
4343  jout << " With NUM_FDC_SIGMA_CUT = " << NUM_FDC_SIGMA_CUT << " and NUM_CDC_SIGMA_CUT = " << NUM_CDC_SIGMA_CUT << endl;
4344  jout << " fdc_anneal_factor = " << fdc_anneal_factor << " cdc_anneal_factor = " << cdc_anneal_factor << endl;
4345  jout << " yields fdc_chi2cut = " << fdc_chi2cut << " cdc_chi2cut = " << cdc_chi2cut << endl;
4346  jout << " Starting from break_point_step_index " << break_point_step_index << endl;
4347  jout << " S0_ which is the state vector of the reference trajectory at the break point step:" << endl;
4348  S0_.Print();
4349  jout << " ===== Beginning pass over reference trajectory ======== " << endl;
4350  }
4351 
4352  for (unsigned int k=break_point_step_index+1;k<forward_traj.size();k++){
4353  unsigned int k_minus_1=k-1;
4354 
4355  // Check that C matrix is positive definite
4356  if (!C.IsPosDef()){
4357  if (DEBUG_LEVEL>0) _DBG_ << "Broken covariance matrix!" <<endl;
4358  return BROKEN_COVARIANCE_MATRIX;
4359  }
4360 
4361  // Get the state vector, jacobian matrix, and multiple scattering matrix
4362  // from reference trajectory
4363  S0=(forward_traj[k].S);
4364  J=(forward_traj[k].J);
4365  Q=(forward_traj[k].Q);
4366 
4367  // State S is perturbation about a seed S0
4368  //dS=S-S0_;
4369 
4370  // Update the actual state vector and covariance matrix
4371  S=S0+J*(S-S0_);
4372 
4373  // Bail if the momentum has dropped below some minimum
4374  if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX){
4375  if (DEBUG_LEVEL>2)
4376  {
4377  _DBG_ << "Bailing: P = " << 1./fabs(S(state_q_over_p)) << endl;
4378  }
4379  break_point_fdc_index=(3*num_fdc)/4;
4380  return MOMENTUM_OUT_OF_RANGE;
4381  }
4382 
4383 
4384  //C=J*(C*J_T)+Q;
4385  //C=Q.AddSym(C.SandwichMultiply(J));
4386  C=Q.AddSym(J*C*J.Transpose());
4387 
4388  // Save the current state and covariance matrix in the deque
4389  forward_traj[k].Skk=S;
4390  forward_traj[k].Ckk=C;
4391 
4392  // Save the current state of the reference trajectory
4393  S0_=S0;
4394 
4395  // Z position along the trajectory
4396  double z=forward_traj[k].z;
4397 
4398  if (DEBUG_LEVEL > 25){
4399  jout << " At reference trajectory index " << k << " at z=" << z << endl;
4400  jout << " The State vector from the reference trajectory" << endl;
4401  S0.Print();
4402  jout << " The Jacobian matrix " << endl;
4403  J.Print();
4404  jout << " The Q matrix "<< endl;
4405  Q.Print();
4406  jout << " The updated State vector S=S0+J*(S-S0_)" << endl;
4407  S.Print();
4408  jout << " The updated Covariance matrix C=J*(C*J_T)+Q;" << endl;
4409  C.Print();
4410  }
4411 
4412  // Add the hit
4413  if (num_fdc_hits>0){
4414  if (forward_traj[k].h_id>0 && forward_traj[k].h_id<1000){
4415  unsigned int id=forward_traj[k].h_id-1;
4416 
4417  // Make the small alignment rotations
4418  // Use small-angle form.
4419 
4420  // Position and direction from state vector
4421  double x=S(state_x) + my_fdchits[id]->phiZ*S(state_y);
4422  double y=S(state_y) - my_fdchits[id]->phiZ*S(state_x);
4423  double tx = (S(state_tx) + my_fdchits[id]->phiZ*S(state_ty) - my_fdchits[id]->phiY) ;
4424  double ty = (S(state_ty) - my_fdchits[id]->phiZ*S(state_tx) + my_fdchits[id]->phiX) ;
4425 
4426  double cosa=my_fdchits[id]->cosa;
4427  double sina=my_fdchits[id]->sina;
4428  double u=my_fdchits[id]->uwire;
4429  double v=my_fdchits[id]->vstrip;
4430 
4431  // Projected position along the wire without doca-dependent corrections
4432  double vpred_uncorrected=x*sina+y*cosa;
4433 
4434  // Projected postion in the plane of the wires transverse to the wires
4435  double upred=x*cosa-y*sina;
4436 
4437  // Direction tangent in the u-z plane
4438  double tu=tx*cosa-ty*sina;
4439  double alpha=atan(tu);
4440  double cosalpha=cos(alpha);
4441  double cosalpha2=cosalpha*cosalpha;
4442  double sinalpha=sin(alpha);
4443 
4444  // (signed) distance of closest approach to wire
4445  double du=upred-u;
4446  double doca=du*cosalpha;
4447 
4448  // Correction for lorentz effect
4449  double nz=my_fdchits[id]->nz;
4450  double nr=my_fdchits[id]->nr;
4451  double nz_sinalpha_plus_nr_cosalpha=nz*sinalpha+nr*cosalpha;
4452 
4453  // Variance in coordinate along wire
4454  V(1,1)=my_fdchits[id]->vvar*fdc_anneal_factor;
4455 
4456  // Difference between measurement and projection
4457  double tv=tx*sina+ty*cosa;
4458  Mdiff(1)=v-(vpred_uncorrected+doca*(nz_sinalpha_plus_nr_cosalpha
4459  -tv*sinalpha
4460  ));
4461  Mdiff(0)=-doca;
4462 
4464  double drift_time=my_fdchits[id]->t-mT0
4466  //double drift=DRIFT_SPEED*drift_time*(du>0?1.:-1.);
4467  double drift=(du>0.0?1.:-1.)*fdc_drift_distance(drift_time,forward_traj[k].B);
4468 
4469  Mdiff(0)=drift-doca;
4470 
4471  // Variance in drift distance
4472  V(0,0)=fdc_drift_variance(drift_time)*fdc_anneal_factor;
4473  }
4474 
4475  // To transform from (x,y) to (u,v), need to do a rotation:
4476  // u = x*cosa-y*sina
4477  // v = y*cosa+x*sina
4478  double temp2=nz_sinalpha_plus_nr_cosalpha-tv*sinalpha;
4479  H_T(state_x,1)=sina+cosa*cosalpha*temp2;
4480  H_T(state_y,1)=cosa-sina*cosalpha*temp2;
4481 
4482  double cos2_minus_sin2=cosalpha2-sinalpha*sinalpha;
4483  double fac=nz*cos2_minus_sin2-2.*nr*cosalpha*sinalpha;
4484  double doca_cosalpha=doca*cosalpha;
4485  double temp=doca_cosalpha*fac;
4486  H_T(state_tx,1)=cosa*temp
4487  -doca_cosalpha*(tu*sina+tv*cosa*cos2_minus_sin2)
4488  ;
4489  H_T(state_ty,1)=-sina*temp
4490  -doca_cosalpha*(tu*cosa-tv*sina*cos2_minus_sin2)
4491  ;
4492 
4493  H_T(state_x,0)=cosa*cosalpha;
4494  H_T(state_y,0)=-sina*cosalpha;
4495  double one_plus_tu2=1.+tu*tu;
4496  double factor=du*tu/sqrt(one_plus_tu2)/one_plus_tu2;
4497  H_T(state_ty,0)=sina*factor;
4498  H_T(state_tx,0)=-cosa*factor;
4499 
4500  // Matrix transpose H_T -> H
4501  H=Transpose(H_T);
4502 
4503  // Check to see if we have multiple hits in the same plane
4504  if (!ALIGNMENT_FORWARD && forward_traj[k].num_hits>1){
4505  // If we do have multiple hits, then all of the hits within some
4506  // validation region are included with weights determined by how
4507  // close the hits are to the track projection of the state to the
4508  // "hit space".
4509  vector<DMatrix5x2> Klist;
4510  vector<DMatrix2x1> Mlist;
4511  vector<DMatrix2x5> Hlist;
4512  vector<DMatrix5x2> HTlist;
4513  vector<DMatrix2x2> Vlist;
4514  vector<double>probs;
4515  vector<unsigned int>used_ids;
4516 
4517  // Deal with the first hit:
4518  //double Vtemp=V+H*C*H_T;
4519  DMatrix2x2 Vtemp=V+H*C*H_T;
4520  InvV=Vtemp.Invert();
4521 
4522  //probability
4523  double chi2_hit=Vtemp.Chi2(Mdiff);
4524  double prob_hit=exp(-0.5*chi2_hit)
4525  /(M_TWO_PI*sqrt(Vtemp.Determinant()));
4526 
4527  if (DEBUG_LEVEL > 25) jout << " == There are multiple (" << forward_traj[k].num_hits << ") FDC hits" << endl;
4528 
4529  // Cut out outliers
4530  if (chi2_hit<fdc_chi2cut && my_fdchits[id]->status==good_hit){
4531  probs.push_back(prob_hit);
4532  Vlist.push_back(V);
4533  Hlist.push_back(H);
4534  HTlist.push_back(H_T);
4535  Mlist.push_back(Mdiff);
4536  Klist.push_back(C*H_T*InvV); // Kalman gain
4537 
4538  used_ids.push_back(id);
4539  fdc_used_in_fit[id]=true;
4540  }
4541 
4542  // loop over the remaining hits
4543  for (unsigned int m=1;m<forward_traj[k].num_hits;m++){
4544  unsigned int my_id=id-m;
4545  if (my_fdchits[my_id]->status==good_hit){
4546  u=my_fdchits[my_id]->uwire;
4547  v=my_fdchits[my_id]->vstrip;
4548 
4549  // Doca to this wire
4550  du=upred-u;
4551  doca=du*cosalpha;
4552 
4553  // variance for coordinate along the wire
4554  V(1,1)=my_fdchits[my_id]->vvar;
4555 
4556  // Difference between measurement and projection
4557  Mdiff(1)=v-(vpred_uncorrected+doca*(nz_sinalpha_plus_nr_cosalpha
4558  -tv*sinalpha
4559  ));
4560  Mdiff(0)=-doca;
4562  double drift_time=my_fdchits[id]->t-mT0
4564  //double drift=DRIFT_SPEED*drift_time*(du>0?1.:-1.);
4565  double drift=(du>0.0?1.:-1.)*fdc_drift_distance(drift_time,forward_traj[k].B);
4566 
4567  Mdiff(0)=drift-doca;
4568 
4569  // Variance in drift distance
4570  V(0,0)=fdc_drift_variance(drift_time);
4571 
4572  }
4573 
4574  // Update the terms in H/H_T that depend on the particular hit
4575  doca_cosalpha=doca*cosalpha;
4576  temp=doca_cosalpha*fac;
4577  H_T(state_tx,1)=cosa*temp
4578  -doca_cosalpha*(tu*sina+tv*cosa*cos2_minus_sin2)
4579  ;
4580  H_T(state_ty,1)=-sina*temp
4581  -doca_cosalpha*(tu*cosa-tv*sina*cos2_minus_sin2)
4582  ;
4583  factor=du*tu/sqrt(one_plus_tu2)/one_plus_tu2;
4584  H_T(state_ty,0)=sina*factor;
4585  H_T(state_tx,0)=-cosa*factor;
4586 
4587  // Matrix transpose H_T -> H
4588  H(1,state_tx)=H_T(state_tx,1);
4589  H(1,state_ty)=H_T(state_ty,1);
4590  H(0,state_ty)=H_T(state_ty,0);
4591  H(0,state_tx)=H_T(state_tx,0);
4592 
4593  // Calculate the kalman gain for this hit
4594  ///Vtemp=V+H*C*H_T;
4595  Vtemp=V+H*C*H_T;
4596  InvV=Vtemp.Invert();
4597 
4598  // probability
4599  double chi2_hit=Vtemp.Chi2(Mdiff);
4600  double prob_hit=exp(-0.5*chi2_hit)
4601  /(M_TWO_PI*sqrt(Vtemp.Determinant()));
4602 
4603  // Cut out outliers
4604  if(chi2_hit<fdc_chi2cut){
4605  probs.push_back(prob_hit);
4606  Mlist.push_back(Mdiff);
4607  Vlist.push_back(V);
4608  Hlist.push_back(H);
4609  HTlist.push_back(H_T);
4610  Klist.push_back(C*H_T*InvV);
4611 
4612  used_ids.push_back(my_id);
4613  fdc_used_in_fit[my_id]=true;
4614 
4615  }
4616  }
4617  }
4618  double prob_tot=1e-100;
4619  for (unsigned int m=0;m<probs.size();m++){
4620  prob_tot+=probs[m];
4621  }
4622 
4623  // Adjust the state vector and the covariance using the hit
4624  //information
4625  bool skip_plane=(my_fdchits[id]->hit->wire->layer==PLANE_TO_SKIP);
4626  if (skip_plane==false){
4628  DMatrix5x5 sum2;
4629  for (unsigned int m=0;m<Klist.size();m++){
4630  double my_prob=probs[m]/prob_tot;
4631  S+=my_prob*(Klist[m]*Mlist[m]);
4632  sum-=my_prob*(Klist[m]*Hlist[m]);
4633  sum2+=(my_prob*my_prob)*(Klist[m]*Vlist[m]*Transpose(Klist[m]));
4634 
4635  // Update chi2
4636  DMatrix2x2 HK=Hlist[m]*Klist[m];
4637  R=Mlist[m]-HK*Mlist[m];
4638  RC=Vlist[m]-HK*Vlist[m];
4639  chisq+=my_prob*RC.Chi2(R);
4640 
4641  unsigned int my_id=used_ids[m];
4642  fdc_updates[my_id].V=RC;
4643 
4644  if (DEBUG_LEVEL > 25) {
4645  jout << " Adjusting state vector for FDC hit " << m << " with prob " << my_prob << " S:" << endl;
4646  S.Print();
4647  }
4648  }
4649  // C=C.SandwichMultiply(sum)+sum2;
4650  C=sum2.AddSym(sum*C*sum.Transpose());
4651 
4652  if (DEBUG_LEVEL > 25) { jout << " C: " << endl; C.Print();}
4653  }
4654 
4655  for (unsigned int m=0;m<Hlist.size();m++){
4656  unsigned int my_id=used_ids[m];
4657  fdc_updates[my_id].S=S;
4658  fdc_updates[my_id].C=C;
4659  fdc_updates[my_id].tdrift
4661  fdc_updates[my_id].tcorr=fdc_updates[my_id].tdrift; // temporary!
4662  fdc_updates[my_id].doca=doca;
4663 
4664  if (skip_plane){
4665  fdc_updates[my_id].V=Vlist[m];
4666  }
4667  }
4668 
4669  // update number of degrees of freedom
4670  if (skip_plane==false){
4671  numdof+=2;
4672  }
4673  }
4674  else{
4675  if (DEBUG_LEVEL > 25) jout << " == There is a single FDC hit on this plane" << endl;
4676 
4677  // Variance for this hit
4678  DMatrix2x2 Vtemp=V+H*C*H_T;
4679  InvV=Vtemp.Invert();
4680 
4681  // Check if this hit is an outlier
4682  double chi2_hit=Vtemp.Chi2(Mdiff);
4683  if (chi2_hit<fdc_chi2cut){
4684  // Compute Kalman gain matrix
4685  K=C*H_T*InvV;
4686 
4687  bool skip_plane=(my_fdchits[id]->hit->wire->layer==PLANE_TO_SKIP);
4688  if (skip_plane==false){
4689  // Update the state vector
4690  S+=K*Mdiff;
4691 
4692  // Update state vector covariance matrix
4693  //C=C-K*(H*C);
4694  C=C.SubSym(K*(H*C));
4695 
4696  if (DEBUG_LEVEL > 25) {
4697  jout << "S Update: " << endl; S.Print();
4698  jout << "C Uodate: " << endl; C.Print();
4699  }
4700  }
4701 
4702  // Store the "improved" values for the state vector and covariance
4703  fdc_updates[id].S=S;
4704  fdc_updates[id].C=C;
4705  fdc_updates[id].tdrift
4707  fdc_updates[id].tcorr=fdc_updates[id].tdrift; // temporary!
4708  fdc_updates[id].doca=doca;
4709  fdc_used_in_fit[id]=true;
4710 
4711  if (skip_plane==false){
4712  // Filtered residual and covariance of filtered residual
4713  R=Mdiff-H*K*Mdiff;
4714  RC=V-H*(C*H_T);
4715 
4716  fdc_updates[id].V=RC;
4717 
4718  // Update chi2 for this segment
4719  chisq+=RC.Chi2(R);
4720 
4721  // update number of degrees of freedom
4722  numdof+=2;
4723 
4724 
4725  if (DEBUG_LEVEL>20)
4726  {
4727  printf("hit %d p %5.2f t %f dm %5.2f sig %f chi2 %5.2f z %5.2f\n",
4728  id,1./S(state_q_over_p),fdc_updates[id].tdrift,Mdiff(1),
4729  sqrt(V(1,1)),RC.Chi2(R),
4730  forward_traj[k].z);
4731 
4732  }
4733  }
4734  else{
4735  fdc_updates[id].V=V;
4736  }
4737 
4740  }
4741  }
4742  if (num_fdc_hits>=forward_traj[k].num_hits)
4743  num_fdc_hits-=forward_traj[k].num_hits;
4744  }
4745  }
4746  else if (more_cdc_measurements /* && z<endplate_z*/){
4747  // new wire position
4748  wirepos=origin;
4749  wirepos+=(z-z0w)*dir;
4750 
4751  // doca variables
4752  double dx=S(state_x)-wirepos.X();
4753  double dy=S(state_y)-wirepos.Y();
4754  double doca2=dx*dx+dy*dy;
4755 
4756  // Check if the doca is no longer decreasing
4757  if (doca2>old_doca2 /* && z<endplate_z */){
4758  if(my_cdchits[cdc_index]->status==good_hit){
4759  double newz=z;
4760 
4761  // energy loss
4762  double dedx=0.;
4763 
4764  // track direction variables
4765  double tx=S(state_tx);
4766  double ty=S(state_ty);
4767  double tanl=1./sqrt(tx*tx+ty*ty);
4768  double sinl=sin(atan(tanl));
4769 
4770  // Wire direction variables
4771  double ux=dir.X();
4772  double uy=dir.Y();
4773  // Variables relating wire direction and track direction
4774  double my_ux=tx-ux;
4775  double my_uy=ty-uy;
4776  double denom=my_ux*my_ux+my_uy*my_uy;
4777  double dz=0.;
4778 
4779 
4780  // variables for dealing with propagation of S and C if we
4781  // need to use Brent's algorithm to find the doca to the wire
4782  int num_steps=0;
4783  double dz3=0.;
4784  double my_dz=0.;
4785 
4786  // if the path length increment is small relative to the radius
4787  // of curvature, use a linear approximation to find dz
4788  bool do_brent=false;
4789  double step1=mStepSizeZ;
4790  double step2=mStepSizeZ;
4791  if (k>=2){
4792  step1=-forward_traj[k].z+forward_traj[k_minus_1].z;
4793  step2=-forward_traj[k_minus_1].z+forward_traj[k-2].z;
4794  }
4795  //printf("step1 %f step 2 %f \n",step1,step2);
4796  double two_step=step1+step2;
4797  if (fabs(qBr2p*S(state_q_over_p)
4798  *bfield->GetBz(S(state_x),S(state_y),z)
4799  *two_step/sinl)<0.05
4800  && denom>EPS)
4801  {
4802  double dzw=z-z0w;
4803  dz=-((S(state_x)-origin.X()-ux*dzw)*my_ux
4804  +(S(state_y)-origin.Y()-uy*dzw)*my_uy)/denom;
4805 
4806  if (fabs(dz)>two_step || dz<0){
4807  do_brent=true;
4808  }
4809  else{
4810  newz=z+dz;
4811  // Check for exiting the straw
4812  if (newz>endplate_z){
4813  dz=endplate_z-z;
4814  }
4815  }
4816  }
4817  else do_brent=true;
4818  if (do_brent){
4819  if (CORRECT_FOR_ELOSS){
4820  dedx=GetdEdx(S(state_q_over_p),
4821  forward_traj[k].K_rho_Z_over_A,
4822  forward_traj[k].rho_Z_over_A,
4823  forward_traj[k].LnI,forward_traj[k].Z);
4824  }
4825 
4826  // We have bracketed the minimum doca: use Brent's agorithm
4827  if (BrentForward(z,dedx,z0w,origin,dir,S,dz)!=NOERROR){
4828  break_point_fdc_index=(3*num_fdc)/4;
4829  return MOMENTUM_OUT_OF_RANGE;
4830  }
4831 
4832  // Step the state and covariance through the field
4833  if (fabs(dz)>mStepSizeZ){
4834  my_dz=(dz>0?1.0:-1.)*mStepSizeZ;
4835  num_steps=int(fabs(dz/my_dz));
4836  dz3=dz-num_steps*my_dz;
4837 
4838  double my_z=z;
4839  for (int m=0;m<num_steps;m++){
4840  newz=my_z+my_dz;
4841 
4842  // Step current state by my_dz
4843  //Step(z,newz,dedx,S);
4844 
4845  // propagate error matrix to z-position of hit
4846  StepJacobian(my_z,newz,S0,dedx,J);
4847  C=J*C*J.Transpose();
4848  //C=C.SandwichMultiply(J);
4849 
4850  // Step reference trajectory by my_dz
4851  Step(my_z,newz,dedx,S0);
4852 
4853  my_z=newz;
4854  }
4855 
4856  newz=my_z+dz3;
4857 
4858  // Step current state by dz3
4859  //Step(my_z,newz,dedx,S);
4860 
4861  // propagate error matrix to z-position of hit
4862  StepJacobian(my_z,newz,S0,dedx,J);
4863  C=J*C*J.Transpose();
4864  //C=C.SandwichMultiply(J);
4865 
4866  // Step reference trajectory by dz3
4867  Step(my_z,newz,dedx,S0);
4868  }
4869  else{
4870  newz = z + dz;
4871 
4872  // Step current state by dz
4873  //Step(z,newz,dedx,S);
4874 
4875  // propagate error matrix to z-position of hit
4876  StepJacobian(z,newz,S0,dedx,J);
4877  C=J*C*J.Transpose();
4878  //C=C.SandwichMultiply(J);
4879 
4880  // Step reference trajectory by dz
4881  Step(z,newz,dedx,S0);
4882  }
4883  }
4884 
4885  // Wire position at current z
4886  wirepos=origin;
4887  wirepos+=(newz-z0w)*dir;
4888 
4889  double xw=wirepos.X();
4890  double yw=wirepos.Y();
4891 
4892  // predicted doca taking into account the orientation of the wire
4893  if (do_brent==false){
4894  // In this case we did not have to swim to find the doca and
4895  // the transformation from the state vector space to the
4896  // measurement space is straight-forward.
4897  dy=S(state_y)+S(state_ty)*dz-yw;
4898  dx=S(state_x)+S(state_tx)*dz-xw;
4899  }
4900  else{
4901  // In this case we swam the state vector to the position of
4902  // the doca
4903  dy=S(state_y)-yw;
4904  dx=S(state_x)-xw;
4905  }
4906  double cosstereo=my_cdchits[cdc_index]->cosstereo;
4907  double d=sqrt(dx*dx+dy*dy)*cosstereo+EPS;
4908 
4909  // Track projection
4910  double cosstereo2_over_d=cosstereo*cosstereo/d;
4911  Hc_T(state_x)=dx*cosstereo2_over_d;
4912  Hc(state_x)=Hc_T(state_x);
4913  Hc_T(state_y)=dy*cosstereo2_over_d;
4914  Hc(state_y)=Hc_T(state_y);
4915  if (do_brent==false){
4916  Hc_T(state_ty)=Hc_T(state_y)*dz;
4917  Hc(state_ty)=Hc_T(state_ty);
4918  Hc_T(state_tx)=Hc_T(state_x)*dz;
4919  Hc(state_tx)=Hc_T(state_tx);
4920  }
4921  else{
4922  Hc_T(state_ty)=0.;
4923  Hc(state_ty)=0.;
4924  Hc_T(state_tx)=0.;
4925  Hc(state_tx)=0.;
4926  }
4927 
4928  //H.Print();
4929 
4930  // The next measurement
4931  double dm=0.39,tdrift=0.,tcorr=0.,dDdt0=0.;
4932  if (fit_type==kTimeBased)
4933  {
4934  // Find offset of wire with respect to the center of the
4935  // straw at this z position
4936  const DCDCWire *mywire=my_cdchits[cdc_index]->hit->wire;
4937  int ring_index=mywire->ring-1;
4938  int straw_index=mywire->straw-1;
4939  double dz=newz-z0w;
4940  double phi_d=atan2(dy,dx);
4941  double delta
4942  =max_sag[ring_index][straw_index]*(1.-dz*dz/5625.)
4943  *cos(phi_d + sag_phi_offset[ring_index][straw_index]);
4944  double dphi=phi_d-mywire->origin.Phi();
4945  while (dphi>M_PI) dphi-=2*M_PI;
4946  while (dphi<-M_PI) dphi+=2*M_PI;
4947  if (mywire->origin.Y()<0) dphi*=-1.;
4948 
4949  tdrift=my_cdchits[cdc_index]->tdrift-mT0
4950  -forward_traj[k_minus_1].t*TIME_UNIT_CONVERSION;
4951  double B=forward_traj[k_minus_1].B;
4952  ComputeCDCDrift(dphi,delta,tdrift,B,dm,Vc,tcorr);
4953  Vc*=cdc_anneal_factor;
4954  if (ALIGNMENT_FORWARD){
4955  double myV=0.;
4956  double mytcorr=0.;
4957  double d_shifted;
4958  double dt=5.0;
4959  // Dont compute this for negative drift times
4960  if (tdrift < 0.) d_shifted = dm;
4961  else ComputeCDCDrift(dphi,delta,tdrift+dt,B,d_shifted,myV,mytcorr);
4962  dDdt0=(d_shifted-dm)/dt;
4963  }
4964 
4965  if (max_num_fdc_used_in_fit>4)
4966  {
4967  Vc*=CDC_VAR_SCALE_FACTOR; //de-weight CDC hits
4968  }
4969  //_DBG_ << "t " << tdrift << " d " << d << " delta " << delta << " dphi " << atan2(dy,dx)-mywire->origin.Phi() << endl;
4970 
4971  //_DBG_ << tcorr << " " << dphi << " " << dm << endl;
4972  }
4973 
4974  // Residual
4975  double res=dm-d;
4976 
4977  // inverse variance including prediction
4978  //double InvV1=1./(Vc+H*(C*H_T));
4979  //double Vproj=C.SandwichMultiply(Hc_T);
4980  double Vproj=Hc*C*Hc_T;
4981  double InvV1=1./(Vc+Vproj);
4982  if (InvV1<0.){
4983  if (DEBUG_LEVEL>0)
4984  _DBG_ << "Negative variance???" << endl;
4985  return NEGATIVE_VARIANCE;
4986  }
4987 
4988  // Check if this hit is an outlier
4989  double chi2_hit=res*res*InvV1;
4990  if (chi2_hit<cdc_chi2cut){
4991  // Compute KalmanSIMD gain matrix
4992  Kc=InvV1*(C*Hc_T);
4993 
4994 
4995  // Update state vector covariance matrix
4996  //C=C-K*(H*C);
4997  Ctest=C.SubSym(Kc*(Hc*C));
4998  //Ctest=C.SandwichMultiply(I5x5-K*H)+Vc*MultiplyTranspose(K);
4999  // Check that Ctest is positive definite
5000  if (!Ctest.IsPosDef()){
5001  if (DEBUG_LEVEL>0) _DBG_ << "Broken covariance matrix!" <<endl;
5002  return BROKEN_COVARIANCE_MATRIX;
5003  }
5004  bool skip_ring
5005  =(my_cdchits[cdc_index]->hit->wire->ring==RING_TO_SKIP);
5006  // update covariance matrix and state vector
5007  if (my_cdchits[cdc_index]->hit->wire->ring!=RING_TO_SKIP && tdrift >= CDC_T_DRIFT_MIN){
5008  C=Ctest;
5009  S+=res*Kc;
5010 
5011  if (DEBUG_LEVEL > 25) {
5012  jout << " == Adding CDC Hit in Ring " << my_cdchits[cdc_index]->hit->wire->ring << endl;
5013  jout << " New S: " << endl; S.Print();
5014  jout << " New C: " << endl; C.Print();
5015  }
5016  }
5017 
5018  // Flag the place along the reference trajectory with hit id
5019  forward_traj[k].h_id=1000+cdc_index;
5020 
5021  // Store updated info related to this hit
5022  double scale=(skip_ring)?1.:(1.-Hc*Kc);
5023  cdc_updates[cdc_index].tdrift=tdrift;
5024  cdc_updates[cdc_index].tcorr=tcorr;
5025  cdc_updates[cdc_index].variance=Vc;
5026  cdc_updates[cdc_index].doca=dm;
5027  cdc_updates[cdc_index].dDdt0=dDdt0;
5028  cdc_used_in_fit[cdc_index]=true;
5029  if(tdrift < CDC_T_DRIFT_MIN){
5030  //_DBG_ << tdrift << endl;
5031  cdc_used_in_fit[cdc_index]=false;
5032  }
5033 
5034  // Update chi2 and number of degrees of freedom for this hit
5035  if (skip_ring==false && tdrift >= CDC_T_DRIFT_MIN){
5036  chisq+=scale*res*res/Vc;
5037  numdof++;
5038  }
5039 
5040  if (DEBUG_LEVEL>10)
5041  jout << "Ring " << my_cdchits[cdc_index]->hit->wire->ring
5042  << " Straw " << my_cdchits[cdc_index]->hit->wire->straw
5043  << " Pred " << d << " Meas " << dm
5044  << " Sigma meas " << sqrt(Vc)
5045  << " t " << tcorr
5046  << " Chi2 " << (1.-Hc*Kc)*res*res/Vc << endl;
5047 
5048  break_point_cdc_index=cdc_index;
5049  break_point_step_index=k_minus_1;
5050 
5051  }
5052 
5053  // If we had to use Brent's algorithm to find the true doca,
5054  // we need to swim the state vector and covariance matrix back to
5055  // the appropriate position along the reference trajectory.
5056  if (do_brent){
5057  if (num_steps==0){
5058  // Step C back to the z-position on the reference trajectory
5059  StepJacobian(newz,z,S0,dedx,J);
5060  C=J*C*J.Transpose();
5061  //C=C.SandwichMultiply(J);
5062 
5063  // Step S to current position on the reference trajectory
5064  Step(newz,z,dedx,S);
5065 
5066  // Step S0 to current position on the reference trajectory
5067  Step(newz,z,dedx,S0);
5068  }
5069  else{
5070  double my_z=newz;
5071  for (int m=0;m<num_steps;m++){
5072  z=my_z-my_dz;
5073 
5074  // Step C along z
5075  StepJacobian(my_z,z,S0,dedx,J);
5076  C=J*C*J.Transpose();
5077  //C=C.SandwichMultiply(J);
5078 
5079  // Step S along z
5080  Step(my_z,z,dedx,S);
5081 
5082  // Step S0 along z
5083  Step(my_z,z,dedx,S0);
5084 
5085  my_z=z;
5086  }
5087  z=my_z-dz3;
5088 
5089  // Step C back to the z-position on the reference trajectory
5090  StepJacobian(my_z,z,S0,dedx,J);
5091  C=J*C*J.Transpose();
5092  //C=C.SandwichMultiply(J);
5093 
5094  // Step S to current position on the reference trajectory
5095  Step(my_z,z,dedx,S);
5096 
5097  // Step S to current position on the reference trajectory
5098  Step(my_z,z,dedx,S0);
5099  }
5100  }
5101  cdc_updates[cdc_index].S=S;
5102  cdc_updates[cdc_index].C=C;
5103  }
5104 
5105  // new wire origin and direction
5106  if (cdc_index>0){
5107  cdc_index--;
5108  origin=my_cdchits[cdc_index]->origin;
5109  z0w=my_cdchits[cdc_index]->z0wire;
5110  dir=my_cdchits[cdc_index]->dir;
5111  }
5112  else more_cdc_measurements=false;
5113 
5114  // Update the wire position
5115  wirepos=origin+(z-z0w)*dir;
5116 
5117  // new doca
5118  dx=S(state_x)-wirepos.X();
5119  dy=S(state_y)-wirepos.Y();
5120  doca2=dx*dx+dy*dy;
5121  }
5122  old_doca2=doca2;
5123  }
5124  }
5125  // Save final z position
5126  z_=forward_traj[forward_traj.size()-1].z;
5127 
5128  // The following code segment addes a fake point at a well-defined z position
5129  // that would correspond to a thin foil target. It should not be turned on
5130  // for an extended target.
5131  if (ADD_VERTEX_POINT){
5132  double dz_to_target=TARGET_Z-z_;
5133  double my_dz=mStepSizeZ*(dz_to_target>0?1.:-1.);
5134  int num_steps=int(fabs(dz_to_target/my_dz));
5135 
5136  for (int k=0;k<num_steps;k++){
5137  double newz=z_+my_dz;
5138  // Step C along z
5139  StepJacobian(z_,newz,S,0.,J);
5140  C=J*C*J.Transpose();
5141  //C=C.SandwichMultiply(J);
5142 
5143  // Step S along z
5144  Step(z_,newz,0.,S);
5145 
5146  z_=newz;
5147  }
5148 
5149  // Step C along z
5150  StepJacobian(z_,TARGET_Z,S,0.,J);
5151  C=J*C*J.Transpose();
5152  //C=C.SandwichMultiply(J);
5153 
5154  // Step S along z
5155  Step(z_,TARGET_Z,0.,S);
5156 
5157  z_=TARGET_Z;
5158 
5159  // predicted doca taking into account the orientation of the wire
5160  double dy=S(state_y);
5161  double dx=S(state_x);
5162  double d=sqrt(dx*dx+dy*dy);
5163 
5164  // Track projection
5165  double one_over_d=1./d;
5166  Hc_T(state_x)=dx*one_over_d;
5167  Hc(state_x)=Hc_T(state_x);
5168  Hc_T(state_y)=dy*one_over_d;
5169  Hc(state_y)=Hc_T(state_y);
5170 
5171  // Variance of target point
5172  // Variance is for average beam spot size assuming triangular distribution
5173  // out to 2.2 mm from the beam line.
5174  // sigma_r = 2.2 mm/ sqrt(18)
5175  Vc=0.002689;
5176 
5177  // inverse variance including prediction
5178  double InvV1=1./(Vc+Hc*(C*Hc_T));
5179  //double InvV1=1./(Vc+C.SandwichMultiply(H_T));
5180  if (InvV1<0.){
5181  if (DEBUG_LEVEL>0)
5182  _DBG_ << "Negative variance???" << endl;
5183  return NEGATIVE_VARIANCE;
5184  }
5185  // Compute KalmanSIMD gain matrix
5186  Kc=InvV1*(C*Hc_T);
5187 
5188  // Update the state vector with the target point
5189  // "Measurement" is average of expected beam spot size
5190  double res=0.1466666667-d;
5191  S+=res*Kc;
5192  // Update state vector covariance matrix
5193  //C=C-K*(H*C);
5194  C=C.SubSym(Kc*(Hc*C));
5195 
5196  // Update chi2 for this segment
5197  chisq+=(1.-Hc*Kc)*res*res/Vc;
5198  numdof++;
5199  }
5200 
5201  // Check that there were enough hits to make this a valid fit
5202  if (numdof<6){
5203  chisq=-1.;
5204  numdof=0;
5205 
5206  if (num_cdc==0){
5207  unsigned int new_index=(3*num_fdc)/4;
5208  break_point_fdc_index=(new_index>=MIN_HITS_FOR_REFIT)?new_index:(MIN_HITS_FOR_REFIT-1);
5209  }
5210  else{
5211  unsigned int new_index=(3*num_fdc)/4;
5212  if (new_index+num_cdc>=MIN_HITS_FOR_REFIT){
5213  break_point_fdc_index=new_index;
5214  }
5215  else{
5217  }
5218  }
5219  return PRUNED_TOO_MANY_HITS;
5220  }
5221 
5222  // chisq*=anneal_factor;
5223  numdof-=5;
5224 
5225  // Final positions in x and y for this leg
5226  x_=S(state_x);
5227  y_=S(state_y);
5228 
5229  if (DEBUG_LEVEL>1){
5230  cout << "Position after forward filter: " << x_ << ", " << y_ << ", " << z_ <<endl;
5231  cout << "Momentum " << 1./S(state_q_over_p) <<endl;
5232  }
5233 
5234  if (!S.IsFinite()) return FIT_FAILED;
5235 
5236  // Check if we have a kink in the track or threw away too many hits
5237  if (num_cdc>0 && break_point_fdc_index>0 && break_point_cdc_index>2){
5239  //_DBG_ << endl;
5240  unsigned int new_index=(3*num_fdc)/4;
5241  if (new_index+num_cdc>=MIN_HITS_FOR_REFIT){
5242  break_point_fdc_index=new_index;
5243  }
5244  else{
5246  }
5247  }
5248  return BREAK_POINT_FOUND;
5249  }
5250  if (num_cdc==0 && break_point_fdc_index>2){
5251  //_DBG_ << endl;
5252  if (break_point_fdc_index<num_fdc/2){
5253  break_point_fdc_index=(3*num_fdc)/4;
5254  }
5257  }
5258  return BREAK_POINT_FOUND;
5259  }
5260  if (num_cdc>5 && break_point_cdc_index>2){
5261  //_DBG_ << endl;
5262  unsigned int new_index=3*(num_fdc)/4;
5263  if (new_index+num_cdc>=MIN_HITS_FOR_REFIT){
5264  break_point_fdc_index=new_index;
5265  }
5266  else{
5268  }
5269  return BREAK_POINT_FOUND;
5270  }
5271  unsigned int num_good=0;
5272  unsigned int num_hits=num_cdc+max_num_fdc_used_in_fit;
5273  for (unsigned int j=0;j<num_cdc;j++){
5274  if (cdc_used_in_fit[j]) num_good++;
5275  }
5276  for (unsigned int j=0;j<num_fdc;j++){
5277  if (fdc_used_in_fit[j]) num_good++;
5278  }
5279  if (double(num_good)/double(num_hits)<MINIMUM_HIT_FRACTION){
5280  //_DBG_ <<endl;
5281  if (num_cdc==0){
5282  unsigned int new_index=(3*num_fdc)/4;
5283  break_point_fdc_index=(new_index>=MIN_HITS_FOR_REFIT)?new_index:(MIN_HITS_FOR_REFIT-1);
5284  }
5285  else{
5286  unsigned int new_index=(3*num_fdc)/4;
5287  if (new_index+num_cdc>=MIN_HITS_FOR_REFIT){
5288  break_point_fdc_index=new_index;
5289  }
5290  else{
5292  }
5293  }
5294  return PRUNED_TOO_MANY_HITS;
5295  }
5296 
5297  return FIT_SUCCEEDED;
5298 
5299 
5300 }
5301 
5302 
5303 
5304 // Kalman engine for forward tracks -- this routine adds CDC hits
5306  DMatrix5x1 &S,
5307  DMatrix5x5 &C,
5308  double &chisq,
5309  unsigned int &numdof){
5310  DMatrix1x5 H; // Track projection matrix
5311  DMatrix5x1 H_T; // Transpose of track projection matrix
5312  DMatrix5x5 J; // State vector Jacobian matrix
5313  //DMatrix5x5 J_T; // transpose of this matrix
5314  DMatrix5x5 Q; // Process noise covariance matrix
5315  DMatrix5x1 K; // KalmanSIMD gain matrix
5316  DMatrix5x1 S0,S0_,Stest; //State vector
5317  DMatrix5x5 Ctest; // covariance matrix
5318  //DMatrix5x1 dS; // perturbation in state vector
5319  double V=0.0507;
5320 
5321  // set used_in_fit flags to false for cdc hits
5322  unsigned int num_cdc=cdc_used_in_fit.size();
5323  for (unsigned int i=0;i<num_cdc;i++) cdc_used_in_fit[i]=false;
5324  for (unsigned int i=0;i<forward_traj.size();i++){
5325  forward_traj[i].h_id=0;
5326  }
5327 
5328  // initialize chi2 info
5329  chisq=0.;
5330  numdof=0;
5331 
5332  double chi2cut=NUM_CDC_SIGMA_CUT*NUM_CDC_SIGMA_CUT;
5333 
5334  // Save the starting values for C and S in the deque
5337 
5338  // z-position
5340 
5341  // Step size variables
5342  double step1=mStepSizeZ;
5343  double step2=mStepSizeZ;
5344 
5345  // wire information
5346  unsigned int cdc_index=break_point_cdc_index;
5347  if (cdc_index<num_cdc-1){
5348  num_cdc=cdc_index+1;
5349  }
5350 
5351  if (num_cdc<MIN_HITS_FOR_REFIT) chi2cut=BIG;
5352 
5353  DVector2 origin=my_cdchits[cdc_index]->origin;
5354  double z0w=my_cdchits[cdc_index]->z0wire;
5355  DVector2 dir=my_cdchits[cdc_index]->dir;
5356  DVector2 wirepos=origin+(z-z0w)*dir;
5357  bool more_measurements=true;
5358 
5359  // doca variables
5360  double dx=S(state_x)-wirepos.X();
5361  double dy=S(state_y)-wirepos.Y();
5362  double doca2=0.,old_doca2=dx*dx+dy*dy;
5363 
5364  // loop over entries in the trajectory
5366  for (unsigned int k=break_point_step_index+1;k<forward_traj.size()/*-1*/;k++){
5367  unsigned int k_minus_1=k-1;
5368 
5369  // Check that C matrix is positive definite
5370  if (!C.IsPosDef()){
5371  if (DEBUG_LEVEL>0) _DBG_ << "Broken covariance matrix!" <<endl;
5372  return BROKEN_COVARIANCE_MATRIX;
5373  }
5374 
5375  z=forward_traj[k].z;
5376 
5377  // Get the state vector, jacobian matrix, and multiple scattering matrix
5378  // from reference trajectory
5379  S0=(forward_traj[k].S);
5380  J=(forward_traj[k].J);
5381  Q=(forward_traj[k].Q);
5382 
5383  // State S is perturbation about a seed S0
5384  //dS=S-S0_;
5385  /*
5386  dS.Print();
5387  J.Print();
5388  */
5389 
5390  // Update the actual state vector and covariance matrix
5391  S=S0+J*(S-S0_);
5392 
5393  // Bail if the position is grossly outside of the tracking volume
5394  if (S(state_x)*S(state_x)+S(state_y)*S(state_y)>R2_MAX){
5395  if (DEBUG_LEVEL>2)
5396  {
5397  _DBG_<< "Went outside of tracking volume at x=" << S(state_x)
5398  << " y=" << S(state_y) <<" z="<<z<<endl;
5399  }
5400  return POSITION_OUT_OF_RANGE;
5401  }
5402  // Bail if the momentum has dropped below some minimum
5403  if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX){
5404  if (DEBUG_LEVEL>2)
5405  {
5406  _DBG_ << "Bailing: P = " << 1./fabs(S(state_q_over_p)) << endl;
5407  }
5408  return MOMENTUM_OUT_OF_RANGE;
5409  }
5410 
5411 
5412 
5413  //C=J*(C*J_T)+Q;
5414  C=Q.AddSym(J*C*J.Transpose());
5415  //C=Q.AddSym(C.SandwichMultiply(J));
5416 
5417  // Save the current state of the reference trajectory
5418  S0_=S0;
5419 
5420  // new wire position
5421  wirepos=origin;
5422  wirepos+=(z-z0w)*dir;
5423 
5424  // new doca
5425  dx=S(state_x)-wirepos.X();
5426  dy=S(state_y)-wirepos.Y();
5427  doca2=dx*dx+dy*dy;
5428 
5429  // Save the current state and covariance matrix in the deque
5430  if (fit_type==kTimeBased){
5431  forward_traj[k].Skk=S;
5432  forward_traj[k].Ckk=C;
5433  }
5434 
5435  // Check if the doca is no longer decreasing
5436  if (more_measurements && doca2>old_doca2 && z<endplate_z_downstream){
5437  if (my_cdchits[cdc_index]->status==good_hit){
5438  double dz=0.,newz=z;
5439 
5440  // energy loss
5441  double dedx=0.;
5442 
5443  // Last 2 step sizes
5444  if (k>=2){
5445  double z1=forward_traj[k_minus_1].z;
5446  step1=-forward_traj[k].z+z1;
5447  step2=-z1+forward_traj[k-2].z;
5448  }
5449 
5450  // Track direction variables
5451  double tx=S(state_tx);
5452  double ty=S(state_ty);
5453  double tanl=1./sqrt(tx*tx+ty*ty);
5454  double sinl=sin(atan(tanl));
5455 
5456  // Wire direction variables
5457  double ux=dir.X();
5458  double uy=dir.Y();
5459  // Variables relating wire direction and track direction
5460  double my_ux=tx-ux;
5461  double my_uy=ty-uy;
5462  double denom=my_ux*my_ux+my_uy*my_uy;
5463 
5464  // variables for dealing with propagation of S and C if we
5465  // need to use Brent's algorithm to find the doca to the wire
5466  int num_steps=0;
5467  double dz3=0.;
5468  double my_dz=0.;
5469 
5470  // if the path length increment is small relative to the radius
5471  // of curvature, use a linear approximation to find dz
5472  bool do_brent=false;
5473  //printf("step1 %f step 2 %f \n",step1,step2);
5474  double two_step=step1+step2;
5475  if (fabs(qBr2p*S(state_q_over_p)
5476  //*bfield->GetBz(S(state_x),S(state_y),z)
5477  *forward_traj[k].B
5478  *two_step/sinl)<0.05
5479  && denom>EPS){
5480  double dzw=z-z0w;
5481  dz=-((S(state_x)-origin.X()-ux*dzw)*my_ux
5482  +(S(state_y)-origin.Y()-uy*dzw)*my_uy)/denom;
5483 
5484  if (fabs(dz)>two_step || dz<0.0){
5485  do_brent=true;
5486  }
5487  else{
5488  newz=z+dz;
5489  // Check for exiting the straw
5490  if (newz>endplate_z){
5491  dz=endplate_z-z;
5492  }
5493  }
5494  }
5495  else{
5496  do_brent=true;
5497  }
5498  if (do_brent){
5499  if (CORRECT_FOR_ELOSS){
5500  dedx=GetdEdx(S(state_q_over_p),
5501  forward_traj[k].K_rho_Z_over_A,
5502  forward_traj[k].rho_Z_over_A,
5503  forward_traj[k].LnI,forward_traj[k].Z);
5504  }
5505 
5506  // We have bracketed the minimum doca: use Brent's agorithm
5507  if (BrentForward(z,dedx,z0w,origin,dir,S,dz)
5508  !=NOERROR){
5509  return MOMENTUM_OUT_OF_RANGE;
5510  }
5511 
5512  // Step the state and covariance through the field
5513  if (fabs(dz)>mStepSizeZ){
5514  my_dz=(dz>0.0?1.0:-1.)*mStepSizeZ;
5515  num_steps=int(fabs(dz/my_dz));
5516  dz3=dz-num_steps*my_dz;
5517 
5518  double my_z=z;
5519  for (int m=0;m<num_steps;m++){
5520  newz=my_z+my_dz;
5521 
5522  // Step current state by my_dz
5523  // Step(z,newz,dedx,S);
5524 
5525  // propagate error matrix to z-position of hit
5526  StepJacobian(my_z,newz,S0,dedx,J);
5527  C=J*C*J.Transpose();
5528  //C=C.SandwichMultiply(J);
5529 
5530  // Step reference trajectory by my_dz
5531  Step(my_z,newz,dedx,S0);
5532 
5533  my_z=newz;
5534  }
5535 
5536  newz=my_z+dz3;
5537 
5538  // Step current state by dz3
5539  //Step(my_z,newz,dedx,S);
5540 
5541  // propagate error matrix to z-position of hit
5542  StepJacobian(my_z,newz,S0,dedx,J);
5543  C=J*C*J.Transpose();
5544  //C=C.SandwichMultiply(J);
5545 
5546  // Step reference trajectory by dz3
5547  Step(my_z,newz,dedx,S0);
5548  }
5549  else{
5550  newz = z + dz;
5551  // Step current state by dz
5552  //Step(z,newz,dedx,S);
5553 
5554  // propagate error matrix to z-position of hit
5555  StepJacobian(z,newz,S0,dedx,J);
5556  C=J*C*J.Transpose();
5557  //C=C.SandwichMultiply(J);
5558 
5559  // Step reference trajectory by dz
5560  Step(z,newz,dedx,S0);
5561  }
5562  }
5563 
5564  // Wire position at current z
5565  wirepos=origin;
5566  wirepos+=(newz-z0w)*dir;
5567 
5568  double xw=wirepos.X();
5569  double yw=wirepos.Y();
5570 
5571  // predicted doca taking into account the orientation of the wire
5572  if (do_brent==false){
5573  // In this case we did not have to swim to find the doca and
5574  // the transformation from the state vector space to the
5575  // measurement space is straight-forward.
5576  dy=S(state_y)+S(state_ty)*dz-yw;
5577  dx=S(state_x)+S(state_tx)*dz-xw;
5578  }
5579  else{
5580  // In this case we swam the state vector to the position of
5581  // the doca
5582  dy=S(state_y)-yw;
5583  dx=S(state_x)-xw;
5584  }
5585  double cosstereo=my_cdchits[cdc_index]->cosstereo;
5586  double d=sqrt(dx*dx+dy*dy)*cosstereo+EPS;
5587 
5588  //printf("z %f d %f z-1 %f\n",newz,d,forward_traj[k_minus_1].z);
5589 
5590  // Track projection
5591  double cosstereo2_over_d=cosstereo*cosstereo/d;
5592  H_T(state_x)=dx*cosstereo2_over_d;
5593  H(state_x)=H_T(state_x);
5594  H_T(state_y)=dy*cosstereo2_over_d;
5595  H(state_y)=H_T(state_y);
5596  if (do_brent==false){
5597  H_T(state_ty)=H_T(state_y)*dz;
5598  H(state_ty)=H_T(state_ty);
5599  H_T(state_tx)=H_T(state_x)*dz;
5600  H(state_tx)=H_T(state_tx);
5601  }
5602  else{
5603  H_T(state_ty)=0.;
5604  H(state_ty)=0.;
5605  H_T(state_tx)=0.;
5606  H(state_tx)=0.;
5607  }
5608 
5609  //H.Print();
5610 
5611  // The next measurement
5612  double dm=0.39,tdrift=0.,tcorr=0.,dDdt0=0.;
5614  // Find offset of wire with respect to the center of the
5615  // straw at this z position
5616  const DCDCWire *mywire=my_cdchits[cdc_index]->hit->wire;
5617  int ring_index=mywire->ring-1;
5618  int straw_index=mywire->straw-1;
5619  double dz=newz-z0w;
5620  double phi_d=atan2(dy,dx);
5621  double delta
5622  =max_sag[ring_index][straw_index]*(1.-dz*dz/5625.)
5623  *cos(phi_d + sag_phi_offset[ring_index][straw_index]);
5624  double dphi=phi_d-mywire->origin.Phi();
5625  while (dphi>M_PI) dphi-=2*M_PI;
5626  while (dphi<-M_PI) dphi+=2*M_PI;
5627  if (mywire->origin.Y()<0) dphi*=-1.;
5628 
5629  tdrift=my_cdchits[cdc_index]->tdrift-mT0
5630  -forward_traj[k_minus_1].t*TIME_UNIT_CONVERSION;
5631  double B=forward_traj[k_minus_1].B;
5632  ComputeCDCDrift(dphi,delta,tdrift,B,dm,V,tcorr);
5633  V*=anneal;
5634  if (ALIGNMENT_FORWARD){
5635  double myV=0.;
5636  double mytcorr=0.;
5637  double d_shifted;
5638  double dt=2.0;
5639  if (tdrift < 0.) d_shifted = dm;
5640  else ComputeCDCDrift(dphi,delta,tdrift+dt,B,d_shifted,myV,mytcorr);
5641  dDdt0=(d_shifted-dm)/dt;
5642  }
5643  //_DBG_ << tcorr << " " << dphi << " " << dm << endl;
5644 
5645  }
5646  // residual
5647  double res=dm-d;
5648 
5649  // inverse of variance including prediction
5650  //InvV=1./(V+H*(C*H_T));
5651  //double Vproj=C.SandwichMultiply(H_T);
5652  double Vproj=H*C*H_T;
5653  double InvV=1./(V+Vproj);
5654  if (InvV<0.){
5655  if (DEBUG_LEVEL>0)
5656  _DBG_ << "Negative variance???" << endl;
5657  break_point_cdc_index=(3*num_cdc)/4;
5658  return NEGATIVE_VARIANCE;
5659  }
5660 
5661  // Check how far this hit is from the expected position
5662  double chi2check=res*res*InvV;
5663  if (chi2check<chi2cut/*&&dm>0.*/)
5664  {
5665  // Compute KalmanSIMD gain matrix
5666  K=InvV*(C*H_T);
5667 
5668  // Update state vector covariance matrix
5669  Ctest=C.SubSym(K*(H*C));
5670  // Joseph form
5671  // C = (I-KH)C(I-KH)^T + KVK^T
5672  //Ctest=C.SandwichMultiply(I5x5-K*H)+V*MultiplyTranspose(K);
5673  // Check that Ctest is positive definite
5674  if (!Ctest.IsPosDef()){
5675  if (DEBUG_LEVEL>0) _DBG_ << "Broken covariance matrix!" <<endl;
5676  return BROKEN_COVARIANCE_MATRIX;
5677  }
5678 
5679  bool skip_ring
5680  =(my_cdchits[cdc_index]->hit->wire->ring==RING_TO_SKIP);
5681  // update covariance matrix and state vector
5682  if (skip_ring==false && tdrift >= CDC_T_DRIFT_MIN){
5683  C=Ctest;
5684  S+=res*K;
5685  }
5686  // Mark point on ref trajectory with a hit id for the straw
5687  forward_traj[k].h_id=cdc_index+1000;
5688 
5689  // Store some updated values related to the hit
5690  double scale=(skip_ring)?1.:(1.-H*K);
5691  cdc_updates[cdc_index].tcorr=tcorr;
5692  cdc_updates[cdc_index].tdrift=tdrift;
5693  cdc_updates[cdc_index].doca=dm;
5694  cdc_updates[cdc_index].variance=V;
5695  cdc_updates[cdc_index].dDdt0=dDdt0;
5696  cdc_used_in_fit[cdc_index]=true;
5697  if(tdrift < CDC_T_DRIFT_MIN) cdc_used_in_fit[cdc_index]=false;
5698 
5699  // Update chi2 for this segment
5700  if (skip_ring==false && tdrift >= CDC_T_DRIFT_MIN){
5701  chisq+=scale*res*res/V;
5702  numdof++;
5703  }
5704  break_point_cdc_index=cdc_index;
5705  break_point_step_index=k_minus_1;
5706 
5707  if (DEBUG_LEVEL>9)
5708  printf("Ring %d straw %d pred %f meas %f chi2 %f useBrent %i \n",
5709  my_cdchits[cdc_index]->hit->wire->ring,
5710  my_cdchits[cdc_index]->hit->wire->straw,
5711  d,dm,(1.-H*K)*res*res/V,do_brent);
5712 
5713  }
5714 
5715  // If we had to use Brent's algorithm to find the true doca,
5716  // we need to swim the state vector and covariance matrix back
5717  // to the appropriate position along the reference trajectory.
5718  if (do_brent){
5719  if (num_steps==0){
5720  // Step C back to the z-position on the reference trajectory
5721  StepJacobian(newz,z,S0,dedx,J);
5722  C=J*C*J.Transpose();
5723  //C=C.SandwichMultiply(J);
5724 
5725  // Step S to current position on the reference trajectory=
5726  Step(newz,z,dedx,S);
5727 
5728  // Step S0 to current position on the reference trajectory=
5729  Step(newz,z,dedx,S0);
5730  }
5731  else{
5732  double my_z=newz;
5733  for (int m=0;m<num_steps;m++){
5734  z=my_z-my_dz;
5735 
5736  // Step C along z
5737  StepJacobian(my_z,z,S0,dedx,J);
5738  C=J*C*J.Transpose();
5739  //C=C.SandwichMultiply(J);
5740 
5741  // Step S along z
5742  Step(my_z,z,dedx,S);
5743 
5744  // Step S0 along z
5745  Step(my_z,z,dedx,S0);
5746 
5747  my_z=z;
5748  }
5749  z=my_z-dz3;
5750 
5751  // Step C back to the z-position on the reference trajectory
5752  StepJacobian(my_z,z,S0,dedx,J);
5753  C=J*C*J.Transpose();
5754  //C=C.SandwichMultiply(J);
5755 
5756  // Step S to current position on the reference trajectory
5757  Step(my_z,z,dedx,S);
5758 
5759  // Step S0 to current position on the reference trajectory
5760  Step(my_z,z,dedx,S0);
5761 
5762  }
5763  }
5764  cdc_updates[cdc_index].S=S;
5765  cdc_updates[cdc_index].C=C;
5766  }
5767  else {
5768  if (cdc_index>0) cdc_index--;
5769  else cdc_index=0;
5770 
5771  }
5772 
5773  // new wire origin and direction
5774  if (cdc_index>0){
5775  cdc_index--;
5776  origin=my_cdchits[cdc_index]->origin;
5777  z0w=my_cdchits[cdc_index]->z0wire;
5778  dir=my_cdchits[cdc_index]->dir;
5779  }
5780  else{
5781  more_measurements=false;
5782  }
5783 
5784  // Update the wire position
5785  wirepos=origin;
5786  wirepos+=(z-z0w)*dir;
5787 
5788  // new doca
5789  dx=S(state_x)-wirepos.X();
5790  dy=S(state_y)-wirepos.Y();
5791  doca2=dx*dx+dy*dy;
5792  }
5793  old_doca2=doca2;
5794 
5795  }
5796 
5797  // Check that there were enough hits to make this a valid fit
5798  if (numdof<6){
5799  chisq=-1.;
5800  numdof=0;
5801  return PRUNED_TOO_MANY_HITS;
5802  }
5803  numdof-=5;
5804 
5805  // Final position for this leg
5806  x_=S(state_x);
5807  y_=S(state_y);
5808  z_=forward_traj[forward_traj.size()-1].z;
5809 
5810  if (!S.IsFinite()) return FIT_FAILED;
5811 
5812  // Check if the momentum is unphysically large
5813  if (1./fabs(S(state_q_over_p))>12.0){
5814  if (DEBUG_LEVEL>2)
5815  {
5816  _DBG_ << "Unphysical momentum: P = " << 1./fabs(S(state_q_over_p))
5817  <<endl;
5818  }
5819  return MOMENTUM_OUT_OF_RANGE;
5820  }
5821 
5822  // Check if we have a kink in the track or threw away too many cdc hits
5823  if (num_cdc>=MIN_HITS_FOR_REFIT){
5824  if (break_point_cdc_index>1){
5825  if (break_point_cdc_index<num_cdc/2){
5826  break_point_cdc_index=(3*num_cdc)/4;
5827  }
5828  return BREAK_POINT_FOUND;
5829  }
5830 
5831  unsigned int num_good=0;
5832  for (unsigned int j=0;j<num_cdc;j++){
5833  if (cdc_used_in_fit[j]) num_good++;
5834  }
5835  if (double(num_good)/double(num_cdc)<MINIMUM_HIT_FRACTION){
5836  return PRUNED_TOO_MANY_HITS;
5837  }
5838  }
5839 
5840  return FIT_SUCCEEDED;
5841 }
5842 
5843 // Extrapolate to the point along z of closest approach to the beam line using
5844 // the forward track state vector parameterization. Converts to the central
5845 // track representation at the end.
5847  DMatrix5x5 &C){
5848  DMatrix5x5 J; // Jacobian matrix
5849  DMatrix5x5 Q; // multiple scattering matrix
5850  DMatrix5x1 S1(S); // copy of S
5851 
5852  // position variables
5853  double z=z_,newz=z_;
5854 
5855  DVector2 beam_pos=beam_center+(z-beam_z0)*beam_dir;
5856  double r2_old=(DVector2(S(state_x),S(state_y))-beam_pos).Mod2();
5857  double dz_old=0.;
5858  double dEdx=0.;
5859  double sign=1.;
5860 
5861  // material properties
5862  double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.;
5863  double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.;
5864 
5865  // if (fit_type==kTimeBased)printf("------Extrapolating\n");
5866 
5867  // printf("-----------\n");
5868  // Current position
5869  DVector3 pos(S(state_x),S(state_y),z);
5870 
5871  // get material properties from the Root Geometry
5872  if (geom->FindMatKalman(pos,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
5873  chi2c_factor,chi2a_factor,chi2a_corr,
5875  !=NOERROR){
5876  if (DEBUG_LEVEL>1)
5877  _DBG_ << "Material error in ExtrapolateToVertex at (x,y,z)=("
5878  << pos.X() <<"," << pos.y()<<","<< pos.z()<<")"<< endl;
5879  return UNRECOVERABLE_ERROR;
5880  }
5881 
5882  // Adjust the step size
5883  double ds_dz=sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
5884  double dz=-mStepSizeS/ds_dz;
5885  if (fabs(dEdx)>EPS){
5886  dz=(-1.)*DE_PER_STEP/fabs(dEdx)/ds_dz;
5887  }
5888  if(fabs(dz)>mStepSizeZ) dz=-mStepSizeZ;
5889  if(fabs(dz)<MIN_STEP_SIZE)dz=-MIN_STEP_SIZE;
5890 
5891  // Get dEdx for the upcoming step
5892  if (CORRECT_FOR_ELOSS){
5893  dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI,Z);
5894  }
5895 
5896 
5897  double ztest=endplate_z;
5898  if (my_fdchits.size()>0){
5899  ztest =my_fdchits[0]->z-1.;
5900  }
5901  if (z<ztest)
5902  {
5903  // Check direction of propagation
5904  DMatrix5x1 S2(S); // second copy of S
5905 
5906  // Step test states through the field and compute squared radii
5907  Step(z,z-dz,dEdx,S1);
5908  // Bail if the momentum has dropped below some minimum
5909  if (fabs(S1(state_q_over_p))>Q_OVER_P_MAX){
5910  if (DEBUG_LEVEL>2)
5911  {
5912  _DBG_ << "Bailing: P = " << 1./fabs(S1(state_q_over_p))
5913  << endl;
5914  }
5915  return UNRECOVERABLE_ERROR;
5916  }
5917  beam_pos=beam_center+(z-dz-beam_z0)*beam_dir;
5918  double r2minus=(DVector2(S1(state_x),S1(state_y))-beam_pos).Mod2();
5919 
5920  Step(z,z+dz,dEdx,S2);
5921  // Bail if the momentum has dropped below some minimum
5922  if (fabs(S2(state_q_over_p))>Q_OVER_P_MAX){
5923  if (DEBUG_LEVEL>2)
5924  {
5925  _DBG_ << "Bailing: P = " << 1./fabs(S2(state_q_over_p))
5926  << endl;
5927  }
5928  return UNRECOVERABLE_ERROR;
5929  }
5930  beam_pos=beam_center+(z+dz-beam_z0)*beam_dir;
5931  double r2plus=(DVector2(S2(state_x),S2(state_y))-beam_pos).Mod2();
5932  // Check to see if we have already bracketed the minimum
5933  if (r2plus>r2_old && r2minus>r2_old){
5934  newz=z+dz;
5935  double dz2=0.;
5936  if (BrentsAlgorithm(newz,dz,dEdx,0.,beam_center,beam_dir,S2,dz2)!=NOERROR){
5937  if (DEBUG_LEVEL>2)
5938  {
5939  _DBG_ << "Bailing: P = " << 1./fabs(S2(state_q_over_p))
5940  << endl;
5941  }
5942  return UNRECOVERABLE_ERROR;
5943  }
5944  z_=newz+dz2;
5945 
5946  // Compute the Jacobian matrix
5947  StepJacobian(z,z_,S,dEdx,J);
5948 
5949  // Propagate the covariance matrix
5950  C=J*C*J.Transpose();
5951  //C=C.SandwichMultiply(J);
5952 
5953  // Step to the position of the doca
5954  Step(z,z_,dEdx,S);
5955 
5956  // update internal variables
5957  x_=S(state_x);
5958  y_=S(state_y);
5959 
5960  return NOERROR;
5961  }
5962 
5963  // Find direction to propagate toward minimum doca
5964  if (r2minus<r2_old && r2_old<r2plus){
5965  newz=z-dz;
5966 
5967  // Compute the Jacobian matrix
5968  StepJacobian(z,newz,S,dEdx,J);
5969 
5970  // Propagate the covariance matrix
5971  C=J*C*J.Transpose();
5972  //C=C.SandwichMultiply(J);
5973 
5974  S2=S;
5975  S=S1;
5976  S1=S2;
5977  dz*=-1.;
5978  sign=-1.;
5979  dz_old=dz;
5980  r2_old=r2minus;
5981  z=z+dz;
5982  }
5983  if (r2minus>r2_old && r2_old>r2plus){
5984  newz=z+dz;
5985 
5986  // Compute the Jacobian matrix
5987  StepJacobian(z,newz,S,dEdx,J);
5988 
5989  // Propagate the covariance matrix
5990  C=J*C*J.Transpose();
5991  //C=C.SandwichMultiply(J);
5992 
5993  S1=S;
5994  S=S2;
5995  dz_old=dz;
5996  r2_old=r2plus;
5997  z=z+dz;
5998  }
5999  }
6000 
6001  double r2=r2_old;
6002  while (z>Z_MIN && r2<R2_MAX && z<ztest && r2>EPS){
6003  // Bail if the momentum has dropped below some minimum
6004  if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){
6005  if (DEBUG_LEVEL>2)
6006  {
6007  _DBG_ << "Bailing: P = " << 1./fabs(S(state_q_over_p))
6008  << endl;
6009  }
6010  return UNRECOVERABLE_ERROR;
6011  }
6012 
6013  // Relationship between arc length and z
6014  double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
6015 
6016  // get material properties from the Root Geometry
6017  pos.SetXYZ(S(state_x),S(state_y),z);
6018  double s_to_boundary=1.e6;
6020  DVector3 mom(S(state_tx),S(state_ty),1.);
6021  if (geom->FindMatKalman(pos,mom,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
6022  chi2c_factor,chi2a_factor,chi2a_corr,
6023  last_material_map,&s_to_boundary)
6024  !=NOERROR){
6025  _DBG_ << "Material error in ExtrapolateToVertex! " << endl;
6026  return UNRECOVERABLE_ERROR;
6027  }
6028  }
6029  else{
6030  if (geom->FindMatKalman(pos,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
6031  chi2c_factor,chi2a_factor,chi2a_corr,
6033  !=NOERROR){
6034  _DBG_ << "Material error in ExtrapolateToVertex! " << endl;
6035  break;
6036  }
6037  }
6038 
6039  // Get dEdx for the upcoming step
6040  if (CORRECT_FOR_ELOSS){
6041  dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI,Z);
6042  }
6043 
6044  // Adjust the step size
6045  //dz=-sign*mStepSizeS*dz_ds;
6046  double ds=mStepSizeS;
6047  if (fabs(dEdx)>EPS){
6048  ds=DE_PER_STEP/fabs(dEdx);
6049  }
6050  /*
6051  if(fabs(dz)>mStepSizeZ) dz=-sign*mStepSizeZ;
6052  if (fabs(dz)<z_to_boundary) dz=-sign*z_to_boundary;
6053  if(fabs(dz)<MIN_STEP_SIZE)dz=-sign*MIN_STEP_SIZE;
6054  */
6055  if (ds>mStepSizeS) ds=mStepSizeS;
6056  if (ds>s_to_boundary) ds=s_to_boundary;
6057  if (ds<MIN_STEP_SIZE) ds=MIN_STEP_SIZE;
6058  dz=-sign*ds*dz_ds;
6059 
6060  // Get the contribution to the covariance matrix due to multiple
6061  // scattering
6062  GetProcessNoise(z,ds,chi2c_factor,chi2a_factor,chi2a_corr,S,Q);
6063 
6064  if (CORRECT_FOR_ELOSS){
6065  double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
6066  double one_over_beta2=1.+mass2*q_over_p_sq;
6067  double varE=GetEnergyVariance(ds,one_over_beta2,K_rho_Z_over_A);
6068  Q(state_q_over_p,state_q_over_p)=varE*q_over_p_sq*q_over_p_sq*one_over_beta2;
6069  }
6070 
6071 
6072  newz=z+dz;
6073  // Compute the Jacobian matrix
6074  StepJacobian(z,newz,S,dEdx,J);
6075 
6076  // Propagate the covariance matrix
6077  C=Q.AddSym(J*C*J.Transpose());
6078  //C=Q.AddSym(C.SandwichMultiply(J));
6079 
6080  // Step through field
6081  Step(z,newz,dEdx,S);
6082 
6083  // Check if we passed the minimum doca to the beam line
6084  beam_pos=beam_center+(newz-beam_z0)*beam_dir;
6085  r2=(DVector2(S(state_x),S(state_y))-beam_pos).Mod2();
6086  //r2=S(state_x)*S(state_x)+S(state_y)*S(state_y);
6087  if (r2>r2_old){
6088  double two_step=dz+dz_old;
6089 
6090  // Find the increment/decrement in z to get to the minimum doca to the
6091  // beam line
6092  S1=S;
6093  if (BrentsAlgorithm(newz,0.5*two_step,dEdx,0.,beam_center,beam_dir,S,dz)!=NOERROR){
6094  //_DBG_<<endl;
6095  return UNRECOVERABLE_ERROR;
6096  }
6097 
6098  // Compute the Jacobian matrix
6099  z_=newz+dz;
6100  StepJacobian(newz,z_,S1,dEdx,J);
6101 
6102  // Propagate the covariance matrix
6103  //C=J*C*J.Transpose()+(dz/(newz-z))*Q;
6104  //C=((dz/newz-z)*Q).AddSym(C.SandwichMultiply(J));
6105  //C=C.SandwichMultiply(J);
6106  C=J*C*J.Transpose();
6107 
6108  // update internal variables
6109  x_=S(state_x);
6110  y_=S(state_y);
6111 
6112  return NOERROR;
6113  }
6114  r2_old=r2;
6115  dz_old=dz;
6116  S1=S;
6117  z=newz;
6118  }
6119  // update internal variables
6120  x_=S(state_x);
6121  y_=S(state_y);
6122  z_=newz;
6123 
6124  return NOERROR;
6125 }
6126 
6127 
6128 // Extrapolate to the point along z of closest approach to the beam line using
6129 // the forward track state vector parameterization.
6131  DMatrix5x5 J; // Jacobian matrix
6132  DMatrix5x1 S1(S); // copy of S
6133 
6134  // position variables
6135  double z=z_,newz=z_;
6136  DVector2 beam_pos=beam_center+(z-beam_z0)*beam_dir;
6137  double r2_old=(DVector2(S(state_x),S(state_y))-beam_pos).Mod2();
6138  double dz_old=0.;
6139  double dEdx=0.;
6140 
6141  // Direction and origin for beam line
6142  DVector2 dir;
6143  DVector2 origin;
6144 
6145  // material properties
6146  double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.;
6147  double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.;
6148  DVector3 pos; // current position along trajectory
6149 
6150  double r2=r2_old;
6151  while (z>Z_MIN && r2<R2_MAX && z<Z_MAX && r2>EPS){
6152  // Bail if the momentum has dropped below some minimum
6153  if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){
6154  if (DEBUG_LEVEL>2)
6155  {
6156  _DBG_ << "Bailing: P = " << 1./fabs(S(state_q_over_p))
6157  << endl;
6158  }
6159  return UNRECOVERABLE_ERROR;
6160  }
6161 
6162  // Relationship between arc length and z
6163  double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
6164 
6165  // get material properties from the Root Geometry
6166  pos.SetXYZ(S(state_x),S(state_y),z);
6167  if (geom->FindMatKalman(pos,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
6168  chi2c_factor,chi2a_factor,chi2a_corr,
6170  !=NOERROR){
6171  _DBG_ << "Material error in ExtrapolateToVertex! " << endl;
6172  break;
6173  }
6174 
6175  // Get dEdx for the upcoming step
6176  if (CORRECT_FOR_ELOSS){
6177  dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI,Z);
6178  }
6179 
6180  // Adjust the step size
6181  double ds=mStepSizeS;
6182  if (fabs(dEdx)>EPS){
6183  ds=DE_PER_STEP/fabs(dEdx);
6184  }
6185  if (ds>mStepSizeS) ds=mStepSizeS;
6186  if (ds<MIN_STEP_SIZE) ds=MIN_STEP_SIZE;
6187  double dz=-ds*dz_ds;
6188 
6189  newz=z+dz;
6190 
6191 
6192  // Step through field
6193  Step(z,newz,dEdx,S);
6194 
6195  // Check if we passed the minimum doca to the beam line
6196  beam_pos=beam_center+(newz-beam_z0)*beam_dir;
6197  r2=(DVector2(S(state_x),S(state_y))-beam_pos).Mod2();
6198 
6199  if (r2>r2_old && newz<endplate_z){
6200  double two_step=dz+dz_old;
6201 
6202  // Find the increment/decrement in z to get to the minimum doca to the
6203  // beam line
6204  if (BrentsAlgorithm(newz,0.5*two_step,dEdx,0.,beam_center,beam_dir,S,dz)!=NOERROR){
6205  return UNRECOVERABLE_ERROR;
6206  }
6207  // update internal variables
6208  x_=S(state_x);
6209  y_=S(state_y);
6210  z_=newz+dz;
6211 
6212  return NOERROR;
6213  }
6214  r2_old=r2;
6215  dz_old=dz;
6216  z=newz;
6217  }
6218 
6219  // If we extrapolate beyond the fiducial volume of the detector before
6220  // finding the doca, abandon the extrapolation...
6221  if (newz<Z_MIN){
6222  //_DBG_ << "Extrapolated z = " << newz << endl;
6223  // Restore old state vector
6224  S=S1;
6225  return VALUE_OUT_OF_RANGE;
6226  }
6227 
6228  // update internal variables
6229  x_=S(state_x);
6230  y_=S(state_y);
6231  z_=newz;
6232 
6233 
6234  return NOERROR;
6235 }
6236 
6237 
6238 
6239 
6240 // Propagate track to point of distance of closest approach to origin
6242  DMatrix5x1 &Sc,DMatrix5x5 &Cc){
6243  DMatrix5x5 Jc=I5x5; //Jacobian matrix
6244  DMatrix5x5 Q; // multiple scattering matrix
6245 
6246  // Position and step variables
6247  DVector2 beam_pos=beam_center+(Sc(state_z)-beam_z0)*beam_dir;
6248  double r2=(xy-beam_pos).Mod2();
6249  double ds=-mStepSizeS; // step along path in cm
6250  double r2_old=r2;
6251 
6252  // Energy loss
6253  double dedx=0.;
6254 
6255  // Check direction of propagation
6256  DMatrix5x1 S0;
6257  S0=Sc;
6258  DVector2 xy0=xy;
6259  DVector2 xy1=xy;
6260  Step(xy0,ds,S0,dedx);
6261  // Bail if the transverse momentum has dropped below some minimum
6262  if (fabs(S0(state_q_over_pt))>Q_OVER_PT_MAX){
6263  if (DEBUG_LEVEL>2)
6264  {
6265  _DBG_ << "Bailing: PT = " << 1./fabs(S0(state_q_over_pt))
6266  << endl;
6267  }
6268  return UNRECOVERABLE_ERROR;
6269  }
6270  beam_pos=beam_center+(S0(state_z)-beam_z0)*beam_dir;
6271  r2=(xy0-beam_pos).Mod2();
6272  if (r2>r2_old) ds*=-1.;
6273  double ds_old=ds;
6274 
6275  // if (fit_type==kTimeBased)printf("------Extrapolating\n");
6276 
6277  if (central_traj.size()==0){
6278  if (DEBUG_LEVEL>1) _DBG_ << "Central trajectory size==0!" << endl;
6279  return UNRECOVERABLE_ERROR;
6280  }
6281 
6282  // D is now on the actual trajectory itself
6283  Sc(state_D)=0.;
6284 
6285  // Track propagation loop
6286  while (Sc(state_z)>Z_MIN && Sc(state_z)<Z_MAX
6287  && r2<R2_MAX){
6288  // Bail if the transverse momentum has dropped below some minimum
6289  if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX){
6290  if (DEBUG_LEVEL>2)
6291  {
6292  _DBG_ << "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
6293  << endl;
6294  }
6295  return UNRECOVERABLE_ERROR;
6296  }
6297 
6298  // get material properties from the Root Geometry
6299  double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.;
6300  double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.;
6301  DVector3 pos3d(xy.X(),xy.Y(),Sc(state_z));
6302  if (geom->FindMatKalman(pos3d,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
6303  chi2c_factor,chi2a_factor,chi2a_corr,
6305  !=NOERROR){
6306  _DBG_ << "Material error in ExtrapolateToVertex! " << endl;
6307  break;
6308  }
6309 
6310  // Get dEdx for the upcoming step
6311  double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl)));
6312  if (CORRECT_FOR_ELOSS){
6313  dedx=-GetdEdx(q_over_p,K_rho_Z_over_A,rho_Z_over_A,LnI,Z);
6314  }
6315  // Adjust the step size
6316  double sign=(ds>0.0)?1.:-1.;
6317  if (fabs(dedx)>EPS){
6318  ds=sign*DE_PER_STEP/fabs(dedx);
6319  }
6320  if(fabs(ds)>mStepSizeS) ds=sign*mStepSizeS;
6321  if(fabs(ds)<MIN_STEP_SIZE)ds=sign*MIN_STEP_SIZE;
6322 
6323  // Multiple scattering
6324  GetProcessNoiseCentral(ds,chi2c_factor,chi2a_factor,chi2a_corr,Sc,Q);
6325 
6326  if (CORRECT_FOR_ELOSS){
6327  double q_over_p_sq=q_over_p*q_over_p;
6328  double one_over_beta2=1.+mass2*q_over_p*q_over_p;
6329  double varE=GetEnergyVariance(ds,one_over_beta2,K_rho_Z_over_A);
6331  +=varE*Sc(state_q_over_pt)*Sc(state_q_over_pt)*one_over_beta2
6332  *q_over_p_sq;
6333  }
6334 
6335  // Propagate the state and covariance through the field
6336  S0=Sc;
6337  DVector2 old_xy=xy;
6338  StepStateAndCovariance(xy,ds,dedx,Sc,Jc,Cc);
6339 
6340  // Add contribution due to multiple scattering
6341  Cc=(sign*Q).AddSym(Cc);
6342 
6343  beam_pos=beam_center+(Sc(state_z)-beam_z0)*beam_dir;
6344  r2=(xy-beam_pos).Mod2();
6345  //printf("r %f r_old %f \n",sqrt(r2),sqrt(r2_old));
6346  if (r2>r2_old) {
6347  // We've passed the true minimum; backtrack to find the "vertex"
6348  // position
6349  double my_ds=0.;
6350  if (BrentsAlgorithm(ds,ds_old,dedx,xy,0.,beam_center,beam_dir,Sc,my_ds)!=NOERROR){
6351  //_DBG_ <<endl;
6352  return UNRECOVERABLE_ERROR;
6353  }
6354  //printf ("Brent min r %f\n",xy.Mod());
6355 
6356  // Find the field and gradient at (old_x,old_y,old_z)
6357  bfield->GetFieldAndGradient(old_xy.X(),old_xy.Y(),S0(state_z),Bx,By,Bz,
6360 
6361  // Compute the Jacobian matrix
6362  my_ds-=ds_old;
6363  StepJacobian(old_xy,xy-old_xy,my_ds,S0,dedx,Jc);
6364 
6365  // Propagate the covariance matrix
6366  //Cc=Jc*Cc*Jc.Transpose()+(my_ds/ds_old)*Q;
6367  //Cc=((my_ds/ds_old)*Q).AddSym(Cc.SandwichMultiply(Jc));
6368  Cc=((my_ds/ds_old)*Q).AddSym(Jc*Cc*Jc.Transpose());
6369 
6370  break;
6371  }
6372  r2_old=r2;
6373  ds_old=ds;
6374  }
6375 
6376  return NOERROR;
6377 }
6378 
6379 // Propagate track to point of distance of closest approach to origin
6381  DMatrix5x1 &Sc){
6382  // Save un-extroplated quantities
6383  DMatrix5x1 S0(Sc);
6384  DVector2 xy0(xy);
6385 
6386  // Initialize the beam position = center of target, and the direction
6387  DVector2 origin;
6388  DVector2 dir;
6389 
6390  // Position and step variables
6391  DVector2 beam_pos=beam_center+(Sc(state_z)-beam_z0)*beam_dir;
6392  double r2=(xy-beam_pos).Mod2();
6393  double ds=-mStepSizeS; // step along path in cm
6394  double r2_old=r2;
6395 
6396  // Energy loss
6397  double dedx=0.;
6398 
6399  // Check direction of propagation
6400  DMatrix5x1 S1=Sc;
6401  DVector2 xy1=xy;
6402  Step(xy1,ds,S1,dedx);
6403  beam_pos=beam_center+(S1(state_z)-beam_z0)*beam_dir;
6404  r2=(xy1-beam_pos).Mod2();
6405  if (r2>r2_old) ds*=-1.;
6406  double ds_old=ds;
6407 
6408  // Track propagation loop
6409  while (Sc(state_z)>Z_MIN && Sc(state_z)<Z_MAX
6410  && r2<R2_MAX){
6411  // get material properties from the Root Geometry
6412  double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0;
6413  double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.;
6414  DVector3 pos3d(xy.X(),xy.Y(),Sc(state_z));
6415  if (geom->FindMatKalman(pos3d,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
6416  chi2c_factor,chi2a_factor,chi2a_corr,
6418  !=NOERROR){
6419  _DBG_ << "Material error in ExtrapolateToVertex! " << endl;
6420  break;
6421  }
6422 
6423  // Get dEdx for the upcoming step
6424  double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl)));
6425  if (CORRECT_FOR_ELOSS){
6426  dedx=GetdEdx(q_over_p,K_rho_Z_over_A,rho_Z_over_A,LnI,Z);
6427  }
6428  // Adjust the step size
6429  double sign=(ds>0.0)?1.:-1.;
6430  if (fabs(dedx)>EPS){
6431  ds=sign*DE_PER_STEP/fabs(dedx);
6432  }
6433  if(fabs(ds)>mStepSizeS) ds=sign*mStepSizeS;
6434  if(fabs(ds)<MIN_STEP_SIZE)ds=sign*MIN_STEP_SIZE;
6435 
6436  // Propagate the state through the field
6437  Step(xy,ds,Sc,dedx);
6438 
6439  beam_pos=beam_center+(Sc(state_z)-beam_z0)*beam_dir;
6440  r2=(xy-beam_pos).Mod2();
6441  //printf("r %f r_old %f \n",r,r_old);
6442  if (r2>r2_old) {
6443  // We've passed the true minimum; backtrack to find the "vertex"
6444  // position
6445  double my_ds=0.;
6446  BrentsAlgorithm(ds,ds_old,dedx,xy,0.,beam_center,beam_dir,Sc,my_ds);
6447  //printf ("Brent min r %f\n",pos.Perp());
6448  break;
6449  }
6450  r2_old=r2;
6451  ds_old=ds;
6452  }
6453 
6454  // If we extrapolate beyond the fiducial volume of the detector before
6455  // finding the doca, abandon the extrapolation...
6456  if (Sc(state_z)<Z_MIN){
6457  //_DBG_ << "Extrapolated z = " << Sc(state_z) << endl;
6458  // Restore un-extrapolated values
6459  Sc=S0;
6460  xy=xy0;
6461  return VALUE_OUT_OF_RANGE;
6462  }
6463 
6464  return NOERROR;
6465 }
6466 
6467 
6468 
6469 
6470 // Transform the 5x5 tracking error matrix into a 7x7 error matrix in cartesian
6471 // coordinates
6473  auto C7x7 = dResourcePool_TMatrixFSym->Get_SharedResource();
6474  C7x7->ResizeTo(7, 7);
6475  DMatrix J(7,5);
6476 
6477  double p=1./fabs(q_over_p_);
6478  double tanl=1./sqrt(tx_*tx_+ty_*ty_);
6479  double tanl2=tanl*tanl;
6480  double lambda=atan(tanl);
6481  double sinl=sin(lambda);
6482  double sinl3=sinl*sinl*sinl;
6483 
6484  J(state_X,state_x)=J(state_Y,state_y)=1.;
6485  J(state_Pz,state_ty)=-p*ty_*sinl3;
6486  J(state_Pz,state_tx)=-p*tx_*sinl3;
6487  J(state_Px,state_ty)=J(state_Py,state_tx)=-p*tx_*ty_*sinl3;
6488  J(state_Px,state_tx)=p*(1.+ty_*ty_)*sinl3;
6489  J(state_Py,state_ty)=p*(1.+tx_*tx_)*sinl3;
6490  J(state_Pz,state_q_over_p)=-p*sinl/q_over_p_;
6493  J(state_Z,state_x)=-tx_*tanl2;
6494  J(state_Z,state_y)=-ty_*tanl2;
6495  double diff=tx_*tx_-ty_*ty_;
6496  double frac=tanl2*tanl2;
6497  J(state_Z,state_tx)=(x_*diff+2.*tx_*ty_*y_)*frac;
6498  J(state_Z,state_ty)=(2.*tx_*ty_*x_-y_*diff)*frac;
6499 
6500  // C'= JCJ^T
6501  *C7x7=C.Similarity(J);
6502 
6503  return C7x7;
6504 }
6505 
6506 
6507 
6508 // Transform the 5x5 tracking error matrix into a 7x7 error matrix in cartesian
6509 // coordinates
6511  auto C7x7 = dResourcePool_TMatrixFSym->Get_SharedResource();
6512  C7x7->ResizeTo(7, 7);
6513  DMatrix J(7,5);
6514  //double cosl=cos(atan(tanl_));
6515  double pt=1./fabs(q_over_pt_);
6516  //double p=pt/cosl;
6517  // double p_sq=p*p;
6518  // double E=sqrt(mass2+p_sq);
6519  double pt_sq=1./(q_over_pt_*q_over_pt_);
6520  double cosphi=cos(phi_);
6521  double sinphi=sin(phi_);
6522  double q=(q_over_pt_>0.0)?1.:-1.;
6523 
6524  J(state_Px,state_q_over_pt)=-q*pt_sq*cosphi;
6525  J(state_Px,state_phi)=-pt*sinphi;
6526 
6527  J(state_Py,state_q_over_pt)=-q*pt_sq*sinphi;
6528  J(state_Py,state_phi)=pt*cosphi;
6529 
6530  J(state_Pz,state_q_over_pt)=-q*pt_sq*tanl_;
6531  J(state_Pz,state_tanl)=pt;
6532 
6533  J(state_X,state_phi)=-D_*cosphi;
6534  J(state_X,state_D)=-sinphi;
6535 
6536  J(state_Y,state_phi)=-D_*sinphi;
6537  J(state_Y,state_D)=cosphi;
6538 
6539  J(state_Z,state_z)=1.;
6540 
6541  // C'= JCJ^T
6542  *C7x7=C.Similarity(J);
6543  // C7x7->Print();
6544  // _DBG_ << " " << C7x7->operator()(3,3) << " " << C7x7->operator()(4,4) << endl;
6545 
6546  return C7x7;
6547 }
6548 
6549 // Track recovery for Central tracks
6550 //-----------------------------------
6551 // This code attempts to recover tracks that are "broken". Sometimes the fit fails because too many hits were pruned
6552 // such that the number of surviving hits is less than the minimum number of degrees of freedom for a five-parameter fit.
6553 // This condition is flagged as PRUNED_TOO_MANY_HITS. It may also be the case that even if we used enough hits for the fit to
6554 // be valid (i.e., make sense in terms of the number of degrees of freedom for the number of parameters (5) we are trying
6555 // to determine), we throw away a number of hits near the target because the projected trajectory deviates too far away from
6556 // the actual hits. This may be an indication of a kink in the trajectory. This condition is flagged as BREAK_POINT_FOUND.
6557 // Sometimes the fit may succeed and no break point is found, but the pruning threw out a large number of hits. This
6558 // condition is flagged as PRUNED_TOO_MANY_HITS. The recovery code proceeds by truncating the reference trajectory to
6559 // to a point just after the hit where a break point was found and all hits are ignored beyond this point subject to a
6560 // minimum number of hits set by MIN_HITS_FOR_REFIT. The recovery code always attempts to use the hits closest to the
6561 // target. The code is allowed to iterate; with each iteration the trajectory and list of useable hits is further truncated.
6563  DMatrix5x1 &S,
6564  DMatrix5x5 &C,
6565  const DMatrix5x5 &C0,
6566  DVector2 &xy,
6567  double &chisq,
6568  unsigned int &numdof){
6569  if (DEBUG_LEVEL>1) _DBG_ << "Attempting to recover broken track ... " <<endl;
6570 
6571  // Initialize degrees of freedom and chi^2
6572  double refit_chisq=-1.;
6573  unsigned int refit_ndf=0;
6574  // State vector and covariance matrix
6575  DMatrix5x5 C1;
6576  DMatrix5x1 S1;
6577  // Position vector
6578  DVector2 refit_xy;
6579 
6580  // save the status of the hits used in the fit
6581  unsigned int num_hits=cdc_used_in_fit.size();
6582  vector<bool>old_cdc_used_status(num_hits);
6583  for (unsigned int j=0;j<num_hits;j++){
6584  old_cdc_used_status[j]=cdc_used_in_fit[j];
6585  }
6586 
6587  // Truncate the reference trajectory to just beyond the break point (or the minimum number of hits)
6588  unsigned int min_cdc_index_for_refit=MIN_HITS_FOR_REFIT-1;
6589  //if (break_point_cdc_index<num_hits/2)
6590  // break_point_cdc_index=num_hits/2;
6591  if (break_point_cdc_index<min_cdc_index_for_refit){
6592  break_point_cdc_index=min_cdc_index_for_refit;
6593  }
6594  // Next determine where we need to truncate the trajectory
6595  DVector2 origin=my_cdchits[break_point_cdc_index]->origin;
6597  double z0=my_cdchits[break_point_cdc_index]->z0wire;
6598  unsigned int k=0;
6599  for (k=central_traj.size()-1;k>1;k--){
6600  double r2=central_traj[k].xy.Mod2();
6601  double r2next=central_traj[k-1].xy.Mod2();
6602  double r2_cdc=(origin+(central_traj[k].S(state_z)-z0)*dir).Mod2();
6603  if (r2next>r2 && r2>r2_cdc) break;
6604  }
6606 
6607  if (break_point_step_index==central_traj.size()-1){
6608  if (DEBUG_LEVEL>0) _DBG_ << "Invalid reference trajectory in track recovery..." << endl;
6609  return FIT_FAILED;
6610  }
6611 
6612  kalman_error_t refit_error=FIT_NOT_DONE;
6613  unsigned int old_cdc_index=break_point_cdc_index;
6614  unsigned int old_step_index=break_point_step_index;
6615  unsigned int refit_iter=0;
6616  unsigned int num_cdchits=my_cdchits.size();
6619  refit_iter++;
6620 
6621  // Flag the cdc hits within the radius of the break point cdc index
6622  // as good, the rest as bad.
6623  for (unsigned int j=0;j<=break_point_cdc_index;j++){
6624  if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
6625  }
6626  for (unsigned int j=break_point_cdc_index+1;j<num_cdchits;j++){
6627  my_cdchits[j]->status=bad_hit;
6628  }
6629 
6630  // Now refit with the truncated trajectory and list of hits
6631  //C1=C0;
6632  //C1=4.0*C0;
6633  C1=1.0*C0;
6635  refit_chisq=-1.;
6636  refit_ndf=0;
6637  refit_error=KalmanCentral(anneal_factor,S1,C1,refit_xy,
6638  refit_chisq,refit_ndf);
6639  if (refit_error==FIT_SUCCEEDED
6640  || (refit_error==BREAK_POINT_FOUND
6641  && break_point_cdc_index==1
6642  )
6643  //|| refit_error==PRUNED_TOO_MANY_HITS
6644  ){
6645  C=C1;
6646  S=S1;
6647  xy=refit_xy;
6648  chisq=refit_chisq;
6649  numdof=refit_ndf;
6650 
6651  if (DEBUG_LEVEL>0) _DBG_ << "Fit recovery succeeded..." << endl;
6652  return FIT_SUCCEEDED;
6653  }
6654 
6655  break_point_cdc_index=old_cdc_index-refit_iter;
6656  break_point_step_index=old_step_index-refit_iter;
6657  }
6658 
6659  // If the refit did not work, restore the old list hits used in the fit
6660  // before the track recovery was attempted.
6661  for (unsigned int k=0;k<num_hits;k++){
6662  cdc_used_in_fit[k]=old_cdc_used_status[k];
6663  }
6664 
6665  if (DEBUG_LEVEL>0) _DBG_ << "Fit recovery failed..." << endl;
6666  return FIT_FAILED;
6667 }
6668 
6669 // Track recovery for forward tracks
6670 //-----------------------------------
6671 // This code attempts to recover tracks that are "broken". Sometimes the fit fails because too many hits were pruned
6672 // such that the number of surviving hits is less than the minimum number of degrees of freedom for a five-parameter fit.
6673 // This condition is flagged as PRUNED_TOO_MANY_HITS. It may also be the case that even if we used enough hits for the fit to
6674 // be valid (i.e., make sense in terms of the number of degrees of freedom for the number of parameters (5) we are trying
6675 // to determine), we throw away a number of hits near the target because the projected trajectory deviates too far away from
6676 // the actual hits. This may be an indication of a kink in the trajectory. This condition is flagged as BREAK_POINT_FOUND.
6677 // Sometimes the fit may succeed and no break point is found, but the pruning threw out a large number of hits. This
6678 // condition is flagged as PRUNED_TOO_MANY_HITS. The recovery code proceeds by truncating the reference trajectory to
6679 // to a point just after the hit where a break point was found and all hits are ignored beyond this point subject to a
6680 // minimum number of hits. The recovery code always attempts to use the hits closest to the target. The code is allowed to
6681 // iterate; with each iteration the trajectory and list of useable hits is further truncated.
6683  DMatrix5x1 &S,
6684  DMatrix5x5 &C,
6685  const DMatrix5x5 &C0,
6686  double &chisq,
6687  unsigned int &numdof
6688  ){
6689  if (DEBUG_LEVEL>1) _DBG_ << "Attempting to recover broken track ... " <<endl;
6690 
6691  unsigned int num_cdchits=my_cdchits.size();
6692  unsigned int num_fdchits=my_fdchits.size();
6693 
6694  // Initialize degrees of freedom and chi^2
6695  double refit_chisq=-1.;
6696  unsigned int refit_ndf=0;
6697  // State vector and covariance matrix
6698  DMatrix5x5 C1;
6699  DMatrix5x1 S1;
6700 
6701  // save the status of the hits used in the fit
6702  vector<bool>old_cdc_used_status(num_cdchits);
6703  vector<bool>old_fdc_used_status(num_fdchits);
6704  for (unsigned int j=0;j<num_fdchits;j++){
6705  old_fdc_used_status[j]=fdc_used_in_fit[j];
6706  }
6707  for (unsigned int j=0;j<num_cdchits;j++){
6708  old_cdc_used_status[j]=cdc_used_in_fit[j];
6709  }
6710 
6711  unsigned int min_cdc_index=MIN_HITS_FOR_REFIT-1;
6712  if (my_fdchits.size()>0){
6713  if (break_point_cdc_index<5){
6715  min_cdc_index=5;
6716  }
6717  }
6718  /*else{
6719  unsigned int half_num_cdchits=num_cdchits/2;
6720  if (break_point_cdc_index<half_num_cdchits
6721  && half_num_cdchits>min_cdc_index)
6722  break_point_cdc_index=half_num_cdchits;
6723  }
6724  */
6725  if (break_point_cdc_index<min_cdc_index){
6726  break_point_cdc_index=min_cdc_index;
6727  }
6728 
6729  // Find the index at which to truncate the reference trajectory
6730  DVector2 origin=my_cdchits[break_point_cdc_index]->origin;
6732  double z0=my_cdchits[break_point_cdc_index]->z0wire;
6733  unsigned int k=forward_traj.size()-1;
6734  for (;k>1;k--){
6735  DMatrix5x1 S1=forward_traj[k].S;
6736  double x1=S1(state_x);
6737  double y1=S1(state_y);
6738  double r2=x1*x1+y1*y1;
6739  DMatrix5x1 S2=forward_traj[k-1].S;
6740  double x2=S2(state_x);
6741  double y2=S2(state_y);
6742  double r2next=x2*x2+y2*y2;
6743  double r2cdc=(origin+(forward_traj[k].z-z0)*dir).Mod2();
6744 
6745  if (r2next>r2 && r2>r2cdc) break;
6746  }
6748 
6749  if (break_point_step_index==forward_traj.size()-1){
6750  if (DEBUG_LEVEL>0) _DBG_ << "Invalid reference trajectory in track recovery..." << endl;
6751  return FIT_FAILED;
6752  }
6753 
6754  // Attemp to refit the track using the abreviated list of hits and the truncated
6755  // reference trajectory. Iterates if the fit fails.
6756  kalman_error_t refit_error=FIT_NOT_DONE;
6757  unsigned int old_cdc_index=break_point_cdc_index;
6758  unsigned int old_step_index=break_point_step_index;
6759  unsigned int refit_iter=0;
6762  refit_iter++;
6763 
6764  // Flag the cdc hits within the radius of the break point cdc index
6765  // as good, the rest as bad.
6766  for (unsigned int j=0;j<=break_point_cdc_index;j++){
6767  if (my_cdchits[j]->status!=late_hit) my_cdchits[j]->status=good_hit;
6768  }
6769  for (unsigned int j=break_point_cdc_index+1;j<num_cdchits;j++){
6770  my_cdchits[j]->status=bad_hit;
6771  }
6772 
6773  // Re-initialize the state vector, covariance, chisq and number of degrees of freedom
6774  //C1=4.0*C0;
6775  C1=1.0*C0;
6777  refit_chisq=-1.;
6778  refit_ndf=0;
6779  // Now refit with the truncated trajectory and list of hits
6780  refit_error=KalmanForwardCDC(anneal_factor,S1,C1,refit_chisq,refit_ndf);
6781  if (refit_error==FIT_SUCCEEDED
6782  || (refit_error==BREAK_POINT_FOUND
6783  && break_point_cdc_index==1
6784  )
6785  //|| refit_error==PRUNED_TOO_MANY_HITS
6786  ){
6787  C=C1;
6788  S=S1;
6789  chisq=refit_chisq;
6790  numdof=refit_ndf;
6791  return FIT_SUCCEEDED;
6792  }
6793  break_point_cdc_index=old_cdc_index-refit_iter;
6794  break_point_step_index=old_step_index-refit_iter;
6795  }
6796  // If the refit did not work, restore the old list hits used in the fit
6797  // before the track recovery was attempted.
6798  for (unsigned int k=0;k<num_cdchits;k++){
6799  cdc_used_in_fit[k]=old_cdc_used_status[k];
6800  }
6801  for (unsigned int k=0;k<num_fdchits;k++){
6802  fdc_used_in_fit[k]=old_fdc_used_status[k];
6803  }
6804 
6805  return FIT_FAILED;
6806 }
6807 
6808 
6809 // Track recovery for forward-going tracks with hits in the FDC
6812  double cdc_anneal,
6813  DMatrix5x1 &S,
6814  DMatrix5x5 &C,
6815  const DMatrix5x5 &C0,
6816  double &chisq,
6817  unsigned int &numdof){
6818  if (DEBUG_LEVEL>1)
6819  _DBG_ << "Attempting to recover broken track ... " <<endl;
6820  unsigned int num_cdchits=my_cdchits.size();
6821  unsigned int num_fdchits=fdc_updates.size();
6822 
6823  // Initialize degrees of freedom and chi^2
6824  double refit_chisq=-1.;
6825  unsigned int refit_ndf=0;
6826  // State vector and covariance matrix
6827  DMatrix5x5 C1;
6828  DMatrix5x1 S1;
6829 
6830  // save the status of the hits used in the fit
6831  vector<int>old_cdc_used_status(num_cdchits);
6832  vector<int>old_fdc_used_status(num_fdchits);
6833  for (unsigned int j=0;j<num_fdchits;j++){
6834  old_fdc_used_status[j]=fdc_used_in_fit[j];
6835  }
6836  for (unsigned int j=0;j<num_cdchits;j++){
6837  old_cdc_used_status[j]=cdc_used_in_fit[j];
6838  }
6839 
6840  // Truncate the trajectory
6841  double zhit=my_fdchits[break_point_fdc_index]->z;
6842  unsigned int k=0;
6843  for (;k<forward_traj.size();k++){
6844  double z=forward_traj[k].z;
6845  if (z<zhit) break;
6846  }
6847  for (unsigned int j=0;j<=break_point_fdc_index;j++){
6848  my_fdchits[j]->status=good_hit;
6849  }
6850  for (unsigned int j=break_point_fdc_index+1;j<num_fdchits;j++){
6851  my_fdchits[j]->status=bad_hit;
6852  }
6853 
6854  if (k==forward_traj.size()) return FIT_NOT_DONE;
6855 
6857 
6858  // Attemp to refit the track using the abreviated list of hits and the truncated
6859  // reference trajectory.
6860  kalman_error_t refit_error=FIT_NOT_DONE;
6861  int refit_iter=0;
6862  unsigned int break_id=break_point_fdc_index;
6863  while (break_id+num_cdchits>=MIN_HITS_FOR_REFIT && break_id>0
6866  && refit_iter<10){
6867  refit_iter++;
6868 
6869  // Mark the hits as bad if they are not included
6870  if (break_id >= 0){
6871  for (unsigned int j=0;j<num_cdchits;j++){
6872  if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
6873  }
6874  for (unsigned int j=0;j<=break_id;j++){
6875  my_fdchits[j]->status=good_hit;
6876  }
6877  for (unsigned int j=break_id+1;j<num_fdchits;j++){
6878  my_fdchits[j]->status=bad_hit;
6879  }
6880  }
6881  else{
6882  // BreakID should always be 0 or positive, so this should never happen, but could be investigated in the future.
6883  for (unsigned int j=0;j<num_cdchits+break_id;j++){
6884  if (my_cdchits[j]->status!=late_hit) my_cdchits[j]->status=good_hit;
6885  }
6886  for (unsigned int j=num_cdchits+break_id;j<num_cdchits;j++){
6887  my_cdchits[j]->status=bad_hit;
6888  }
6889  for (unsigned int j=0;j<num_fdchits;j++){
6890  my_fdchits[j]->status=bad_hit;
6891  }
6892  }
6893 
6894  // Re-initialize the state vector, covariance, chisq and number of degrees of freedom
6895  //C1=4.0*C0;
6896  C1=1.0*C0;
6898  refit_chisq=-1.;
6899  refit_ndf=0;
6900 
6901  // Now refit with the truncated trajectory and list of hits
6902  refit_error=KalmanForward(fdc_anneal,cdc_anneal,S1,C1,refit_chisq,refit_ndf);
6903  if (refit_error==FIT_SUCCEEDED
6904  //|| (refit_error==PRUNED_TOO_MANY_HITS)
6905  ){
6906  C=C1;
6907  S=S1;
6908  chisq=refit_chisq;
6909  numdof=refit_ndf;
6910 
6911  if (DEBUG_LEVEL>1) _DBG_ << "Refit succeeded" << endl;
6912  return FIT_SUCCEEDED;
6913  }
6914  // Truncate the trajectory
6915  if (break_id>0) break_id--;
6916  else break;
6917  zhit=my_fdchits[break_id]->z;
6918  k=0;
6919  for (;k<forward_traj.size();k++){
6920  double z=forward_traj[k].z;
6921  if (z<zhit) break;
6922  }
6924 
6925  }
6926 
6927  // If the refit did not work, restore the old list hits used in the fit
6928  // before the track recovery was attempted.
6929  for (unsigned int k=0;k<num_cdchits;k++){
6930  cdc_used_in_fit[k]=old_cdc_used_status[k];
6931  }
6932  for (unsigned int k=0;k<num_fdchits;k++){
6933  fdc_used_in_fit[k]=old_fdc_used_status[k];
6934  }
6935 
6936  return FIT_FAILED;
6937 }
6938 
6939 
6940 
6941 // Routine to fit hits in the FDC and the CDC using the forward parametrization
6943  unsigned int num_cdchits=my_cdchits.size();
6944  unsigned int num_fdchits=my_fdchits.size();
6945  unsigned int max_fdc_index=num_fdchits-1;
6946 
6947  // Vectors to keep track of updated state vectors and covariance matrices (after
6948  // adding the hit information)
6949  vector<bool>last_fdc_used_in_fit(num_fdchits);
6950  vector<bool>last_cdc_used_in_fit(num_cdchits);
6951  vector<pull_t>forward_pulls;
6952  vector<pull_t>last_forward_pulls;
6953 
6954  // Charge
6955  // double q=input_params.charge();
6956 
6957  // Covariance matrix and state vector
6958  DMatrix5x5 C;
6959  DMatrix5x1 S=S0;
6960 
6961  // Create matrices to store results from previous iteration
6962  DMatrix5x1 Slast(S);
6963  DMatrix5x5 Clast(C0);
6964  // last z position
6965  double last_z=z_;
6966 
6967  double fdc_anneal=FORWARD_ANNEAL_SCALE+1.; // variable for scaling cut for hit pruning
6968  double cdc_anneal=ANNEAL_SCALE+1.; // variable for scaling cut for hit pruning
6969 
6970  // Chi-squared and degrees of freedom
6971  double chisq=-1.,chisq_forward=-1.;
6972  unsigned int my_ndf=0;
6973  unsigned int last_ndf=1;
6974  kalman_error_t error=FIT_NOT_DONE,last_error=FIT_NOT_DONE;
6975 
6976  // Iterate over reference trajectories
6977  for (int iter=0;
6979  iter++) {
6980  // These variables provide the approximate location along the trajectory
6981  // where there is an indication of a kink in the track
6982  break_point_fdc_index=max_fdc_index;
6985 
6986  // Reset material map index
6988 
6989  // Abort if momentum is too low
6990  if (fabs(S(state_q_over_p))>Q_OVER_P_MAX) break;
6991 
6992  // Initialize path length variable and flight time
6993  len=0;
6994  ftime=0.;
6995  var_ftime=0.;
6996 
6997  // Scale cut for pruning hits according to the iteration number
6998  fdc_anneal=(iter<MIN_ITER)?(FORWARD_ANNEAL_SCALE/pow(FORWARD_ANNEAL_POW_CONST,iter)+1.):1.;
6999  cdc_anneal=(iter<MIN_ITER)?(ANNEAL_SCALE/pow(ANNEAL_POW_CONST,iter)+1.):1.;
7000 
7001  // Swim through the field out to the most upstream FDC hit
7002  jerror_t ref_track_error=SetReferenceTrajectory(S);
7003  if (ref_track_error!=NOERROR){
7004  if (iter==0) return FIT_FAILED;
7005  break;
7006  }
7007 
7008  // Reset the status of the cdc hits
7009  for (unsigned int j=0;j<num_cdchits;j++){
7010  if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
7011  }
7012 
7013  // perform the kalman filter
7014  C=C0;
7015  bool did_second_refit=false;
7016  error=KalmanForward(fdc_anneal,cdc_anneal,S,C,chisq,my_ndf);
7017  if (DEBUG_LEVEL>1){
7018  _DBG_ << "Iter: " << iter+1 << " Chi2=" << chisq << " Ndf=" << my_ndf << " Error code: " << error << endl;
7019  }
7020  // Try to recover tracks that failed the first attempt at fitting by
7021  // cutting outer hits
7022  if (error!=FIT_SUCCEEDED && RECOVER_BROKEN_TRACKS
7023  && num_fdchits>2 // some minimum to make this worthwhile...
7024  && break_point_fdc_index<num_fdchits
7026  && forward_traj.size()>2*MIN_HITS_FOR_REFIT // avoid small track stubs
7027  ){
7028  DMatrix5x5 Ctemp=C;
7029  DMatrix5x1 Stemp=S;
7030  unsigned int temp_ndf=my_ndf;
7031  double temp_chi2=chisq;
7032  double x=x_,y=y_,z=z_;
7033 
7034  kalman_error_t refit_error=RecoverBrokenForwardTracks(fdc_anneal,
7035  cdc_anneal,
7036  S,C,C0,chisq,
7037  my_ndf);
7038  if (fit_type==kTimeBased && refit_error!=FIT_SUCCEEDED){
7039  fdc_anneal=1000.;
7040  cdc_anneal=1000.;
7041  refit_error=RecoverBrokenForwardTracks(fdc_anneal,
7042  cdc_anneal,
7043  S,C,C0,chisq,
7044  my_ndf);
7045  chisq=1e6;
7046  did_second_refit=true;
7047  }
7048  if (refit_error!=FIT_SUCCEEDED){
7049  if (error==PRUNED_TOO_MANY_HITS || error==BREAK_POINT_FOUND){
7050  C=Ctemp;
7051  S=Stemp;
7052  my_ndf=temp_ndf;
7053  chisq=temp_chi2;
7054  x_=x,y_=y,z_=z;
7055 
7056  if (num_cdchits<6) error=FIT_SUCCEEDED;
7057  }
7058  else error=FIT_FAILED;
7059  }
7060  else error=FIT_SUCCEEDED;
7061  }
7062  if ((error==POSITION_OUT_OF_RANGE || error==MOMENTUM_OUT_OF_RANGE)
7063  && iter==0){
7064  return FIT_FAILED;
7065  }
7066  if (error==FIT_FAILED || error==INVALID_FIT || my_ndf==0){
7067  if (iter==0) return FIT_FAILED; // first iteration failed
7068  break;
7069  }
7070 
7071  if (iter>MIN_ITER && did_second_refit==false){
7072  double new_reduced_chisq=chisq/my_ndf;
7073  double old_reduced_chisq=chisq_forward/last_ndf;
7074  double new_prob=TMath::Prob(chisq,my_ndf);
7075  double old_prob=TMath::Prob(chisq_forward,last_ndf);
7076  if (new_prob<old_prob
7077  || fabs(new_reduced_chisq-old_reduced_chisq)<CHISQ_DELTA){
7078  break;
7079  }
7080  }
7081 
7082  chisq_forward=chisq;
7083  last_ndf=my_ndf;
7084  last_error=error;
7085  Slast=S;
7086  Clast=C;
7087  last_z=z_;
7088 
7089  last_fdc_used_in_fit=fdc_used_in_fit;
7090  last_cdc_used_in_fit=cdc_used_in_fit;
7091  } //iteration
7092 
7093  IsSmoothed=false;
7094  if(fit_type==kTimeBased){
7095  forward_pulls.clear();
7096  if (SmoothForward(forward_pulls) == NOERROR){
7097  IsSmoothed = true;
7098  pulls.assign(forward_pulls.begin(),forward_pulls.end());
7099  }
7100  }
7101 
7102  // total chisq and ndf
7103  chisq_=chisq_forward;
7104  ndf_=last_ndf;
7105 
7106  // output lists of hits used in the fit and fill pull vector
7107  cdchits_used_in_fit.clear();
7108  for (unsigned int m=0;m<last_cdc_used_in_fit.size();m++){
7109  if (last_cdc_used_in_fit[m]){
7110  cdchits_used_in_fit.push_back(my_cdchits[m]->hit);
7111  }
7112  }
7113  fdchits_used_in_fit.clear();
7114  for (unsigned int m=0;m<last_fdc_used_in_fit.size();m++){
7115  if (last_fdc_used_in_fit[m]){
7116  fdchits_used_in_fit.push_back(my_fdchits[m]->hit);
7117  }
7118  }
7119  // fill pull vector
7120  //pulls.assign(last_forward_pulls.begin(),last_forward_pulls.end());
7121 
7122  // fill vector of extrapolations
7125  if (extrapolations.at(SYS_BCAL).size()==1){
7126  // There needs to be some steps inside the the volume of the BCAL for
7127  // the extrapolation to be useful. If this is not the case, clear
7128  // the extrolation vector.
7129  extrapolations[SYS_BCAL].clear();
7130  }
7131 
7132  // Extrapolate to the point of closest approach to the beam line
7133  z_=last_z;
7134  if (sqrt(Slast(state_x)*Slast(state_x)+Slast(state_y)*Slast(state_y))
7135  >EPS2){
7136  DMatrix5x5 Ctemp=Clast;
7137  DMatrix5x1 Stemp=Slast;
7138  double ztemp=z_;
7139  if (ExtrapolateToVertex(Stemp,Ctemp)==NOERROR){
7140  Clast=Ctemp;
7141  Slast=Stemp;
7142  }
7143  else{
7144  //_DBG_ << endl;
7145  z_=ztemp;
7146  }
7147  }
7148 
7149  // Final momentum, positions and tangents
7150  x_=Slast(state_x), y_=Slast(state_y);
7151  tx_=Slast(state_tx),ty_=Slast(state_ty);
7152  q_over_p_=Slast(state_q_over_p);
7153 
7154  // Convert from forward rep. to central rep.
7155  double tsquare=tx_*tx_+ty_*ty_;
7156  tanl_=1./sqrt(tsquare);
7157  double cosl=cos(atan(tanl_));
7158  q_over_pt_=q_over_p_/cosl;
7159  phi_=atan2(ty_,tx_);
7160  if (FORWARD_PARMS_COV==false){
7161  DVector2 beam_pos=beam_center+(z_-beam_z0)*beam_dir;
7162  double dx=x_-beam_pos.X();
7163  double dy=y_-beam_pos.Y();
7164  D_=sqrt(dx*dx+dy*dy)+EPS;
7165  x_ = dx; y_ = dy;
7166  double cosphi=cos(phi_);
7167  double sinphi=sin(phi_);
7168  if ((dx>0.0 && sinphi>0.0) || (dy<0.0 && cosphi>0.0)
7169  || (dy>0.0 && cosphi<0.0) || (dx<0.0 && sinphi<0.0)) D_*=-1.;
7170  TransformCovariance(Clast);
7171  }
7172  // Covariance matrix
7173  vector<double>dummy;
7174  for (unsigned int i=0;i<5;i++){
7175  dummy.clear();
7176  for(unsigned int j=0;j<5;j++){
7177  dummy.push_back(Clast(i,j));
7178  }
7179  fcov.push_back(dummy);
7180  }
7181 
7182  return last_error;
7183 }
7184 
7185 // Routine to fit hits in the CDC using the forward parametrization
7187  unsigned int num_cdchits=my_cdchits.size();
7188  unsigned int max_cdc_index=num_cdchits-1;
7189  unsigned int min_cdc_index_for_refit=MIN_HITS_FOR_REFIT-1;
7190 
7191  // Charge
7192  // double q=input_params.charge();
7193 
7194  // Covariance matrix and state vector
7195  DMatrix5x5 C;
7196  DMatrix5x1 S=S0;
7197 
7198  // Create matrices to store results from previous iteration
7199  DMatrix5x1 Slast(S);
7200  DMatrix5x5 Clast(C0);
7201 
7202  // Vectors to keep track of updated state vectors and covariance matrices (after
7203  // adding the hit information)
7204  vector<pull_t>cdc_pulls;
7205  vector<pull_t>last_cdc_pulls;
7206  vector<bool>last_cdc_used_in_fit;
7207 
7208  double anneal_factor=ANNEAL_SCALE+1.;
7209  kalman_error_t error=FIT_NOT_DONE,last_error=FIT_NOT_DONE;
7210 
7211  // Chi-squared and degrees of freedom
7212  double chisq=-1.,chisq_forward=-1.;
7213  unsigned int my_ndf=0;
7214  unsigned int last_ndf=1;
7215  // last z position
7216  double zlast=0.;
7217  // unsigned int last_break_point_index=0,last_break_point_step_index=0;
7218 
7219  // Iterate over reference trajectories
7220  for (int iter2=0;
7222  iter2++){
7223  if (DEBUG_LEVEL>1){
7224  _DBG_ <<"-------- iteration " << iter2+1 << " -----------" <<endl;
7225  }
7226 
7227  // These variables provide the approximate location along the trajectory
7228  // where there is an indication of a kink in the track
7229  break_point_cdc_index=max_cdc_index;
7231 
7232  // Reset material map index
7234 
7235  // Abort if momentum is too low
7236  if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){
7237  //printf("Too low momentum? %f\n",1/S(state_q_over_p));
7238  break;
7239  }
7240 
7241  // Scale cut for pruning hits according to the iteration number
7242  anneal_factor=(iter2<MIN_ITER)?(ANNEAL_SCALE/pow(ANNEAL_POW_CONST,iter2)+1.):1.;
7243 
7244  // Initialize path length variable and flight time
7245  len=0;
7246  ftime=0.;
7247  var_ftime=0.;
7248 
7249  // Swim to create the reference trajectory
7250  jerror_t ref_track_error=SetCDCForwardReferenceTrajectory(S);
7251  if (ref_track_error!=NOERROR){
7252  if (iter2==0) return FIT_FAILED;
7253  break;
7254  }
7255 
7256  // Reset the status of the cdc hits
7257  for (unsigned int j=0;j<num_cdchits;j++){
7258  if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
7259  }
7260 
7261  // perform the filter
7262  C=C0;
7263  bool did_second_refit=false;
7264  error=KalmanForwardCDC(anneal_factor,S,C,chisq,my_ndf);
7265 
7266  // Try to recover tracks that failed the first attempt at fitting by
7267  // cutting outer hits
7268  if (error!=FIT_SUCCEEDED && RECOVER_BROKEN_TRACKS
7269  && num_cdchits>=MIN_HITS_FOR_REFIT){
7270  DMatrix5x5 Ctemp=C;
7271  DMatrix5x1 Stemp=S;
7272  unsigned int temp_ndf=my_ndf;
7273  double temp_chi2=chisq;
7274  double x=x_,y=y_,z=z_;
7275 
7276  if (error==MOMENTUM_OUT_OF_RANGE){
7277  //_DBG_ << "Momentum out of range" <<endl;
7278  unsigned int new_index=(3*max_cdc_index)/4;
7279  break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
7280  }
7281 
7282  if (error==BROKEN_COVARIANCE_MATRIX){
7283  break_point_cdc_index=min_cdc_index_for_refit;
7284  //_DBG_ << "Bad Cov" <<endl;
7285  }
7286  if (error==POSITION_OUT_OF_RANGE){
7287  //_DBG_ << "Bad position" << endl;
7288  unsigned int new_index=(max_cdc_index)/2;
7289  break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
7290  }
7291  if (error==PRUNED_TOO_MANY_HITS){
7292  // _DBG_ << "Prune" << endl;
7293  unsigned int new_index=(3*max_cdc_index)/4;
7294  break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
7295  // anneal_factor*=10.;
7296  }
7297 
7298  kalman_error_t refit_error=RecoverBrokenTracks(anneal_factor,S,C,C0,chisq,my_ndf);
7299  if (fit_type==kTimeBased && refit_error!=FIT_SUCCEEDED){
7300  anneal_factor=1000.;
7301  refit_error=RecoverBrokenTracks(anneal_factor,S,C,C0,chisq,my_ndf);
7302  chisq=1e6;
7303  did_second_refit=true;
7304  }
7305 
7306  if (refit_error!=FIT_SUCCEEDED){
7307  if (error==PRUNED_TOO_MANY_HITS || error==BREAK_POINT_FOUND){
7308  C=Ctemp;
7309  S=Stemp;
7310  my_ndf=temp_ndf;
7311  chisq=temp_chi2;
7312  x_=x,y_=y,z_=z;
7313 
7314  // error=FIT_SUCCEEDED;
7315  }
7316  else error=FIT_FAILED;
7317  }
7318  else error=FIT_SUCCEEDED;
7319  }
7320  if ((error==POSITION_OUT_OF_RANGE || error==MOMENTUM_OUT_OF_RANGE)
7321  && iter2==0){
7322  return FIT_FAILED;
7323  }
7324  if (error==FIT_FAILED || error==INVALID_FIT || my_ndf==0){
7325  if (iter2==0) return error;
7326  break;
7327  }
7328 
7329  if (DEBUG_LEVEL>1) _DBG_ << "--> Chisq " << chisq << " NDF "
7330  << my_ndf
7331  << " Prob: " << TMath::Prob(chisq,my_ndf)
7332  << endl;
7333 
7334  if (iter2>MIN_ITER && did_second_refit==false){
7335  double new_reduced_chisq=chisq/my_ndf;
7336  double old_reduced_chisq=chisq_forward/last_ndf;
7337  double new_prob=TMath::Prob(chisq,my_ndf);
7338  double old_prob=TMath::Prob(chisq_forward,last_ndf);
7339  if (new_prob<old_prob
7340  || fabs(new_reduced_chisq-old_reduced_chisq)<CHISQ_DELTA) break;
7341  }
7342 
7343  chisq_forward=chisq;
7344  Slast=S;
7345  Clast=C;
7346  last_error=error;
7347  last_ndf=my_ndf;
7348  zlast=z_;
7349 
7350  last_cdc_used_in_fit=cdc_used_in_fit;
7351  } //iteration
7352 
7353  // Run the smoother
7354  IsSmoothed=false;
7355  if(fit_type==kTimeBased){
7356  cdc_pulls.clear();
7357  if (SmoothForwardCDC(cdc_pulls) == NOERROR){
7358  IsSmoothed = true;
7359  pulls.assign(cdc_pulls.begin(),cdc_pulls.end());
7360  }
7361  }
7362 
7363  // total chisq and ndf
7364  chisq_=chisq_forward;
7365  ndf_=last_ndf;
7366 
7367  // output lists of hits used in the fit and fill the pull vector
7368  cdchits_used_in_fit.clear();
7369  for (unsigned int m=0;m<last_cdc_used_in_fit.size();m++){
7370  if (last_cdc_used_in_fit[m]){
7371  cdchits_used_in_fit.push_back(my_cdchits[m]->hit);
7372  }
7373  }
7374  // output pulls vector
7375  //pulls.assign(last_cdc_pulls.begin(),last_cdc_pulls.end());
7376 
7377  // Fill extrapolation vector
7380  if (extrapolations.at(SYS_BCAL).size()==1){
7381  // There needs to be some steps inside the the volume of the BCAL for
7382  // the extrapolation to be useful. If this is not the case, clear
7383  // the extrolation vector.
7384  extrapolations[SYS_BCAL].clear();
7385  }
7386 
7387  // Extrapolate to the point of closest approach to the beam line
7388  z_=zlast;
7389  if (sqrt(Slast(state_x)*Slast(state_x)+Slast(state_y)*Slast(state_y))
7390  >EPS2)
7391  if (ExtrapolateToVertex(Slast,Clast)!=NOERROR) return EXTRAPOLATION_FAILED;
7392 
7393  // Final momentum, positions and tangents
7394  x_=Slast(state_x), y_=Slast(state_y);
7395  tx_=Slast(state_tx),ty_=Slast(state_ty);
7396  q_over_p_=Slast(state_q_over_p);
7397 
7398  // Convert from forward rep. to central rep.
7399  double tsquare=tx_*tx_+ty_*ty_;
7400  tanl_=1./sqrt(tsquare);
7401  double cosl=cos(atan(tanl_));
7402  q_over_pt_=q_over_p_/cosl;
7403  phi_=atan2(ty_,tx_);
7404  if (FORWARD_PARMS_COV==false){
7405  DVector2 beam_pos=beam_center+(z_-beam_z0)*beam_dir;
7406  double dx=x_-beam_pos.X();
7407  double dy=y_-beam_pos.Y();
7408  D_=sqrt(dx*dx+dy*dy)+EPS;
7409  x_ = dx; y_ = dy;
7410  double cosphi=cos(phi_);
7411  double sinphi=sin(phi_);
7412  if ((dx>0.0 && sinphi>0.0) || (dy<0.0 && cosphi>0.0)
7413  || (dy>0.0 && cosphi<0.0) || (dx<0.0 && sinphi<0.0)) D_*=-1.;
7414  TransformCovariance(Clast);
7415  }
7416  // Covariance matrix
7417  vector<double>dummy;
7418  // ... forward parameterization
7419  fcov.clear();
7420  for (unsigned int i=0;i<5;i++){
7421  dummy.clear();
7422  for(unsigned int j=0;j<5;j++){
7423  dummy.push_back(Clast(i,j));
7424  }
7425  fcov.push_back(dummy);
7426  }
7427 
7428  return last_error;
7429 }
7430 
7431 // Routine to fit hits in the CDC using the central parametrization
7433  const DMatrix5x1 &S0,
7434  const DMatrix5x5 &C0){
7435  // Initial position in x and y
7436  DVector2 pos(startpos);
7437 
7438  // Charge
7439  // double q=input_params.charge();
7440 
7441  // Covariance matrix and state vector
7442  DMatrix5x5 Cc;
7443  DMatrix5x1 Sc=S0;
7444 
7445  // Variables to store values from previous iterations
7446  DMatrix5x1 Sclast(Sc);
7447  DMatrix5x5 Cclast(C0);
7448  DVector2 last_pos=pos;
7449 
7450  unsigned int num_cdchits=my_cdchits.size();
7451  unsigned int max_cdc_index=num_cdchits-1;
7452  unsigned int min_cdc_index_for_refit=MIN_HITS_FOR_REFIT-1;
7453 
7454  // Vectors to keep track of updated state vectors and covariance matrices (after
7455  // adding the hit information)
7456  vector<pull_t>last_cdc_pulls;
7457  vector<pull_t>cdc_pulls;
7458  vector<bool>last_cdc_used_in_fit(num_cdchits);
7459 
7460  double anneal_factor=ANNEAL_SCALE+1.; // variable for scaling cut for hit pruning
7461 
7462  //Initialization of chisq, ndf, and error status
7463  double chisq_iter=-1.,chisq=-1.;
7464  unsigned int my_ndf=0;
7465  ndf_=0.;
7466  unsigned int last_ndf=1;
7467  kalman_error_t error=FIT_NOT_DONE,last_error=FIT_NOT_DONE;
7468 
7469  // Iterate over reference trajectories
7470  int iter2=0;
7472  iter2++){
7473  if (DEBUG_LEVEL>1){
7474  _DBG_ <<"-------- iteration " << iter2+1 << " -----------" <<endl;
7475  }
7476 
7477  // These variables provide the approximate location along the trajectory
7478  // where there is an indication of a kink in the track
7479  break_point_cdc_index=max_cdc_index;
7481 
7482  // Reset material map index
7484 
7485  // Break out of loop if p is too small
7486  double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl)));
7487  if (fabs(q_over_p)>Q_OVER_P_MAX) break;
7488 
7489  // Initialize path length variable and flight time
7490  len=0.;
7491  ftime=0.;
7492  var_ftime=0.;
7493 
7494  // Scale cut for pruning hits according to the iteration number
7495  anneal_factor=(iter2<MIN_ITER)?(ANNEAL_SCALE/pow(ANNEAL_POW_CONST,iter2)+1.):1.;
7496 
7497  // Initialize trajectory deque
7498  jerror_t ref_track_error=SetCDCReferenceTrajectory(last_pos,Sc);
7499  if (ref_track_error!=NOERROR){
7500  if (iter2==0) return FIT_FAILED;
7501  break;
7502  }
7503 
7504  // Reset the status of the cdc hits
7505  for (unsigned int j=0;j<num_cdchits;j++){
7506  if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
7507  }
7508 
7509  // perform the fit
7510  Cc=C0;
7511  bool did_second_refit=false;
7512  error=KalmanCentral(anneal_factor,Sc,Cc,pos,chisq,my_ndf);
7513 
7514  // Try to recover tracks that failed the first attempt at fitting by
7515  // throwing away outer hits.
7516  if (error!=FIT_SUCCEEDED && RECOVER_BROKEN_TRACKS
7517  && num_cdchits>=MIN_HITS_FOR_REFIT){
7518  DVector2 temp_pos=pos;
7519  DMatrix5x1 Stemp=Sc;
7520  DMatrix5x5 Ctemp=Cc;
7521  unsigned int temp_ndf=my_ndf;
7522  double temp_chi2=chisq;
7523 
7524  if (error==MOMENTUM_OUT_OF_RANGE){
7525  //_DBG_ << "Momentum out of range" <<endl;
7526  unsigned int new_index=(3*max_cdc_index)/4;
7527  break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
7528  }
7529 
7530  if (error==BROKEN_COVARIANCE_MATRIX){
7531  break_point_cdc_index=min_cdc_index_for_refit;
7532  //_DBG_ << "Bad Cov" <<endl;
7533  }
7534  if (error==POSITION_OUT_OF_RANGE){
7535  //_DBG_ << "Bad position" << endl;
7536  unsigned int new_index=(max_cdc_index)/2;
7537  break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
7538  }
7539  if (error==PRUNED_TOO_MANY_HITS){
7540  unsigned int new_index=(3*max_cdc_index)/4;
7541  break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
7542  //anneal_factor*=10.;
7543  //_DBG_ << "Prune" << endl;
7544  }
7545 
7546  kalman_error_t refit_error=RecoverBrokenTracks(anneal_factor,Sc,Cc,C0,pos,chisq,my_ndf);
7547  if (fit_type==kTimeBased && refit_error!=FIT_SUCCEEDED){
7548  anneal_factor=1000.;
7549  refit_error=RecoverBrokenTracks(anneal_factor,Sc,Cc,C0,pos,chisq,my_ndf);
7550  chisq=1e6;
7551  did_second_refit=true;
7552  }
7553 
7554  if (refit_error!=FIT_SUCCEEDED){
7555  //_DBG_ << error << endl;
7556  if (error==PRUNED_TOO_MANY_HITS || error==BREAK_POINT_FOUND){
7557  Cc=Ctemp;
7558  Sc=Stemp;
7559  my_ndf=temp_ndf;
7560  chisq=temp_chi2;
7561  pos=temp_pos;
7562  if (DEBUG_LEVEL > 1) _DBG_ << " Refit did not succeed, but restoring old values" << endl;
7563 
7564  //error=FIT_SUCCEEDED;
7565  }
7566  }
7567  else error=FIT_SUCCEEDED;
7568  }
7569  if ((error==POSITION_OUT_OF_RANGE || error==MOMENTUM_OUT_OF_RANGE)
7570  && iter2==0){
7571  return FIT_FAILED;
7572  }
7573  if (error==FIT_FAILED || error==INVALID_FIT || my_ndf==0){
7574  if (iter2==0) return error;
7575  break;
7576  }
7577 
7578  if (DEBUG_LEVEL>0) _DBG_ << "--> Chisq " << chisq << " Ndof " << my_ndf
7579  << " Prob: " << TMath::Prob(chisq,my_ndf)
7580  << endl;
7581 
7582  if (iter2>MIN_ITER && did_second_refit==false){
7583  double new_reduced_chisq=chisq/my_ndf;
7584  double old_reduced_chisq=chisq_iter/last_ndf;
7585  double new_prob=TMath::Prob(chisq,my_ndf);
7586  double old_prob=TMath::Prob(chisq_iter,last_ndf);
7587  if (new_prob<old_prob
7588  || fabs(new_reduced_chisq-old_reduced_chisq)<CHISQ_DELTA) break;
7589  }
7590 
7591  // Save the current state vector and covariance matrix
7592  Cclast=Cc;
7593  Sclast=Sc;
7594  last_pos=pos;
7595  chisq_iter=chisq;
7596  last_ndf=my_ndf;
7597  last_error=error;
7598 
7599  last_cdc_used_in_fit=cdc_used_in_fit;
7600  }
7601 
7602  // Run smoother and fill pulls vector
7603  IsSmoothed=false;
7604  if(fit_type==kTimeBased){
7605  cdc_pulls.clear();
7606  if (SmoothCentral(cdc_pulls) == NOERROR){
7607  IsSmoothed = true;
7608  pulls.assign(cdc_pulls.begin(),cdc_pulls.end());
7609  }
7610  }
7611 
7612  // Fill extrapolations vector
7615  if (extrapolations.at(SYS_BCAL).size()==1){
7616  // There needs to be some steps inside the the volume of the BCAL for
7617  // the extrapolation to be useful. If this is not the case, clear
7618  // the extrolation vector.
7619  extrapolations[SYS_BCAL].clear();
7620  }
7621  if (last_pos.Mod()>0.001){ // in cm
7622  if (ExtrapolateToVertex(last_pos,Sclast,Cclast)!=NOERROR) return EXTRAPOLATION_FAILED;
7623  }
7624 
7625  // output lists of hits used in the fit
7626  cdchits_used_in_fit.clear();
7627  for (unsigned int m=0;m<last_cdc_used_in_fit.size();m++){
7628  if (last_cdc_used_in_fit[m]){
7629  cdchits_used_in_fit.push_back(my_cdchits[m]->hit);
7630  }
7631  }
7632  // output the pull information
7633  //pulls.assign(last_cdc_pulls.begin(),last_cdc_pulls.end());
7634 
7635  // Track Parameters at "vertex"
7636  phi_=Sclast(state_phi);
7637  q_over_pt_=Sclast(state_q_over_pt);
7638  tanl_=Sclast(state_tanl);
7639  x_=last_pos.X();
7640  y_=last_pos.Y();
7641  z_=Sclast(state_z);
7642  // Find the (signed) distance of closest approach to the beam line
7643  DVector2 beam_pos=beam_center+(z_-beam_z0)*beam_dir;
7644  double dx=x_-beam_pos.X();
7645  double dy=y_-beam_pos.Y();
7646  D_=sqrt(dx*dx+dy*dy)+EPS;
7647  x_ = dx; y_ = dy;
7648  double cosphi=cos(phi_);
7649  double sinphi=sin(phi_);
7650  if ((dx>0.0 && sinphi>0.0) || (dy <0.0 && cosphi>0.0)
7651  || (dy>0.0 && cosphi<0.0) || (dx<0.0 && sinphi<0.0)) D_*=-1.;
7652  // Rotate covariance matrix to coordinate system centered on x=0,y=0 in the
7653  // lab
7654  DMatrix5x5 Jc=I5x5;
7655  Jc(state_D,state_D)=(dy*cosphi-dx*sinphi)/D_;
7656  //Cclast=Cclast.SandwichMultiply(Jc);
7657  Cclast=Jc*Cclast*Jc.Transpose();
7658 
7659  if (!isfinite(x_) || !isfinite(y_) || !isfinite(z_) || !isfinite(phi_)
7660  || !isfinite(q_over_pt_) || !isfinite(tanl_)){
7661  if (DEBUG_LEVEL>0){
7662  _DBG_ << "At least one parameter is NaN or +-inf!!" <<endl;
7663  _DBG_ << "x " << x_ << " y " << y_ << " z " << z_ << " phi " << phi_
7664  << " q/pt " << q_over_pt_ << " tanl " << tanl_ << endl;
7665  }
7666  return INVALID_FIT;
7667  }
7668 
7669  // Covariance matrix at vertex
7670  fcov.clear();
7671  vector<double>dummy;
7672  for (unsigned int i=0;i<5;i++){
7673  dummy.clear();
7674  for(unsigned int j=0;j<5;j++){
7675  dummy.push_back(Cclast(i,j));
7676  }
7677  cov.push_back(dummy);
7678  }
7679 
7680  // total chisq and ndf
7681  chisq_=chisq_iter;
7682  ndf_=last_ndf;
7683  //printf("NDof %d\n",ndf);
7684 
7685  return last_error;
7686 }
7687 
7688 // Smoothing algorithm for the forward trajectory. Updates the state vector
7689 // at each step (going in the reverse direction to the filter) based on the
7690 // information from all the steps and outputs the state vector at the
7691 // outermost step.
7692 jerror_t DTrackFitterKalmanSIMD::SmoothForward(vector<pull_t>&forward_pulls){
7693  if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE;
7694 
7695  unsigned int max=forward_traj.size()-1;
7696  DMatrix5x1 S=(forward_traj[max].Skk);
7697  DMatrix5x5 C=(forward_traj[max].Ckk);
7698  DMatrix5x5 JT=forward_traj[max].J.Transpose();
7699  DMatrix5x1 Ss=S;
7700  DMatrix5x5 Cs=C;
7701  DMatrix5x5 A,dC;
7702 
7703  if (DEBUG_LEVEL>19){
7704  jout << "---- Smoothed residuals ----" <<endl;
7705  jout << setprecision(4);
7706  }
7707 
7708  for (unsigned int m=max-1;m>0;m--){
7709 
7711  mlfile << forward_traj[m].z;
7712  for (unsigned int k=0;k<5;k++){
7713  mlfile << " " << Ss(k);
7714  }
7715  for (unsigned int k=0;k<5;k++){
7716  mlfile << " " << Cs(k,k);
7717  for (unsigned int j=k+1;j<5;j++){
7718  mlfile <<" " << Cs(k,j);
7719  }
7720  }
7721  mlfile << endl;
7722  }
7723 
7724  if (forward_traj[m].h_id>0){
7725  if (forward_traj[m].h_id<1000){
7726  unsigned int id=forward_traj[m].h_id-1;
7727  if (DEBUG_LEVEL>1) _DBG_ << " Smoothing FDC ID " << id << endl;
7728  if (fdc_used_in_fit[id] && my_fdchits[id]->status==good_hit){
7729  if (DEBUG_LEVEL>1) _DBG_ << " Used in fit " << endl;
7730  A=fdc_updates[id].C*JT*C.InvertSym();
7731  Ss=fdc_updates[id].S+A*(Ss-S);
7732 
7733  if (!Ss.IsFinite()){
7734  if (DEBUG_LEVEL>1) _DBG_ << "Invalid values for smoothed parameters..." << endl;
7735  return VALUE_OUT_OF_RANGE;
7736  }
7737  dC=A*(Cs-C)*A.Transpose();
7738  Cs=fdc_updates[id].C+dC;
7739  if (!Cs.IsPosDef()){
7740  if (DEBUG_LEVEL>1)
7741  _DBG_ << "Covariance Matrix not PosDef..." << endl;
7742  return VALUE_OUT_OF_RANGE;
7743  }
7744 
7745  // Position and direction from state vector with small angle
7746  // alignment correction
7747  double x=Ss(state_x) + my_fdchits[id]->phiZ*Ss(state_y);
7748  double y=Ss(state_y) - my_fdchits[id]->phiZ*Ss(state_x);
7749  double tx=Ss(state_tx)+ my_fdchits[id]->phiZ*Ss(state_ty)
7750  - my_fdchits[id]->phiY;
7751  double ty=Ss(state_ty) - my_fdchits[id]->phiZ*Ss(state_tx)
7752  + my_fdchits[id]->phiX;
7753 
7754  double cosa=my_fdchits[id]->cosa;
7755  double sina=my_fdchits[id]->sina;
7756  double u=my_fdchits[id]->uwire;
7757  double v=my_fdchits[id]->vstrip;
7758 
7759  // Projected position along the wire without doca-dependent corrections
7760  double vpred_uncorrected=x*sina+y*cosa;
7761 
7762  // Projected position in the plane of the wires transverse to the wires
7763  double upred=x*cosa-y*sina;
7764 
7765  // Direction tangent in the u-z plane
7766  double tu=tx*cosa-ty*sina;
7767  double one_plus_tu2=1.+tu*tu;
7768  double alpha=atan(tu);
7769  double cosalpha=cos(alpha);
7770  //double cosalpha2=cosalpha*cosalpha;
7771  double sinalpha=sin(alpha);
7772 
7773  // (signed) distance of closest approach to wire
7774  double du=upred-u;
7775  double doca=du*cosalpha;
7776 
7777  // Correction for lorentz effect
7778  double nz=my_fdchits[id]->nz;
7779  double nr=my_fdchits[id]->nr;
7780  double nz_sinalpha_plus_nr_cosalpha=nz*sinalpha+nr*cosalpha;
7781 
7782  // Difference between measurement and projection
7783  double tv=tx*sina+ty*cosa;
7784  double resi=v-(vpred_uncorrected+doca*(nz_sinalpha_plus_nr_cosalpha
7785  -tv*sinalpha));
7786  double drift_time=my_fdchits[id]->t-mT0
7788  double drift = 0.0;
7789  if (USE_FDC_DRIFT_TIMES){
7790  drift=(du>0.0?1.:-1.)*fdc_drift_distance(drift_time,forward_traj[m].B);
7791  }
7792 
7793  double resi_a=drift-doca;
7794 
7795  // Variance from filter step
7796  // This V is really "R" in Fruhwirths notation, in the case that the track is used in the fit.
7797  DMatrix2x2 V=fdc_updates[id].V;
7798  // Compute projection matrix and find the variance for the residual
7799  DMatrix5x2 H_T;
7800  double temp2=nz_sinalpha_plus_nr_cosalpha-tv*sinalpha;
7801  H_T(state_x,1)=sina+cosa*cosalpha*temp2;
7802  H_T(state_y,1)=cosa-sina*cosalpha*temp2;
7803 
7804  double cos2_minus_sin2=cosalpha*cosalpha-sinalpha*sinalpha;
7805  double fac=nz*cos2_minus_sin2-2.*nr*cosalpha*sinalpha;
7806  double doca_cosalpha=doca*cosalpha;
7807  double temp=doca_cosalpha*fac;
7808  H_T(state_tx,1)=cosa*temp
7809  -doca_cosalpha*(tu*sina+tv*cosa*cos2_minus_sin2)
7810  ;
7811  H_T(state_ty,1)=-sina*temp
7812  -doca_cosalpha*(tu*cosa-tv*sina*cos2_minus_sin2)
7813  ;
7814 
7815  H_T(state_x,0)=cosa*cosalpha;
7816  H_T(state_y,0)=-sina*cosalpha;
7817  double factor=du*tu/sqrt(one_plus_tu2)/one_plus_tu2;
7818  H_T(state_ty,0)=sina*factor;
7819  H_T(state_tx,0)=-cosa*factor;
7820 
7821  // Matrix transpose H_T -> H
7822  DMatrix2x5 H=Transpose(H_T);
7823 
7824  if (my_fdchits[id]->hit->wire->layer==PLANE_TO_SKIP){
7825  //V+=Cs.SandwichMultiply(H_T);
7826  V=V+H*Cs*H_T;
7827  }
7828  else{
7829  //V-=dC.SandwichMultiply(H_T);
7830  V=V-H*dC*H_T;
7831  }
7832 
7833 
7834  vector<double> alignmentDerivatives;
7835  if (ALIGNMENT_FORWARD){
7836  alignmentDerivatives.resize(FDCTrackD::size);
7837  // Let's get the alignment derivatives
7838 
7839  // Things are assumed to be linear near the wire, derivatives can be determined analytically.
7840  // First for the wires
7841 
7842  //dDOCAW/ddeltax
7843  alignmentDerivatives[FDCTrackD::dDOCAW_dDeltaX] = -(1/sqrt(1 + pow(tx*cosa - ty*sina,2)));
7844 
7845  //dDOCAW/ddeltaz
7846  alignmentDerivatives[FDCTrackD::dDOCAW_dDeltaZ] = (tx*cosa - ty*sina)/sqrt(1 + pow(tx*cosa - ty*sina,2));
7847 
7848  //dDOCAW/ddeltaPhiX
7849  double cos2a = cos(2.*my_fdchits[id]->hit->wire->angle);
7850  double sin2a = sin(2.*my_fdchits[id]->hit->wire->angle);
7851  double cos3a = cos(3.*my_fdchits[id]->hit->wire->angle);
7852  double sin3a = sin(3.*my_fdchits[id]->hit->wire->angle);
7853  //double tx2 = tx*tx;
7854  //double ty2 = ty*ty;
7855  alignmentDerivatives[FDCTrackD::dDOCAW_dDeltaPhiX] = (sina*(-(tx*cosa) + ty*sina)*(u - x*cosa + y*sina))/
7856  pow(1 + pow(tx*cosa - ty*sina,2),1.5);
7857  alignmentDerivatives[FDCTrackD::dDOCAW_dDeltaPhiY] = -((cosa*(tx*cosa - ty*sina)*(u - x*cosa + y*sina))/
7858  pow(1 + pow(tx*cosa - ty*sina,2),1.5));
7859  alignmentDerivatives[FDCTrackD::dDOCAW_dDeltaPhiZ] = (tx*ty*u*cos2a + (x + pow(ty,2)*x - tx*ty*y)*sina +
7860  cosa*(-(tx*ty*x) + y + pow(tx,2)*y + (tx - ty)*(tx + ty)*u*sina))/
7861  pow(1 + pow(tx*cosa - ty*sina,2),1.5);
7862 
7863  // dDOCAW/dt0
7864  double t0shift=4.;//ns
7865  double drift_shift = 0.0;
7866  if(USE_FDC_DRIFT_TIMES){
7867  if (drift_time < 0.) drift_shift = drift;
7868  else drift_shift = (du>0.0?1.:-1.)*fdc_drift_distance(drift_time+t0shift,forward_traj[m].B);
7869  }
7870  alignmentDerivatives[FDCTrackD::dW_dt0]= (drift_shift-drift)/t0shift;
7871 
7872  // dDOCAW/dx
7873  alignmentDerivatives[FDCTrackD::dDOCAW_dx] = cosa/sqrt(1 + pow(tx*cosa - ty*sina,2));
7874 
7875  // dDOCAW/dy
7876  alignmentDerivatives[FDCTrackD::dDOCAW_dy] = -(sina/sqrt(1 + pow(tx*cosa - ty*sina,2)));
7877 
7878  // dDOCAW/dtx
7879  alignmentDerivatives[FDCTrackD::dDOCAW_dtx] = (cosa*(tx*cosa - ty*sina)*(u - x*cosa + y*sina))/pow(1 + pow(tx*cosa - ty*sina,2),1.5);
7880 
7881  // dDOCAW/dty
7882  alignmentDerivatives[FDCTrackD::dDOCAW_dty] = (sina*(-(tx*cosa) + ty*sina)*(u - x*cosa + y*sina))/
7883  pow(1 + pow(tx*cosa - ty*sina,2),1.5);
7884 
7885  // Then for the cathodes. The magnetic field correction now correlates the alignment constants for the wires and cathodes.
7886 
7887  //dDOCAC/ddeltax
7888  alignmentDerivatives[FDCTrackD::dDOCAC_dDeltaX] =
7889  (-nr + (-nz + ty*cosa + tx*sina)*(tx*cosa - ty*sina))/(1 + pow(tx*cosa - ty*sina,2));
7890 
7891  //dDOCAC/ddeltaz
7892  alignmentDerivatives[FDCTrackD::dDOCAC_dDeltaZ] =
7893  nz + (-nz + (nr*tx + ty)*cosa + (tx - nr*ty)*sina)/(1 + pow(tx*cosa - ty*sina,2));
7894 
7895  //dDOCAC/ddeltaPhiX
7896  alignmentDerivatives[FDCTrackD::dDOCAC_dDeltaPhiX] =
7897  (-2*y*cosa*sina*(tx*cosa - ty*sina) - 2*x*pow(sina,2)*(tx*cosa - ty*sina) -
7898  (u - x*cosa + y*sina)*(-(nz*sina) + sina*(ty*cosa + tx*sina) -
7899  cosa*(tx*cosa - ty*sina)))/(1 + pow(tx*cosa - ty*sina,2)) +
7900  (2*sina*(tx*cosa - ty*sina)*(-((u - x*cosa + y*sina)*
7901  (nr + nz*(tx*cosa - ty*sina) - (ty*cosa + tx*sina)*(tx*cosa - ty*sina))) +
7902  y*cosa*(1 + pow(tx*cosa - ty*sina,2)) + x*sina*(1 + pow(tx*cosa - ty*sina,2))))/
7903  pow(1 + pow(tx*cosa - ty*sina,2),2);
7904 
7905 
7906  //dDOCAC/ddeltaPhiY
7907  alignmentDerivatives[FDCTrackD::dDOCAC_dDeltaPhiY] = (-2*y*pow(cosa,2)*(tx*cosa - ty*sina) - 2*x*cosa*sina*(tx*cosa - ty*sina) -
7908  (u - x*cosa + y*sina)*(-(nz*cosa) + cosa*(ty*cosa + tx*sina) +
7909  sina*(tx*cosa - ty*sina)))/(1 + pow(tx*cosa - ty*sina,2)) +
7910  (2*cosa*(tx*cosa - ty*sina)*(-((u - x*cosa + y*sina)*
7911  (nr + nz*(tx*cosa - ty*sina) - (ty*cosa + tx*sina)*(tx*cosa - ty*sina))) +
7912  y*cosa*(1 + pow(tx*cosa - ty*sina,2)) + x*sina*(1 + pow(tx*cosa - ty*sina,2))))/
7913  pow(1 + pow(tx*cosa - ty*sina,2),2);
7914 
7915  //dDOCAC/ddeltaPhiZ
7916  alignmentDerivatives[FDCTrackD::dDOCAC_dDeltaPhiZ] = (-2*(ty*cosa + tx*sina)*(tx*cosa - ty*sina)*
7917  (-((u - x*cosa + y*sina)*(nr + nz*(tx*cosa - ty*sina) -
7918  (ty*cosa + tx*sina)*(tx*cosa - ty*sina))) +
7919  y*cosa*(1 + pow(tx*cosa - ty*sina,2)) + x*sina*(1 + pow(tx*cosa - ty*sina,2))))/
7920  pow(1 + pow(tx*cosa - ty*sina,2),2) +
7921  (2*y*cosa*(ty*cosa + tx*sina)*(tx*cosa - ty*sina) +
7922  2*x*sina*(ty*cosa + tx*sina)*(tx*cosa - ty*sina) -
7923  (-(y*cosa) - x*sina)*(nr + nz*(tx*cosa - ty*sina) -
7924  (ty*cosa + tx*sina)*(tx*cosa - ty*sina)) -
7925  x*cosa*(1 + pow(tx*cosa - ty*sina,2)) + y*sina*(1 + pow(tx*cosa - ty*sina,2)) -
7926  (u - x*cosa + y*sina)*(nz*(ty*cosa + tx*sina) - pow(ty*cosa + tx*sina,2) -
7927  (tx*cosa - ty*sina)*(-(tx*cosa) + ty*sina)))/(1 + pow(tx*cosa - ty*sina,2));
7928 
7929  //dDOCAC/dx
7930  alignmentDerivatives[FDCTrackD::dDOCAC_dx] = (cosa*(nr - tx*ty + nz*tx*cosa) + sina + ty*(ty - nz*cosa)*sina)/
7931  (1 + pow(tx*cosa - ty*sina,2));
7932 
7933  //dDOCAC/dy
7934  alignmentDerivatives[FDCTrackD::dDOCAC_dy] = ((1 + pow(tx,2))*cosa - (nr + tx*ty + nz*tx*cosa)*sina + nz*ty*pow(sina,2))/
7935  (1 + pow(tx*cosa - ty*sina,2));
7936 
7937  //dDOCAC/dtx
7938  alignmentDerivatives[FDCTrackD::dDOCAC_dtx] = ((u - x*cosa + y*sina)*(4*nr*tx - 2*ty*(pow(tx,2) + pow(ty,2)) + nz*(-4 + 3*pow(tx,2) + pow(ty,2))*cosa +
7939  2*(2*nr*tx + ty*(2 - pow(tx,2) + pow(ty,2)))*cos2a + nz*(tx - ty)*(tx + ty)*cos3a - 2*nz*tx*ty*sina +
7940  4*(tx - nr*ty + tx*pow(ty,2))*sin2a - 2*nz*tx*ty*sin3a))/
7941  pow(2 + pow(tx,2) + pow(ty,2) + (tx - ty)*(tx + ty)*cos2a - 2*tx*ty*sin2a,2);
7942 
7943  //dDOCAC/dty
7944  alignmentDerivatives[FDCTrackD::dDOCAC_dty] = -(((u - x*cosa + y*sina)*(-2*(pow(tx,3) + 2*nr*ty + tx*pow(ty,2)) - 2*nz*tx*ty*cosa -
7945  2*(2*tx + pow(tx,3) - 2*nr*ty - tx*pow(ty,2))*cos2a + 2*nz*tx*ty*cos3a +
7946  nz*(-4 + pow(tx,2) + 3*pow(ty,2))*sina + 4*(ty + tx*(nr + tx*ty))*sin2a + nz*(tx - ty)*(tx + ty)*sin3a))
7947  /pow(2 + pow(tx,2) + pow(ty,2) + (tx - ty)*(tx + ty)*cos2a - 2*tx*ty*sin2a,2));
7948 
7949  }
7950 
7951  if (DEBUG_LEVEL>19){
7952  jout << "Layer " << my_fdchits[id]->hit->wire->layer
7953  <<": t " << drift_time << " x "<< x << " y " << y
7954  << " coordinate along wire " << v << " resi_c " <<resi
7955  << " coordinate transverse to wire " << drift
7956  <<" resi_a " << resi_a
7957  <<endl;
7958  }
7959 
7960  double scale=1./sqrt(1.+tx*tx+ty*ty);
7961  double cosThetaRel=my_fdchits[id]->hit->wire->udir.Dot(DVector3(scale*tx,scale*ty,scale));
7962  DTrackFitter::pull_t thisPull = pull_t(resi_a,sqrt(V(0,0)),
7963  forward_traj[m].s,
7964  fdc_updates[id].tdrift,
7965  fdc_updates[id].doca,
7966  NULL,my_fdchits[id]->hit,
7967  0.,
7968  forward_traj[m].z,
7969  cosThetaRel,0.,
7970  resi,sqrt(V(1,1)));
7971  thisPull.AddTrackDerivatives(alignmentDerivatives);
7972  forward_pulls.push_back(thisPull);
7973  }
7974  else{
7975  A=forward_traj[m].Ckk*JT*C.InvertSym();
7976  Ss=forward_traj[m].Skk+A*(Ss-S);
7977  Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose();
7978  }
7979 
7980  }
7981  else{
7982  unsigned int id=forward_traj[m].h_id-1000;
7983  if (DEBUG_LEVEL>1) _DBG_ << " Smoothing CDC ID " << id << endl;
7984  if (cdc_used_in_fit[id]&&my_cdchits[id]->status==good_hit){
7985  if (DEBUG_LEVEL>1) _DBG_ << " Used in fit " << endl;
7986  A=cdc_updates[id].C*JT*C.InvertSym();
7987  Ss=cdc_updates[id].S+A*(Ss-S);
7988  Cs=cdc_updates[id].C+A*(Cs-C)*A.Transpose();
7989  if (!Cs.IsPosDef()){
7990  if (DEBUG_LEVEL>1)
7991  _DBG_ << "Covariance Matrix not PosDef..." << endl;
7992  return VALUE_OUT_OF_RANGE;
7993  }
7994  if (!Ss.IsFinite()){
7995  if (DEBUG_LEVEL>5) _DBG_ << "Invalid values for smoothed parameters..." << endl;
7996  return VALUE_OUT_OF_RANGE;
7997  }
7998 
7999  // Fill in pulls information for cdc hits
8001  cdc_updates[id],forward_pulls) != NOERROR) return VALUE_OUT_OF_RANGE;
8002  }
8003  else{
8004  A=forward_traj[m].Ckk*JT*C.InvertSym();
8005  Ss=forward_traj[m].Skk+A*(Ss-S);
8006  Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose();
8007  }
8008  }
8009  }
8010  else{
8011  A=forward_traj[m].Ckk*JT*C.InvertSym();
8012  Ss=forward_traj[m].Skk+A*(Ss-S);
8013  Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose();
8014  }
8015 
8016  S=forward_traj[m].Skk;
8017  C=forward_traj[m].Ckk;
8018  JT=forward_traj[m].J.Transpose();
8019  }
8020 
8021  return NOERROR;
8022 }
8023 
8024 // at each step (going in the reverse direction to the filter) based on the
8025 // information from all the steps.
8026 jerror_t DTrackFitterKalmanSIMD::SmoothCentral(vector<pull_t>&cdc_pulls){
8027  if (central_traj.size()<2) return RESOURCE_UNAVAILABLE;
8028 
8029  unsigned int max = central_traj.size()-1;
8030  DMatrix5x1 S=(central_traj[max].Skk);
8031  DMatrix5x5 C=(central_traj[max].Ckk);
8032  DMatrix5x5 JT=central_traj[max].J.Transpose();
8033  DMatrix5x1 Ss=S;
8034  DMatrix5x5 Cs=C;
8035  DMatrix5x5 A,dC;
8036 
8037  if (DEBUG_LEVEL>1) {
8038  _DBG_ << " S C JT at start of smoothing " << endl;
8039  S.Print(); C.Print(); JT.Print();
8040  }
8041 
8042  for (unsigned int m=max-1;m>0;m--){
8043  if (central_traj[m].h_id>0){
8044  unsigned int id=central_traj[m].h_id-1;
8045  if (DEBUG_LEVEL>1) _DBG_ << " Encountered Hit ID " << id << " At trajectory position " << m << "/" << max << endl;
8046  if (cdc_used_in_fit[id] && my_cdchits[id]->status == good_hit){
8047  if (DEBUG_LEVEL>1) _DBG_ << " SmoothCentral CDC Hit ID " << id << " used in fit " << endl;
8048 
8049  A=cdc_updates[id].C*JT*C.InvertSym();
8050  dC=Cs-C;
8051  Ss=cdc_updates[id].S+A*(Ss-S);
8052  Cs=cdc_updates[id].C+A*dC*A.Transpose();
8053 
8054  if (!Ss.IsFinite()){
8055  if (DEBUG_LEVEL>5)
8056  _DBG_ << "Invalid values for smoothed parameters..." << endl;
8057  return VALUE_OUT_OF_RANGE;
8058  }
8059  if (!Cs.IsPosDef()){
8060  if (DEBUG_LEVEL>5){
8061  _DBG_ << "Covariance Matrix not PosDef... Ckk dC A" << endl;
8062  cdc_updates[id].C.Print(); dC.Print(); A.Print();
8063  }
8064  return VALUE_OUT_OF_RANGE;
8065  }
8066 
8067  // Get estimate for energy loss
8068  double q_over_p=Ss(state_q_over_pt)*cos(atan(Ss(state_tanl)));
8069  double dEdx=GetdEdx(q_over_p,central_traj[m].K_rho_Z_over_A,
8070  central_traj[m].rho_Z_over_A,
8071  central_traj[m].LnI,central_traj[m].Z);
8072 
8073  // Use Brent's algorithm to find doca to the wire
8074  DVector2 xy(central_traj[m].xy.X()-Ss(state_D)*sin(Ss(state_phi)),
8075  central_traj[m].xy.Y()+Ss(state_D)*cos(Ss(state_phi)));
8076  DVector2 old_xy=xy;
8077  DMatrix5x1 myS=Ss;
8078  double myds;
8079  DVector2 origin=my_cdchits[id]->origin;
8080  DVector2 dir=my_cdchits[id]->dir;
8081  double z0wire=my_cdchits[id]->z0wire;
8082  //BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy,z0wire,origin,dir,myS,myds);
8083  if(BrentCentral(dEdx,xy,z0wire,origin,dir,myS,myds)!=NOERROR) return VALUE_OUT_OF_RANGE;
8084  if(DEBUG_HISTS) alignDerivHists[0]->Fill(myds);
8085  DVector2 wirepos=origin+(myS(state_z)-z0wire)*dir;
8086  double cosstereo=my_cdchits[id]->cosstereo;
8087  DVector2 diff=xy-wirepos;
8088  // here we add a small number to avoid division by zero errors
8089  double d=cosstereo*diff.Mod()+EPS;
8090 
8091  // If we are doing the alignment, we need to numerically calculate the derivatives
8092  // wrt the wire origin, direction, and the track parameters.
8093  vector<double> alignmentDerivatives;
8094  if (ALIGNMENT_CENTRAL){
8095  double dscut_min=0., dscut_max=1.;
8096  DVector3 wireDir = my_cdchits[id]->hit->wire->udir;
8097  double cosstereo_shifted;
8098  DMatrix5x1 alignS=Ss; // We will mess with this one
8099  double alignds;
8100  alignmentDerivatives.resize(12);
8101  alignmentDerivatives[CDCTrackD::dDdt0]=cdc_updates[id].dDdt0;
8102  // Wire position shift
8103  double wposShift=0.025;
8104  double wdirShift=0.00005;
8105 
8106  // Shift each track parameter value
8107  double shiftFraction=0.01;
8108  double shift_q_over_pt=shiftFraction*Ss(state_q_over_pt);
8109  double shift_phi=0.0001;
8110  double shift_tanl=shiftFraction*Ss(state_tanl);
8111  double shift_D=0.01;
8112  double shift_z=0.01;
8113 
8114  // Some data containers we don't need multiples of
8115  double z0_shifted;
8116  DVector2 shift, origin_shifted, dir_shifted, wirepos_shifted, diff_shifted, xy_shifted;
8117 
8118  // The DOCA for the shifted states == f(x+h)
8119  double d_dOriginX=0., d_dOriginY=0., d_dOriginZ=0.;
8120  double d_dDirX=0., d_dDirY=0., d_dDirZ=0.;
8121  double d_dS0=0., d_dS1=0., d_dS2=0., d_dS3=0., d_dS4=0.;
8122  // Let's do the wire shifts first
8123 
8124  //dOriginX
8125  alignS=Ss;
8126  alignds=0.;
8127  shift.Set(wposShift, 0.);
8128  origin_shifted=origin+shift;
8129  dir_shifted=dir;
8130  z0_shifted=z0wire;
8131  xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
8132  central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
8133  if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted,
8134  dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE;
8135  if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
8136  //if (BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted,
8137  // dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE;
8138  wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted;
8139  diff_shifted=xy_shifted-wirepos_shifted;
8140  d_dOriginX=cosstereo*diff_shifted.Mod()+EPS;
8141  alignmentDerivatives[CDCTrackD::dDOCAdOriginX] = (d_dOriginX - d)/wposShift;
8142  if(DEBUG_HISTS){
8143  alignDerivHists[12]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginX]);
8144  alignDerivHists[1]->Fill(alignds);
8145  brentCheckHists[1]->Fill(alignds,d_dOriginX);
8146  }
8147 
8148  //dOriginY
8149  alignS=Ss;
8150  alignds=0.;
8151  shift.Set(0.,wposShift);
8152  origin_shifted=origin+shift;
8153  dir_shifted=dir;
8154  z0_shifted=z0wire;
8155  xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
8156  central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
8157  if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted,
8158  dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE;
8159  if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
8160  //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted,
8161  // dir_shifted,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
8162  wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted;
8163  diff_shifted=xy_shifted-wirepos_shifted;
8164  d_dOriginY=cosstereo*diff_shifted.Mod()+EPS;
8165  alignmentDerivatives[CDCTrackD::dDOCAdOriginY] = (d_dOriginY - d)/wposShift;
8166  if(DEBUG_HISTS){
8167  alignDerivHists[13]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginY]);
8168  alignDerivHists[2]->Fill(alignds);
8169  brentCheckHists[1]->Fill(alignds,d_dOriginY);
8170  }
8171 
8172  //dOriginZ
8173  alignS=Ss;
8174  alignds=0.;
8175  origin_shifted=origin;
8176  dir_shifted=dir;
8177  z0_shifted=z0wire+wposShift;
8178  xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
8179  central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
8180  if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted,
8181  dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE;
8182  if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
8183  //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted,
8184  // dir_shifted,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
8185  wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted;
8186  diff_shifted=xy_shifted-wirepos_shifted;
8187  d_dOriginZ=cosstereo*diff_shifted.Mod()+EPS;
8188  alignmentDerivatives[CDCTrackD::dDOCAdOriginZ] = (d_dOriginZ - d)/wposShift;
8189  if(DEBUG_HISTS){
8190  alignDerivHists[14]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginZ]);
8191  alignDerivHists[3]->Fill(alignds);
8192  brentCheckHists[1]->Fill(alignds,d_dOriginZ);
8193  }
8194 
8195  //dDirX
8196  alignS=Ss;
8197  alignds=0.;
8198  shift.Set(wdirShift,0.);
8199  origin_shifted=origin;
8200  z0_shifted=z0wire;
8201  xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
8202  central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
8203  dir_shifted=dir+shift;
8204  cosstereo_shifted = cos((wireDir+DVector3(wdirShift,0.,0.)).Angle(DVector3(0.,0.,1.)));
8205  if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted,
8206  dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE;
8207  if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
8208  //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted,
8209  // dir_shifted,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
8210  wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted;
8211  diff_shifted=xy_shifted-wirepos_shifted;
8212  d_dDirX=cosstereo_shifted*diff_shifted.Mod()+EPS;
8213  alignmentDerivatives[CDCTrackD::dDOCAdDirX] = (d_dDirX - d)/wdirShift;
8214  if(DEBUG_HISTS){
8215  alignDerivHists[15]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirX]);
8216  alignDerivHists[4]->Fill(alignds);
8217  }
8218 
8219  //dDirY
8220  alignS=Ss;
8221  alignds=0.;
8222  shift.Set(0.,wdirShift);
8223  origin_shifted=origin;
8224  z0_shifted=z0wire;
8225  xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
8226  central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
8227  dir_shifted=dir+shift;
8228  cosstereo_shifted = cos((wireDir+DVector3(0.,wdirShift,0.)).Angle(DVector3(0.,0.,1.)));
8229  if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted,
8230  dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE;
8231  if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
8232  //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted,
8233  // dir_shifted,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
8234  wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted;
8235  diff_shifted=xy_shifted-wirepos_shifted;
8236  d_dDirY=cosstereo_shifted*diff_shifted.Mod()+EPS;
8237  alignmentDerivatives[CDCTrackD::dDOCAdDirY] = (d_dDirY - d)/wdirShift;
8238  if(DEBUG_HISTS){
8239  alignDerivHists[16]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirY]);
8240  alignDerivHists[5]->Fill(alignds);
8241  }
8242 
8243  //dDirZ
8244  alignS=Ss;
8245  alignds=0.;
8246  origin_shifted=origin;
8247  dir_shifted.Set(wireDir.X()/(wireDir.Z()+wdirShift), wireDir.Y()/(wireDir.Z()+wdirShift));
8248  z0_shifted=z0wire;
8249  xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
8250  central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
8251  cosstereo_shifted = cos((wireDir+DVector3(0.,0.,wdirShift)).Angle(DVector3(0.,0.,1.)));
8252  if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted,
8253  dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE;
8254  if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
8255  //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted,
8256  // dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE;
8257  wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted;
8258  diff_shifted=xy_shifted-wirepos_shifted;
8259  d_dDirZ=cosstereo_shifted*diff_shifted.Mod()+EPS;
8260  alignmentDerivatives[CDCTrackD::dDOCAdDirZ] = (d_dDirZ - d)/wdirShift;
8261  if(DEBUG_HISTS){
8262  alignDerivHists[17]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirZ]);
8263  alignDerivHists[6]->Fill(alignds);
8264  }
8265 
8266  // And now the derivatives wrt the track parameters
8267  //DMatrix5x1 trackShift(shift_q_over_pt, shift_phi, shift_tanl, shift_D, shift_z);
8268 
8269  DMatrix5x1 trackShiftS0(shift_q_over_pt, 0., 0., 0., 0.);
8270  DMatrix5x1 trackShiftS1(0., shift_phi, 0., 0., 0.);
8271  DMatrix5x1 trackShiftS2(0., 0., shift_tanl, 0., 0.);
8272  DMatrix5x1 trackShiftS3(0., 0., 0., shift_D, 0.);
8273  DMatrix5x1 trackShiftS4(0., 0., 0., 0., shift_z);
8274 
8275  // dS0
8276  alignS=Ss+trackShiftS0;
8277  alignds=0.;
8278  xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
8279  central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
8280  if(BrentCentral(dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
8281  if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
8282  //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
8283  wirepos_shifted=origin+(alignS(state_z)-z0wire)*dir;
8284  diff_shifted=xy_shifted-wirepos_shifted;
8285  d_dS0=cosstereo*diff_shifted.Mod()+EPS;
8286  alignmentDerivatives[CDCTrackD::dDOCAdS0] = (d_dS0 - d)/shift_q_over_pt;
8287  if(DEBUG_HISTS){
8288  alignDerivHists[18]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS0]);
8289  alignDerivHists[7]->Fill(alignds);
8290  }
8291 
8292  // dS1
8293  alignS=Ss+trackShiftS1;
8294  alignds=0.;
8295  xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
8296  central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
8297  if(BrentCentral(dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
8298  if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
8299  //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
8300  wirepos_shifted=origin+(alignS(state_z)-z0wire)*dir;
8301  diff_shifted=xy_shifted-wirepos_shifted;
8302  d_dS1=cosstereo*diff_shifted.Mod()+EPS;
8303  alignmentDerivatives[CDCTrackD::dDOCAdS1] = (d_dS1 - d)/shift_phi;
8304  if(DEBUG_HISTS){
8305  alignDerivHists[19]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS1]);
8306  alignDerivHists[8]->Fill(alignds);
8307  }
8308 
8309  // dS2
8310  alignS=Ss+trackShiftS2;
8311  alignds=0.;
8312  xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
8313  central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
8314  if(BrentCentral(dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
8315  if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
8316  //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
8317  wirepos_shifted=origin+(alignS(state_z)-z0wire)*dir;
8318  diff_shifted=xy_shifted-wirepos_shifted;
8319  d_dS2=cosstereo*diff_shifted.Mod()+EPS;
8320  alignmentDerivatives[CDCTrackD::dDOCAdS2] = (d_dS2 - d)/shift_tanl;
8321  if(DEBUG_HISTS){
8322  alignDerivHists[20]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS2]);
8323  alignDerivHists[9]->Fill(alignds);
8324  }
8325 
8326  // dS3
8327  alignS=Ss+trackShiftS3;
8328  alignds=0.;
8329  xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
8330  central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
8331  if(BrentCentral(dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
8332  if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
8333  //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
8334  wirepos_shifted=origin+(alignS(state_z)-z0wire)*dir;
8335  diff_shifted=xy_shifted-wirepos_shifted;
8336  d_dS3=cosstereo*diff_shifted.Mod()+EPS;
8337  alignmentDerivatives[CDCTrackD::dDOCAdS3] = (d_dS3 - d)/shift_D;
8338  if(DEBUG_HISTS){
8339  alignDerivHists[21]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS3]);
8340  alignDerivHists[10]->Fill(alignds);
8341  }
8342 
8343  // dS4
8344  alignS=Ss+trackShiftS4;
8345  alignds=0.;
8346  xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
8347  central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
8348  if(BrentCentral(dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
8349  if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
8350  //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
8351  wirepos_shifted=origin+(alignS(state_z)-z0wire)*dir;
8352  diff_shifted=xy_shifted-wirepos_shifted;
8353  d_dS4=cosstereo*diff_shifted.Mod()+EPS;
8354  alignmentDerivatives[CDCTrackD::dDOCAdS4] = (d_dS4 - d)/shift_z;
8355  if(DEBUG_HISTS){
8356  alignDerivHists[22]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS4]);
8357  alignDerivHists[11]->Fill(alignds);
8358  }
8359  }
8360 
8361  // Compute the Jacobian matrix
8362  // Find the field and gradient at (old_x,old_y,old_z)
8363  bfield->GetFieldAndGradient(old_xy.X(),old_xy.Y(),Ss(state_z),
8364  Bx,By,Bz,
8367  DMatrix5x5 Jc;
8368  StepJacobian(old_xy,xy-old_xy,myds,Ss,dEdx,Jc);
8369 
8370  // Projection matrix
8371  DMatrix5x1 H_T;
8372  double sinphi=sin(myS(state_phi));
8373  double cosphi=cos(myS(state_phi));
8374  double dx=diff.X();
8375  double dy=diff.Y();
8376  double cosstereo2_over_doca=cosstereo*cosstereo/d;
8377  H_T(state_D)=(dy*cosphi-dx*sinphi)*cosstereo2_over_doca;
8378  H_T(state_phi)
8379  =-myS(state_D)*cosstereo2_over_doca*(dx*cosphi+dy*sinphi);
8380  H_T(state_z)=-cosstereo2_over_doca*(dx*dir.X()+dy*dir.Y());
8381  DMatrix1x5 H;
8382  H(state_D)=H_T(state_D);
8383  H(state_phi)=H_T(state_phi);
8384  H(state_z)=H_T(state_z);
8385 
8386  double Vhit=cdc_updates[id].variance;
8387  Cs=Jc*Cs*Jc.Transpose();
8388  //double Vtrack = Cs.SandwichMultiply(Jc*H_T);
8389  double Vtrack=H*Cs*H_T;
8390  double VRes;
8391 
8392  bool skip_ring=(my_cdchits[id]->hit->wire->ring==RING_TO_SKIP);
8393  if (skip_ring) VRes = Vhit + Vtrack;
8394  else VRes = Vhit - Vtrack;
8395 
8396  if (DEBUG_LEVEL>1 && (!isfinite(VRes) || VRes < 0.0) ) _DBG_ << " SmoothCentral Problem: VRes is " << VRes << " = " << Vhit << " - " << Vtrack << endl;
8397 
8398  double lambda=atan(Ss(state_tanl));
8399  double sinl=sin(lambda);
8400  double cosl=cos(lambda);
8401  double cosThetaRel=my_cdchits[id]->hit->wire->udir.Dot(DVector3(cosphi*cosl,
8402  sinphi*cosl,
8403  sinl));
8404  pull_t thisPull(cdc_updates[id].doca-d,sqrt(VRes),
8405  central_traj[m].s,cdc_updates[id].tdrift,
8406  d,my_cdchits[id]->hit,NULL,
8407  diff.Phi(),myS(state_z),cosThetaRel,
8408  cdc_updates[id].tcorr);
8409 
8410  thisPull.AddTrackDerivatives(alignmentDerivatives);
8411  cdc_pulls.push_back(thisPull);
8412  }
8413  else{
8414  A=central_traj[m].Ckk*JT*C.InvertSym();
8415  Ss=central_traj[m].Skk+A*(Ss-S);
8416  Cs=central_traj[m].Ckk+A*(Cs-C)*A.Transpose();
8417  }
8418  }
8419  else{
8420  A=central_traj[m].Ckk*JT*C.InvertSym();
8421  Ss=central_traj[m].Skk+A*(Ss-S);
8422  Cs=central_traj[m].Ckk+A*(Cs-C)*A.Transpose();
8423  }
8424  S=central_traj[m].Skk;
8425  C=central_traj[m].Ckk;
8426  JT=central_traj[m].J.Transpose();
8427  }
8428 
8429  // ... last entries?
8430  // Don't really need since we should have already encountered all of the hits
8431 
8432  return NOERROR;
8433 
8434 }
8435 
8436 // Smoothing algorithm for the forward_traj_cdc trajectory.
8437 // Updates the state vector
8438 // at each step (going in the reverse direction to the filter) based on the
8439 // information from all the steps and outputs the state vector at the
8440 // outermost step.
8441 jerror_t DTrackFitterKalmanSIMD::SmoothForwardCDC(vector<pull_t>&cdc_pulls){
8442  if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE;
8443 
8444  unsigned int max=forward_traj.size()-1;
8445  DMatrix5x1 S=(forward_traj[max].Skk);
8446  DMatrix5x5 C=(forward_traj[max].Ckk);
8447  DMatrix5x5 JT=forward_traj[max].J.Transpose();
8448  DMatrix5x1 Ss=S;
8449  DMatrix5x5 Cs=C;
8450  DMatrix5x5 A;
8451  for (unsigned int m=max-1;m>0;m--){
8452  if (forward_traj[m].h_id>999){
8453  unsigned int cdc_index=forward_traj[m].h_id-1000;
8454  if(cdc_used_in_fit[cdc_index] && my_cdchits[cdc_index]->status == good_hit){
8455  if (DEBUG_LEVEL > 5) {
8456  _DBG_ << " Smoothing CDC index " << cdc_index << " ring " << my_cdchits[cdc_index]->hit->wire->ring
8457  << " straw " << my_cdchits[cdc_index]->hit->wire->straw << endl;
8458  }
8459 
8460  A=cdc_updates[cdc_index].C*JT*C.InvertSym();
8461  Ss=cdc_updates[cdc_index].S+A*(Ss-S);
8462  if (!Ss.IsFinite()){
8463  if (DEBUG_LEVEL>5)
8464  _DBG_ << "Invalid values for smoothed parameters..." << endl;
8465  return VALUE_OUT_OF_RANGE;
8466  }
8467 
8468  Cs=cdc_updates[cdc_index].C+A*(Cs-C)*A.Transpose();
8469 
8470  if (!Cs.IsPosDef()){
8471  if (DEBUG_LEVEL>5){
8472  _DBG_ << "Covariance Matrix not Pos Def..." << endl;
8473  _DBG_ << " cdc_updates[cdc_index].C A C_ Cs " << endl;
8474  cdc_updates[cdc_index].C.Print();
8475  A.Print();
8476  C.Print();
8477  Cs.Print();
8478  }
8479  return VALUE_OUT_OF_RANGE;
8480  }
8481  if(FillPullsVectorEntry(Ss,Cs,forward_traj[m],my_cdchits[cdc_index],
8482  cdc_updates[cdc_index],cdc_pulls) != NOERROR) return VALUE_OUT_OF_RANGE;
8483 
8484  }
8485  else{
8486  A=forward_traj[m].Ckk*JT*C.InvertSym();
8487  Ss=forward_traj[m].Skk+A*(Ss-S);
8488  Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose();
8489  }
8490  }
8491  else{
8492  A=forward_traj[m].Ckk*JT*C.InvertSym();
8493  Ss=forward_traj[m].Skk+A*(Ss-S);
8494  Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose();
8495  }
8496 
8497  S=forward_traj[m].Skk;
8498  C=forward_traj[m].Ckk;
8499  JT=forward_traj[m].J.Transpose();
8500  }
8501 
8502  return NOERROR;
8503 }
8504 
8505 // Fill the pulls vector with the best residual information using the smoothed
8506 // filter results. Uses Brent's algorithm to find the distance of closest
8507 // approach to the wire hit.
8509  const DMatrix5x5 &Cs,
8510  const DKalmanForwardTrajectory_t &traj,const DKalmanSIMDCDCHit_t *hit,const DKalmanUpdate_t &update,
8511  vector<pull_t>&my_pulls){
8512 
8513  // Get estimate for energy loss
8514  double dEdx=GetdEdx(Ss(state_q_over_p),traj.K_rho_Z_over_A,traj.rho_Z_over_A,
8515  traj.LnI,traj.Z);
8516 
8517  // Use Brent's algorithm to find the doca to the wire
8518  DMatrix5x1 myS=Ss;
8519  DMatrix5x1 myS_temp=Ss;
8520  DMatrix5x5 myC=Cs;
8521  double mydz;
8522  double z=traj.z;
8523  DVector2 origin=hit->origin;
8524  DVector2 dir=hit->dir;
8525  double z0wire=hit->z0wire;
8526  if(BrentForward(z,dEdx,z0wire,origin,dir,myS,mydz) != NOERROR) return VALUE_OUT_OF_RANGE;
8527  if(DEBUG_HISTS)alignDerivHists[23]->Fill(mydz);
8528  double new_z=z+mydz;
8529  DVector2 wirepos=origin+(new_z-z0wire)*dir;
8530  double cosstereo=hit->cosstereo;
8531  DVector2 xy(myS(state_x),myS(state_y));
8532 
8533  DVector2 diff=xy-wirepos;
8534  double d=cosstereo*diff.Mod();
8535 
8536  // If we are doing the alignment, we need to numerically calculate the derivatives
8537  // wrt the wire origin, direction, and the track parameters.
8538  vector<double> alignmentDerivatives;
8539  if (ALIGNMENT_FORWARD){
8540  double dzcut_min=0., dzcut_max=1.;
8541  DMatrix5x1 alignS=Ss; // We will mess with this one
8542  DVector3 wireDir = hit->hit->wire->udir;
8543  double cosstereo_shifted;
8544  double aligndz;
8545  alignmentDerivatives.resize(12);
8546 
8547  // Set t0 derivative
8548  alignmentDerivatives[CDCTrackD::dDdt0]=update.dDdt0;
8549 
8550  // Wire position shift
8551  double wposShift=0.025;
8552  double wdirShift=0.00005;
8553 
8554  // Shift each track parameter
8555  double shiftFraction=0.01;
8556  double shift_x=0.01;
8557  double shift_y=0.01;
8558  double shift_tx=shiftFraction*Ss(state_tx);
8559  double shift_ty=shiftFraction*Ss(state_ty);;
8560  double shift_q_over_p=shiftFraction*Ss(state_q_over_p);
8561 
8562  // Some data containers we don't need multiples of
8563  double z0_shifted, new_z_shifted;
8564  DVector2 shift, origin_shifted, dir_shifted, wirepos_shifted, diff_shifted, xy_shifted;
8565 
8566  // The DOCA for the shifted states == f(x+h)
8567  double d_dOriginX=0., d_dOriginY=0., d_dOriginZ=0.;
8568  double d_dDirX=0., d_dDirY=0., d_dDirZ=0.;
8569  double d_dS0=0., d_dS1=0., d_dS2=0., d_dS3=0., d_dS4=0.;
8570  // Let's do the wire shifts first
8571 
8572  //dOriginX
8573  alignS=Ss;
8574  aligndz=0.;
8575  shift.Set(wposShift, 0.);
8576  origin_shifted=origin+shift;
8577  dir_shifted=dir;
8578  z0_shifted=z0wire;
8579  if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8580  if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8581  //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8582  new_z_shifted=z+aligndz;
8583  wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted;
8584  xy_shifted.Set(alignS(state_x),alignS(state_y));
8585  diff_shifted=xy_shifted-wirepos_shifted;
8586  d_dOriginX=cosstereo*diff_shifted.Mod()+EPS;
8587  alignmentDerivatives[CDCTrackD::dDOCAdOriginX] = (d_dOriginX - d)/wposShift;
8588  if(DEBUG_HISTS){
8589  alignDerivHists[24]->Fill(aligndz);
8590  alignDerivHists[35]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginX]);
8591  brentCheckHists[0]->Fill(aligndz,d_dOriginX);
8592  }
8593 
8594  //dOriginY
8595  alignS=Ss;
8596  aligndz=0.;
8597  shift.Set(0.,wposShift);
8598  origin_shifted=origin+shift;
8599  dir_shifted=dir;
8600  z0_shifted=z0wire;
8601  if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8602  if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8603  //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8604  new_z_shifted=z+aligndz;
8605  wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted;
8606  xy_shifted.Set(alignS(state_x),alignS(state_y));
8607  diff_shifted=xy_shifted-wirepos_shifted;
8608  d_dOriginY=cosstereo*diff_shifted.Mod()+EPS;
8609  alignmentDerivatives[CDCTrackD::dDOCAdOriginY] = (d_dOriginY - d)/wposShift;
8610  if(DEBUG_HISTS){
8611  alignDerivHists[25]->Fill(aligndz);
8612  alignDerivHists[36]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginY]);
8613  brentCheckHists[0]->Fill(aligndz,d_dOriginY);
8614  }
8615 
8616  //dOriginZ
8617  alignS=Ss;
8618  aligndz=0.;
8619  origin_shifted=origin;
8620  dir_shifted=dir;
8621  z0_shifted=z0wire+wposShift;
8622  if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8623  if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8624  //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8625  new_z_shifted=z+aligndz;
8626  wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted;
8627  xy_shifted.Set(alignS(state_x),alignS(state_y));
8628  diff_shifted=xy_shifted-wirepos_shifted;
8629  d_dOriginZ=cosstereo*diff_shifted.Mod()+EPS;
8630  alignmentDerivatives[CDCTrackD::dDOCAdOriginZ] = (d_dOriginZ - d)/wposShift;
8631  if(DEBUG_HISTS){
8632  alignDerivHists[26]->Fill(aligndz);
8633  alignDerivHists[37]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginZ]);
8634  brentCheckHists[0]->Fill(aligndz,d_dOriginZ);
8635  }
8636 
8637  //dDirX
8638  alignS=Ss;
8639  aligndz=0.;
8640  shift.Set(wdirShift,0.);
8641  origin_shifted=origin;
8642  z0_shifted=z0wire;
8643  dir_shifted=dir+shift;
8644  cosstereo_shifted = cos((wireDir+DVector3(wdirShift,0.,0.)).Angle(DVector3(0.,0.,1.)));
8645  if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8646  if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8647  //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8648  new_z_shifted=z+aligndz;
8649  wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted;
8650  xy_shifted.Set(alignS(state_x),alignS(state_y));
8651  diff_shifted=xy_shifted-wirepos_shifted;
8652  d_dDirX=cosstereo_shifted*diff_shifted.Mod()+EPS;
8653  alignmentDerivatives[CDCTrackD::dDOCAdDirX] = (d_dDirX - d)/wdirShift;
8654  if(DEBUG_HISTS){
8655  alignDerivHists[27]->Fill(aligndz);
8656  alignDerivHists[38]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirX]);
8657  }
8658 
8659  //dDirY
8660  alignS=Ss;
8661  aligndz=0.;
8662  shift.Set(0.,wdirShift);
8663  origin_shifted=origin;
8664  z0_shifted=z0wire;
8665  dir_shifted=dir+shift;
8666  cosstereo_shifted = cos((wireDir+DVector3(0.,wdirShift,0.)).Angle(DVector3(0.,0.,1.)));
8667  if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8668  if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8669  //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8670  new_z_shifted=z+aligndz;
8671  wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted;
8672  xy_shifted.Set(alignS(state_x),alignS(state_y));
8673  diff_shifted=xy_shifted-wirepos_shifted;
8674  d_dDirY=cosstereo_shifted*diff_shifted.Mod()+EPS;
8675  alignmentDerivatives[CDCTrackD::dDOCAdDirY] = (d_dDirY - d)/wdirShift;
8676  if(DEBUG_HISTS){
8677  alignDerivHists[28]->Fill(aligndz);
8678  alignDerivHists[39]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirY]);
8679  }
8680 
8681  //dDirZ - This is divided out in this code
8682  alignS=Ss;
8683  aligndz=0.;
8684  origin_shifted=origin;
8685  dir_shifted.Set(wireDir.X()/(wireDir.Z()+wdirShift), wireDir.Y()/(wireDir.Z()+wdirShift));
8686  z0_shifted=z0wire;
8687  cosstereo_shifted = cos((wireDir+DVector3(0.,0.,wdirShift)).Angle(DVector3(0.,0.,1.)));
8688  if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8689  if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8690  //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8691  new_z_shifted=z+aligndz;
8692  wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted;
8693  xy_shifted.Set(alignS(state_x),alignS(state_y));
8694  diff_shifted=xy_shifted-wirepos_shifted;
8695  d_dDirZ=cosstereo_shifted*diff_shifted.Mod()+EPS;
8696  alignmentDerivatives[CDCTrackD::dDOCAdDirZ] = (d_dDirZ - d)/wdirShift;
8697  if(DEBUG_HISTS){
8698  alignDerivHists[29]->Fill(aligndz);
8699  alignDerivHists[40]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirZ]);
8700  }
8701 
8702  // And now the derivatives wrt the track parameters
8703 
8704  DMatrix5x1 trackShiftS0(shift_x, 0., 0., 0., 0.);
8705  DMatrix5x1 trackShiftS1(0., shift_y, 0., 0., 0.);
8706  DMatrix5x1 trackShiftS2(0., 0., shift_tx, 0., 0.);
8707  DMatrix5x1 trackShiftS3(0., 0., 0., shift_ty, 0.);
8708  DMatrix5x1 trackShiftS4(0., 0., 0., 0., shift_q_over_p);
8709 
8710  // dS0
8711  alignS=Ss+trackShiftS0;
8712  aligndz=0.;
8713  if(BrentForward(z,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8714  if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8715  //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8716  new_z_shifted=z+aligndz;
8717  wirepos_shifted=origin+(new_z_shifted-z0wire)*dir;
8718  xy_shifted.Set(alignS(state_x),alignS(state_y));
8719  diff_shifted=xy_shifted-wirepos_shifted;
8720  d_dS0=cosstereo*diff_shifted.Mod()+EPS;
8721  alignmentDerivatives[CDCTrackD::dDOCAdS0] = (d_dS0 - d)/shift_x;
8722  if(DEBUG_HISTS){
8723  alignDerivHists[30]->Fill(aligndz);
8724  alignDerivHists[41]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS0]);
8725  }
8726 
8727  // dS1
8728  alignS=Ss+trackShiftS1;
8729  aligndz=0.;
8730  if(BrentForward(z,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8731  if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8732  //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8733  new_z_shifted=z+aligndz;
8734  wirepos_shifted=origin+(new_z_shifted-z0wire)*dir;
8735  xy_shifted.Set(alignS(state_x),alignS(state_y));
8736  diff_shifted=xy_shifted-wirepos_shifted;
8737  d_dS1=cosstereo*diff_shifted.Mod()+EPS;
8738  alignmentDerivatives[CDCTrackD::dDOCAdS1] = (d_dS1 - d)/shift_y;
8739  if(DEBUG_HISTS){
8740  alignDerivHists[31]->Fill(aligndz);
8741  alignDerivHists[42]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS1]);
8742  }
8743 
8744  // dS2
8745  alignS=Ss+trackShiftS2;
8746  aligndz=0.;
8747  if(BrentForward(z,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8748  if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8749  //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8750  new_z_shifted=z+aligndz;
8751  wirepos_shifted=origin+(new_z_shifted-z0wire)*dir;
8752  xy_shifted.Set(alignS(state_x),alignS(state_y));
8753  diff_shifted=xy_shifted-wirepos_shifted;
8754  d_dS2=cosstereo*diff_shifted.Mod()+EPS;
8755  alignmentDerivatives[CDCTrackD::dDOCAdS2] = (d_dS2 - d)/shift_tx;
8756  if(DEBUG_HISTS){
8757  alignDerivHists[32]->Fill(aligndz);
8758  alignDerivHists[43]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS2]);
8759  }
8760 
8761  // dS3
8762  alignS=Ss+trackShiftS3;
8763  aligndz=0.;
8764  if(BrentForward(z,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8765  if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8766  //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8767  new_z_shifted=z+aligndz;
8768  wirepos_shifted=origin+(new_z_shifted-z0wire)*dir;
8769  xy_shifted.Set(alignS(state_x),alignS(state_y));
8770  diff_shifted=xy_shifted-wirepos_shifted;
8771  d_dS3=cosstereo*diff_shifted.Mod()+EPS;
8772  alignmentDerivatives[CDCTrackD::dDOCAdS3] = (d_dS3 - d)/shift_ty;
8773  if(DEBUG_HISTS){
8774  alignDerivHists[33]->Fill(aligndz);
8775  alignDerivHists[44]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS3]);
8776  }
8777 
8778  // dS4
8779  alignS=Ss+trackShiftS4;
8780  aligndz=0.;
8781  if(BrentForward(z,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8782  if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8783  //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8784  new_z_shifted=z+aligndz;
8785  wirepos_shifted=origin+(new_z_shifted-z0wire)*dir;
8786  xy_shifted.Set(alignS(state_x),alignS(state_y));
8787  diff_shifted=xy_shifted-wirepos_shifted;
8788  d_dS4=cosstereo*diff_shifted.Mod()+EPS;
8789  alignmentDerivatives[CDCTrackD::dDOCAdS4] = (d_dS4 - d)/shift_q_over_p;
8790  if(DEBUG_HISTS){
8791  alignDerivHists[34]->Fill(aligndz);
8792  alignDerivHists[45]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS4]);
8793  }
8794  }
8795 
8796  // Find the field and gradient at (old_x,old_y,old_z) and compute the
8797  // Jacobian matrix for transforming from S to myS
8801  DMatrix5x5 Jc;
8802  StepJacobian(z,new_z,Ss,dEdx,Jc);
8803 
8804  // Find the projection matrix
8805  DMatrix5x1 H_T;
8806  double cosstereo2_over_d=cosstereo*cosstereo/d;
8807  H_T(state_x)=diff.X()*cosstereo2_over_d;
8808  H_T(state_y)=diff.Y()*cosstereo2_over_d;
8809  DMatrix1x5 H;
8810  H(state_x)=H_T(state_x);
8811  H(state_y)=H_T(state_y);
8812 
8813  // Find the variance for this hit
8814 
8815  bool skip_ring=(hit->hit->wire->ring==RING_TO_SKIP);
8816 
8817  double V=update.variance;
8818  myC=Jc*myC*Jc.Transpose();
8819  if (skip_ring) V+=H*myC*H_T;
8820  else V-=H*myC*H_T;
8821 
8822  if (DEBUG_LEVEL>1 && (!isfinite(V) || V < 0.0) ) _DBG_ << " Problem: V is " << V << endl;
8823 
8824  double tx=Ss(state_tx);
8825  double ty=Ss(state_ty);
8826  double scale=1./sqrt(1.+tx*tx+ty*ty);
8827  double cosThetaRel=hit->hit->wire->udir.Dot(DVector3(scale*tx,scale*ty,scale));
8828 
8829  pull_t thisPull(update.doca-d,sqrt(V),traj.s,update.tdrift,d,hit->hit,
8830  NULL,diff.Phi(),new_z,cosThetaRel,update.tcorr);
8831  thisPull.AddTrackDerivatives(alignmentDerivatives);
8832  my_pulls.push_back(thisPull);
8833  return NOERROR;
8834 }
8835 
8836 // Transform the 5x5 covariance matrix from the forward parametrization to the
8837 // central parametrization.
8839  DMatrix5x5 J;
8840  double tsquare=tx_*tx_+ty_*ty_;
8841  double cosl=cos(atan(tanl_));
8842  double tanl2=tanl_*tanl_;
8843  double tanl3=tanl2*tanl_;
8844  double factor=1./sqrt(1.+tsquare);
8845  J(state_z,state_x)=tx_/tsquare;
8846  J(state_z,state_y)=ty_/tsquare;
8847  double diff=tx_*tx_-ty_*ty_;
8848  double frac=1./(tsquare*tsquare);
8849  J(state_z,state_tx)=-(x_*diff+2.*tx_*ty_*y_)*frac;
8850  J(state_z,state_ty)=-(2.*tx_*ty_*x_-y_*diff)*frac;
8851  J(state_tanl,state_tx)=-tx_*tanl3;
8852  J(state_tanl,state_ty)=-ty_*tanl3;
8853  J(state_q_over_pt,state_q_over_p)=1./cosl;
8854  J(state_q_over_pt,state_tx)=-q_over_p_*tx_*tanl3*factor;
8855  J(state_q_over_pt,state_ty)=-q_over_p_*ty_*tanl3*factor;
8856  J(state_phi,state_tx)=-ty_*tanl2;
8857  J(state_phi,state_ty)=tx_*tanl2;
8858  J(state_D,state_x)=x_/D_;
8859  J(state_D,state_y)=y_/D_;
8860 
8861  C=J*C*J.Transpose();
8862 
8863 }
8864 
8865 jerror_t DTrackFitterKalmanSIMD::BrentForward(double z, double dedx, const double z0w,
8866  const DVector2 &origin, const DVector2 &dir, DMatrix5x1 &S, double &dz){
8867 
8868  DVector2 wirepos=origin;
8869  wirepos+=(z-z0w)*dir;
8870  double dx=S(state_x)-wirepos.X();
8871  double dy=S(state_y)-wirepos.Y();
8872  double doca2 = dx*dx+dy*dy;
8873 
8874  if (BrentsAlgorithm(z,-mStepSizeZ,dedx,z0w,origin,dir,S,dz)!=NOERROR){
8875  return VALUE_OUT_OF_RANGE;
8876  }
8877 
8878  double newz = z+dz;
8879  unsigned int maxSteps=5;
8880  unsigned int stepCounter=0;
8881  if (fabs(dz)<EPS3){
8882  // doca
8883  double old_doca2=doca2;
8884 
8885  double ztemp=newz;
8886  newz=ztemp-mStepSizeZ;
8887  Step(ztemp,newz,dedx,S);
8888  // new wire position
8889  wirepos=origin;
8890  wirepos+=(newz-z0w)*dir;
8891 
8892  dx=S(state_x)-wirepos.X();
8893  dy=S(state_y)-wirepos.Y();
8894  doca2=dx*dx+dy*dy;
8895  ztemp=newz;
8896 
8897  while(doca2<old_doca2 && stepCounter<maxSteps){
8898  newz=ztemp-mStepSizeZ;
8899  old_doca2=doca2;
8900 
8901  // Step to the new z position
8902  Step(ztemp,newz,dedx,S);
8903  stepCounter++;
8904 
8905  // find the new distance to the wire
8906  wirepos=origin;
8907  wirepos+=(newz-z0w)*dir;
8908 
8909  dx=S(state_x)-wirepos.X();
8910  dy=S(state_y)-wirepos.Y();
8911  doca2=dx*dx+dy*dy;
8912 
8913  ztemp=newz;
8914  }
8915 
8916  // Find the true doca
8917  double dz2=0.;
8918  if (BrentsAlgorithm(newz,-mStepSizeZ,dedx,z0w,origin,dir,S,dz2)!=NOERROR){
8919  return VALUE_OUT_OF_RANGE;
8920  }
8921  newz=ztemp+dz2;
8922 
8923  // Change in z relative to where we started for this wire
8924  dz=newz-z;
8925  }
8926  else if (fabs(dz)>2.*mStepSizeZ-EPS3){
8927  // whoops, looks like we didn't actually bracket the minimum
8928  // after all. Swim to make sure we pass the minimum doca.
8929 
8930  double ztemp=newz;
8931  // new wire position
8932  wirepos=origin;
8933  wirepos+=(ztemp-z0w)*dir;
8934 
8935  // doca
8936  double old_doca2=doca2;
8937 
8938  dx=S(state_x)-wirepos.X();
8939  dy=S(state_y)-wirepos.Y();
8940  doca2=dx*dx+dy*dy;
8941 
8942  while(doca2<old_doca2 && stepCounter<10*maxSteps){
8943  newz=ztemp+mStepSizeZ;
8944  old_doca2=doca2;
8945 
8946  // Step to the new z position
8947  Step(ztemp,newz,dedx,S);
8948  stepCounter++;
8949 
8950  // find the new distance to the wire
8951  wirepos=origin;
8952  wirepos+=(newz-z0w)*dir;
8953 
8954  dx=S(state_x)-wirepos.X();
8955  dy=S(state_y)-wirepos.Y();
8956  doca2=dx*dx+dy*dy;
8957 
8958  ztemp=newz;
8959  }
8960 
8961  // Find the true doca
8962  double dz2=0.;
8963  if (BrentsAlgorithm(newz,mStepSizeZ,dedx,z0w,origin,dir,S,dz2)!=NOERROR){
8964  return VALUE_OUT_OF_RANGE;
8965  }
8966  newz=ztemp+dz2;
8967 
8968  // Change in z relative to where we started for this wire
8969  dz=newz-z;
8970  }
8971  return NOERROR;
8972 }
8973 
8974 jerror_t DTrackFitterKalmanSIMD::BrentCentral(double dedx, DVector2 &xy, const double z0w, const DVector2 &origin, const DVector2 &dir, DMatrix5x1 &Sc, double &ds){
8975 
8976  DVector2 wirexy=origin;
8977  wirexy+=(Sc(state_z)-z0w)*dir;
8978 
8979  // new doca
8980  double doca2=(xy-wirexy).Mod2();
8981  double old_doca2=doca2;
8982 
8983  if (BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dedx,xy,z0w,
8984  origin,dir,Sc,ds)!=NOERROR){
8985  return VALUE_OUT_OF_RANGE;
8986  }
8987 
8988  unsigned int maxSteps=3;
8989  unsigned int stepCounter=0;
8990 
8991  if (fabs(ds)<EPS3){
8992  double my_ds=ds;
8993  old_doca2=doca2;
8994  Step(xy,-mStepSizeS,Sc,dedx);
8995  my_ds-=mStepSizeS;
8996  wirexy=origin;
8997  wirexy+=(Sc(state_z)-z0w)*dir;
8998  doca2=(xy-wirexy).Mod2();
8999  while(doca2<old_doca2 && stepCounter<maxSteps){
9000  old_doca2=doca2;
9001  // Bail if the transverse momentum has dropped below some minimum
9002  if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX){
9003  return VALUE_OUT_OF_RANGE;
9004  }
9005 
9006  // Step through the field
9007  Step(xy,-mStepSizeS,Sc,dedx);
9008  stepCounter++;
9009 
9010  wirexy=origin;
9011  wirexy+=(Sc(state_z)-z0w)*dir;
9012  doca2=(xy-wirexy).Mod2();
9013 
9014  my_ds-=mStepSizeS;
9015  }
9016  // Swim to the "true" doca
9017  double ds2=0.;
9018  if (BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dedx,xy,z0w,
9019  origin,dir,Sc,ds2)!=NOERROR){
9020  return VALUE_OUT_OF_RANGE;
9021  }
9022  ds=my_ds+ds2;
9023  }
9024  else if (fabs(ds)>2*mStepSizeS-EPS3){
9025  double my_ds=ds;
9026 
9027  // new wire position
9028  wirexy=origin;
9029  wirexy+=(Sc(state_z)-z0w)*dir;
9030 
9031  // doca
9032  old_doca2=doca2;
9033  doca2=(xy-wirexy).Mod2();
9034 
9035  while(doca2<old_doca2 && stepCounter<maxSteps){
9036  old_doca2=doca2;
9037 
9038  // Bail if the transverse momentum has dropped below some minimum
9039  if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX){
9040  return VALUE_OUT_OF_RANGE;
9041  }
9042 
9043  // Step through the field
9044  Step(xy,mStepSizeS,Sc,dedx);
9045  stepCounter++;
9046 
9047  // Find the new distance to the wire
9048  wirexy=origin;
9049  wirexy+=(Sc(state_z)-z0w)*dir;
9050  doca2=(xy-wirexy).Mod2();
9051 
9052  my_ds+=mStepSizeS;
9053  }
9054  // Swim to the "true" doca
9055  double ds2=0.;
9056  if (BrentsAlgorithm(mStepSizeS,mStepSizeS,dedx,xy,z0w,
9057  origin,dir,Sc,ds2)!=NOERROR){
9058  return VALUE_OUT_OF_RANGE;
9059  }
9060  ds=my_ds+ds2;
9061  }
9062  return NOERROR;
9063 }
9064 
9065 // Routine to find intersections with surfaces useful at a later stage for track
9066 // matching
9068  if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE;
9069 
9070  // First deal with start counter. Only do this if the track has a chance
9071  // to intersect with the start counter volume.
9072  unsigned int inner_index=forward_traj.size()-1;
9073  unsigned int index_beyond_start_counter=inner_index;
9074  DMatrix5x1 S=forward_traj[inner_index].S;
9075  bool intersected_start_counter=false;
9076  if (sc_norm.empty()==false
9078  && forward_traj[inner_index].z<SC_END_NOSE_Z){
9079  double d_old=1000.,d=1000.,z=0.;
9080  unsigned int index=0;
9081  for (unsigned int m=0;m<12;m++){
9082  unsigned int k=inner_index;
9083  for (;k>1;k--){
9084  S=forward_traj[k].S;
9085  z=forward_traj[k].z;
9086 
9087  double dphi=atan2(S(state_y),S(state_x))-SC_PHI_SECTOR1;
9088  if (dphi<0) dphi+=2.*M_PI;
9089  index=int(floor(dphi/(2.*M_PI/30.)));
9090  if (index>29) index=0;
9091  d=sc_norm[index][m].Dot(DVector3(S(state_x),S(state_y),z)
9092  -sc_pos[index][m]);
9093  if (d*d_old<0){ // break if we cross the current plane
9094  if (m==0) index_beyond_start_counter=k;
9095  break;
9096  }
9097  d_old=d;
9098  }
9099  // if the z position would be beyond the current segment along z of
9100  // the start counter, move to the next plane
9101  if (z>sc_pos[index][m+1].z()&&m<11){
9102  continue;
9103  }
9104  // allow for a little slop at the end of the nose
9105  else if (z<sc_pos[index][sc_pos[0].size()-1].z()+0.1){
9106  // Hone in on intersection with the appropriate segment of the start
9107  // counter
9108  int count=0;
9109  DMatrix5x1 bestS=S;
9110  double dmin=d;
9111  double bestz=z;
9112  double t=forward_traj[k].t;
9113  double s=forward_traj[k].s;
9114  // Magnetic field
9115  bfield->GetField(S(state_x),S(state_y),z,Bx,By,Bz);
9116 
9117  while (fabs(d)>0.001 && count<20){
9118  // track direction
9119  DVector3 phat(S(state_tx),S(state_ty),1);
9120  phat.SetMag(1.);
9121 
9122  // Step to the start counter plane
9123  double ds=d/sc_norm[index][m].Dot(phat);
9124  FastStep(z,-ds,0.,S);
9125 
9126  // Flight time
9127  double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
9128  double one_over_beta2=1.+mass2*q_over_p_sq;
9129  if (one_over_beta2>BIG) one_over_beta2=BIG;
9130  t-=ds*sqrt(one_over_beta2); // in units where c=1
9131  s-=ds;
9132 
9133  // Find the index for the nearest start counter paddle
9134  double dphi=atan2(S(state_y),S(state_x))-SC_PHI_SECTOR1;
9135  if (dphi<0) dphi+=2.*M_PI;
9136  index=int(floor(dphi/(2.*M_PI/30.)));
9137 
9138  // Find the new distance to the start counter (which could now be to
9139  // a plane in the one adjacent to the one before the step...)
9140  d=sc_norm[index][m].Dot(DVector3(S(state_x),S(state_y),z)
9141  -sc_pos[index][m]);
9142  if (fabs(d)<fabs(dmin)){
9143  bestS=S;
9144  dmin=d;
9145  bestz=z;
9146  }
9147  count++;
9148  }
9149 
9150  // New position and momentum
9151  double tsquare=bestS(state_tx)*bestS(state_tx)
9152  +bestS(state_ty)*bestS(state_ty);
9153  double tanl=1./sqrt(tsquare);
9154  double cosl=cos(atan(tanl));
9155  double pt=cosl/fabs(bestS(state_q_over_p));
9156  double phi=atan2(bestS(state_ty),bestS(state_tx));
9157  DVector3 position(bestS(state_x),bestS(state_y),bestz);
9158  DVector3 momentum(pt*cos(phi),pt*sin(phi),pt*tanl);
9159  extrapolations[SYS_START].push_back(Extrapolation_t(position,momentum,
9160  t*TIME_UNIT_CONVERSION,s));
9161 
9162  //printf("forward track:\n");
9163  //position.Print();
9164  intersected_start_counter=true;
9165  break;
9166  }
9167  }
9168  }
9169  // Accumulate multiple-scattering terms for use in matching routines
9170  double s_theta_ms_sum=0.;
9171  double theta2ms_sum=0.;
9172  if (intersected_start_counter){
9173  for (unsigned int k=inner_index;k>index_beyond_start_counter;k--){
9174  double ds_theta_ms_sq=3.*fabs(forward_traj[k].Q(state_x,state_x));
9175  s_theta_ms_sum+=sqrt(ds_theta_ms_sq);
9176  double ds=forward_traj[k].s-forward_traj[k-1].s;
9177  theta2ms_sum+=ds_theta_ms_sq/(ds*ds);
9178  }
9179  }
9180 
9181  // Deal with points within fiducial volume of chambers
9182  unsigned int fdc_plane=0;
9184  mT0MinimumDriftTime=1e6;
9185  for (int k=intersected_start_counter?index_beyond_start_counter:inner_index;k>=0;k--){
9186  double z=forward_traj[k].z;
9187  double t=forward_traj[k].t*TIME_UNIT_CONVERSION;
9188  double s=forward_traj[k].s;
9189  DMatrix5x1 S=forward_traj[k].S;
9190  double tsquare=S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty);
9191  double tanl=1./sqrt(tsquare);
9192  double cosl=cos(atan(tanl));
9193  double pt=cosl/fabs(S(state_q_over_p));
9194  double phi=atan2(S(state_ty),S(state_tx));
9195 
9196  // Find estimate for t0 using earliest drift time
9197  if (forward_traj[k].h_id>999){
9198  unsigned int index=forward_traj[k].h_id-1000;
9199  double dt=my_cdchits[index]->tdrift-t;
9200  if (dt<mT0MinimumDriftTime){
9203  }
9204  }
9205  else if (forward_traj[k].h_id>0){
9206  unsigned int index=forward_traj[k].h_id-1;
9207  double dt=my_fdchits[index]->t-t;
9208  if (dt<mT0MinimumDriftTime){
9211  }
9212  }
9213 
9214  //multiple scattering terms
9215  if (k>0){
9216  double ds_theta_ms_sq=3.*fabs(forward_traj[k].Q(state_x,state_x));
9217  s_theta_ms_sum+=sqrt(ds_theta_ms_sq);
9218  double ds=forward_traj[k].s-forward_traj[k-1].s;
9219  theta2ms_sum+=ds_theta_ms_sq/(ds*ds);
9220  }
9221  // Extrapolations in CDC region
9222  if (z<endplate_z_downstream){
9223  DVector3 position(S(state_x),S(state_y),z);
9224  DVector3 momentum(pt*cos(phi),pt*sin(phi),pt*tanl);
9225  extrapolations[SYS_CDC].push_back(Extrapolation_t(position,momentum,
9227  s_theta_ms_sum,theta2ms_sum));
9228 
9229  }
9230  else{ // extrapolations in FDC region
9231  if (fdc_plane==24){
9232  break;
9233  }
9234 
9235  // output step near wire plane
9236  if (z>fdc_z_wires[fdc_plane]-0.25){
9237  double dz=z-fdc_z_wires[fdc_plane];
9238  //printf("extrp dz %f\n",dz);
9239  if (fabs(dz)>EPS2){
9240  Step(z,fdc_z_wires[fdc_plane],0.,S);
9241  tsquare=S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty);
9242  tanl=1./sqrt(tsquare);
9243  cosl=cos(atan(tanl));
9244  pt=cosl/fabs(S(state_q_over_p));
9245  phi=atan2(S(state_ty),S(state_tx));
9246  }
9247  DVector3 position(S(state_x),S(state_y),fdc_z_wires[fdc_plane]);
9248  DVector3 momentum(pt*cos(phi),pt*sin(phi),pt*tanl);
9249  extrapolations[SYS_FDC].push_back(Extrapolation_t(position,momentum,
9251  s_theta_ms_sum,theta2ms_sum));
9252 
9253  fdc_plane++;
9254  }
9255 
9256  }
9257 
9258  }
9259 
9260 
9261  //--------------------------------
9262  // Next swim to outer detectors...
9263  //--------------------------------
9264  DMatrix5x5 Q; // multiple scattering matrix
9265 
9266  // Direction and origin of beam line
9267  DVector2 dir;
9268  DVector2 origin;
9269 
9270  // Energy loss
9271  double dEdx=0.;
9272 
9273  // material properties
9274  double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.;
9275  double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.;
9276 
9277  // Position variables
9278  double z=forward_traj[0].z;
9279  double newz=z,dz=0.;
9280  S=forward_traj[0].S;
9281 
9282  // Current time and path length
9283  double t=forward_traj[0].t;
9284  double s=forward_traj[0].s;
9285 
9286  // Loop to propagate track to outer detectors
9287  const double z_outer_max=650.;
9288  const double x_max=130.;
9289  const double y_max=130.;
9290  bool hit_tof=false;
9291  bool hit_dirc=false;
9292  while (z>Z_MIN && z<z_outer_max && fabs(S(state_x))<x_max
9293  && fabs(S(state_y))<y_max){
9294  // Bail if the momentum has dropped below some minimum
9295  if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){
9296  if (DEBUG_LEVEL>2)
9297  {
9298  _DBG_ << "Bailing: P = " << 1./fabs(S(state_q_over_p))
9299  << endl;
9300  }
9301  return VALUE_OUT_OF_RANGE;
9302  }
9303 
9304  // Check if we have passed into the BCAL
9305  double r2=S(state_x)*S(state_x)+S(state_y)*S(state_y);
9306  if (r2>89.*89. && z<400.) return VALUE_OUT_OF_RANGE;
9307  if (r2>64.9*64.9 && r2<89.*89.){
9308  if (extrapolations.at(SYS_BCAL).size()>299){
9309  return VALUE_OUT_OF_RANGE;
9310  }
9311  if (z<406.){
9312  double tsquare=S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty);
9313  double tanl=1./sqrt(tsquare);
9314  double cosl=cos(atan(tanl));
9315  double pt=cosl/fabs(S(state_q_over_p));
9316  double phi=atan2(S(state_ty),S(state_tx));
9317  DVector3 position(S(state_x),S(state_y),z);
9318  DVector3 momentum(pt*cos(phi),pt*sin(phi),pt*tanl);
9319  extrapolations[SYS_BCAL].push_back(Extrapolation_t(position,momentum,
9320  t*TIME_UNIT_CONVERSION,s));
9321  }
9322  else if (extrapolations.at(SYS_BCAL).size()<5){
9323  // There needs to be some steps inside the the volume of the BCAL for
9324  // the extrapolation to be useful. If this is not the case, clear
9325  // the extrapolation vector.
9326  extrapolations[SYS_BCAL].clear();
9327  }
9328  }
9329 
9330  // Relationship between arc length and z
9331  double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)
9332  +S(state_ty)*S(state_ty));
9333 
9334  // get material properties from the Root Geometry
9335  DVector3 pos(S(state_x),S(state_y),z);
9336  DVector3 dir(S(state_tx),S(state_ty),1.);
9337  double s_to_boundary=0.;
9338  if (geom->FindMatKalman(pos,dir,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
9339  chi2c_factor,chi2a_factor,chi2a_corr,
9340  last_material_map,&s_to_boundary)
9341  !=NOERROR){
9342  if (DEBUG_LEVEL>0)
9343  {
9344  _DBG_ << "Material error in ExtrapolateForwardToOuterDetectors!"<< endl;
9345  _DBG_ << " Position (x,y,z)=("<<pos.x()<<","<<pos.y()<<","<<pos.z()<<")"
9346  <<endl;
9347  }
9348  return VALUE_OUT_OF_RANGE;
9349  }
9350 
9351  // Get dEdx for the upcoming step
9352  if (CORRECT_FOR_ELOSS){
9353  dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI,Z);
9354  }
9355 
9356  // Adjust the step size
9357  double ds=mStepSizeS;
9358  if (fabs(dEdx)>EPS){
9359  ds=DE_PER_STEP/fabs(dEdx);
9360  }
9361  if (ds>mStepSizeS) ds=mStepSizeS;
9362  if (s_to_boundary<ds) ds=s_to_boundary;
9363  if (ds<MIN_STEP_SIZE) ds=MIN_STEP_SIZE;
9364  if (ds<0.5 && z<406. && r2>65.*65.) ds=0.5;
9365  dz=ds*dz_ds;
9366  newz=z+dz;
9367  if (hit_tof==false && newz>dTOFz){
9368  newz=dTOFz+EPS;
9369  ds=(newz-z)/dz_ds;
9370  }
9371  if (hit_dirc==false && newz>dDIRCz){
9372  newz=dDIRCz+EPS;
9373  ds=(newz-z)/dz_ds;
9374  }
9375  if (newz>dFCALz){
9376  newz=dFCALz+EPS;
9377  ds=(newz-z)/dz_ds;
9378  }
9379  bool got_fdc_hit=false;
9380  if (fdc_plane<24 && newz>fdc_z_wires[fdc_plane]){
9381  newz=fdc_z_wires[fdc_plane];
9382  ds=(newz-z)/dz_ds;
9383  got_fdc_hit=true;
9384  }
9385  s+=ds;
9386 
9387  // Flight time
9388  double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
9389  double one_over_beta2=1.+mass2*q_over_p_sq;
9390  if (one_over_beta2>BIG) one_over_beta2=BIG;
9391  t+=ds*sqrt(one_over_beta2); // in units where c=1
9392 
9393  // Get the contribution to the covariance matrix due to multiple
9394  // scattering
9395  GetProcessNoise(z,ds,chi2c_factor,chi2a_factor,chi2a_corr,S,Q);
9396  double ds_theta_ms_sq=3.*fabs(Q(state_x,state_x));
9397  s_theta_ms_sum+=sqrt(ds_theta_ms_sq);
9398  theta2ms_sum+=ds_theta_ms_sq/(ds*ds);
9399 
9400  // Step through field
9401  Step(z,newz,dEdx,S);
9402 
9403  if (got_fdc_hit){
9404  double tsquare=S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty);
9405  double tanl=1./sqrt(tsquare);
9406  double cosl=cos(atan(tanl));
9407  double pt=cosl/fabs(S(state_q_over_p));
9408  double phi=atan2(S(state_ty),S(state_tx));
9409  DVector3 position(S(state_x),S(state_y),z);
9410  DVector3 momentum(pt*cos(phi),pt*sin(phi),pt*tanl);
9411  extrapolations[SYS_FDC].push_back(Extrapolation_t(position,momentum,
9413  s_theta_ms_sum,theta2ms_sum));
9414 
9415  fdc_plane++;
9416  }
9417  if (hit_dirc==false && newz>dDIRCz){
9418  hit_dirc=true;
9419 
9420  double tsquare=S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty);
9421  double tanl=1./sqrt(tsquare);
9422  double cosl=cos(atan(tanl));
9423  double pt=cosl/fabs(S(state_q_over_p));
9424  double phi=atan2(S(state_ty),S(state_tx));
9425  DVector3 position(S(state_x),S(state_y),z);
9426  DVector3 momentum(pt*cos(phi),pt*sin(phi),pt*tanl);
9427  extrapolations[SYS_DIRC].push_back(Extrapolation_t(position,momentum,
9428  t*TIME_UNIT_CONVERSION,s));
9429  }
9430  if (hit_tof==false && newz>dTOFz){
9431  hit_tof=true;
9432 
9433  double tsquare=S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty);
9434  double tanl=1./sqrt(tsquare);
9435  double cosl=cos(atan(tanl));
9436  double pt=cosl/fabs(S(state_q_over_p));
9437  double phi=atan2(S(state_ty),S(state_tx));
9438  DVector3 position(S(state_x),S(state_y),z);
9439  DVector3 momentum(pt*cos(phi),pt*sin(phi),pt*tanl);
9440  extrapolations[SYS_TOF].push_back(Extrapolation_t(position,momentum,
9441  t*TIME_UNIT_CONVERSION,s));
9442  }
9443  if (newz>dFCALz){
9444  double tsquare=S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty);
9445  double tanl=1./sqrt(tsquare);
9446  double cosl=cos(atan(tanl));
9447  double pt=cosl/fabs(S(state_q_over_p));
9448  double phi=atan2(S(state_ty),S(state_tx));
9449  DVector3 position(S(state_x),S(state_y),z);
9450  DVector3 momentum(pt*cos(phi),pt*sin(phi),pt*tanl);
9451  extrapolations[SYS_FCAL].push_back(Extrapolation_t(position,momentum,
9452  t*TIME_UNIT_CONVERSION,s));
9453 
9454  // add another extrapolation point at downstream end of FCAL
9455  double zend=newz+45.;
9456  Step(newz,zend,dEdx,S);
9457  ds=(zend-newz)/dz_ds;
9458  t+=ds*sqrt(one_over_beta2); // in units where c=1
9459  s+=ds;
9460  tsquare=S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty);
9461  tanl=1./sqrt(tsquare);
9462  cosl=cos(atan(tanl));
9463  pt=cosl/fabs(S(state_q_over_p));
9464  phi=atan2(S(state_ty),S(state_tx));
9465  position.SetXYZ(S(state_x),S(state_y),zend);
9466  momentum.SetXYZ(pt*cos(phi),pt*sin(phi),pt*tanl);
9467  extrapolations[SYS_FCAL].push_back(Extrapolation_t(position,momentum,
9468  t*TIME_UNIT_CONVERSION,s));
9469 
9470  return NOERROR;
9471  }
9472  z=newz;
9473  }
9474  return NOERROR;
9475 }
9476 
9477 // Routine to find intersections with surfaces useful at a later stage for track
9478 // matching
9480  if (central_traj.size()<2) return RESOURCE_UNAVAILABLE;
9481 
9482  // First deal with start counter. Only do this if the track has a chance
9483  // to intersect with the start counter volume.
9484  unsigned int inner_index=central_traj.size()-1;
9485  unsigned int index_beyond_start_counter=inner_index;
9486  DVector2 xy=central_traj[inner_index].xy;
9487  DMatrix5x1 S=central_traj[inner_index].S;
9488  if (sc_norm.empty()==false
9489  &&xy.Mod2()<SC_BARREL_R2&& S(state_z)<SC_END_NOSE_Z){
9490  double d_old=1000.,d=1000.,z=0.;
9491  unsigned int index=0;
9492  for (unsigned int m=0;m<12;m++){
9493  unsigned int k=inner_index;
9494  for (;k>1;k--){
9495  S=central_traj[k].S;
9496  z=S(state_z);
9497  xy=central_traj[k].xy;
9498 
9499  double dphi=xy.Phi()-SC_PHI_SECTOR1;
9500  if (dphi<0) dphi+=2.*M_PI;
9501  index=int(floor(dphi/(2.*M_PI/30.)));
9502  if (index>29) index=0;
9503  //cout << "dphi " << dphi << " " << index << endl;
9504 
9505  d=sc_norm[index][m].Dot(DVector3(xy.X(),xy.Y(),z)
9506  -sc_pos[index][m]);
9507 
9508  if (d*d_old<0){ // break if we cross the current plane
9509  if (m==0) index_beyond_start_counter=k;
9510  break;
9511  }
9512  d_old=d;
9513  }
9514  // if the z position would be beyond the current segment along z of
9515  // the start counter, move to the next plane
9516  if (z>sc_pos[index][m+1].z()&&m<11){
9517  continue;
9518  }
9519  // allow for a little slop at the end of the nose
9520  else if (z<sc_pos[index][sc_pos[0].size()-1].z()+0.1){
9521  // Propagate the state and covariance through the field
9522  // using a straight-line approximation for each step to zero in on the
9523  // start counter paddle
9524  int count=0;
9525  DMatrix5x1 bestS=S;
9526  double dmin=d;
9527  DVector2 bestXY=central_traj[k].xy;
9528  double t=central_traj[k].t;
9529  double s=central_traj[k].s;
9530  // Magnetic field
9531  bfield->GetField(xy.X(),xy.Y(),S(state_z),Bx,By,Bz);
9532 
9533  while (fabs(d)>0.05 && count<20){
9534  // track direction
9535  DVector3 phat(cos(S(state_phi)),sin(S(state_phi)),S(state_tanl));
9536  phat.SetMag(1.);
9537 
9538  // path length increment
9539  double ds=d/sc_norm[index][m].Dot(phat);
9540  s-=ds;
9541 
9542  // Flight time
9543  double q_over_p=S(state_q_over_pt)*cos(atan(S(state_tanl)));
9544  double q_over_p_sq=q_over_p*q_over_p;
9545  double one_over_beta2=1.+mass2*q_over_p_sq;
9546  if (one_over_beta2>BIG) one_over_beta2=BIG;
9547  t-=ds*sqrt(one_over_beta2); // in units where c=1
9548 
9549  // Step along the trajectory using d to estimate path length
9550  FastStep(xy,-ds,0.,S);
9551  // Find the index for the nearest start counter paddle
9552  double dphi=xy.Phi()-SC_PHI_SECTOR1;
9553  if (dphi<0) dphi+=2.*M_PI;
9554  index=int(floor(dphi/(2.*M_PI/30.)));
9555  if (index>29) index=0;
9556 
9557  // Find the new distance to the start counter (which could now be to
9558  // a plane in the one adjacent to the one before the step...)
9559  d=sc_norm[index][m].Dot(DVector3(xy.X(),xy.Y(),S(state_z))
9560  -sc_pos[index][m]);
9561  if (fabs(d)<fabs(dmin)){
9562  bestS=S;
9563  dmin=d;
9564  bestXY=xy;
9565  }
9566  count++;
9567  }
9568 
9569  if (bestS(state_z)>sc_pos[0][0].z()-0.1){
9570  double tanl=bestS(state_tanl);
9571  double pt=1/fabs(bestS(state_q_over_pt));
9572  double phi=bestS(state_phi);
9573  DVector3 position(bestXY.X(),bestXY.Y(),bestS(state_z));
9574  DVector3 momentum(pt*cos(phi),pt*sin(phi),pt*tanl);
9575  extrapolations[SYS_START].push_back(Extrapolation_t(position,momentum,
9576  t*TIME_UNIT_CONVERSION,s));
9577  //printf("Central track:\n");
9578  //position.Print();
9579  }
9580  break;
9581  }
9582  }
9583  }
9584 
9585  // Accumulate multiple-scattering terms for use in matching routines
9586  double s_theta_ms_sum=0.,theta2ms_sum=0.;
9587  for (unsigned int k=inner_index;k>index_beyond_start_counter;k--){
9588  double ds_theta_ms_sq=3.*fabs(central_traj[k].Q(state_D,state_D));
9589  s_theta_ms_sum+=sqrt(ds_theta_ms_sq);
9590  double ds=central_traj[k].s-central_traj[k-1].s;
9591  theta2ms_sum+=ds_theta_ms_sq/(ds*ds);
9592  }
9593 
9594  // Deal with points within fiducial volume of chambers
9596  mT0MinimumDriftTime=1e6;
9597  for (int k=index_beyond_start_counter;k>=0;k--){
9598  S=central_traj[k].S;
9599  xy=central_traj[k].xy;
9600  double t=central_traj[k].t*TIME_UNIT_CONVERSION; // convert to ns
9601  double s=central_traj[k].s;
9602  double tanl=S(state_tanl);
9603  double pt=1/fabs(S(state_q_over_pt));
9604  double phi=S(state_phi);
9605 
9606  // Find estimate for t0 using earliest drift time
9607  if (central_traj[k].h_id>0){
9608  unsigned int index=central_traj[k].h_id-1;
9609  double dt=my_cdchits[index]->tdrift-t;
9610  if (dt<mT0MinimumDriftTime){
9613  }
9614  }
9615 
9616  //multiple scattering terms
9617  if (k>0){
9618  double ds_theta_ms_sq=3.*fabs(central_traj[k].Q(state_D,state_D));
9619  s_theta_ms_sum+=sqrt(ds_theta_ms_sq);
9620  double ds=central_traj[k].s-central_traj[k-1].s;
9621  theta2ms_sum+=ds_theta_ms_sq/(ds*ds);
9622  }
9623  if (S(state_z)<endplate_z){
9624  DVector3 position(xy.X(),xy.Y(),S(state_z));
9625  DVector3 momentum(pt*cos(phi),pt*sin(phi),pt*tanl);
9626  extrapolations[SYS_CDC].push_back(Extrapolation_t(position,momentum,t,s,
9627  s_theta_ms_sum,theta2ms_sum));
9628 
9629  }
9630  }
9631 
9632  //------------------------------
9633  // Next swim to outer detectors
9634  //------------------------------
9635  S=central_traj[0].S;
9636 
9637  // Position and step variables
9638  xy=central_traj[0].xy;
9639  double r2=xy.Mod2();
9640  double ds=mStepSizeS; // step along path in cm
9641 
9642  // Energy loss
9643  double dedx=0.;
9644 
9645  // Current time and path length
9646  double t=central_traj[0].t;
9647  double s=central_traj[0].s;
9648 
9649  // Matrix for multiple scattering covariance terms
9650  DMatrix5x5 Q;
9651 
9652  // Track propagation loop
9653  //if (false)
9654  while (S(state_z)>0. && S(state_z)<Z_MAX
9655  && r2<89.*89.){
9656  // Bail if the transverse momentum has dropped below some minimum
9657  if (fabs(S(state_q_over_pt))>Q_OVER_PT_MAX){
9658  if (DEBUG_LEVEL>2)
9659  {
9660  _DBG_ << "Bailing: PT = " << 1./fabs(S(state_q_over_pt))
9661  << endl;
9662  }
9663  return VALUE_OUT_OF_RANGE;
9664  }
9665 
9666  // get material properties from the Root Geometry
9667  double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.;
9668  double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.;
9669  DVector3 pos3d(xy.X(),xy.Y(),S(state_z));
9670  double s_to_boundary=0.;
9672  if (geom->FindMatKalman(pos3d,dir,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
9673  chi2c_factor,chi2a_factor,chi2a_corr,
9674  last_material_map,&s_to_boundary)
9675  !=NOERROR){
9676  _DBG_ << "Material error in ExtrapolateToVertex! " << endl;
9677  _DBG_ << " Position (x,y,z)=("<<pos3d.x()<<","<<pos3d.y()<<","
9678  << pos3d.z()<<")"
9679  <<endl;
9680  break;
9681  }
9682 
9683  // Get dEdx for the upcoming step
9684  double q_over_p=S(state_q_over_pt)*cos(atan(S(state_tanl)));
9685  if (CORRECT_FOR_ELOSS){
9686  dedx=GetdEdx(q_over_p,K_rho_Z_over_A,rho_Z_over_A,LnI,Z);
9687  }
9688  // Adjust the step size
9689  if (fabs(dedx)>EPS){
9690  ds=DE_PER_STEP/fabs(dedx);
9691  }
9692 
9693  if (ds>mStepSizeS) ds=mStepSizeS;
9694  if (s_to_boundary<ds) ds=s_to_boundary;
9695  if (ds<MIN_STEP_SIZE)ds=MIN_STEP_SIZE;
9696  if (ds<0.5 && S(state_z)<400. && pos3d.Perp()>65.) ds=0.5;
9697  s+=ds;
9698 
9699  // Flight time
9700  double q_over_p_sq=q_over_p*q_over_p;
9701  double one_over_beta2=1.+mass2*q_over_p_sq;
9702  if (one_over_beta2>BIG) one_over_beta2=BIG;
9703  t+=ds*sqrt(one_over_beta2); // in units where c=1
9704 
9705  // Multiple scattering
9706  GetProcessNoiseCentral(ds,chi2c_factor,chi2a_factor,chi2a_corr,S,Q);
9707 
9708  double ds_theta_ms_sq=3.*fabs(Q(state_D,state_D));
9709  s_theta_ms_sum+=sqrt(fabs(Q(state_D,state_D)));
9710  theta2ms_sum+=ds_theta_ms_sq/(ds*ds);
9711 
9712  // Propagate the state through the field
9713  Step(xy,ds,S,dedx);
9714 
9715  r2=xy.Mod2();
9716  // Check if we have passed into the BCAL
9717  if (r2>64.9*64.9){
9718  if (extrapolations.at(SYS_BCAL).size()>299){
9719  return VALUE_OUT_OF_RANGE;
9720  }
9721  if (S(state_z)<406.&&S(state_z)>17.0){
9722  double tanl=S(state_tanl);
9723  double pt=1/fabs(S(state_q_over_pt));
9724  double phi=S(state_phi);
9725  DVector3 position(xy.X(),xy.Y(),S(state_z));
9726  DVector3 momentum(pt*cos(phi),pt*sin(phi),pt*tanl);
9727  extrapolations[SYS_BCAL].push_back(Extrapolation_t(position,momentum,
9728  t*TIME_UNIT_CONVERSION,s));
9729  }
9730  else if (extrapolations.at(SYS_BCAL).size()<5){
9731  // There needs to be some steps inside the the volume of the BCAL for
9732  // the extrapolation to be useful. If this is not the case, clear
9733  // the extrolation vector.
9734  extrapolations[SYS_BCAL].clear();
9735  }
9736  }
9737  }
9738 
9739  return NOERROR;
9740 }
9741 
9742 /*---------------------------------------------------------------------------*/
9743 
9744 
#define ALPHA
const DFDCPseudo * hit
jerror_t ExtrapolateToVertex(DVector2 &xy, DMatrix5x1 &Sc, DMatrix5x5 &Cc)
#define EPS3
#define CGOLD
void setMomentum(const DVector3 &aMomentum)
double fdc_drift_variance(double t) const
jerror_t SetCDCForwardReferenceTrajectory(DMatrix5x1 &S)
vector< pull_t > pulls
Definition: DTrackFitter.h:237
double CalcDensityEffect(double p, double mass, double density, double Z_over_A, double I)
void setTime(double locTime)
DApplication * dapp
#define Q_OVER_PT_MAX
jerror_t ExtrapolateCentralToOtherDetectors(void)
bool GetFDCZ(vector< double > &z_wires) const
z-locations for each of the FDC wire planes in cm
Definition: DGeometry.cc:1221
vector< vector< double > > fcov
DMatrix5x5 Zero()
Definition: DMatrix5x5.h:210
DMatrix2x2 Invert()
Definition: DMatrix2x2.h:64
#define SPEED_OF_LIGHT
#define ITMAX
TMatrixD DMatrix
Definition: DMatrix.h:14
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)
double t0(void) const
Definition: DTrackingData.h:23
const DCDCWire * wire
Definition: DCDCTrackHit.h:37
virtual jerror_t SmoothForward(vector< pull_t > &mypulls)
DVector3 angles
radians
Definition: DFDCWire.h:20
DMatrix5x5 Transpose()
Definition: DMatrix5x5.h:66
The DTrackFitter class is a base class for different charged track fitting algorithms. It does not actually fit the track itself, but provides the interface and some common support features most algorthims will need to implement.
Definition: DTrackFitter.h:61
vector< vector< double > > max_sag
TVector2 DVector2
Definition: DVector2.h:9
float angle
radians
Definition: DFDCWire.h:19
jerror_t CalcDerivAndJacobian(double z, double dz, const DMatrix5x1 &S, double dEdx, DMatrix5x5 &J, DMatrix5x1 &D)
TVector3 DVector3
Definition: DVector3.h:14
void ClearExtrapolations(void)
Definition: DTrackFitter.h:141
Definition: GlueX.h:16
#define EPS2
double fdc_drift_distance(double t, double Bz) const
#define SIGN(a, b)
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
#define EPS
double t_v
time of the two cathode clusters
Definition: DFDCPseudo.h:86
virtual void GetFieldAndGradient(double x, double y, double z, double &Bx, double &By, double &Bz, double &dBxdx, double &dBxdy, double &dBxdz, double &dBydx, double &dBydy, double &dBydz, double &dBzdx, double &dBzdy, double &dBzdz) const =0
#define c
#define C0
Definition: src/md5.cpp:24
fit_type_t fit_type
Definition: DTrackFitter.h:227
#define y
deque< DKalmanForwardTrajectory_t > forward_traj
jerror_t PropagateForward(int length, int &index, double &z, double zhit, DMatrix5x1 &S, bool &done, bool &stepped_to_boundary, bool &stepped_to_endplate)
#define MAX_TB_PASSES
bool Get(string xpath, string &sval) const
Definition: DGeometry.h:50
bool GetFDCRmin(vector< double > &rmin_packages) const
beam hole size for each FDC package in cm
Definition: DGeometry.cc:1361
const DVector3 & position(void) const
void setTrackingErrorMatrix(const shared_ptr< const TMatrixFSym > &aMatrix)
Definition: DTrackingData.h:29
const DFDCWire * wire
DFDCWire for this wire.
Definition: DFDCPseudo.h:92
virtual jerror_t ExtrapolateForwardToOtherDetectors(void)
bool IsFinite()
Definition: DMatrix5x1.h:60
#define qBr2p
Definition: DHelicalFit.cc:15
vector< vector< DVector3 > > sc_norm
void setT0(double at0, double at0_err, DetectorSystem_t at0_detector)
Definition: DTrackingData.h:64
void setForwardParmFlag(bool aFlag)
Definition: DTrackingData.h:28
kalman_error_t ForwardFit(const DMatrix5x1 &S, const DMatrix5x5 &C0)
void Print()
Definition: DMatrix5x5.h:603
shared_ptr< DResourcePool< TMatrixFSym > > dResourcePool_TMatrixFSym
vector< DKalmanUpdate_t > fdc_updates
kalman_error_t CentralFit(const DVector2 &startpos, const DMatrix5x1 &Sc, const DMatrix5x5 &C0)
class DFDCPseudo: definition for a reconstructed point in the FDC
Definition: DFDCPseudo.h:74
map< DetectorSystem_t, vector< Extrapolation_t > > extrapolations
Definition: DTrackFitter.h:238
vector< const DFDCPseudo * > fdchits_used_in_fit
Definition: DTrackFitter.h:242
vector< DKalmanSIMDFDCHit_t * > my_fdchits
TMatrixDSym DMatrixDSym
Definition: DMatrixDSym.h:13
unsigned int potential_cdc_hits_on_track
Definition: DTrackFitter.h:247
bool GetFCALZ(double &z_fcal) const
z-location of front face of CCAL in cm
Definition: DGeometry.cc:1718
static char index(char c)
Definition: base64.cpp:115
#define FDC_CATHODE_VARIANCE
vector< vector< DCDCWire * > > cdcwires
vector< vector< double > > sag_phi_offset
double ds
local coordinate of pseudopoint in the direction along the wire and its uncertainty ...
Definition: DFDCPseudo.h:91
bool GetFDCRmax(double &rmax_active_fdc) const
outer radius of FDC active area in cm
Definition: DGeometry.cc:1381
Definition: GlueX.h:17
Definition: GlueX.h:19
jerror_t SetCDCReferenceTrajectory(const DVector2 &xy, DMatrix5x1 &Sc)
#define TAN_MAX
Double_t c1[2][NMODULES]
Definition: tw_corr.C:68
double Determinant()
Definition: DMatrix2x2.h:72
static bool DKalmanSIMDFDCHit_cmp(DKalmanSIMDFDCHit_t *a, DKalmanSIMDFDCHit_t *b)
bool GetCDCWires(vector< vector< DCDCWire * > > &cdcwires) const
Definition: DGeometry.cc:773
DTrackFitterKalmanSIMD(JEventLoop *loop)
TF1 * f
Definition: FitGains.C:21
double Chi2(const DMatrix2x1 &R) const
Definition: DMatrix2x2.h:78
#define ONE_SIXTH
#define ONE_THIRD
double t_u
Definition: DFDCPseudo.h:86
Double_t c2[2][NMODULES]
Definition: tw_corr.C:69
#define ELECTRON_MASS
vector< double > fdc_rmin_packages
#define R2_MAX
const DMagneticFieldMap * bfield
Definition: DTrackFitter.h:228
DMatrix2x5 Transpose(const DMatrix5x2 &M)
Definition: DMatrixSIMD.h:227
jerror_t BrentForward(double z, double dedx, const double z0w, const DVector2 &origin, const DVector2 &dir, DMatrix5x1 &S, double &dz)
void setTrackingStateVector(double a1, double a2, double a3, double a4, double a5)
Definition: DTrackingData.h:55
void setErrorMatrix(const shared_ptr< const TMatrixFSym > &aMatrix)
TEllipse * e
jerror_t AddCDCHit(const DCDCTrackHit *cdchit)
vector< const DCDCTrackHit * > cdchits
Definition: DTrackFitter.h:224
const double alpha
void locate(const double *xx, int n, double x, int *j)
#define H(x, y, z)
const DGeometry * geom
Definition: DTrackFitter.h:229
#define DE_PER_STEP
TLatex tx
Definition: GlueX.h:20
bool CORRECT_FOR_ELOSS
Definition: DTrackFitter.h:250
jerror_t PropagateForwardCDC(int length, int &index, double &z, double &r2, DMatrix5x1 &S, bool &stepped_to_boundary)
vector< vector< double > > cov
DMatrix5x5 InvertSym()
Definition: DMatrix5x5.h:221
Definition: GlueX.h:18
int straw
Definition: DCDCWire.h:81
void Print()
Definition: DMatrix5x1.h:65
fit_status_t fit_status
Definition: DTrackFitter.h:240
#define ZEPS
DMatrix5x5 SubSym(const DMatrix5x5 &m2) const
Definition: DMatrix5x5.h:108
kalman_error_t ForwardCDCFit(const DMatrix5x1 &S, const DMatrix5x5 &C0)
double dE
energy deposition, from integral
Definition: DFDCPseudo.h:96
#define TIME_UNIT_CONVERSION
Definition: GlueX.h:22
kalman_error_t KalmanCentral(double anneal_factor, DMatrix5x1 &S, DMatrix5x5 &C, DVector2 &xy, double &chisq, unsigned int &myndf)
#define SHFT(a, b, c, d)
kalman_error_t RecoverBrokenTracks(double anneal_factor, DMatrix5x1 &S, DMatrix5x5 &C, const DMatrix5x5 &C0, double &chisq, unsigned int &numdof)
#define _DBG_
Definition: HDEVIO.h:12
Definition: GlueX.h:26
double s
&lt; wire position computed from cathode data, assuming the avalanche occurs at the wire ...
Definition: DFDCPseudo.h:91
Double_t sigma[NCHANNELS]
Definition: st_tw_resols.C:37
shared_ptr< TMatrixFSym > Get7x7ErrorMatrixForward(DMatrixDSym C)
vector< DKalmanSIMDCDCHit_t * > my_cdchits
vector< const DCDCTrackHit * > cdchits_used_in_fit
Definition: DTrackFitter.h:241
void FastStep(double &z, double ds, double dEdx, DMatrix5x1 &S)
double charge(void) const
jerror_t SmoothForwardCDC(vector< pull_t > &mypulls)
TH1D * py[NCHANNELS]
void TransformCovariance(DMatrix5x5 &C)
double w
Definition: DFDCPseudo.h:89
double time
time corresponding to this pseudopoint.
Definition: DFDCPseudo.h:93
#define CHISQ_DELTA
void setPID(Particle_t locPID)
kalman_error_t KalmanForwardCDC(double anneal, DMatrix5x1 &S, DMatrix5x5 &C, double &chisq, unsigned int &numdof)
void cdc_hit(Int_t &, Int_t &, Int_t &, Int_t[], Int_t, Int_t, Int_t, Int_t, Int_t, Int_t)
Definition: fa125fns.h:55
double sqrt(double)
#define Z_MIN
virtual double GetBz(double x, double y, double z) const =0
vector< const DFDCPseudo * > fdchits
Definition: DTrackFitter.h:225
double sin(double)
double ChiSq(fit_type_t fit_type, DReferenceTrajectory *rt, double *chisq_ptr=NULL, int *dof_ptr=NULL, vector< pull_t > *pulls_ptr=NULL)
#define MAX_WB_PASSES
jerror_t StepJacobian(double oldz, double newz, const DMatrix5x1 &S, double dEdx, DMatrix5x5 &J)
#define S(str)
Definition: hddm-c.cpp:84
void AddTrackDerivatives(vector< double > d)
Definition: DTrackFitter.h:122
void ComputeCDCDrift(double dphi, double delta, double t, double B, double &d, double &V, double &tcorr)
const DVector3 & momentum(void) const
jerror_t SmoothCentral(vector< pull_t > &cdc_pulls)
DTrackingData input_params
Definition: DTrackFitter.h:226
jerror_t StepStateAndCovariance(DVector2 &xy, double ds, double dEdx, DMatrix5x1 &S, DMatrix5x5 &J, DMatrix5x5 &C)
#define MIN_ITER
vector< vector< DVector3 > > sc_pos
const DCDCTrackHit * hit
DetectorSystem_t t0_detector(void) const
Definition: DTrackingData.h:25
jerror_t GetProcessNoise(double z, double ds, double chi2c_factor, double chi2a_factor, double chi2a_corr, const DMatrix5x1 &S, DMatrix5x5 &Q)
kalman_error_t RecoverBrokenForwardTracks(double fdc_anneal_factor, double cdc_anneal_factor, DMatrix5x1 &S, DMatrix5x5 &C, const DMatrix5x5 &C0, double &chisq, unsigned int &numdof)
#define M_TWO_PI
Definition: DGeometry.cc:20
int ring
Definition: DCDCWire.h:80
double Step(double oldz, double newz, double dEdx, DMatrix5x1 &S)
jerror_t CalcDeriv(double z, const DMatrix5x1 &S, double dEdx, DMatrix5x1 &D)
shared_ptr< TMatrixFSym > Get7x7ErrorMatrix(DMatrixDSym C)
#define MIN_STEP_SIZE
jerror_t AddFDCHit(const DFDCPseudo *fdchit)
jerror_t FindMatKalman(const DVector3 &pos, const DVector3 &mom, double &KrhoZ_overA, double &rhoZ_overA, double &LnI, double &Z, double &chi2c_factor, double &chi2a_factor, double &chi2a_factor2, unsigned int &last_index, double *s_to_boundary=NULL) const
Definition: DGeometry.cc:254
bool GetCDCEndplate(double &z, double &dz, double &rmin, double &rmax) const
Definition: DGeometry.cc:1497
static bool DKalmanSIMDCDCHit_cmp(DKalmanSIMDCDCHit_t *a, DKalmanSIMDCDCHit_t *b)
jerror_t SetReferenceTrajectory(DMatrix5x1 &S)
bool GetDIRCZ(double &z_dirc) const
z-location of DIRC in cm
Definition: DGeometry.cc:1735
void setPosition(const DVector3 &aPosition)
jerror_t GetProcessNoiseCentral(double ds, double chi2c_factor, double chi2a_factor, double chi2a_corr, const DMatrix5x1 &S, DMatrix5x5 &Q)
virtual void GetField(const DVector3 &pos, DVector3 &Bout) const =0
#define BIG
TDirectory * dir
Definition: bcal_hist_eff.C:31
bool IsPosDef()
Definition: DMatrix5x5.h:595
#define Z_MAX
TCanvas * c3
static Particle_t IDTrack(float locCharge, float locMass)
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)
DTrackingData fit_params
Definition: DTrackFitter.h:234
printf("string=%s", string)
TH2F * temp
bool GetTargetZ(double &z_target) const
z-location of center of target
Definition: DGeometry.cc:1933
vector< DKalmanUpdate_t > cdc_updates
union @6::@8 u
DMatrix5x5 AddSym(const DMatrix5x5 &m2) const
Definition: DMatrix5x5.h:96
jerror_t BrentCentral(double dedx, DVector2 &xy, const double z0w, const DVector2 &origin, const DVector2 &dir, DMatrix5x1 &Sc, double &ds)
unsigned int potential_fdc_hits_on_track
Definition: DTrackFitter.h:246
vector< vector< DVector3 > > sc_dir
float stereo
Definition: DCDCWire.h:82
double GetEnergyVariance(double ds, double beta2, double K_rho_Z_over_A)
jerror_t PropagateCentral(int length, int &index, DVector2 &my_xy, double &var_t_factor, DMatrix5x1 &Sc, bool &stepped_to_boundary)
double mass(void) const
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)
bool GetStartCounterGeom(vector< vector< DVector3 > > &pos, vector< vector< DVector3 > > &norm) const
Definition: DGeometry.cc:1983
deque< DKalmanCentralTrajectory_t > central_traj
virtual kalman_error_t KalmanForward(double fdc_anneal, double cdc_anneal, DMatrix5x1 &S, DMatrix5x5 &C, double &chisq, unsigned int &numdof)
double FasterStep(double oldz, double newz, double dEdx, DMatrix5x1 &S)