Bug Summary

File:libraries/TRACKING/DTrackFitterKalmanSIMD.cc
Location:line 5701, column 12
Description:Value stored to 'dz' during its initialization is never read

Annotated Source Code

1//************************************************************************
2// DTrackFitterKalmanSIMD.cc
3//************************************************************************
4
5#include "DTrackFitterKalmanSIMD.h"
6#include "CDC/DCDCTrackHit.h"
7#include "HDGEOMETRY/DLorentzDeflections.h"
8#include "HDGEOMETRY/DMaterialMap.h"
9#include "HDGEOMETRY/DRootGeom.h"
10#include "DANA/DApplication.h"
11#include <JANA/JCalibration.h>
12
13#include <TH2F.h>
14#include <TROOT.h>
15#include <TMath.h>
16#include <DMatrix.h>
17
18#include <iomanip>
19#include <math.h>
20
21#define MAX_TB_PASSES20 20
22#define MAX_WB_PASSES20 20
23#define MIN_PROTON_P0.3 0.3
24#define MIN_PION_P0.08 0.08
25#define MAX_P12.0 12.0
26
27#define NaNstd::numeric_limits<double>::quiet_NaN() std::numeric_limits<double>::quiet_NaN()
28
29// Local boolean routines for sorting
30//bool static DKalmanSIMDHit_cmp(DKalmanSIMDHit_t *a, DKalmanSIMDHit_t *b){
31// return a->z<b->z;
32//}
33
34inline bool static DKalmanSIMDFDCHit_cmp(DKalmanSIMDFDCHit_t *a, DKalmanSIMDFDCHit_t *b){
35 if (fabs(a->z-b->z)<EPS3.0e-8) return(a->t<b->t);
36
37 return a->z<b->z;
38}
39inline bool static DKalmanSIMDCDCHit_cmp(DKalmanSIMDCDCHit_t *a, DKalmanSIMDCDCHit_t *b){
40 if (a==NULL__null || b==NULL__null){
41 cout << "Null pointer in CDC hit list??" << endl;
42 return false;
43 }
44 const DCDCWire *wire_a= a->hit->wire;
45 const DCDCWire *wire_b= b->hit->wire;
46 if(wire_b->ring == wire_a->ring){
47 return wire_b->straw < wire_a->straw;
48 }
49
50 return (wire_b->ring>wire_a->ring);
51}
52
53
54// Locate a position in array xx given x
55void DTrackFitterKalmanSIMD::locate(const double *xx,int n,double x,int *j){
56 int jl=-1;
57 int ju=n;
58 int ascnd=(xx[n-1]>=xx[0]);
59 while(ju-jl>1){
60 int jm=(ju+jl)>>1;
61 if ( (x>=xx[jm])==ascnd)
62 jl=jm;
63 else
64 ju=jm;
65 }
66 if (x==xx[0]) *j=0;
67 else if (x==xx[n-1]) *j=n-2;
68 else *j=jl;
69}
70
71
72
73// Locate a position in vector xx given x
74unsigned int DTrackFitterKalmanSIMD::locate(vector<double>&xx,double x){
75 int n=xx.size();
76 if (x==xx[0]) return 0;
77 else if (x==xx[n-1]) return n-2;
78
79 int jl=-1;
80 int ju=n;
81 int ascnd=(xx[n-1]>=xx[0]);
82 while(ju-jl>1){
83 int jm=(ju+jl)>>1;
84 if ( (x>=xx[jm])==ascnd)
85 jl=jm;
86 else
87 ju=jm;
88 }
89 return jl;
90}
91
92// Crude approximation for the variance in drift distance due to smearing
93double fdc_drift_variance(double t){
94 //return FDC_ANODE_VARIANCE;
95 if (t<1) t=1;
96 double par[4]={6.051e-3,-1.118e-5,-1.658e-6,2.036e-8};
97 double sigma=8.993e-3/(t+0.001);
98 for (int i=0;i<4;i++) sigma+=par[i]*pow(t,i);
99 sigma*=1.1;
100
101 return sigma*sigma;
102}
103
104// Convert time to distance for the cdc
105double DTrackFitterKalmanSIMD::cdc_drift_distance(double t,double B){
106 double d=0.;
107 if (t>0){
108 double dtc =(CDC_DRIFT_BSCALE_PAR1 + CDC_DRIFT_BSCALE_PAR2 * B)* t;
109 double tcorr=t-dtc;
110
111 if (tcorr>cdc_drift_table[cdc_drift_table.size()-1]){
112 return 0.78;
113 }
114
115 unsigned int index=0;
116 index=locate(cdc_drift_table,tcorr);
117 double dt=cdc_drift_table[index+1]-cdc_drift_table[index];
118 double frac=(tcorr-cdc_drift_table[index])/dt;
119 d=0.01*(double(index)+frac);
120 }
121 return d;
122
123 // The following functional form was derived from the simulated
124 // time-to-distance relationship derived from GARFIELD. It should really
125 // be determined empirically...
126 /*
127 double two_a=2.*(1129.0+78.66*B);
128 double b=49.41-4.74*B;
129 d=b/two_a;
130 // if (t>0.0) d+=0.0279*sqrt(t);
131 if (t>0.0) d+=sqrt(b*b+2.*two_a*t)/two_a;
132
133 //_DBG_ << d << endl;
134
135 return d;
136 */
137}
138
139// Convert time to distance for the cdc and compute variance
140void DTrackFitterKalmanSIMD::ComputeCDCDrift(double dphi,double delta,double t,
141 double B,
142 double &d, double &V, double &tcorr){
143 //d=0.39; // initialize at half-cell
144 //V=0.0507; // initialize with (cell size)/12.
145 double cutoffTime = 40.0;
146 tcorr = t; // Need this value even when t is negative for calibration
147 if (t>0){
148 //double dtc =(CDC_DRIFT_BSCALE_PAR1 + CDC_DRIFT_BSCALE_PAR2 * B)* t;
149 //tcorr=t-dtc;
150
151 double sigma=CDC_RES_PAR1/(tcorr+1.)+CDC_RES_PAR2;
152 // This function is very poorly behaved at low drift times
153 // For times less than cutoffTime assume a linear behavior of our function.
154 if( tcorr < cutoffTime ){
155 double slope = -1.0 * CDC_RES_PAR1 / (( cutoffTime + 1) * (cutoffTime + 1));
156 sigma = (CDC_RES_PAR1/(cutoffTime+1.)+CDC_RES_PAR2) + slope * (tcorr - cutoffTime);
157 }
158
159
160 // Variables to store values for time-to-distance functions for delta=0
161 // and delta!=0
162 double f_0=0.;
163 double f_delta=0.;
164 // Derivative of d with respect to t, needed to add t0 variance
165 // dependence to sigma
166 double dd_dt=0;
167 // Scale factor to account for affect of B-field on maximum drift time
168 double Bscale=long_drift_Bscale_par1+long_drift_Bscale_par2*B;
169
170 // if (delta>0)
171 if (delta>-EPS21.e-4){
172 double a1=long_drift_func[0][0];
173 double a2=long_drift_func[0][1];
174 double b1=long_drift_func[1][0];
175 double b2=long_drift_func[1][1];
176 double c1=long_drift_func[2][0];
177 double c2=long_drift_func[2][1];
178 double c3=long_drift_func[2][2];
179
180 // use "long side" functional form
181 double my_t=0.001*tcorr;
182 double sqrt_t=sqrt(my_t);
183 double t3=my_t*my_t*my_t;
184 double delta_mag=fabs(delta);
185 double a=a1+a2*delta_mag;
186 double b=b1+b2*delta_mag;
187 double c=c1+c2*delta_mag+c3*delta*delta;
188 f_delta=a*sqrt_t+b*my_t+c*t3;
189 f_0=a1*sqrt_t+b1*my_t+c1*t3;
190
191 dd_dt=0.001*(0.5*a/sqrt_t+b+3.*c*my_t*my_t);
192 }
193 else{
194 double my_t=0.001*tcorr;
195 double sqrt_t=sqrt(my_t);
196 double delta_mag=fabs(delta);
197
198 // use "short side" functional form
199 double a1=short_drift_func[0][0];
200 double a2=short_drift_func[0][1];
201 double a3=short_drift_func[0][2];
202 double b1=short_drift_func[1][0];
203 double b2=short_drift_func[1][1];
204 double b3=short_drift_func[1][2];
205
206 double delta_sq=delta*delta;
207 double a=a1+a2*delta_mag+a3*delta_sq;
208 double b=b1+b2*delta_mag+b3*delta_sq;
209 f_delta=a*sqrt_t+b*my_t;
210 f_0=a1*sqrt_t+b1*my_t;
211
212 dd_dt=0.001*(0.5*a/sqrt_t+b);
213 }
214
215 unsigned int max_index=cdc_drift_table.size()-1;
216 if (tcorr>cdc_drift_table[max_index]){
217 //_DBG_ << "t: " << tcorr <<" d " << f_delta <<endl;
218 d=f_delta*Bscale;
219 V=sigma*sigma+mVarT0*dd_dt*dd_dt*Bscale*Bscale;
220
221 return;
222 }
223
224 // Drift time is within range of table -- interpolate...
225 unsigned int index=0;
226 index=locate(cdc_drift_table,tcorr);
227 double dt=cdc_drift_table[index+1]-cdc_drift_table[index];
228 double frac=(tcorr-cdc_drift_table[index])/dt;
229 double d_0=0.01*(double(index)+frac);
230
231 double P=0.;
232 double tcut=250.0; // ns
233 if (tcorr<tcut) {
234 P=(tcut-tcorr)/tcut;
235 }
236 d=f_delta*(d_0/f_0*P+1.-P)*Bscale;
237 V=sigma*sigma+mVarT0*dd_dt*dd_dt*Bscale*Bscale;
238 }
239 else { // Time is negative, or exactly zero, choose position at wire, with error of t=0 hit
240 d=0.;
241 double slope = -1.0 * CDC_RES_PAR1 / (( cutoffTime + 1) * (cutoffTime + 1));
242 double sigma = (CDC_RES_PAR1/(cutoffTime+1.)+CDC_RES_PAR2) + slope * (0.0 - cutoffTime);
243 double dt=cdc_drift_table[1]-cdc_drift_table[0];
244 V=sigma*sigma+mVarT0*0.0001/(dt*dt);
245 //V=0.0507; // straw radius^2 / 12
246 }
247
248
249}
250
251#define FDC_T0_OFFSET17.6 17.6
252// Interpolate on a table to convert time to distance for the fdc
253double DTrackFitterKalmanSIMD::fdc_drift_distance(double t,double Bz){
254 double a=93.31,b=4.614,Bref=2.143;
255 t*=(a+b*Bref)/(a+b*Bz);
256 int id=int((t+FDC_T0_OFFSET17.6)/2.);
257 if (id<0) id=0;
258 if (id>138) id=138;
259 double d=fdc_drift_table[id];
260 if (id!=138){
261 double frac=0.5*(t+FDC_T0_OFFSET17.6-2.*double(id));
262 double dd=fdc_drift_table[id+1]-fdc_drift_table[id];
263 d+=frac*dd;
264 }
265
266 return d;
267}
268
269
270DTrackFitterKalmanSIMD::DTrackFitterKalmanSIMD(JEventLoop *loop):DTrackFitter(loop){
271 FactorForSenseOfRotation=(bfield->GetBz(0.,0.,65.)>0.)?-1.:1.;
272
273 // Get the position of the CDC downstream endplate from DGeometry
274 double endplate_rmin,endplate_rmax;
275 geom->GetCDCEndplate(endplate_z,endplate_dz,endplate_rmin,endplate_rmax);
276 endplate_z-=0.5*endplate_dz;
277 endplate_r2min=endplate_rmin*endplate_rmin;
278 endplate_r2max=endplate_rmax*endplate_rmax;
279
280 // Beginning of the cdc
281 vector<double>cdc_center;
282 vector<double>cdc_upstream_endplate_pos;
283 vector<double>cdc_endplate_dim;
284 geom->Get("//posXYZ[@volume='CentralDC'/@X_Y_Z",cdc_origin);
285 geom->Get("//posXYZ[@volume='centralDC']/@X_Y_Z",cdc_center);
286 geom->Get("//posXYZ[@volume='CDPU']/@X_Y_Z",cdc_upstream_endplate_pos);
287 geom->Get("//tubs[@name='CDPU']/@Rio_Z",cdc_endplate_dim);
288 cdc_origin[2]+=cdc_center[2]+cdc_upstream_endplate_pos[2]
289 +0.5*cdc_endplate_dim[2];
290
291 ADD_VERTEX_POINT=false;
292 gPARMS->SetDefaultParameter("KALMAN:ADD_VERTEX_POINT", ADD_VERTEX_POINT);
293
294 THETA_CUT=70.0;
295 gPARMS->SetDefaultParameter("KALMAN:THETA_CUT", THETA_CUT);
296
297 RING_TO_SKIP=0;
298 gPARMS->SetDefaultParameter("KALMAN:RING_TO_SKIP",RING_TO_SKIP);
299
300 PLANE_TO_SKIP=0;
301 gPARMS->SetDefaultParameter("KALMAN:PLANE_TO_SKIP",PLANE_TO_SKIP);
302
303 MIN_HITS_FOR_REFIT=8;
304 gPARMS->SetDefaultParameter("KALMAN:MIN_HITS_FOR_REFIT", MIN_HITS_FOR_REFIT);
305
306 DEBUG_HISTS=false;
307 gPARMS->SetDefaultParameter("KALMAN:DEBUG_HISTS", DEBUG_HISTS);
308
309 DEBUG_LEVEL=0;
310 gPARMS->SetDefaultParameter("KALMAN:DEBUG_LEVEL", DEBUG_LEVEL);
311
312 USE_T0_FROM_WIRES=0;
313 gPARMS->SetDefaultParameter("KALMAN:USE_T0_FROM_WIRES", USE_T0_FROM_WIRES);
314
315 ESTIMATE_T0_TB=false;
316 gPARMS->SetDefaultParameter("KALMAN:ESTIMATE_T0_TB",ESTIMATE_T0_TB);
317
318 ENABLE_BOUNDARY_CHECK=true;
319 gPARMS->SetDefaultParameter("GEOM:ENABLE_BOUNDARY_CHECK",
320 ENABLE_BOUNDARY_CHECK);
321
322 USE_MULS_COVARIANCE=true;
323 gPARMS->SetDefaultParameter("TRKFIT:USE_MULS_COVARIANCE",
324 USE_MULS_COVARIANCE);
325
326 USE_PASS1_TIME_MODE=false;
327 gPARMS->SetDefaultParameter("KALMAN:USE_PASS1_TIME_MODE",USE_PASS1_TIME_MODE);
328
329 RECOVER_BROKEN_TRACKS=true;
330 gPARMS->SetDefaultParameter("KALMAN:RECOVER_BROKEN_TRACKS",RECOVER_BROKEN_TRACKS);
331
332 MIN_FIT_P = 0.050; // GeV
333 gPARMS->SetDefaultParameter("TRKFIT:MIN_FIT_P", MIN_FIT_P, "Minimum fit momentum in GeV/c for fit to be considered successful");
334
335 NUM_CDC_SIGMA_CUT=3.5;
336 NUM_FDC_SIGMA_CUT=3.5;
337 gPARMS->SetDefaultParameter("KALMAN:NUM_CDC_SIGMA_CUT",NUM_CDC_SIGMA_CUT,
338 "maximum distance in number of sigmas away from projection to accept cdc hit");
339 gPARMS->SetDefaultParameter("KALMAN:NUM_FDC_SIGMA_CUT",NUM_FDC_SIGMA_CUT,
340 "maximum distance in number of sigmas away from projection to accept fdc hit");
341
342 ANNEAL_SCALE=1.5;
343 ANNEAL_POW_CONST=20.0;
344 gPARMS->SetDefaultParameter("KALMAN:ANNEAL_SCALE",ANNEAL_SCALE,
345 "Scale factor for annealing");
346 gPARMS->SetDefaultParameter("KALMAN:ANNEAL_POW_CONST",ANNEAL_POW_CONST,
347 "Annealing parameter");
348 FORWARD_ANNEAL_SCALE=1.5;
349 FORWARD_ANNEAL_POW_CONST=20.0;
350 gPARMS->SetDefaultParameter("KALMAN:FORWARD_ANNEAL_SCALE",
351 FORWARD_ANNEAL_SCALE,
352 "Scale factor for annealing");
353 gPARMS->SetDefaultParameter("KALMAN:FORWARD_ANNEAL_POW_CONST",
354 FORWARD_ANNEAL_POW_CONST,
355 "Annealing parameter");
356
357 FORWARD_PARMS_COV=false;
358 gPARMS->SetDefaultParameter("KALMAN:FORWARD_PARMS_COV",FORWARD_PARMS_COV);
359
360 DApplication* dapp = dynamic_cast<DApplication*>(loop->GetJApplication());
361
362 if(DEBUG_HISTS){
363 dapp->Lock();
364
365 Hstepsize=(TH2F*)gROOT->FindObject("Hstepsize");
366 if (!Hstepsize){
367 Hstepsize=new TH2F("Hstepsize","step size numerator",
368 900,-100,350,130,0,65);
369 Hstepsize->SetXTitle("z (cm)");
370 Hstepsize->SetYTitle("r (cm)");
371 }
372 HstepsizeDenom=(TH2F*)gROOT->FindObject("HstepsizeDenom");
373 if (!HstepsizeDenom){
374 HstepsizeDenom=new TH2F("HstepsizeDenom","step size denominator",
375 900,-100,350,130,0,65);
376 HstepsizeDenom->SetXTitle("z (cm)");
377 HstepsizeDenom->SetYTitle("r (cm)");
378 }
379
380 dapp->Unlock();
381 }
382
383
384 JCalibration *jcalib = dapp->GetJCalibration((loop->GetJEvent()).GetRunNumber());
385 vector< map<string, double> > tvals;
386 cdc_drift_table.clear();
387 if (jcalib->Get("CDC/cdc_drift_table", tvals)==false){
388 for(unsigned int i=0; i<tvals.size(); i++){
389 map<string, double> &row = tvals[i];
390 cdc_drift_table.push_back(1000.*row["t"]);
391 }
392 }
393 else{
394 jerr << " CDC time-to-distance table not available... bailing..." << endl;
395 exit(0);
396 }
397
398 int straw_number[28]={42,42,54,54,66,66,80,80,93,93,106,106,
399 123,123,135,135,146,146,158,158,170,170,
400 182,182,197,197,209,209};
401 max_sag.clear();
402 sag_phi_offset.clear();
403 int straw_count=0,ring_count=0;
404 if (jcalib->Get("CDC/sag_parameters", tvals)==false){
405 vector<double>temp,temp2;
406 for(unsigned int i=0; i<tvals.size(); i++){
407 map<string, double> &row = tvals[i];
408
409 temp.push_back(row["offset"]);
410 temp2.push_back(row["phi"]);
411
412 straw_count++;
413 if (straw_count==straw_number[ring_count]){
414 max_sag.push_back(temp);
415 sag_phi_offset.push_back(temp2);
416 temp.clear();
417 temp2.clear();
418 straw_count=0;
419 ring_count++;
420 }
421 }
422 }
423
424 if (jcalib->Get("CDC/drift_parameters", tvals)==false){
425 map<string, double> &row = tvals[0]; // long drift side
426 long_drift_func[0][0]=row["a1"];
427 long_drift_func[0][1]=row["a2"];
428 long_drift_func[0][2]=row["a3"];
429 long_drift_func[1][0]=row["b1"];
430 long_drift_func[1][1]=row["b2"];
431 long_drift_func[1][2]=row["b3"];
432 long_drift_func[2][0]=row["c1"];
433 long_drift_func[2][1]=row["c2"];
434 long_drift_func[2][2]=row["c3"];
435 long_drift_Bscale_par1=row["B1"];
436 long_drift_Bscale_par2=row["B2"];
437
438 row = tvals[1]; // short drift side
439 short_drift_func[0][0]=row["a1"];
440 short_drift_func[0][1]=row["a2"];
441 short_drift_func[0][2]=row["a3"];
442 short_drift_func[1][0]=row["b1"];
443 short_drift_func[1][1]=row["b2"];
444 short_drift_func[1][2]=row["b3"];
445 short_drift_func[2][0]=row["c1"];
446 short_drift_func[2][1]=row["c2"];
447 short_drift_func[2][2]=row["c3"];
448 short_drift_Bscale_par1=row["B1"];
449 short_drift_Bscale_par2=row["B2"];
450 }
451
452 map<string, double> cdc_drift_parms;
453 jcalib->Get("CDC/cdc_drift_parms", cdc_drift_parms);
454 CDC_DRIFT_BSCALE_PAR1 = cdc_drift_parms["bscale_par1"];
455 CDC_DRIFT_BSCALE_PAR2 = cdc_drift_parms["bscale_par2"];
456
457 map<string, double> cdc_res_parms;
458 jcalib->Get("CDC/cdc_resolution_parms", cdc_res_parms);
459 CDC_RES_PAR1 = cdc_res_parms["res_par1"];
460 CDC_RES_PAR2 = cdc_res_parms["res_par2"];
461
462 // Parameters for correcting for deflection due to Lorentz force
463 map<string,double>lorentz_parms;
464 jcalib->Get("FDC/lorentz_deflection_parms",lorentz_parms);
465 LORENTZ_NR_PAR1=lorentz_parms["nr_par1"];
466 LORENTZ_NR_PAR2=lorentz_parms["nr_par2"];
467 LORENTZ_NZ_PAR1=lorentz_parms["nz_par1"];
468 LORENTZ_NZ_PAR2=lorentz_parms["nz_par2"];
469
470 /*
471 if (jcalib->Get("FDC/fdc_drift2", tvals)==false){
472 for(unsigned int i=0; i<tvals.size(); i++){
473 map<string, float> &row = tvals[i];
474 iter_float iter = row.begin();
475 fdc_drift_table[i] = iter->second;
476 }
477 }
478 else{
479 jerr << " FDC time-to-distance table not available... bailing..." << endl;
480 exit(0);
481 }
482 */
483
484 for (unsigned int i=0;i<5;i++)I5x5(i,i)=1.;
485
486
487 // center of the target
488 map<string, double> targetparms;
489 if (jcalib->Get("TARGET/target_parms",targetparms)==false){
490 TARGET_Z = targetparms["TARGET_Z_POSITION"];
491 }
492 else{
493 geom->GetTargetZ(TARGET_Z);
494 }
495
496 // Inform user of some configuration settings
497 static bool config_printed = false;
498 if(!config_printed){
499 config_printed = true;
500 stringstream ss;
501 ss << "vertex constraint: " ;
502 if(ADD_VERTEX_POINT){
503 ss << "z = " << TARGET_Z << "cm" << endl;
504 }else{
505 ss << "<none>" << endl;
506 }
507 jout << ss.str();
508 } // config_printed
509
510
511}
512
513//-----------------
514// ResetKalmanSIMD
515//-----------------
516void DTrackFitterKalmanSIMD::ResetKalmanSIMD(void)
517{
518 last_material_map=0;
519
520 for (unsigned int i=0;i<my_cdchits.size();i++){
521 delete my_cdchits[i];
522 }
523 for (unsigned int i=0;i<my_fdchits.size();i++){
524 delete my_fdchits[i];
525 }
526 central_traj.clear();
527 forward_traj.clear();
528 my_fdchits.clear();
529 my_cdchits.clear();
530 fdc_updates.clear();
531 cdc_updates.clear();
532
533 cov.clear();
534 fcov.clear();
535 pulls.clear();
536
537 len = 0.0;
538 ftime=0.0;
539 var_ftime=0.0;
540 x_=0.,y_=0.,tx_=0.,ty_=0.,q_over_p_ = 0.0;
541 z_=0.,phi_=0.,tanl_=0.,q_over_pt_ =0, D_= 0.0;
542 chisq_ = 0.0;
543 ndf_ = 0;
544 MASS=0.13957;
545 mass2=MASS*MASS;
546 Bx=By=0.;
547 Bz=2.;
548 dBxdx=0.,dBxdy=0.,dBxdz=0.,dBydx=0.,dBydy=0.,dBydy=0.,dBzdx=0.,dBzdy=0.,dBzdz=0.;
549 // Step sizes
550 mStepSizeS=2.0;
551 mStepSizeZ=2.0;
552 //mStepSizeZ=0.5;
553 /*
554 if (fit_type==kTimeBased){
555 mStepSizeS=0.5;
556 mStepSizeZ=0.5;
557 }
558 */
559
560 mT0=0.,mT0MinimumDriftTime=1e6;
561 mMinDriftTime=1e6;
562 mMinDriftID=2000;
563 mVarT0=0.;
564
565 mCDCInternalStepSize=0.5;
566 //mCDCInternalStepSize=1.0;
567 //mCentralStepSize=0.75;
568 mCentralStepSize=0.75;
569
570 mT0Detector=SYS_CDC;
571
572}
573
574//-----------------
575// FitTrack
576//-----------------
577DTrackFitter::fit_status_t DTrackFitterKalmanSIMD::FitTrack(void)
578{
579 // Reset member data and free an memory associated with the last fit,
580 // but some of which only for wire-based fits
581 ResetKalmanSIMD();
582
583 // Check that we have enough FDC and CDC hits to proceed
584 if (cdchits.size()+fdchits.size()<6) return kFitNotDone;
585
586 // Copy hits from base class into structures specific to DTrackFitterKalmanSIMD
587 if (cdchits.size()>=MIN_CDC_HITS2)
588 for(unsigned int i=0; i<cdchits.size(); i++)AddCDCHit(cdchits[i]);
589 if (fdchits.size()>=MIN_FDC_HITS2)
590 for(unsigned int i=0; i<fdchits.size(); i++)AddFDCHit(fdchits[i]);
591
592 unsigned int num_good_cdchits=my_cdchits.size();
593 unsigned int num_good_fdchits=my_fdchits.size();
594
595 // Order the cdc hits by ring number
596 if (num_good_cdchits>0){
597 sort(my_cdchits.begin(),my_cdchits.end(),DKalmanSIMDCDCHit_cmp);
598
599 // Find earliest time to use for estimate for T0
600 for (unsigned int i=0;i<my_cdchits.size();i++){
601 if (my_cdchits[i]->tdrift<mMinDriftTime){
602 mMinDriftTime=my_cdchits[i]->tdrift;
603 mMinDriftID=1000+i;
604 }
605 }
606
607 // Look for multiple hits on the same wire
608 for (unsigned int i=0;i<my_cdchits.size()-1;i++){
609 if (my_cdchits[i]->hit->wire->ring==my_cdchits[i+1]->hit->wire->ring &&
610 my_cdchits[i]->hit->wire->straw==my_cdchits[i+1]->hit->wire->straw){
611 num_good_cdchits--;
612 if (my_cdchits[i]->tdrift<my_cdchits[i+1]->tdrift){
613 my_cdchits[i+1]->status=late_hit;
614 }
615 else{
616 my_cdchits[i]->status=late_hit;
617 }
618 }
619 }
620
621 }
622 // Order the fdc hits by z
623 if (num_good_fdchits>0){
624 sort(my_fdchits.begin(),my_fdchits.end(),DKalmanSIMDFDCHit_cmp);
625
626 // Find earliest time to use for estimate for T0
627 for (unsigned int i=0;i<my_fdchits.size();i++){
628 if (my_fdchits[i]->t<mMinDriftTime){
629 mMinDriftID=i;
630 mMinDriftTime=my_fdchits[i]->t;
631 }
632 }
633
634 // Look for multiple hits on the same wire
635 for (unsigned int i=0;i<my_fdchits.size()-1;i++){
636 if (my_fdchits[i]->hit->wire->layer==my_fdchits[i+1]->hit->wire->layer &&
637 my_fdchits[i]->hit->wire->wire==my_fdchits[i+1]->hit->wire->wire){
638 num_good_fdchits--;
639 if (my_fdchits[i]->t<my_fdchits[i+1]->t){
640 my_fdchits[i+1]->status=late_hit;
641 }
642 else{
643 my_fdchits[i]->status=late_hit;
644 }
645 }
646 }
647 }
648 if(num_good_cdchits+num_good_fdchits<6) return kFitNotDone;
649
650 // Create vectors of updates (from hits) to S and C
651 if (my_cdchits.size()>0) cdc_updates=vector<DKalmanUpdate_t>(my_cdchits.size());
652 if (my_fdchits.size()>0) fdc_updates=vector<DKalmanUpdate_t>(my_fdchits.size());
653
654
655
656 // start time and variance
657 mT0=NaNstd::numeric_limits<double>::quiet_NaN();
658 if (fit_type==kTimeBased){
659 mT0=input_params.t0();
660 if (mT0>mMinDriftTime){
661 mT0=mMinDriftTime;
662 mVarT0=7.5;
663 }
664 else{
665 switch(input_params.t0_detector()){
666 case SYS_TOF:
667 mVarT0=0.01;
668 break;
669 case SYS_CDC:
670 mVarT0=7.5;
671 break;
672 case SYS_FDC:
673 mVarT0=7.5;
674 break;
675 case SYS_BCAL:
676 mVarT0=0.25;
677 break;
678 default:
679 mVarT0=0.09;
680 break;
681 }
682 }
683
684 // _DBG_ << SystemName(input_params.t0_detector()) << " " << mT0 <<endl;
685 // _DBG_ << mMinDriftTime << endl;
686
687 }
688
689 //Set the mass
690 MASS=input_params.mass();
691 mass2=MASS*MASS;
692 m_ratio=ELECTRON_MASS0.000511/MASS;
693 m_ratio_sq=m_ratio*m_ratio;
694 two_m_e=2.*ELECTRON_MASS0.000511;
695
696 if (DEBUG_LEVEL>0){
697 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<697<<" "
<< "------Starting "
698 <<(fit_type==kTimeBased?"Time-based":"Wire-based")
699 << " Fit with " << my_fdchits.size() << " FDC hits and "
700 << my_cdchits.size() << " CDC hits.-------" <<endl;
701 if (fit_type==kTimeBased){
702 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<702<<" "
<< " Using t0=" << mT0 << " from DET="
703 << input_params.t0_detector() <<endl;
704 }
705 }
706 // Do the fit
707 jerror_t error = KalmanLoop();
708 if (error!=NOERROR){
709 if (DEBUG_LEVEL>0)
710 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<710<<" "
<< "Fit failed with Error = " << error <<endl;
711 return kFitFailed;
712 }
713
714 // Copy fit results into DTrackFitter base-class data members
715 DVector3 mom,pos;
716 GetPosition(pos);
717 GetMomentum(mom);
718 double charge = GetCharge();
719 fit_params.setPosition(pos);
720 fit_params.setMomentum(mom);
721 fit_params.setCharge(charge);
722 fit_params.setMass(MASS);
723 fit_params.setT0(mT0MinimumDriftTime,4.,mT0Detector);
724
725 if (DEBUG_LEVEL>0){
726 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<726<<" "
<< "----- Pass: "
727 << (fit_type==kTimeBased?"Time-based ---":"Wire-based ---")
728 << " Mass: " << MASS
729 << " p=" << mom.Mag()
730 << " theta=" << 90.0-180./M_PI3.14159265358979323846*atan(tanl_)
731 << " vertex=(" << x_ << "," << y_ << "," << z_<<")"
732 << " chi2=" << chisq_
733 <<endl;
734 }
735
736 DMatrixDSym errMatrix(5);
737 // Fill the tracking error matrix and the one needed for kinematic fitting
738 if (FORWARD_PARMS_COV && fcov.size()!=0){
739 fit_params.setForwardParmFlag(true);
740
741 // We MUST fill the entire matrix (not just upper right) even though
742 // this is a DMatrixDSym
743 for (unsigned int i=0;i<5;i++){
744 for (unsigned int j=0;j<5;j++){
745 errMatrix(i,j)=fcov[i][j];
746 }
747 }
748 fit_params.setTrackingStateVector(x_,y_,tx_,ty_,q_over_p_);
749
750 // Compute and fill the error matrix needed for kinematic fitting
751 fit_params.setErrorMatrix(Get7x7ErrorMatrixForward(errMatrix));
752 }
753 else if (cov.size()!=0){
754 fit_params.setForwardParmFlag(false);
755
756 // We MUST fill the entire matrix (not just upper right) even though
757 // this is a DMatrixDSym
758 for (unsigned int i=0;i<5;i++){
759 for (unsigned int j=0;j<5;j++){
760 errMatrix(i,j)=cov[i][j];
761 }
762 }
763 fit_params.setTrackingStateVector(q_over_pt_,phi_,tanl_,D_,z_);
764
765 // Compute and fill the error matrix needed for kinematic fitting
766 fit_params.setErrorMatrix(Get7x7ErrorMatrix(errMatrix));
767 }
768 fit_params.setTrackingErrorMatrix(errMatrix);
769 this->chisq = GetChiSq();
770 this->Ndof = GetNDF();
771 fit_status = kFitSuccess;
772
773 // Check that the momentum is above some minimal amount. If
774 // not, return that the fit failed.
775 if(fit_params.momentum().Mag() < MIN_FIT_P)fit_status = kFitFailed;
776
777
778 //_DBG_ << "========= done!" << endl;
779
780 return fit_status;
781}
782
783//-----------------
784// ChiSq
785//-----------------
786double DTrackFitterKalmanSIMD::ChiSq(fit_type_t fit_type, DReferenceTrajectory *rt, double *chisq_ptr, int *dof_ptr, vector<pull_t> *pulls_ptr)
787{
788 // This simply returns whatever was left in for the chisq/NDF from the last fit.
789 // Using a DReferenceTrajectory is not really appropriate here so the base class'
790 // requirement of it should be reviewed.
791 double chisq = GetChiSq();
792 unsigned int ndf = GetNDF();
793
794 if(chisq_ptr)*chisq_ptr = chisq;
795 if(dof_ptr)*dof_ptr = int(ndf);
796 if(pulls_ptr)*pulls_ptr = pulls;
797
798 return chisq/double(ndf);
799}
800
801// Initialize the state vector
802jerror_t DTrackFitterKalmanSIMD::SetSeed(double q,DVector3 pos, DVector3 mom){
803 if (!isfinite(pos.Mag()) || !isfinite(mom.Mag())){
804 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<804<<" "
<< "Invalid seed data." <<endl;
805 return UNRECOVERABLE_ERROR;
806 }
807 if (mom.Mag()<MIN_FIT_P){
808 mom.SetMag(MIN_FIT_P);
809 }
810 else if (MASS>0.9 && mom.Mag()<MIN_PROTON_P0.3){
811 mom.SetMag(MIN_PROTON_P0.3);
812 }
813 else if (MASS<0.9 && mom.Mag()<MIN_FIT_P){
814 mom.SetMag(MIN_PION_P0.08);
815 }
816 if (mom.Mag()>MAX_P12.0){
817 mom.SetMag(MAX_P12.0);
818 }
819
820 // Forward parameterization
821 x_=pos.x();
822 y_=pos.y();
823 z_=pos.z();
824 tx_= mom.x()/mom.z();
825 ty_= mom.y()/mom.z();
826 q_over_p_=q/mom.Mag();
827
828 // Central parameterization
829 phi_=mom.Phi();
830 tanl_=tan(M_PI_21.57079632679489661923-mom.Theta());
831 q_over_pt_=q/mom.Perp();
832
833 return NOERROR;
834}
835
836// Return the momentum at the distance of closest approach to the origin.
837inline void DTrackFitterKalmanSIMD::GetMomentum(DVector3 &mom){
838 double pt=1./fabs(q_over_pt_);
839 mom.SetXYZ(pt*cos(phi_),pt*sin(phi_),pt*tanl_);
840}
841
842// Return the "vertex" position (position at which track crosses beam line)
843inline void DTrackFitterKalmanSIMD::GetPosition(DVector3 &pos){
844 pos.SetXYZ(x_,y_,z_);
845}
846
847// Add FDC hits
848jerror_t DTrackFitterKalmanSIMD::AddFDCHit(const DFDCPseudo *fdchit){
849 DKalmanSIMDFDCHit_t *hit= new DKalmanSIMDFDCHit_t;
850
851 hit->package=fdchit->wire->layer/6;
852 hit->t=fdchit->time;
853 hit->uwire=fdchit->w;
854 hit->vstrip=fdchit->s;
855 hit->vvar=fdchit->ds*fdchit->ds;
856 hit->z=fdchit->wire->origin.z();
857 hit->cosa=fdchit->wire->udir.y();
858 hit->sina=fdchit->wire->udir.x();
859 hit->nr=0.;
860 hit->nz=0.;
861 hit->dE=1e6*fdchit->dE;
862 hit->xres=hit->yres=1000.;
863 hit->hit=fdchit;
864 hit->status=good_hit;
865
866 my_fdchits.push_back(hit);
867
868 return NOERROR;
869}
870
871// Add CDC hits
872jerror_t DTrackFitterKalmanSIMD::AddCDCHit (const DCDCTrackHit *cdchit){
873 DKalmanSIMDCDCHit_t *hit= new DKalmanSIMDCDCHit_t;
874
875 hit->hit=cdchit;
876 hit->status=good_hit;
877 hit->residual=1000.;
878 hit->origin.Set(cdchit->wire->origin.x(),cdchit->wire->origin.y());
879 double one_over_uz=1./cdchit->wire->udir.z();
880 hit->dir.Set(one_over_uz*cdchit->wire->udir.x(),
881 one_over_uz*cdchit->wire->udir.y());
882 hit->z0wire=cdchit->wire->origin.z();
883 hit->cosstereo=cos(cdchit->wire->stereo);
884 hit->tdrift=cdchit->tdrift;
885 my_cdchits.push_back(hit);
886
887 return NOERROR;
888}
889
890// Calculate the derivative of the state vector with respect to z
891jerror_t DTrackFitterKalmanSIMD::CalcDeriv(double z,
892 const DMatrix5x1 &S,
893 double dEdx,
894 DMatrix5x1 &D){
895 double tx=S(state_tx),ty=S(state_ty);
896 double q_over_p=S(state_q_over_p);
897
898 // Turn off dEdx if the magnitude of the momentum drops below some cutoff
899 if (fabs(q_over_p)>Q_OVER_P_MAX100.){
900 dEdx=0.;
901 }
902 // Try to keep the direction tangents from heading towards 90 degrees
903 if (fabs(tx)>TAN_MAX10.) tx=TAN_MAX10.*(tx>0.0?1.:-1.);
904 if (fabs(ty)>TAN_MAX10.) ty=TAN_MAX10.*(ty>0.0?1.:-1.);
905
906 // useful combinations of terms
907 double kq_over_p=qBr2p0.003*q_over_p;
908 double tx2=tx*tx;
909 double ty2=ty*ty;
910 double txty=tx*ty;
911 double one_plus_tx2=1.+tx2;
912 double dsdz=sqrt(one_plus_tx2+ty2);
913 double dtx_Bfac=ty*Bz+txty*Bx-one_plus_tx2*By;
914 double dty_Bfac=Bx*(1.+ty2)-txty*By-tx*Bz;
915 double kq_over_p_dsdz=kq_over_p*dsdz;
916
917 // Derivative of S with respect to z
918 D(state_x)=tx;
919 D(state_y)=ty;
920 D(state_tx)=kq_over_p_dsdz*dtx_Bfac;
921 D(state_ty)=kq_over_p_dsdz*dty_Bfac;
922
923 D(state_q_over_p)=0.;
924 if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS3.0e-8){
925 double q_over_p_sq=q_over_p*q_over_p;
926 double E=sqrt(1./q_over_p_sq+mass2);
927 D(state_q_over_p)=-q_over_p_sq*q_over_p*E*dEdx*dsdz;
928 }
929 return NOERROR;
930}
931
932// Reference trajectory for forward tracks in CDC region
933// At each point we store the state vector and the Jacobian needed to get to
934//this state along z from the previous state.
935jerror_t DTrackFitterKalmanSIMD::SetCDCForwardReferenceTrajectory(DMatrix5x1 &S){
936 int i=0,forward_traj_length=forward_traj.size();
937 double z=z_;
938 double r2=0.;
939 bool stepped_to_boundary=false;
940
941 // Coordinates for outermost cdc hit
942 unsigned int id=my_cdchits.size()-1;
943 const DKalmanSIMDCDCHit_t *outerhit=my_cdchits[id];
944 double rmax=(outerhit->origin+(endplate_z-outerhit->z0wire)*outerhit->dir).Mod()+DELTA_R1.0;
945 double r2max=rmax*rmax;
946
947 // Magnetic field and gradient at beginning of trajectory
948 //bfield->GetField(x_,y_,z_,Bx,By,Bz);
949 bfield->GetFieldAndGradient(x_,y_,z_,Bx,By,Bz,
950 dBxdx,dBxdy,dBxdz,dBydx,
951 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
952
953 // Reset cdc status flags
954 for (unsigned int i=0;i<my_cdchits.size();i++){
955 if (my_cdchits[i]->status!=late_hit) my_cdchits[i]->status=good_hit;
956 }
957
958 // Continue adding to the trajectory until we have reached the endplate
959 // or the maximum radius
960 while(z<endplate_z && z>cdc_origin[2] &&
961 r2<r2max && fabs(S(state_q_over_p))<Q_OVER_P_MAX100.
962 && fabs(S(state_tx))<TAN_MAX10.
963 && fabs(S(state_ty))<TAN_MAX10.
964 ){
965 if (PropagateForwardCDC(forward_traj_length,i,z,r2,S,stepped_to_boundary)
966 !=NOERROR) return UNRECOVERABLE_ERROR;
967 }
968
969 // Only use hits that would fall within the range of the reference trajectory
970 for (unsigned int i=0;i<my_cdchits.size();i++){
971 DKalmanSIMDCDCHit_t *hit=my_cdchits[i];
972 double my_r2=(hit->origin+(z-hit->z0wire)*hit->dir).Mod2();
973 if (my_r2>r2) hit->status=bad_hit;
974 }
975
976 // If the current length of the trajectory deque is less than the previous
977 // trajectory deque, remove the extra elements and shrink the deque
978 if (i<(int)forward_traj.size()){
979 forward_traj_length=forward_traj.size();
980 for (int j=0;j<forward_traj_length-i;j++){
981 forward_traj.pop_front();
982 }
983 }
984
985 // return an error if there are still no entries in the trajectory
986 if (forward_traj.size()==0) return RESOURCE_UNAVAILABLE;
987
988 // Find estimate for t0 using smallest drift time
989 if (fit_type==kWireBased){
990 mT0Detector=SYS_CDC;
991 int id=my_cdchits.size()-1;
992 double old_time=0.,doca2=0.,old_doca2=1e6;
993 int min_id=mMinDriftID-1000;
994 for (unsigned int m=0;m<forward_traj.size();m++){
995 if (id>=0){
996 DVector2 origin=my_cdchits[id]->origin;
997 DVector2 dir=my_cdchits[id]->dir;
998 DVector2 wire_xy=origin+(forward_traj[m].z-my_cdchits[id]->z0wire)*dir;
999 DVector2 my_xy(forward_traj[m].S(state_x),forward_traj[m].S(state_y));
1000 doca2=(wire_xy-my_xy).Mod2();
1001
1002 if (doca2>old_doca2){
1003 if (id==min_id){
1004 double tcorr=1.18; // not sure why needed..
1005 mT0MinimumDriftTime=my_cdchits[id]->tdrift-old_time+tcorr;
1006 // _DBG_ << "T0 = " << mT0MinimumDriftTime << endl;
1007 break;
1008 }
1009 doca2=1e6;
1010 id--;
1011 }
1012 }
1013 old_doca2=doca2;
1014 old_time=forward_traj[m].t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
1015 }
1016 }
1017
1018 if (DEBUG_LEVEL>20)
1019 {
1020 cout << "--- Forward cdc trajectory ---" <<endl;
1021 for (unsigned int m=0;m<forward_traj.size();m++){
1022 // DMatrix5x1 S=*(forward_traj[m].S);
1023 DMatrix5x1 S=(forward_traj[m].S);
1024 double tx=S(state_tx),ty=S(state_ty);
1025 double phi=atan2(ty,tx);
1026 double cosphi=cos(phi);
1027 double sinphi=sin(phi);
1028 double p=fabs(1./S(state_q_over_p));
1029 double tanl=1./sqrt(tx*tx+ty*ty);
1030 double sinl=sin(atan(tanl));
1031 double cosl=cos(atan(tanl));
1032 cout
1033 << setiosflags(ios::fixed)<< "pos: " << setprecision(4)
1034 << forward_traj[m].S(state_x) << ", "
1035 << forward_traj[m].S(state_y) << ", "
1036 << forward_traj[m].z << " mom: "
1037 << p*cosphi*cosl<< ", " << p*sinphi*cosl << ", "
1038 << p*sinl << " -> " << p
1039 <<" s: " << setprecision(3)
1040 << forward_traj[m].s
1041 <<" t: " << setprecision(3)
1042 << forward_traj[m].t/SPEED_OF_LIGHT29.9792
1043 <<" B: " << forward_traj[m].B
1044 << endl;
1045 }
1046 }
1047
1048 // Current state vector
1049 S=forward_traj[0].S;
1050
1051 // position at the end of the swim
1052 x_=forward_traj[0].S(state_x);
1053 y_=forward_traj[0].S(state_y);
1054 z_=forward_traj[0].z;
1055
1056 return NOERROR;
1057}
1058
1059// Routine that extracts the state vector propagation part out of the reference
1060// trajectory loop
1061jerror_t DTrackFitterKalmanSIMD::PropagateForwardCDC(int length,int &index,
1062 double &z,double &r2,
1063 DMatrix5x1 &S,
1064 bool &stepped_to_boundary){
1065 DMatrix5x5 J,Q;
1066 DKalmanForwardTrajectory_t temp;
1067 int my_i=0;
1068 temp.h_id=0;
1069 temp.num_hits=0;
1070 double dEdx=0.;
1071 double s_to_boundary=1e6;
1072 double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
1073
1074 // current position
1075 DVector3 pos(S(state_x),S(state_y),z);
1076 temp.z=z;
1077 // squared radius
1078 r2=pos.Perp2();
1079
1080 temp.s=len;
1081 temp.t=ftime;
1082 temp.K_rho_Z_over_A=temp.rho_Z_over_A=temp.LnI=0.; //initialize
1083 temp.chi2c_factor=temp.chi2a_factor=temp.chi2a_corr=0.;
1084 temp.S=S;
1085
1086 // Kinematic variables
1087 double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
1088 double one_over_beta2=1.+mass2*q_over_p_sq;
1089 if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8;
1090
1091 // get material properties from the Root Geometry
1092 if (ENABLE_BOUNDARY_CHECK && fit_type==kTimeBased){
1093 DVector3 mom(S(state_tx),S(state_ty),1.);
1094 if(geom->FindMatKalman(pos,mom,temp.K_rho_Z_over_A,
1095 temp.rho_Z_over_A,temp.LnI,
1096 temp.chi2c_factor,temp.chi2a_factor,
1097 temp.chi2a_corr,
1098 last_material_map,
1099 &s_to_boundary)!=NOERROR){
1100 return UNRECOVERABLE_ERROR;
1101 }
1102 }
1103 else
1104 {
1105 if(geom->FindMatKalman(pos,temp.K_rho_Z_over_A,
1106 temp.rho_Z_over_A,temp.LnI,
1107 temp.chi2c_factor,temp.chi2a_factor,
1108 temp.chi2a_corr,
1109 last_material_map)!=NOERROR){
1110 return UNRECOVERABLE_ERROR;
1111 }
1112 }
1113
1114 // Get dEdx for the upcoming step
1115 if (CORRECT_FOR_ELOSS){
1116 dEdx=GetdEdx(S(state_q_over_p),temp.K_rho_Z_over_A,temp.rho_Z_over_A,
1117 temp.LnI);
1118 }
1119
1120 index++;
1121 if (index<=length){
1122 my_i=length-index;
1123 forward_traj[my_i].s=temp.s;
1124 forward_traj[my_i].t=temp.t;
1125 forward_traj[my_i].h_id=temp.h_id;
1126 forward_traj[my_i].num_hits=0;
1127 forward_traj[my_i].z=temp.z;
1128 forward_traj[my_i].rho_Z_over_A=temp.rho_Z_over_A;
1129 forward_traj[my_i].K_rho_Z_over_A=temp.K_rho_Z_over_A;
1130 forward_traj[my_i].LnI=temp.LnI;
1131 forward_traj[my_i].S=S;
1132 }
1133
1134 // Determine the step size based on energy loss
1135 //double step=mStepSizeS*dz_ds;
1136 double ds=mStepSizeS;
1137 if (z<endplate_z && r2<endplate_r2max && z>cdc_origin[2]){
1138 if (!stepped_to_boundary){
1139 stepped_to_boundary=false;
1140 if (fabs(dEdx)>EPS3.0e-8){
1141 ds=DE_PER_STEP0.0005/fabs(dEdx);
1142 }
1143 if(ds>mStepSizeS) ds=mStepSizeS;
1144 if (s_to_boundary<ds){
1145 ds=s_to_boundary;
1146 stepped_to_boundary=true;
1147 }
1148 if(ds<MIN_STEP_SIZE0.1)ds=MIN_STEP_SIZE0.1;
1149 }
1150 else{
1151 ds=MIN_STEP_SIZE0.1;
1152 stepped_to_boundary=false;
1153 }
1154 }
1155
1156 if (DEBUG_HISTS && fit_type==kTimeBased){
1157 if (Hstepsize && HstepsizeDenom){
1158 Hstepsize->Fill(z,sqrt(S(state_x)*S(state_x)+S(state_y)*S(state_y))
1159 ,ds);
1160 HstepsizeDenom->Fill(z,sqrt(S(state_x)*S(state_x)+S(state_y)*S(state_y)));
1161 }
1162 }
1163 double newz=z+ds*dz_ds; // new z position
1164
1165 // Store magnetic field
1166 temp.B=sqrt(Bx*Bx+By*By+Bz*Bz);
1167
1168 // Step through field
1169 ds=FasterStep(z,newz,dEdx,S);
1170
1171 // update path length
1172 len+=fabs(ds);
1173
1174 // Update flight time
1175 ftime+=ds*sqrt(one_over_beta2);// in units where c=1
1176
1177 // Get the contribution to the covariance matrix due to multiple
1178 // scattering
1179 GetProcessNoise(ds,temp.chi2c_factor,temp.chi2a_factor,temp.chi2a_corr,
1180 temp.S,Q);
1181
1182 // Energy loss straggling
1183 if (CORRECT_FOR_ELOSS){
1184 double varE=GetEnergyVariance(ds,one_over_beta2,temp.K_rho_Z_over_A);
1185 Q(state_q_over_p,state_q_over_p)=varE*q_over_p_sq*q_over_p_sq*one_over_beta2;
1186 }
1187
1188 // Compute the Jacobian matrix and its transpose
1189 StepJacobian(newz,z,S,dEdx,J);
1190
1191 // update the trajectory
1192 if (index<=length){
1193 forward_traj[my_i].B=temp.B;
1194 forward_traj[my_i].Q=Q;
1195 forward_traj[my_i].J=J;
1196 forward_traj[my_i].JT=J.Transpose();
1197 }
1198 else{
1199 temp.Q=Q;
1200 temp.J=J;
1201 temp.JT=J.Transpose();
1202 temp.Ckk=Zero5x5;
1203 temp.Skk=Zero5x1;
1204 forward_traj.push_front(temp);
1205 }
1206
1207 //update z
1208 z=newz;
1209
1210 return NOERROR;
1211}
1212
1213// Routine that extracts the state vector propagation part out of the reference
1214// trajectory loop
1215jerror_t DTrackFitterKalmanSIMD::PropagateCentral(int length, int &index,
1216 DVector2 &my_xy,
1217 double &var_t_factor,
1218 DMatrix5x1 &Sc,
1219 bool &stepped_to_boundary){
1220 DKalmanCentralTrajectory_t temp;
1221 DMatrix5x5 J; // State vector Jacobian matrix
1222 DMatrix5x5 Q; // Process noise covariance matrix
1223
1224 //Initialize some variables needed later
1225 double dEdx=0.;
1226 double s_to_boundary=1e6;
1227 int my_i=0;
1228 // Kinematic variables
1229 double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl)));
1230 double q_over_p_sq=q_over_p*q_over_p;
1231 double one_over_beta2=1.+mass2*q_over_p_sq;
1232 if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8;
1233
1234 // Reset D to zero
1235 Sc(state_D)=0.;
1236
1237 temp.xy=my_xy;
1238 temp.s=len;
1239 temp.t=ftime;
1240 temp.h_id=0;
1241 temp.K_rho_Z_over_A=0.,temp.rho_Z_over_A=0.,temp.LnI=0.; //initialize
1242 temp.chi2c_factor=0.,temp.chi2a_factor=0.,temp.chi2a_corr=0.;
1243 temp.S=Sc;
1244
1245 // Store magnitude of magnetic field
1246 temp.B=sqrt(Bx*Bx+By*By+Bz*Bz);
1247
1248 // get material properties from the Root Geometry
1249 DVector3 pos3d(my_xy.X(),my_xy.Y(),Sc(state_z));
1250 if (ENABLE_BOUNDARY_CHECK && fit_type==kTimeBased){
1251 DVector3 mom(cos(Sc(state_phi)),sin(Sc(state_phi)),Sc(state_tanl));
1252 if(geom->FindMatKalman(pos3d,mom,temp.K_rho_Z_over_A,
1253 temp.rho_Z_over_A,temp.LnI,
1254 temp.chi2c_factor,temp.chi2a_factor,
1255 temp.chi2a_corr,
1256 last_material_map,
1257 &s_to_boundary)
1258 !=NOERROR){
1259 return UNRECOVERABLE_ERROR;
1260 }
1261 }
1262 else if(geom->FindMatKalman(pos3d,temp.K_rho_Z_over_A,
1263 temp.rho_Z_over_A,temp.LnI,
1264 temp.chi2c_factor,temp.chi2a_factor,
1265 temp.chi2a_corr,
1266 last_material_map)!=NOERROR){
1267 return UNRECOVERABLE_ERROR;
1268 }
1269
1270 if (CORRECT_FOR_ELOSS){
1271 dEdx=GetdEdx(q_over_p,temp.K_rho_Z_over_A,temp.rho_Z_over_A,temp.LnI);
1272 }
1273
1274 // If the deque already exists, update it
1275 index++;
1276 if (index<=length){
1277 my_i=length-index;
1278 central_traj[my_i].B=temp.B;
1279 central_traj[my_i].s=temp.s;
1280 central_traj[my_i].t=temp.t;
1281 central_traj[my_i].h_id=0;
1282 central_traj[my_i].xy=temp.xy;
1283 central_traj[my_i].rho_Z_over_A=temp.rho_Z_over_A;
1284 central_traj[my_i].K_rho_Z_over_A=temp.K_rho_Z_over_A;
1285 central_traj[my_i].LnI=temp.LnI;
1286 central_traj[my_i].S=Sc;
1287 }
1288
1289 // Adjust the step size
1290 double step_size=mStepSizeS;
1291 if (stepped_to_boundary){
1292 step_size=MIN_STEP_SIZE0.1;
1293 stepped_to_boundary=false;
1294 }
1295 else{
1296 if (fabs(dEdx)>EPS3.0e-8){
1297 step_size=DE_PER_STEP0.0005/fabs(dEdx);
1298 }
1299 if(step_size>mStepSizeS) step_size=mStepSizeS;
1300 if (s_to_boundary<step_size){
1301 step_size=s_to_boundary;
1302 stepped_to_boundary=true;
1303 }
1304 if(step_size<MIN_STEP_SIZE0.1)step_size=MIN_STEP_SIZE0.1;
1305 }
1306 double r2=my_xy.Mod2();
1307 if (r2>endplate_r2min
1308 && step_size>mCDCInternalStepSize) step_size=mCDCInternalStepSize;
1309
1310 if (DEBUG_HISTS && fit_type==kTimeBased){
1311 if (Hstepsize && HstepsizeDenom){
1312 Hstepsize->Fill(Sc(state_z),my_xy.Mod(),step_size);
1313 HstepsizeDenom->Fill(Sc(state_z),my_xy.Mod());
1314 }
1315 }
1316
1317 // Propagate the state through the field
1318 FasterStep(my_xy,step_size,Sc,dEdx);
1319
1320 // update path length
1321 len+=step_size;
1322
1323 // Update flight time
1324 double dt=step_size*sqrt(one_over_beta2); // in units of c=1
1325 double one_minus_beta2=1.-1./one_over_beta2;
1326 ftime+=dt;
1327 var_ftime+=dt*dt*one_minus_beta2*one_minus_beta2*0.0004;
1328 var_t_factor=dt*dt*one_minus_beta2*one_minus_beta2;
1329
1330 //printf("t %f sigt %f\n",TIME_UNIT_CONVERSION*ftime,TIME_UNIT_CONVERSION*sqrt(var_ftime));
1331
1332 // Multiple scattering
1333 GetProcessNoiseCentral(step_size,temp.chi2c_factor,temp.chi2a_factor,
1334 temp.chi2a_corr,temp.S,Q);
1335
1336 // Energy loss straggling in the approximation of thick absorbers
1337 if (CORRECT_FOR_ELOSS){
1338 double varE
1339 =GetEnergyVariance(step_size,one_over_beta2,temp.K_rho_Z_over_A);
1340 Q(state_q_over_pt,state_q_over_pt)
1341 +=varE*temp.S(state_q_over_pt)*temp.S(state_q_over_pt)*one_over_beta2
1342 *q_over_p_sq;
1343 }
1344
1345 // B-field and gradient at current (x,y,z)
1346 bfield->GetFieldAndGradient(my_xy.X(),my_xy.Y(),Sc(state_z),Bx,By,Bz,
1347 dBxdx,dBxdy,dBxdz,dBydx,
1348 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
1349
1350 // Compute the Jacobian matrix and its transpose
1351 StepJacobian(my_xy,temp.xy-my_xy,-step_size,Sc,dEdx,J);
1352
1353 // Update the trajectory info
1354 if (index<=length){
1355 central_traj[my_i].Q=Q;
1356 central_traj[my_i].J=J;
1357 central_traj[my_i].JT=J.Transpose();
1358 }
1359 else{
1360 temp.Q=Q;
1361 temp.J=J;
1362 temp.JT=J.Transpose();
1363 temp.Ckk=Zero5x5;
1364 temp.Skk=Zero5x1;
1365 central_traj.push_front(temp);
1366 }
1367
1368 return NOERROR;
1369}
1370
1371
1372
1373// Reference trajectory for central tracks
1374// At each point we store the state vector and the Jacobian needed to get to this state
1375// along s from the previous state.
1376// The tricky part is that we swim out from the target to find Sc and pos along the trajectory
1377// but we need the Jacobians for the opposite direction, because the filter proceeds from
1378// the outer hits toward the target.
1379jerror_t DTrackFitterKalmanSIMD::SetCDCReferenceTrajectory(const DVector2 &xy,
1380 DMatrix5x1 &Sc){
1381 bool stepped_to_boundary=false;
1382 int i=0,central_traj_length=central_traj.size();
1383 // factor for scaling momentum resolution to propagate variance in flight
1384 // time
1385 double var_t_factor=0;
1386
1387 // Magnetic field and gradient at beginning of trajectory
1388 //bfield->GetField(x_,y_,z_,Bx,By,Bz);
1389 bfield->GetFieldAndGradient(x_,y_,z_,Bx,By,Bz,
1390 dBxdx,dBxdy,dBxdz,dBydx,
1391 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
1392
1393 // Copy of initial position in xy
1394 DVector2 my_xy=xy;
1395
1396 // Coordinates for outermost cdc hit
1397 unsigned int id=my_cdchits.size()-1;
1398 DVector2 origin=my_cdchits[id]->origin;
1399 DVector2 dir=my_cdchits[id]->dir;
1400 double rmax=(origin+(endplate_z-my_cdchits[id]->z0wire)*dir).Mod()+DELTA_R1.0;
1401 double r2max=rmax*rmax;
1402 double r2=xy.Mod2(),z=z_;
1403
1404 // Reset cdc status flags
1405 for (unsigned int j=0;j<my_cdchits.size();j++){
1406 if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
1407 }
1408
1409 // Continue adding to the trajectory until we have reached the endplate
1410 // or the maximum radius
1411 while(z<endplate_z && z>=Z_MIN-100. && r2<r2max
1412 && fabs(Sc(state_q_over_pt))<Q_OVER_PT_MAX100.
1413 && fabs(Sc(state_tanl))<TAN_MAX10.
1414 ){
1415 if (PropagateCentral(central_traj_length,i,my_xy,var_t_factor,Sc,stepped_to_boundary)
1416 !=NOERROR) return UNRECOVERABLE_ERROR;
1417 z=Sc(state_z);
1418 r2=my_xy.Mod2();
1419 }
1420
1421 // If the current length of the trajectory deque is less than the previous
1422 // trajectory deque, remove the extra elements and shrink the deque
1423 if (i<(int)central_traj.size()){
1424 int central_traj_length=central_traj.size();
1425 for (int j=0;j<central_traj_length-i;j++){
1426 central_traj.pop_front();
1427 }
1428 }
1429
1430 // Only use hits that would fall within the range of the reference trajectory
1431 for (unsigned int j=0;j<my_cdchits.size();j++){
1432 DKalmanSIMDCDCHit_t *hit=my_cdchits[j];
1433 double my_r2=(hit->origin+(z-hit->z0wire)*hit->dir).Mod2();
1434 if (my_r2>r2) hit->status=bad_hit;
1435 }
1436
1437
1438 // return an error if there are still no entries in the trajectory
1439 if (central_traj.size()==0) return RESOURCE_UNAVAILABLE;
1440
1441 // Find estimate for t0 using smallest drift time
1442 if (fit_type==kWireBased){
1443 mT0Detector=SYS_CDC;
1444 int id=my_cdchits.size()-1;
1445 double old_time=0.;
1446 double doca2=0.,old_doca2=1e6;
1447 int min_id=mMinDriftID-1000;
1448 for (unsigned int m=0;m<central_traj.size();m++){
1449 if (id>=0){
1450 origin=my_cdchits[id]->origin;
1451 dir=my_cdchits[id]->dir;
1452 DVector2 wire_xy=origin+(central_traj[m].S(state_z)-my_cdchits[id]->z0wire)*dir;
1453 DVector2 my_xy=central_traj[m].xy;
1454 doca2=(wire_xy-my_xy).Mod2();
1455
1456 if (doca2>old_doca2){
1457 if (id==min_id){
1458 double tcorr=1.18; // not sure why needed..
1459 mT0MinimumDriftTime=my_cdchits[id]->tdrift-old_time+tcorr;
1460 //_DBG_ << "T0 = " << mT0MinimumDriftTime << endl;
1461 break;
1462 }
1463 doca2=1e6;
1464 id--;
1465 }
1466 }
1467 old_doca2=doca2;
1468 old_time=central_traj[m].t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
1469 }
1470 }
1471
1472
1473 if (DEBUG_LEVEL>20)
1474 {
1475 cout << "---------" << central_traj.size() <<" entries------" <<endl;
1476 for (unsigned int m=0;m<central_traj.size();m++){
1477 DMatrix5x1 S=central_traj[m].S;
1478 double cosphi=cos(S(state_phi));
1479 double sinphi=sin(S(state_phi));
1480 double pt=fabs(1./S(state_q_over_pt));
1481 double tanl=S(state_tanl);
1482
1483 cout
1484 << m << "::"
1485 << setiosflags(ios::fixed)<< "pos: " << setprecision(4)
1486 << central_traj[m].xy.X() << ", "
1487 << central_traj[m].xy.Y() << ", "
1488 << central_traj[m].S(state_z) << " mom: "
1489 << pt*cosphi << ", " << pt*sinphi << ", "
1490 << pt*tanl << " -> " << pt/cos(atan(tanl))
1491 <<" s: " << setprecision(3)
1492 << central_traj[m].s
1493 <<" t: " << setprecision(3)
1494 << central_traj[m].t/SPEED_OF_LIGHT29.9792
1495 <<" B: " << central_traj[m].B
1496 << endl;
1497 }
1498 }
1499
1500 // State at end of swim
1501 Sc=central_traj[0].S;
1502
1503 return NOERROR;
1504}
1505
1506// Routine that extracts the state vector propagation part out of the reference
1507// trajectory loop
1508jerror_t DTrackFitterKalmanSIMD::PropagateForward(int length,int &i,
1509 double &z,double zhit,
1510 DMatrix5x1 &S, bool &done,
1511 bool &stepped_to_boundary,
1512 bool &stepped_to_endplate){
1513 DMatrix5x5 J,Q,JT;
1514 DKalmanForwardTrajectory_t temp;
1515
1516 // Initialize some variables
1517 temp.h_id=0;
1518 temp.num_hits=0;
1519 int my_i=0;
1520 double s_to_boundary=1e6;
1521 double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
1522
1523 // current position
1524 DVector3 pos(S(state_x),S(state_y),z);
1525
1526 temp.s=len;
1527 temp.t=ftime;
1528 temp.z=z;
1529 temp.K_rho_Z_over_A=temp.rho_Z_over_A=temp.LnI=0.; //initialize
1530 temp.chi2c_factor=temp.chi2a_factor=temp.chi2a_corr=0.;
1531 temp.S=S;
1532
1533 // Kinematic variables
1534 double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
1535 double one_over_beta2=1.+mass2*q_over_p_sq;
1536 if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8;
1537
1538 // get material properties from the Root Geometry
1539 if (ENABLE_BOUNDARY_CHECK && fit_type==kTimeBased){
1540 DVector3 mom(S(state_tx),S(state_ty),1.);
1541 if (geom->FindMatKalman(pos,mom,temp.K_rho_Z_over_A,
1542 temp.rho_Z_over_A,temp.LnI,
1543 temp.chi2c_factor,temp.chi2a_factor,
1544 temp.chi2a_corr,
1545 last_material_map,
1546 &s_to_boundary)
1547 !=NOERROR){
1548 return UNRECOVERABLE_ERROR;
1549 }
1550 }
1551 else
1552 {
1553 if (geom->FindMatKalman(pos,temp.K_rho_Z_over_A,
1554 temp.rho_Z_over_A,temp.LnI,
1555 temp.chi2c_factor,temp.chi2a_factor,
1556 temp.chi2a_corr,
1557 last_material_map)!=NOERROR){
1558 return UNRECOVERABLE_ERROR;
1559 }
1560 }
1561 // Get dEdx for the upcoming step
1562 double dEdx=0.;
1563 if (CORRECT_FOR_ELOSS){
1564 dEdx=GetdEdx(S(state_q_over_p),temp.K_rho_Z_over_A,
1565 temp.rho_Z_over_A,temp.LnI);
1566 }
1567 i++;
1568 my_i=length-i;
1569 if (i<=length){
1570 forward_traj[my_i].s=temp.s;
1571 forward_traj[my_i].t=temp.t;
1572 forward_traj[my_i].h_id=temp.h_id;
1573 forward_traj[my_i].num_hits=temp.num_hits;
1574 forward_traj[my_i].z=temp.z;
1575 forward_traj[my_i].rho_Z_over_A=temp.rho_Z_over_A;
1576 forward_traj[my_i].K_rho_Z_over_A=temp.K_rho_Z_over_A;
1577 forward_traj[my_i].LnI=temp.LnI;
1578 forward_traj[my_i].S=S;
1579 }
1580 else{
1581 temp.S=S;
1582 }
1583
1584 // Determine the step size based on energy loss
1585 // step=mStepSizeS*dz_ds;
1586 double ds=mStepSizeS;
1587 if (z>cdc_origin[2]){
1588 if (!stepped_to_boundary){
1589 stepped_to_boundary=false;
1590 if (fabs(dEdx)>EPS3.0e-8){
1591 ds=DE_PER_STEP0.0005/fabs(dEdx);
1592 }
1593 if(ds>mStepSizeS) ds=mStepSizeS;
1594 if (s_to_boundary<ds){
1595 ds=s_to_boundary;
1596 stepped_to_boundary=true;
1597 }
1598 if(ds<MIN_STEP_SIZE0.1)ds=MIN_STEP_SIZE0.1;
1599 }
1600 else{
1601 ds=MIN_STEP_SIZE0.1;
1602 stepped_to_boundary=false;
1603 }
1604 }
1605
1606 if (DEBUG_HISTS && fit_type==kTimeBased){
1607 if (Hstepsize && HstepsizeDenom){
1608 Hstepsize->Fill(z,sqrt(S(state_x)*S(state_x)+S(state_y)*S(state_y)),
1609 ds);
1610 HstepsizeDenom->Fill(z,sqrt(S(state_x)*S(state_x)+S(state_y)*S(state_y)));
1611 }
1612 }
1613 double dz=stepped_to_endplate ? endplate_dz : ds*dz_ds;
1614 double newz=z+dz; // new z position
1615 // Check if we are stepping through the CDC endplate
1616 if (newz>endplate_z && z<endplate_z){
1617 // _DBG_ << endl;
1618 newz=endplate_z+EPS31.e-2;
1619 stepped_to_endplate=true;
1620 }
1621
1622 // Check if we are about to step to one of the wire planes
1623 done=false;
1624 if (newz>zhit){
1625 newz=zhit;
1626 done=true;
1627 }
1628
1629 // Store magnitude of magnetic field
1630 temp.B=sqrt(Bx*Bx+By*By+Bz*Bz);
1631
1632 // Step through field
1633 ds=FasterStep(z,newz,dEdx,S);
1634
1635 // update path length
1636 len+=ds;
1637
1638 // update flight time
1639 ftime+=ds*sqrt(one_over_beta2); // in units where c=1
1640
1641 // Get the contribution to the covariance matrix due to multiple
1642 // scattering
1643 GetProcessNoise(ds,temp.chi2c_factor,temp.chi2a_factor,temp.chi2a_corr,
1644 temp.S,Q);
1645
1646 // Energy loss straggling
1647 if (CORRECT_FOR_ELOSS){
1648 double varE=GetEnergyVariance(ds,one_over_beta2,temp.K_rho_Z_over_A);
1649 Q(state_q_over_p,state_q_over_p)=varE*q_over_p_sq*q_over_p_sq*one_over_beta2;
1650 }
1651
1652 // Compute the Jacobian matrix and its transpose
1653 StepJacobian(newz,z,S,dEdx,J);
1654
1655 // update the trajectory data
1656 if (i<=length){
1657 forward_traj[my_i].B=temp.B;
1658 forward_traj[my_i].Q=Q;
1659 forward_traj[my_i].J=J;
1660 forward_traj[my_i].JT=J.Transpose();
1661 }
1662 else{
1663 temp.Q=Q;
1664 temp.J=J;
1665 temp.JT=J.Transpose();
1666 temp.Ckk=Zero5x5;
1667 temp.Skk=Zero5x1;
1668 forward_traj.push_front(temp);
1669 }
1670
1671 // update z
1672 z=newz;
1673
1674 return NOERROR;
1675}
1676
1677// Reference trajectory for trajectories with hits in the forward direction
1678// At each point we store the state vector and the Jacobian needed to get to this state
1679// along z from the previous state.
1680jerror_t DTrackFitterKalmanSIMD::SetReferenceTrajectory(DMatrix5x1 &S){
1681
1682 // Magnetic field and gradient at beginning of trajectory
1683 //bfield->GetField(x_,y_,z_,Bx,By,Bz);
1684 bfield->GetFieldAndGradient(x_,y_,z_,Bx,By,Bz,
1685 dBxdx,dBxdy,dBxdz,dBydx,
1686 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
1687
1688 // progress in z from hit to hit
1689 double z=z_;
1690 int i=0;
1691
1692 int forward_traj_length=forward_traj.size();
1693 // loop over the fdc hits
1694 double zhit=0.,old_zhit=0.;
1695 bool stepped_to_boundary=false;
1696 bool stepped_to_endplate=false;
1697 unsigned int m=0;
1698 for (m=0;m<my_fdchits.size();m++){
1699 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX100.
1700 || fabs(S(state_tx))>TAN_MAX10.
1701 || fabs(S(state_ty))>TAN_MAX10.
1702 ){
1703 break;
1704 }
1705
1706 zhit=my_fdchits[m]->z;
1707 if (fabs(old_zhit-zhit)>EPS3.0e-8){
1708 bool done=false;
1709 while (!done){
1710 if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX100.
1711 || fabs(S(state_tx))>TAN_MAX10.
1712 || fabs(S(state_ty))>TAN_MAX10.
1713 ){
1714 break;
1715 }
1716
1717 if (PropagateForward(forward_traj_length,i,z,zhit,S,done,
1718 stepped_to_boundary,stepped_to_endplate)
1719 !=NOERROR)
1720 return UNRECOVERABLE_ERROR;
1721 }
1722 }
1723 old_zhit=zhit;
1724 }
1725
1726 // If m<2 then no useable FDC hits survived the check on the magnitude on the
1727 // momentum
1728 if (m<2) return UNRECOVERABLE_ERROR;
1729
1730 // Make sure the reference trajectory goes one step beyond the most
1731 // downstream hit plane
1732 if (m==my_fdchits.size()){
1733 bool done=false;
1734 if (PropagateForward(forward_traj_length,i,z,400.,S,done,
1735 stepped_to_boundary,stepped_to_endplate)
1736 !=NOERROR)
1737 return UNRECOVERABLE_ERROR;
1738 if (PropagateForward(forward_traj_length,i,z,400.,S,done,
1739 stepped_to_boundary,stepped_to_endplate)
1740 !=NOERROR)
1741 return UNRECOVERABLE_ERROR;
1742 }
1743
1744 // Shrink the deque if the new trajectory has less points in it than the
1745 // old trajectory
1746 if (i<(int)forward_traj.size()){
1747 int mylen=forward_traj.size();
1748 //_DBG_ << "Shrinking: " << mylen << " to " << i << endl;
1749 for (int j=0;j<mylen-i;j++){
1750 forward_traj.pop_front();
1751 }
1752 // _DBG_ << " Now " << forward_traj.size() << endl;
1753 }
1754
1755 // If we lopped off some hits on the downstream end, truncate the trajectory to
1756 // the point in z just beyond the last valid hit
1757 unsigned int my_id=my_fdchits.size();
1758 if (m<my_id){
1759 if (zhit<z) my_id=m;
1760 else my_id=m-1;
1761 zhit=my_fdchits[my_id-1]->z;
1762 //_DBG_ << "Shrinking: " << forward_traj.size()<< endl;
1763 for (;;){
1764 z=forward_traj[0].z;
1765 if (z<zhit+EPS21.e-4) break;
1766 forward_traj.pop_front();
1767 }
1768 //_DBG_ << " Now " << forward_traj.size() << endl;
1769
1770 // Temporory structure keeping state and trajectory information
1771 DKalmanForwardTrajectory_t temp;
1772 temp.h_id=0;
1773 temp.num_hits=0;
1774 temp.B=0.;
1775 temp.K_rho_Z_over_A=temp.rho_Z_over_A=temp.LnI=0.;
1776 temp.Q=Zero5x5;
1777
1778 // last S vector
1779 S=forward_traj[0].S;
1780
1781 // Step just beyond the last hit
1782 double newz=z+0.01;
1783 double ds=Step(z,newz,0.,S); // ignore energy loss for this small step
1784 temp.s=forward_traj[0].s+ds;
1785 temp.z=newz;
1786 temp.S=S;
1787
1788 // Flight time
1789 double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
1790 double one_over_beta2=1.+mass2*q_over_p_sq;
1791 if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8;
1792 temp.t=forward_traj[0].t+ds*sqrt(one_over_beta2); // in units where c=1
1793
1794 // Covariance and state vector needed for smoothing code
1795 temp.Ckk=Zero5x5;
1796 temp.Skk=Zero5x1;
1797
1798 // Jacobian matrices
1799 temp.JT=temp.J=I5x5;
1800
1801 forward_traj.push_front(temp);
1802 }
1803
1804 // return an error if there are no entries in the trajectory
1805 if (forward_traj.size()==0) return RESOURCE_UNAVAILABLE;
1806
1807 // Fill in Lorentz deflection parameters
1808 for (unsigned int m=0;m<forward_traj.size();m++){
1809 if (my_id>0){
1810 unsigned int hit_id=my_id-1;
1811 double z=forward_traj[m].z;
1812 if (fabs(z-my_fdchits[hit_id]->z)<EPS21.e-4){
1813 forward_traj[m].h_id=my_id;
1814
1815 // Get the magnetic field at this position along the trajectory
1816 bfield->GetField(forward_traj[m].S(state_x),forward_traj[m].S(state_y),
1817 z,Bx,By,Bz);
1818 double Br=sqrt(Bx*Bx+By*By);
1819
1820 // Angle between B and wire
1821 double my_phi=0.;
1822 if (Br>0.) my_phi=acos((Bx*my_fdchits[hit_id]->sina
1823 +By*my_fdchits[hit_id]->cosa)/Br);
1824 /*
1825 lorentz_def->GetLorentzCorrectionParameters(forward_traj[m].pos.x(),
1826 forward_traj[m].pos.y(),
1827 forward_traj[m].pos.z(),
1828 tanz,tanr);
1829 my_fdchits[hit_id]->nr=tanr;
1830 my_fdchits[hit_id]->nz=tanz;
1831 */
1832
1833 my_fdchits[hit_id]->nr=LORENTZ_NR_PAR1*Bz*(1.+LORENTZ_NR_PAR2*Br);
1834 my_fdchits[hit_id]->nz=(LORENTZ_NZ_PAR1+LORENTZ_NZ_PAR2*Bz)*(Br*cos(my_phi));
1835
1836
1837 my_id--;
1838
1839 unsigned int num=1;
1840 while (hit_id>0
1841 && fabs(my_fdchits[hit_id]->z-my_fdchits[hit_id-1]->z)<EPS3.0e-8){
1842 hit_id=my_id-1;
1843 num++;
1844 my_id--;
1845 }
1846 forward_traj[m].num_hits=num;
1847 }
1848
1849 }
1850 }
1851
1852 // Find estimate for t0 using smallest drift time
1853 if (fit_type==kWireBased){
1854 if (mMinDriftID<1000){
1855 mT0Detector=SYS_FDC;
1856 bool found_minimum=false;
1857 for (unsigned int m=0;m<forward_traj.size();m++){
1858 if (found_minimum) break;
1859 unsigned int numhits=forward_traj[m].num_hits;
1860 if (numhits>0){
1861 unsigned int first_hit=forward_traj[m].h_id-1;
1862 for (unsigned int n=0;n<numhits;n++){
1863 unsigned int myid=first_hit-n;
1864 if (myid==mMinDriftID){
1865 double tcorr=-1.66;
1866 mT0MinimumDriftTime=my_fdchits[myid]->t-forward_traj[m].t*TIME_UNIT_CONVERSION3.33564095198152014e-02+tcorr;
1867 //_DBG_ << "T0 = " << mT0MinimumDriftTime << endl;
1868 found_minimum=true;
1869 break;
1870 }
1871 }
1872 }
1873 }
1874 }
1875 else if (my_cdchits.size()>0 && mMinDriftID>=1000){
1876 mT0Detector=SYS_CDC;
1877 int id=my_cdchits.size()-1;
1878 double old_time=0.,doca2=0.,old_doca2=1e6;
1879 int min_id=mMinDriftID-1000;
1880 for (unsigned int m=0;m<forward_traj.size();m++){
1881 if (id>=0){
1882 DVector2 origin=my_cdchits[id]->origin;
1883 DVector2 dir=my_cdchits[id]->dir;
1884 DVector2 wire_xy=origin+(forward_traj[m].z-my_cdchits[id]->z0wire)*dir;
1885 DVector2 my_xy(forward_traj[m].S(state_x),forward_traj[m].S(state_y));
1886 doca2=(wire_xy-my_xy).Mod2();
1887
1888 if (doca2>old_doca2){
1889 if (id==min_id){
1890 double tcorr=1.18; // not sure why needed..
1891 mT0MinimumDriftTime=my_cdchits[id]->tdrift-old_time+tcorr;
1892 //_DBG_ << "T0 = " << mT0MinimumDriftTime << endl;
1893 break;
1894 }
1895 doca2=1e6;
1896 id--;
1897 }
1898 }
1899 old_doca2=doca2;
1900 old_time=forward_traj[m].t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
1901 }
1902 }
1903 }
1904
1905 if (DEBUG_LEVEL>20)
1906 {
1907 cout << "--- Forward fdc trajectory ---" <<endl;
1908 for (unsigned int m=0;m<forward_traj.size();m++){
1909 DMatrix5x1 S=(forward_traj[m].S);
1910 double tx=S(state_tx),ty=S(state_ty);
1911 double phi=atan2(ty,tx);
1912 double cosphi=cos(phi);
1913 double sinphi=sin(phi);
1914 double p=fabs(1./S(state_q_over_p));
1915 double tanl=1./sqrt(tx*tx+ty*ty);
1916 double sinl=sin(atan(tanl));
1917 double cosl=cos(atan(tanl));
1918 cout
1919 << setiosflags(ios::fixed)<< "pos: " << setprecision(4)
1920 << forward_traj[m].S(state_x) << ", "
1921 << forward_traj[m].S(state_y) << ", "
1922 << forward_traj[m].z << " mom: "
1923 << p*cosphi*cosl<< ", " << p*sinphi*cosl << ", "
1924 << p*sinl << " -> " << p
1925 <<" s: " << setprecision(3)
1926 << forward_traj[m].s
1927 <<" t: " << setprecision(3)
1928 << forward_traj[m].t/SPEED_OF_LIGHT29.9792
1929 <<" id: " << forward_traj[m].h_id
1930 << endl;
1931 }
1932 }
1933
1934
1935 // position at the end of the swim
1936 z_=z;
1937 x_=S(state_x);
1938 y_=S(state_y);
1939
1940 return NOERROR;
1941}
1942
1943// Step the state vector through the field from oldz to newz.
1944// Uses the 4th-order Runga-Kutte algorithm.
1945double DTrackFitterKalmanSIMD::Step(double oldz,double newz, double dEdx,
1946 DMatrix5x1 &S){
1947 double delta_z=newz-oldz;
1948 if (fabs(delta_z)<EPS3.0e-8) return 0.; // skip if the step is too small
1949
1950 // Direction tangents
1951 double tx=S(state_tx);
1952 double ty=S(state_ty);
1953 double ds=sqrt(1.+tx*tx+ty*ty)*delta_z;
1954
1955 double delta_z_over_2=0.5*delta_z;
1956 double midz=oldz+delta_z_over_2;
1957 DMatrix5x1 D1,D2,D3,D4;
1958
1959 //B-field and gradient at at (x,y,z)
1960 bfield->GetFieldAndGradient(S(state_x),S(state_y),oldz,Bx,By,Bz,
1961 dBxdx,dBxdy,dBxdz,dBydx,
1962 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
1963 double Bx0=Bx,By0=By,Bz0=Bz;
1964
1965 // Calculate the derivative and propagate the state to the next point
1966 CalcDeriv(oldz,S,dEdx,D1);
1967 DMatrix5x1 S1=S+delta_z_over_2*D1;
1968
1969 // Calculate the field at the first intermediate point
1970 double dx=S1(state_x)-S(state_x);
1971 double dy=S1(state_y)-S(state_y);
1972 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z_over_2;
1973 By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z_over_2;
1974 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z_over_2;
1975
1976 // Calculate the derivative and propagate the state to the next point
1977 CalcDeriv(midz,S1,dEdx,D2);
1978 S1=S+delta_z_over_2*D2;
1979
1980 // Calculate the field at the second intermediate point
1981 dx=S1(state_x)-S(state_x);
1982 dy=S1(state_y)-S(state_y);
1983 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z_over_2;
1984 By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z_over_2;
1985 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z_over_2;
1986
1987 // Calculate the derivative and propagate the state to the next point
1988 CalcDeriv(midz,S1,dEdx,D3);
1989 S1=S+delta_z*D3;
1990
1991 // Calculate the field at the final point
1992 dx=S1(state_x)-S(state_x);
1993 dy=S1(state_y)-S(state_y);
1994 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z;
1995 By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z;
1996 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z;
1997
1998 // Final derivative
1999 CalcDeriv(newz,S1,dEdx,D4);
2000
2001 // S+=delta_z*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4);
2002 double dz_over_6=delta_z*ONE_SIXTH0.16666666666666667;
2003 double dz_over_3=delta_z*ONE_THIRD0.33333333333333333;
2004 S+=dz_over_6*D1;
2005 S+=dz_over_3*D2;
2006 S+=dz_over_3*D3;
2007 S+=dz_over_6*D4;
2008
2009 // Don't let the magnitude of the momentum drop below some cutoff
2010 //if (fabs(S(state_q_over_p))>Q_OVER_P_MAX)
2011 // S(state_q_over_p)=Q_OVER_P_MAX*(S(state_q_over_p)>0.0?1.:-1.);
2012 // Try to keep the direction tangents from heading towards 90 degrees
2013 //if (fabs(S(state_tx))>TAN_MAX)
2014 // S(state_tx)=TAN_MAX*(S(state_tx)>0.0?1.:-1.);
2015 //if (fabs(S(state_ty))>TAN_MAX)
2016 // S(state_ty)=TAN_MAX*(S(state_ty)>0.0?1.:-1.);
2017
2018 return ds;
2019}
2020// Step the state vector through the field from oldz to newz.
2021// Uses the 4th-order Runga-Kutte algorithm.
2022// Uses the gradient to compute the field at the intermediate and last
2023// points.
2024double DTrackFitterKalmanSIMD::FasterStep(double oldz,double newz, double dEdx,
2025 DMatrix5x1 &S){
2026 double delta_z=newz-oldz;
2027 if (fabs(delta_z)<EPS3.0e-8) return 0.; // skip if the step is too small
2028
2029 // Direction tangents
2030 double tx=S(state_tx);
2031 double ty=S(state_ty);
2032 double ds=sqrt(1.+tx*tx+ty*ty)*delta_z;
2033
2034 double delta_z_over_2=0.5*delta_z;
2035 double midz=oldz+delta_z_over_2;
2036 DMatrix5x1 D1,D2,D3,D4;
2037 double Bx0=Bx,By0=By,Bz0=Bz;
2038
2039 // The magnetic field at the beginning of the step is assumed to be
2040 // obtained at the end of the previous step through StepJacobian
2041
2042 // Calculate the derivative and propagate the state to the next point
2043 CalcDeriv(oldz,S,dEdx,D1);
2044 DMatrix5x1 S1=S+delta_z_over_2*D1;
2045
2046 // Calculate the field at the first intermediate point
2047 double dx=S1(state_x)-S(state_x);
2048 double 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,D2);
2055 S1=S+delta_z_over_2*D2;
2056
2057 // Calculate the field at the second intermediate 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_over_2;
2061 By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z_over_2;
2062 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z_over_2;
2063
2064 // Calculate the derivative and propagate the state to the next point
2065 CalcDeriv(midz,S1,dEdx,D3);
2066 S1=S+delta_z*D3;
2067
2068 // Calculate the field at the final point
2069 dx=S1(state_x)-S(state_x);
2070 dy=S1(state_y)-S(state_y);
2071 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z;
2072 By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z;
2073 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z;
2074
2075 // Final derivative
2076 CalcDeriv(newz,S1,dEdx,D4);
2077
2078 // S+=delta_z*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4);
2079 double dz_over_6=delta_z*ONE_SIXTH0.16666666666666667;
2080 double dz_over_3=delta_z*ONE_THIRD0.33333333333333333;
2081 S+=dz_over_6*D1;
2082 S+=dz_over_3*D2;
2083 S+=dz_over_3*D3;
2084 S+=dz_over_6*D4;
2085
2086 // Don't let the magnitude of the momentum drop below some cutoff
2087 //if (fabs(S(state_q_over_p))>Q_OVER_P_MAX)
2088 // S(state_q_over_p)=Q_OVER_P_MAX*(S(state_q_over_p)>0.0?1.:-1.);
2089 // Try to keep the direction tangents from heading towards 90 degrees
2090 //if (fabs(S(state_tx))>TAN_MAX)
2091 // S(state_tx)=TAN_MAX*(S(state_tx)>0.0?1.:-1.);
2092 //if (fabs(S(state_ty))>TAN_MAX)
2093 // S(state_ty)=TAN_MAX*(S(state_ty)>0.0?1.:-1.);
2094
2095 return ds;
2096}
2097
2098
2099
2100// Compute the Jacobian matrix for the forward parametrization.
2101jerror_t DTrackFitterKalmanSIMD::StepJacobian(double oldz,double newz,
2102 const DMatrix5x1 &S,
2103 double dEdx,DMatrix5x5 &J){
2104 // Initialize the Jacobian matrix
2105 //J.Zero();
2106 //for (int i=0;i<5;i++) J(i,i)=1.;
2107 J=I5x5;
2108
2109 // Step in z
2110 double delta_z=newz-oldz;
2111 if (fabs(delta_z)<EPS3.0e-8) return NOERROR; //skip if the step is too small
2112
2113 // Current values of state vector variables
2114 double x=S(state_x), y=S(state_y),tx=S(state_tx),ty=S(state_ty);
2115 double q_over_p=S(state_q_over_p);
2116
2117 //B-field and field gradient at (x,y,z)
2118 //if (get_field)
2119 bfield->GetFieldAndGradient(x,y,oldz,Bx,By,Bz,dBxdx,dBxdy,
2120 dBxdz,dBydx,dBydy,
2121 dBydz,dBzdx,dBzdy,dBzdz);
2122
2123 // Don't let the magnitude of the momentum drop below some cutoff
2124 if (fabs(q_over_p)>Q_OVER_P_MAX100.){
2125 q_over_p=Q_OVER_P_MAX100.*(q_over_p>0.0?1.:-1.);
2126 dEdx=0.;
2127 }
2128 // Try to keep the direction tangents from heading towards 90 degrees
2129 if (fabs(tx)>TAN_MAX10.) tx=TAN_MAX10.*(tx>0.0?1.:-1.);
2130 if (fabs(ty)>TAN_MAX10.) ty=TAN_MAX10.*(ty>0.0?1.:-1.);
2131 // useful combinations of terms
2132 double kq_over_p=qBr2p0.003*q_over_p;
2133 double tx2=tx*tx;
2134 double twotx2=2.*tx2;
2135 double ty2=ty*ty;
2136 double twoty2=2.*ty2;
2137 double txty=tx*ty;
2138 double one_plus_tx2=1.+tx2;
2139 double one_plus_ty2=1.+ty2;
2140 double one_plus_twotx2_plus_ty2=one_plus_ty2+twotx2;
2141 double one_plus_twoty2_plus_tx2=one_plus_tx2+twoty2;
2142 double dsdz=sqrt(1.+tx2+ty2);
2143 double ds=dsdz*delta_z;
2144 double kds=qBr2p0.003*ds;
2145 double kqdz_over_p_over_dsdz=kq_over_p*delta_z/dsdz;
2146 double kq_over_p_ds=kq_over_p*ds;
2147 double dtx_Bdep=ty*Bz+txty*Bx-one_plus_tx2*By;
2148 double dty_Bdep=Bx*one_plus_ty2-txty*By-tx*Bz;
2149 double Bxty=Bx*ty;
2150 double Bytx=By*tx;
2151 double Bztxty=Bz*txty;
2152 double Byty=By*ty;
2153 double Bxtx=Bx*tx;
2154
2155 // Jacobian
2156 J(state_x,state_tx)=J(state_y,state_ty)=delta_z;
2157 J(state_tx,state_q_over_p)=kds*dtx_Bdep;
2158 J(state_ty,state_q_over_p)=kds*dty_Bdep;
2159 J(state_tx,state_tx)+=kqdz_over_p_over_dsdz*(Bxty*(one_plus_twotx2_plus_ty2)
2160 -Bytx*(3.*one_plus_tx2+twoty2)
2161 +Bztxty);
2162 J(state_tx,state_x)=kq_over_p_ds*(ty*dBzdx+txty*dBxdx-one_plus_tx2*dBydx);
2163 J(state_ty,state_ty)+=kqdz_over_p_over_dsdz*(Bxty*(3.*one_plus_ty2+twotx2)
2164 -Bytx*(one_plus_twoty2_plus_tx2)
2165 -Bztxty);
2166 J(state_ty,state_y)= kq_over_p_ds*(one_plus_ty2*dBxdy-txty*dBydy-tx*dBzdy);
2167 J(state_tx,state_ty)=kqdz_over_p_over_dsdz
2168 *((Bxtx+Bz)*(one_plus_twoty2_plus_tx2)-Byty*one_plus_tx2);
2169 J(state_tx,state_y)= kq_over_p_ds*(tx*dBzdy+txty*dBxdy-one_plus_tx2*dBydy);
2170 J(state_ty,state_tx)=-kqdz_over_p_over_dsdz*((Byty+Bz)*(one_plus_twotx2_plus_ty2)
2171 -Bxtx*one_plus_ty2);
2172 J(state_ty,state_x)=kq_over_p_ds*(one_plus_ty2*dBxdx-txty*dBydx-tx*dBzdx);
2173 if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS3.0e-8){
2174 double one_over_p_sq=q_over_p*q_over_p;
2175 double E=sqrt(1./one_over_p_sq+mass2);
2176 J(state_q_over_p,state_q_over_p)-=dEdx*ds/E*(2.+3.*mass2*one_over_p_sq);
2177 double temp=-(q_over_p*one_over_p_sq/dsdz)*E*dEdx*delta_z;
2178 J(state_q_over_p,state_tx)=tx*temp;
2179 J(state_q_over_p,state_ty)=ty*temp;
2180 }
2181
2182 return NOERROR;
2183}
2184
2185// Calculate the derivative for the alternate set of parameters {q/pT, phi,
2186// tan(lambda),D,z}
2187jerror_t DTrackFitterKalmanSIMD::CalcDeriv(DVector2 &dpos,const DMatrix5x1 &S,
2188 double dEdx,DMatrix5x1 &D1){
2189 //Direction at current point
2190 double tanl=S(state_tanl);
2191 // Don't let tanl exceed some maximum
2192 if (fabs(tanl)>TAN_MAX10.) tanl=TAN_MAX10.*(tanl>0.0?1.:-1.);
2193
2194 double phi=S(state_phi);
2195 double cosphi=cos(phi);
2196 double sinphi=sin(phi);
2197 double lambda=atan(tanl);
2198 double sinl=sin(lambda);
2199 double cosl=cos(lambda);
2200 // Other parameters
2201 double q_over_pt=S(state_q_over_pt);
2202 double pt=fabs(1./q_over_pt);
2203
2204 // Turn off dEdx if the pt drops below some minimum
2205 if (pt<PT_MIN0.01) {
2206 dEdx=0.;
2207 }
2208 double kq_over_pt=qBr2p0.003*q_over_pt;
2209
2210 // Derivative of S with respect to s
2211 double By_cosphi_minus_Bx_sinphi=By*cosphi-Bx*sinphi;
2212 D1(state_q_over_pt)
2213 =kq_over_pt*q_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2214 double one_over_cosl=1./cosl;
2215 if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS3.0e-8){
2216 double p=pt*one_over_cosl;
2217 double p_sq=p*p;
2218 double E=sqrt(p_sq+mass2);
2219 D1(state_q_over_pt)-=q_over_pt*E*dEdx/p_sq;
2220 }
2221 // D1(state_phi)
2222 // =kq_over_pt*(Bx*cosphi*sinl+By*sinphi*sinl-Bz*cosl);
2223 D1(state_phi)=kq_over_pt*((Bx*cosphi+By*sinphi)*sinl-Bz*cosl);
2224 D1(state_tanl)=kq_over_pt*By_cosphi_minus_Bx_sinphi*one_over_cosl;
2225 D1(state_z)=sinl;
2226
2227 // New direction
2228 dpos.Set(cosl*cosphi,cosl*sinphi);
2229
2230 return NOERROR;
2231}
2232
2233// Calculate the derivative and Jacobian matrices for the alternate set of
2234// parameters {q/pT, phi, tan(lambda),D,z}
2235jerror_t DTrackFitterKalmanSIMD::CalcDerivAndJacobian(const DVector2 &xy,
2236 DVector2 &dxy,
2237 const DMatrix5x1 &S,
2238 double dEdx,
2239 DMatrix5x5 &J1,
2240 DMatrix5x1 &D1){
2241 //Direction at current point
2242 double tanl=S(state_tanl);
2243 // Don't let tanl exceed some maximum
2244 if (fabs(tanl)>TAN_MAX10.) tanl=TAN_MAX10.*(tanl>0.0?1.:-1.);
2245
2246 double phi=S(state_phi);
2247 double cosphi=cos(phi);
2248 double sinphi=sin(phi);
2249 double lambda=atan(tanl);
2250 double sinl=sin(lambda);
2251 double cosl=cos(lambda);
2252 double cosl2=cosl*cosl;
2253 double cosl3=cosl*cosl2;
2254 double one_over_cosl=1./cosl;
2255 // Other parameters
2256 double q_over_pt=S(state_q_over_pt);
2257 double pt=fabs(1./q_over_pt);
2258 double q=pt*q_over_pt;
2259
2260 // Turn off dEdx if pt drops below some minimum
2261 if (pt<PT_MIN0.01) {
2262 dEdx=0.;
2263 }
2264 double kq_over_pt=qBr2p0.003*q_over_pt;
2265
2266 // B-field and gradient at (x,y,z)
2267 bfield->GetFieldAndGradient(xy.X(),xy.Y(),S(state_z),Bx,By,Bz,
2268 dBxdx,dBxdy,dBxdz,dBydx,
2269 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
2270
2271 // Derivative of S with respect to s
2272 double By_cosphi_minus_Bx_sinphi=By*cosphi-Bx*sinphi;
2273 double By_sinphi_plus_Bx_cosphi=By*sinphi+Bx*cosphi;
2274 D1(state_q_over_pt)=kq_over_pt*q_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2275 D1(state_phi)=kq_over_pt*(By_sinphi_plus_Bx_cosphi*sinl-Bz*cosl);
2276 D1(state_tanl)=kq_over_pt*By_cosphi_minus_Bx_sinphi*one_over_cosl;
2277 D1(state_z)=sinl;
2278
2279 // New direction
2280 dxy.Set(cosl*cosphi,cosl*sinphi);
2281
2282 // Jacobian matrix elements
2283 J1(state_phi,state_phi)=kq_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2284 J1(state_phi,state_q_over_pt)
2285 =qBr2p0.003*(By_sinphi_plus_Bx_cosphi*sinl-Bz*cosl);
2286 J1(state_phi,state_tanl)=kq_over_pt*(By_sinphi_plus_Bx_cosphi*cosl
2287 +Bz*sinl)*cosl2;
2288 J1(state_phi,state_z)
2289 =kq_over_pt*(dBxdz*cosphi*sinl+dBydz*sinphi*sinl-dBzdz*cosl);
2290
2291 J1(state_tanl,state_phi)=-kq_over_pt*By_sinphi_plus_Bx_cosphi*one_over_cosl;
2292 J1(state_tanl,state_q_over_pt)=qBr2p0.003*By_cosphi_minus_Bx_sinphi*one_over_cosl;
2293 J1(state_tanl,state_tanl)=kq_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2294 J1(state_tanl,state_z)=kq_over_pt*(dBydz*cosphi-dBxdz*sinphi)*one_over_cosl;
2295 J1(state_q_over_pt,state_phi)
2296 =-kq_over_pt*q_over_pt*sinl*By_sinphi_plus_Bx_cosphi;
2297 J1(state_q_over_pt,state_q_over_pt)
2298 =2.*kq_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2299 J1(state_q_over_pt,state_tanl)
2300 =kq_over_pt*q_over_pt*cosl3*By_cosphi_minus_Bx_sinphi;
2301 if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS3.0e-8){
2302 double p=pt*one_over_cosl;
2303 double p_sq=p*p;
2304 double m2_over_p2=mass2/p_sq;
2305 double E=sqrt(p_sq+mass2);
2306
2307 D1(state_q_over_pt)-=q_over_pt*E/p_sq*dEdx;
2308 J1(state_q_over_pt,state_q_over_pt)-=dEdx*(2.+3.*m2_over_p2)/E;
2309 J1(state_q_over_pt,state_tanl)+=q*dEdx*sinl*(1.+2.*m2_over_p2)/(p*E);
2310 }
2311 J1(state_q_over_pt,state_z)
2312 =kq_over_pt*q_over_pt*sinl*(dBydz*cosphi-dBxdz*sinphi);
2313 J1(state_z,state_tanl)=cosl3;
2314
2315 return NOERROR;
2316}
2317
2318// Convert between the forward parameter set {x,y,tx,ty,q/p} and the central
2319// parameter set {q/pT,phi,tan(lambda),D,z}
2320jerror_t DTrackFitterKalmanSIMD::ConvertStateVectorAndCovariance(double z,
2321 const DMatrix5x1 &S,
2322 DMatrix5x1 &Sc,
2323 const DMatrix5x5 &C,
2324 DMatrix5x5 &Cc){
2325 //double x=S(state_x),y=S(state_y);
2326 //double tx=S(state_tx),ty=S(state_ty),q_over_p=S(state_q_over_p);
2327 // Copy over to the class variables
2328 x_=S(state_x), y_=S(state_y);
2329 tx_=S(state_tx),ty_=S(state_ty);
2330 double tsquare=tx_*tx_+ty_*ty_;
2331 double tanl=1./sqrt(tsquare);
2332 double cosl=cos(atan(tanl));
2333 q_over_p_=S(state_q_over_p);
2334 Sc(state_q_over_pt)=q_over_p_/cosl;
2335 Sc(state_phi)=atan2(ty_,tx_);
2336 Sc(state_tanl)=tanl;
2337 Sc(state_D)=sqrt(x_*x_+y_*y_);
2338 Sc(state_z)=z;
2339
2340 // D is a signed quantity
2341 double cosphi=cos(Sc(state_phi));
2342 double sinphi=sin(Sc(state_phi));
2343 if ((x_>0.0 && sinphi>0.0) || (y_ <0.0 && cosphi>0.0) || (y_>0.0 && cosphi<0.0)
2344 || (x_<0.0 && sinphi<0.0)) Sc(state_D)*=-1.;
2345
2346 // Rotate the covariance matrix from forward parameter space to central
2347 // parameter space
2348 DMatrix5x5 J;
2349
2350 double tanl2=tanl*tanl;
2351 double tanl3=tanl2*tanl;
2352 double factor=1./sqrt(1.+tsquare);
2353 J(state_z,state_x)=-tx_/tsquare;
2354 J(state_z,state_y)=-ty_/tsquare;
2355 double diff=tx_*tx_-ty_*ty_;
2356 double frac=1./(tsquare*tsquare);
2357 J(state_z,state_tx)=(x_*diff+2.*tx_*ty_*y_)*frac;
2358 J(state_z,state_ty)=(2.*tx_*ty_*x_-y_*diff)*frac;
2359 J(state_tanl,state_tx)=-tx_*tanl3;
2360 J(state_tanl,state_ty)=-ty_*tanl3;
2361 J(state_q_over_pt,state_q_over_p)=1./cosl;
2362 J(state_q_over_pt,state_tx)=-q_over_p_*tx_*tanl3*factor;
2363 J(state_q_over_pt,state_ty)=-q_over_p_*ty_*tanl3*factor;
2364 J(state_phi,state_tx)=-ty_*tanl2;
2365 J(state_phi,state_ty)=tx_*tanl2;
2366 J(state_D,state_x)=x_/Sc(state_D);
2367 J(state_D,state_y)=y_/Sc(state_D);
2368
2369 Cc=J*C*J.Transpose();
2370
2371 return NOERROR;
2372}
2373
2374// Step the state and the covariance matrix through the field
2375jerror_t DTrackFitterKalmanSIMD::StepStateAndCovariance(DVector2 &xy,
2376 double ds,
2377 double dEdx,
2378 DMatrix5x1 &S,
2379 DMatrix5x5 &J,
2380 DMatrix5x5 &C){
2381 //Initialize the Jacobian matrix
2382 J=I5x5;
2383 if (fabs(ds)<EPS3.0e-8) return NOERROR; // break out if ds is too small
2384
2385 // B-field and gradient at current (x,y,z)
2386 bfield->GetFieldAndGradient(xy.X(),xy.Y(),S(state_z),Bx,By,Bz,
2387 dBxdx,dBxdy,dBxdz,dBydx,
2388 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
2389 double Bx0=Bx,By0=By,Bz0=Bz;
2390
2391 // Matrices for intermediate steps
2392 DMatrix5x1 D1,D2,D3,D4;
2393 DMatrix5x1 S1;
2394 DMatrix5x5 J1;
2395 DVector2 dxy1,dxy2,dxy3,dxy4;
2396 double ds_2=0.5*ds;
2397
2398 // Find the derivative at the first point, propagate the state to the
2399 // first intermediate point and start filling the Jacobian matrix
2400 CalcDerivAndJacobian(xy,dxy1,S,dEdx,J1,D1);
2401 S1=S+ds_2*D1;
2402
2403 // Calculate the field at the first intermediate point
2404 double dz=S1(state_z)-S(state_z);
2405 double dx=ds_2*dxy1.X();
2406 double dy=ds_2*dxy1.Y();
2407 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2408 By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2409 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2410
2411 // Calculate the derivative and propagate the state to the next point
2412 CalcDeriv(dxy2,S1,dEdx,D2);
2413 S1=S+ds_2*D2;
2414
2415 // Calculate the field at the second intermediate point
2416 dz=S1(state_z)-S(state_z);
2417 dx=ds_2*dxy2.X();
2418 dy=ds_2*dxy2.Y();
2419 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2420 By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2421 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2422
2423 // Calculate the derivative and propagate the state to the next point
2424 CalcDeriv(dxy3,S1,dEdx,D3);
2425 S1=S+ds*D3;
2426
2427 // Calculate the field at the final point
2428 dz=S1(state_z)-S(state_z);
2429 dx=ds*dxy3.X();
2430 dy=ds*dxy3.Y();
2431 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2432 By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2433 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2434
2435 // Final derivative
2436 CalcDeriv(dxy4,S1,dEdx,D4);
2437
2438 // Position vector increment
2439 //DVector3 dpos
2440 // =ds*(ONE_SIXTH*dpos1+ONE_THIRD*dpos2+ONE_THIRD*dpos3+ONE_SIXTH*dpos4);
2441 double ds_over_6=ds*ONE_SIXTH0.16666666666666667;
2442 double ds_over_3=ds*ONE_THIRD0.33333333333333333;
2443 DVector2 dxy=ds_over_6*dxy1;
2444 dxy+=ds_over_3*dxy2;
2445 dxy+=ds_over_3*dxy3;
2446 dxy+=ds_over_6*dxy4;
2447
2448 // New Jacobian matrix
2449 J+=ds*J1;
2450
2451 // Deal with changes in D
2452 double B=sqrt(Bx0*Bx0+By0*By0+Bz0*Bz0);
2453 //double qrc_old=qpt/(qBr2p*Bz_);
2454 double qpt=1./S(state_q_over_pt);
2455 double q=(qpt>0.)?1.:-1.;
2456 double qrc_old=qpt/(qBr2p0.003*B);
2457 double sinphi=sin(S(state_phi));
2458 double cosphi=cos(S(state_phi));
2459 double qrc_plus_D=S(state_D)+qrc_old;
2460 dx=dxy.X();
2461 dy=dxy.Y();
2462 double dx_sinphi_minus_dy_cosphi=dx*sinphi-dy*cosphi;
2463 double rc=sqrt(dxy.Mod2()
2464 +2.*qrc_plus_D*(dx_sinphi_minus_dy_cosphi)
2465 +qrc_plus_D*qrc_plus_D);
2466 double q_over_rc=q/rc;
2467
2468 J(state_D,state_D)=q_over_rc*(dx_sinphi_minus_dy_cosphi+qrc_plus_D);
2469 J(state_D,state_q_over_pt)=qpt*qrc_old*(J(state_D,state_D)-1.);
2470 J(state_D,state_phi)=q_over_rc*qrc_plus_D*(dx*cosphi+dy*sinphi);
2471
2472 // New xy vector
2473 xy+=dxy;
2474
2475 // New state vector
2476 //S+=ds*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4);
2477 S+=ds_over_6*D1;
2478 S+=ds_over_3*D2;
2479 S+=ds_over_3*D3;
2480 S+=ds_over_6*D4;
2481
2482 // Don't let the pt drop below some minimum
2483 //if (fabs(1./S(state_q_over_pt))<PT_MIN) {
2484 // S(state_q_over_pt)=(1./PT_MIN)*(S(state_q_over_pt)>0.0?1.:-1.);
2485 // }
2486 // Don't let tanl exceed some maximum
2487 if (fabs(S(state_tanl))>TAN_MAX10.){
2488 S(state_tanl)=TAN_MAX10.*(S(state_tanl)>0.0?1.:-1.);
2489 }
2490
2491 // New covariance matrix
2492 // C=J C J^T
2493 C=C.SandwichMultiply(J);
2494
2495 return NOERROR;
2496}
2497
2498// Runga-Kutte for alternate parameter set {q/pT,phi,tanl(lambda),D,z}
2499// Uses the gradient to compute the field at the intermediate and last
2500// points.
2501jerror_t DTrackFitterKalmanSIMD::FasterStep(DVector2 &xy,double ds,
2502 DMatrix5x1 &S,
2503 double dEdx){
2504 if (fabs(ds)<EPS3.0e-8) return NOERROR; // break out if ds is too small
2505
2506 // Matrices for intermediate steps
2507 DMatrix5x1 D1,D2,D3,D4;
2508 DMatrix5x1 S1;
2509 DVector2 dxy1,dxy2,dxy3,dxy4;
2510 double ds_2=0.5*ds;
2511 double Bx0=Bx,By0=By,Bz0=Bz;
2512
2513 // The magnetic field at the beginning of the step is assumed to be
2514 // obtained at the end of the previous step through StepJacobian
2515
2516 // Calculate the derivative and propagate the state to the next point
2517 CalcDeriv(dxy1,S,dEdx,D1);
2518 S1=S+ds_2*D1;
2519
2520 // Calculate the field at the first intermediate point
2521 double dz=S1(state_z)-S(state_z);
2522 double dx=ds_2*dxy1.X();
2523 double dy=ds_2*dxy1.Y();
2524 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2525 By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2526 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2527
2528 // Calculate the derivative and propagate the state to the next point
2529 CalcDeriv(dxy2,S1,dEdx,D2);
2530 S1=S+ds_2*D2;
2531
2532 // Calculate the field at the second intermediate point
2533 dz=S1(state_z)-S(state_z);
2534 dx=ds_2*dxy2.X();
2535 dy=ds_2*dxy2.Y();
2536 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2537 By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2538 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2539
2540 // Calculate the derivative and propagate the state to the next point
2541 CalcDeriv(dxy3,S1,dEdx,D3);
2542 S1=S+ds*D3;
2543
2544 // Calculate the field at the final point
2545 dz=S1(state_z)-S(state_z);
2546 dx=ds*dxy3.X();
2547 dy=ds*dxy3.Y();
2548 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2549 By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2550 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2551
2552 // Final derivative
2553 CalcDeriv(dxy4,S1,dEdx,D4);
2554
2555 // New state vector
2556 // S+=ds*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4);
2557 double ds_over_6=ds*ONE_SIXTH0.16666666666666667;
2558 double ds_over_3=ds*ONE_THIRD0.33333333333333333;
2559 S+=ds_over_6*D1;
2560 S+=ds_over_3*D2;
2561 S+=ds_over_3*D3;
2562 S+=ds_over_6*D4;
2563
2564 // New position
2565 //pos+=ds*(ONE_SIXTH*dpos1+ONE_THIRD*dpos2+ONE_THIRD*dpos3+ONE_SIXTH*dpos4);
2566 xy+=ds_over_6*dxy1;
2567 xy+=ds_over_3*dxy2;
2568 xy+=ds_over_3*dxy3;
2569 xy+=ds_over_6*dxy4;
2570
2571 // Don't let the pt drop below some minimum
2572 //if (fabs(1./S(state_q_over_pt))<PT_MIN) {
2573 // S(state_q_over_pt)=(1./PT_MIN)*(S(state_q_over_pt)>0.0?1.:-1.);
2574 //}
2575 // Don't let tanl exceed some maximum
2576 if (fabs(S(state_tanl))>TAN_MAX10.){
2577 S(state_tanl)=TAN_MAX10.*(S(state_tanl)>0.0?1.:-1.);
2578 }
2579
2580 return NOERROR;
2581}
2582
2583// Runga-Kutte for alternate parameter set {q/pT,phi,tanl(lambda),D,z}
2584jerror_t DTrackFitterKalmanSIMD::Step(DVector2 &xy,double ds,
2585 DMatrix5x1 &S,
2586 double dEdx){
2587 if (fabs(ds)<EPS3.0e-8) return NOERROR; // break out if ds is too small
2588
2589 // B-field and gradient at current (x,y,z)
2590 bfield->GetFieldAndGradient(xy.X(),xy.Y(),S(state_z),Bx,By,Bz,
2591 dBxdx,dBxdy,dBxdz,dBydx,
2592 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
2593 double Bx0=Bx,By0=By,Bz0=Bz;
2594
2595 // Matrices for intermediate steps
2596 DMatrix5x1 D1,D2,D3,D4;
2597 DMatrix5x1 S1;
2598 DVector2 dxy1,dxy2,dxy3,dxy4;
2599 double ds_2=0.5*ds;
2600
2601 // Find the derivative at the first point, propagate the state to the
2602 // first intermediate point
2603 CalcDeriv(dxy1,S,dEdx,D1);
2604 S1=S+ds_2*D1;
2605
2606 // Calculate the field at the first intermediate point
2607 double dz=S1(state_z)-S(state_z);
2608 double dx=ds_2*dxy1.X();
2609 double dy=ds_2*dxy1.Y();
2610 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2611 By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2612 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2613
2614 // Calculate the derivative and propagate the state to the next point
2615 CalcDeriv(dxy2,S1,dEdx,D2);
2616 S1=S+ds_2*D2;
2617
2618 // Calculate the field at the second intermediate point
2619 dz=S1(state_z)-S(state_z);
2620 dx=ds_2*dxy2.X();
2621 dy=ds_2*dxy2.Y();
2622 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2623 By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2624 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2625
2626 // Calculate the derivative and propagate the state to the next point
2627 CalcDeriv(dxy3,S1,dEdx,D3);
2628 S1=S+ds*D3;
2629
2630 // Calculate the field at the final point
2631 dz=S1(state_z)-S(state_z);
2632 dx=ds*dxy3.X();
2633 dy=ds*dxy3.Y();
2634 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2635 By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2636 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2637
2638 // Final derivative
2639 CalcDeriv(dxy4,S1,dEdx,D4);
2640
2641 // New state vector
2642 // S+=ds*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4);
2643 double ds_over_6=ds*ONE_SIXTH0.16666666666666667;
2644 double ds_over_3=ds*ONE_THIRD0.33333333333333333;
2645 S+=ds_over_6*D1;
2646 S+=ds_over_3*D2;
2647 S+=ds_over_3*D3;
2648 S+=ds_over_6*D4;
2649
2650 // New position
2651 //pos+=ds*(ONE_SIXTH*dpos1+ONE_THIRD*dpos2+ONE_THIRD*dpos3+ONE_SIXTH*dpos4);
2652 xy+=ds_over_6*dxy1;
2653 xy+=ds_over_3*dxy2;
2654 xy+=ds_over_3*dxy3;
2655 xy+=ds_over_6*dxy4;
2656
2657 // Don't let the pt drop below some minimum
2658 //if (fabs(1./S(state_q_over_pt))<PT_MIN) {
2659 // S(state_q_over_pt)=(1./PT_MIN)*(S(state_q_over_pt)>0.0?1.:-1.);
2660 //}
2661 // Don't let tanl exceed some maximum
2662 if (fabs(S(state_tanl))>TAN_MAX10.){
2663 S(state_tanl)=TAN_MAX10.*(S(state_tanl)>0.0?1.:-1.);
2664 }
2665
2666 return NOERROR;
2667}
2668
2669
2670// Calculate the jacobian matrix for the alternate parameter set
2671// {q/pT,phi,tanl(lambda),D,z}
2672jerror_t DTrackFitterKalmanSIMD::StepJacobian(const DVector2 &xy,
2673 const DVector2 &dxy,
2674 double ds,const DMatrix5x1 &S,
2675 double dEdx,DMatrix5x5 &J){
2676 // Initialize the Jacobian matrix
2677 //J.Zero();
2678 //for (int i=0;i<5;i++) J(i,i)=1.;
2679 J=I5x5;
2680
2681 if (fabs(ds)<EPS3.0e-8) return NOERROR; // break out if ds is too small
2682 // B-field and gradient at current (x,y,z)
2683 //bfield->GetFieldAndGradient(xy.X(),xy.Y(),S(state_z),Bx,By,Bz,
2684 //dBxdx,dBxdy,dBxdz,dBydx,
2685 //dBydy,dBydz,dBzdx,dBzdy,dBzdz);
2686
2687 // Charge
2688 double q=(S(state_q_over_pt)>0.0)?1.:-1.;
2689
2690 //kinematic quantities
2691 double q_over_pt=S(state_q_over_pt);
2692 double sinphi=sin(S(state_phi));
2693 double cosphi=cos(S(state_phi));
2694 double D=S(state_D);
2695 double lambda=atan(S(state_tanl));
2696 double sinl=sin(lambda);
2697 double cosl=cos(lambda);
2698 double cosl2=cosl*cosl;
2699 double cosl3=cosl*cosl2;
2700 double one_over_cosl=1./cosl;
2701 double pt=fabs(1./q_over_pt);
2702
2703 // Turn off dEdx if pt drops below some minimum
2704 if (pt<PT_MIN0.01) {
2705 dEdx=0.;
2706 }
2707 double kds=qBr2p0.003*ds;
2708 double kq_ds_over_pt=kds*q_over_pt;
2709 double By_cosphi_minus_Bx_sinphi=By*cosphi-Bx*sinphi;
2710 double By_sinphi_plus_Bx_cosphi=By*sinphi+Bx*cosphi;
2711
2712 // Jacobian matrix elements
2713 J(state_phi,state_phi)+=kq_ds_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2714 J(state_phi,state_q_over_pt)=kds*(By_sinphi_plus_Bx_cosphi*sinl-Bz*cosl);
2715 J(state_phi,state_tanl)=kq_ds_over_pt*(By_sinphi_plus_Bx_cosphi*cosl
2716 +Bz*sinl)*cosl2;
2717 J(state_phi,state_z)
2718 =kq_ds_over_pt*(dBxdz*cosphi*sinl+dBydz*sinphi*sinl-dBzdz*cosl);
2719
2720 J(state_tanl,state_phi)=-kq_ds_over_pt*By_sinphi_plus_Bx_cosphi*one_over_cosl;
2721 J(state_tanl,state_q_over_pt)=kds*By_cosphi_minus_Bx_sinphi*one_over_cosl;
2722 J(state_tanl,state_tanl)+=kq_ds_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2723 J(state_tanl,state_z)=kq_ds_over_pt*(dBydz*cosphi-dBxdz*sinphi)*one_over_cosl;
2724 J(state_q_over_pt,state_phi)
2725 =-kq_ds_over_pt*q_over_pt*sinl*By_sinphi_plus_Bx_cosphi;
2726 J(state_q_over_pt,state_q_over_pt)
2727 +=2.*kq_ds_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2728 J(state_q_over_pt,state_tanl)
2729 =kq_ds_over_pt*q_over_pt*cosl3*By_cosphi_minus_Bx_sinphi;
2730 if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS3.0e-8){
2731 double p=pt*one_over_cosl;
2732 double p_sq=p*p;
2733 double m2_over_p2=mass2/p_sq;
2734 double E=sqrt(p_sq+mass2);
2735 double dE_over_E=dEdx*ds/E;
2736
2737 J(state_q_over_pt,state_q_over_pt)-=dE_over_E*(2.+3.*m2_over_p2);
2738 J(state_q_over_pt,state_tanl)+=q*dE_over_E*sinl*(1.+2.*m2_over_p2)/p;
2739 }
2740 J(state_q_over_pt,state_z)
2741 =kq_ds_over_pt*q_over_pt*sinl*(dBydz*cosphi-dBxdz*sinphi);
2742 J(state_z,state_tanl)=cosl3*ds;
2743
2744 // Deal with changes in D
2745 double B=sqrt(Bx*Bx+By*By+Bz*Bz);
2746 //double qrc_old=qpt/(qBr2p*fabs(Bz));
2747 double qpt=FactorForSenseOfRotation/q_over_pt;
2748 double qrc_old=qpt/(qBr2p0.003*B);
2749 double qrc_plus_D=D+qrc_old;
2750 double dx=dxy.X();
2751 double dy=dxy.Y();
2752 double dx_sinphi_minus_dy_cosphi=dx*sinphi-dy*cosphi;
2753 double rc=sqrt(dxy.Mod2()
2754 +2.*qrc_plus_D*(dx_sinphi_minus_dy_cosphi)
2755 +qrc_plus_D*qrc_plus_D);
2756 double q_over_rc=FactorForSenseOfRotation*q/rc;
2757
2758 J(state_D,state_D)=q_over_rc*(dx_sinphi_minus_dy_cosphi+qrc_plus_D);
2759 J(state_D,state_q_over_pt)=qpt*qrc_old*(J(state_D,state_D)-1.);
2760 J(state_D,state_phi)=q_over_rc*qrc_plus_D*(dx*cosphi+dy*sinphi);
2761
2762 return NOERROR;
2763}
2764
2765
2766
2767
2768// Runga-Kutte for alternate parameter set {q/pT,phi,tanl(lambda),D,z}
2769jerror_t DTrackFitterKalmanSIMD::StepJacobian(const DVector2 &xy,
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)<EPS3.0e-8) return NOERROR; // break out if ds is too small
2778
2779 // Matrices for intermediate steps
2780 DMatrix5x5 J1;
2781 DMatrix5x1 D1;
2782 DVector2 dxy1;
2783
2784 // charge
2785 double q=(S(state_q_over_pt)>0.0)?1.:-1.;
2786 q*=FactorForSenseOfRotation;
2787
2788 //kinematic quantities
2789 double qpt=1./S(state_q_over_pt) * FactorForSenseOfRotation;
2790 double sinphi=sin(S(state_phi));
2791 double cosphi=cos(S(state_phi));
2792 double D=S(state_D);
2793
2794 CalcDerivAndJacobian(xy,dxy1,S,dEdx,J1,D1);
2795 // double Bz_=fabs(Bz); // needed for computing D
2796
2797 // New Jacobian matrix
2798 J+=ds*J1;
2799
2800 // change in position
2801 DVector2 dxy =ds*dxy1;
2802
2803 // Deal with changes in D
2804 double B=sqrt(Bx*Bx+By*By+Bz*Bz);
2805 //double qrc_old=qpt/(qBr2p*Bz_);
2806 double qrc_old=qpt/(qBr2p0.003*B);
2807 double qrc_plus_D=D+qrc_old;
2808 double dx=dxy.X();
2809 double dy=dxy.Y();
2810 double dx_sinphi_minus_dy_cosphi=dx*sinphi-dy*cosphi;
2811 double rc=sqrt(dxy.Mod2()
2812 +2.*qrc_plus_D*(dx_sinphi_minus_dy_cosphi)
2813 +qrc_plus_D*qrc_plus_D);
2814 double q_over_rc=q/rc;
2815
2816 J(state_D,state_D)=q_over_rc*(dx_sinphi_minus_dy_cosphi+qrc_plus_D);
2817 J(state_D,state_q_over_pt)=qpt*qrc_old*(J(state_D,state_D)-1.);
2818 J(state_D,state_phi)=q_over_rc*qrc_plus_D*(dx*cosphi+dy*sinphi);
2819
2820 return NOERROR;
2821}
2822
2823// Compute contributions to the covariance matrix due to multiple scattering
2824// using the Lynch/Dahl empirical formulas
2825jerror_t DTrackFitterKalmanSIMD::GetProcessNoiseCentral(double ds,
2826 double chi2c_factor,
2827 double chi2a_factor,
2828 double chi2a_corr,
2829 const DMatrix5x1 &Sc,
2830 DMatrix5x5 &Q){
2831 Q.Zero();
2832 //return NOERROR;
2833 if (USE_MULS_COVARIANCE && chi2c_factor>0. && fabs(ds)>EPS3.0e-8){
2834 double tanl=Sc(state_tanl);
2835 double tanl2=tanl*tanl;
2836 double one_plus_tanl2=1.+tanl2;
2837 double one_over_pt=fabs(Sc(state_q_over_pt));
2838 double my_ds=fabs(ds);
2839 double my_ds_2=0.5*my_ds;
2840
2841 Q(state_phi,state_phi)=one_plus_tanl2;
2842 Q(state_tanl,state_tanl)=one_plus_tanl2*one_plus_tanl2;
2843 Q(state_q_over_pt,state_q_over_pt)=one_over_pt*one_over_pt*tanl2;
2844 Q(state_q_over_pt,state_tanl)=Q(state_tanl,state_q_over_pt)
2845 =Sc(state_q_over_pt)*tanl*one_plus_tanl2;
2846 Q(state_D,state_D)=ONE_THIRD0.33333333333333333*ds*ds;
2847
2848 // I am not sure the following is correct...
2849 double sign_D=(Sc(state_D)>0.0)?1.:-1.;
2850 Q(state_D,state_phi)=Q(state_phi,state_D)=sign_D*my_ds_2*sqrt(one_plus_tanl2);
2851 Q(state_D,state_tanl)=Q(state_tanl,state_D)=sign_D*my_ds_2*one_plus_tanl2;
2852 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);
2853
2854 double one_over_p_sq=one_over_pt*one_over_pt/one_plus_tanl2;
2855 double one_over_beta2=1.+mass2*one_over_p_sq;
2856 double chi2c_p_sq=chi2c_factor*my_ds*one_over_beta2;
2857 double chi2a_p_sq=chi2a_factor*(1.+chi2a_corr*one_over_beta2);
2858 // F=Fraction of Moliere distribution to be taken into account
2859 // nu=0.5*chi2c/(chi2a*(1.-F));
2860 double nu=MOLIERE_RATIO15.0*chi2c_p_sq/chi2a_p_sq;
2861 double one_plus_nu=1.+nu;
2862 // sig2_ms=chi2c*1e-6/(1.+F*F)*((one_plus_nu)/nu*log(one_plus_nu)-1.);
2863 double sig2_ms=chi2c_p_sq*one_over_p_sq*MOLIERE_RATIO311.0e-7
2864 *(one_plus_nu/nu*log(one_plus_nu)-1.);
2865
2866 Q*=sig2_ms;
2867 }
2868
2869 return NOERROR;
2870}
2871
2872// Compute contributions to the covariance matrix due to multiple scattering
2873// using the Lynch/Dahl empirical formulas
2874jerror_t DTrackFitterKalmanSIMD::GetProcessNoise(double ds,
2875 double chi2c_factor,
2876 double chi2a_factor,
2877 double chi2a_corr,
2878 const DMatrix5x1 &S,
2879 DMatrix5x5 &Q){
2880
2881 Q.Zero();
2882 //return NOERROR;
2883 if (USE_MULS_COVARIANCE && chi2c_factor>0. && fabs(ds)>EPS3.0e-8){
2884 double tx=S(state_tx),ty=S(state_ty);
2885 double one_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
2886 double my_ds=fabs(ds);
2887 double my_ds_2=0.5*my_ds;
2888 double tx2=tx*tx;
2889 double ty2=ty*ty;
2890 double one_plus_tx2=1.+tx2;
2891 double one_plus_ty2=1.+ty2;
2892 double tsquare=tx2+ty2;
2893 double one_plus_tsquare=1.+tsquare;
2894
2895 Q(state_tx,state_tx)=one_plus_tx2*one_plus_tsquare;
2896 Q(state_ty,state_ty)=one_plus_ty2*one_plus_tsquare;
2897 Q(state_tx,state_ty)=Q(state_ty,state_tx)=tx*ty*one_plus_tsquare;
2898
2899 Q(state_x,state_x)=ONE_THIRD0.33333333333333333*ds*ds;
2900 Q(state_y,state_y)=Q(state_x,state_x);
2901 Q(state_y,state_ty)=Q(state_ty,state_y)
2902 = my_ds_2*sqrt(one_plus_tsquare*one_plus_ty2);
2903 Q(state_x,state_tx)=Q(state_tx,state_x)
2904 = my_ds_2*sqrt(one_plus_tsquare*one_plus_tx2);
2905
2906 double one_over_beta2=1.+one_over_p_sq*mass2;
2907 double chi2c_p_sq=chi2c_factor*my_ds*one_over_beta2;
2908 double chi2a_p_sq=chi2a_factor*(1.+chi2a_corr*one_over_beta2);
2909 // F=MOLIERE_FRACTION =Fraction of Moliere distribution to be taken into account
2910 // nu=0.5*chi2c/(chi2a*(1.-F));
2911 double nu=MOLIERE_RATIO15.0*chi2c_p_sq/chi2a_p_sq;
2912 double one_plus_nu=1.+nu;
2913 double sig2_ms=chi2c_p_sq*one_over_p_sq*MOLIERE_RATIO211.0e-7
2914 *(one_plus_nu/nu*log(one_plus_nu)-1.);
2915
2916
2917 // printf("fac %f %f %f\n",chi2c_factor,chi2a_factor,chi2a_corr);
2918 //printf("omega %f\n",chi2c/chi2a);
2919
2920
2921 Q*=sig2_ms;
2922 }
2923
2924 return NOERROR;
2925}
2926
2927// Calculate the energy loss per unit length given properties of the material
2928// through which a particle of momentum p is passing
2929double DTrackFitterKalmanSIMD::GetdEdx(double q_over_p,double K_rho_Z_over_A,
2930 double rho_Z_over_A,double LnI){
2931 if (rho_Z_over_A<=0.) return 0.;
2932 //return 0.;
2933
2934 double p=fabs(1./q_over_p);
2935 double betagamma=p/MASS;
2936 double betagamma2=betagamma*betagamma;
2937 double gamma2=1.+betagamma2;
2938 double beta2=betagamma2/gamma2;
2939 if (beta2<EPS3.0e-8) beta2=EPS3.0e-8;
2940
2941 double two_Me_betagamma_sq=two_m_e*betagamma2;
2942 double Tmax
2943 =two_Me_betagamma_sq/(1.+2.*sqrt(gamma2)*m_ratio+m_ratio_sq);
2944
2945 // density effect
2946 double delta=CalcDensityEffect(betagamma,rho_Z_over_A,LnI);
2947
2948 return K_rho_Z_over_A/beta2*(-log(two_Me_betagamma_sq*Tmax)
2949 +2.*(LnI + beta2)+delta);
2950}
2951
2952// Calculate the variance in the energy loss in a Gaussian approximation.
2953// The standard deviation of the energy loss distribution is
2954// approximated by sigma=(scale factor) x Xi, where
2955// Xi=0.1535*density*(Z/A)*x/beta^2 [MeV]
2956inline double DTrackFitterKalmanSIMD::GetEnergyVariance(double ds,
2957 double one_over_beta2,
2958 double K_rho_Z_over_A){
2959 if (K_rho_Z_over_A<=0.) return 0.;
2960 //return 0;
2961
2962 double sigma=10.0*K_rho_Z_over_A*one_over_beta2*ds;
2963
2964 return sigma*sigma;
2965}
2966
2967// Interface routine for Kalman filter
2968jerror_t DTrackFitterKalmanSIMD::KalmanLoop(void){
2969 if (z_<Z_MIN-100.) return VALUE_OUT_OF_RANGE;
2970
2971 // Vector to store the list of hits used in the fit for the forward parametrization
2972 vector<const DCDCTrackHit*>forward_cdc_used_in_fit;
2973
2974 // State vector and initial guess for covariance matrix
2975 DMatrix5x1 S0;
2976 DMatrix5x5 C0;
2977
2978 chisq_=MAX_CHI21e16;
2979
2980 // Angle with respect to beam line
2981 double theta_deg=(180/M_PI3.14159265358979323846)*input_params.momentum().Theta();
2982 //double theta_deg_sq=theta_deg*theta_deg;
2983 double tanl0=tanl_=tan(M_PI_21.57079632679489661923-input_params.momentum().Theta());
2984
2985 // Azimuthal angle
2986 double phi0=phi_=input_params.momentum().Phi();
2987
2988 // Guess for momentum error
2989 double dpt_over_pt=0.1;
2990 /*
2991 if (theta_deg<15){
2992 dpt_over_pt=0.107-0.0178*theta_deg+0.000966*theta_deg_sq;
2993 }
2994 else {
2995 dpt_over_pt=0.0288+0.00579*theta_deg-2.77e-5*theta_deg_sq;
2996 }
2997 */
2998 /*
2999 if (theta_deg<28.){
3000 theta_deg=28.;
3001 theta_deg_sq=theta_deg*theta_deg;
3002 }
3003 else if (theta_deg>125.){
3004 theta_deg=125.;
3005 theta_deg_sq=theta_deg*theta_deg;
3006 }
3007 */
3008 double sig_lambda=0.01;
3009 double dp_over_p_sq
3010 =dpt_over_pt*dpt_over_pt+tanl_*tanl_*sig_lambda*sig_lambda;
3011
3012 // Input charge
3013 double q=input_params.charge();
3014
3015 // Input momentum
3016 DVector3 pvec=input_params.momentum();
3017 double p_mag=pvec.Mag();
3018 if (MASS>0.9 && p_mag<MIN_PROTON_P0.3){
3019 pvec.SetMag(MIN_PROTON_P0.3);
3020 p_mag=MIN_PROTON_P0.3;
3021 }
3022 else if (MASS<0.9 && p_mag<MIN_PION_P0.08){
3023 pvec.SetMag(MIN_PION_P0.08);
3024 p_mag=MIN_PION_P0.08;
3025 }
3026 if (p_mag>MAX_P12.0){
3027 pvec.SetMag(MAX_P12.0);
3028 p_mag=MAX_P12.0;
3029 }
3030 double pz=pvec.z();
3031 double q_over_p0=q_over_p_=q/p_mag;
3032 double q_over_pt0=q_over_pt_=q/pvec.Perp();
3033
3034 // Initial position
3035 double x0=x_=input_params.position().x();
3036 double y0=y_=input_params.position().y();
3037 double z0=z_=input_params.position().z();
3038
3039 // Check integrity of input parameters
3040 if (!isfinite(x0) || !isfinite(y0) || !isfinite(q_over_p0)){
3041 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3041<<" "
<< "Invalid input parameters!" <<endl;
3042 return UNRECOVERABLE_ERROR;
3043 }
3044
3045 // Initial direction tangents
3046 double tx0=tx_=pvec.x()/pz;
3047 double ty0=ty_=pvec.y()/pz;
3048 double one_plus_tsquare=1.+tx_*tx_+ty_*ty_;
3049
3050 // deal with hits in FDC
3051 double fdc_prob=0.,fdc_chisq=1e16;
3052 unsigned int fdc_ndf=0;
3053 if (my_fdchits.size()>0
3054 && // Make sure that these parameters are valid for forward-going tracks
3055 (isfinite(tx0) && isfinite(ty0))
3056 ){
3057 if (DEBUG_LEVEL>0){
3058 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3058<<" "
<< "Using forward parameterization." <<endl;
3059 }
3060
3061 // Initial guess for the state vector
3062 S0(state_x)=x_;
3063 S0(state_y)=y_;
3064 S0(state_tx)=tx_;
3065 S0(state_ty)=ty_;
3066 S0(state_q_over_p)=q_over_p_;
3067
3068 // Initial guess for forward representation covariance matrix
3069 C0(state_x,state_x)=2.0;
3070 C0(state_y,state_y)=2.0;
3071 C0(state_tx,state_tx)=0.001;
3072 C0(state_ty,state_ty)=0.001;
3073 if (theta_deg>12.35)
3074 {
3075 double temp=sig_lambda*one_plus_tsquare;
3076 C0(state_tx,state_tx)=C0(state_ty,state_ty)=temp*temp;
3077 }
3078 C0(state_q_over_p,state_q_over_p)=dp_over_p_sq*q_over_p_*q_over_p_;
3079
3080 // The position from the track candidate is reported just outside the
3081 // start counter for tracks containing cdc hits. Propagate to the distance
3082 // of closest approach to the beam line
3083 if (fit_type==kWireBased) ExtrapolateToVertex(S0);
3084
3085 kalman_error_t error=ForwardFit(S0,C0);
3086 if (error!=FIT_FAILED){
3087 if (my_cdchits.size()<6){
3088 if (ndf_==0) return UNRECOVERABLE_ERROR;
3089 return NOERROR;
3090 }
3091 fdc_prob=TMath::Prob(chisq_,ndf_);
3092 if (fdc_prob>0.001 && error==FIT_SUCCEEDED) return NOERROR;
3093 fdc_ndf=ndf_;
3094 fdc_chisq=chisq_;
3095 }
3096 if (my_cdchits.size()<6) return UNRECOVERABLE_ERROR;
3097 }
3098
3099 // Deal with hits in the CDC
3100 if (my_cdchits.size()>5){
3101 kalman_error_t error=FIT_NOT_DONE;
3102 kalman_error_t cdc_error=FIT_NOT_DONE;
3103
3104 // Chi-squared, degrees of freedom, and probability
3105 double forward_prob=0.;
3106 double chisq_forward=MAX_CHI21e16;
3107 unsigned int ndof_forward=0;
3108
3109 // Parameters at "vertex"
3110 double D=D_,phi=phi_,q_over_pt=q_over_pt_,tanl=tanl_,x=x_,y=y_,z=z_;
3111
3112 // Use forward parameters for CDC-only tracks with theta<THETA_CUT degrees
3113 if (theta_deg<THETA_CUT){
3114 if (DEBUG_LEVEL>0){
3115 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3115<<" "
<< "Using forward parameterization." <<endl;
3116 }
3117
3118 // Step size
3119 mStepSizeS=mCentralStepSize;
3120
3121 // Initialize the state vector
3122 S0(state_x)=x_=x0;
3123 S0(state_y)=y_=y0;
3124 S0(state_tx)=tx_=tx0;
3125 S0(state_ty)=ty_=ty0;
3126 S0(state_q_over_p)=q_over_p_=q_over_p0;
3127 z_=z0;
3128
3129 // Initial guess for forward representation covariance matrix
3130 double temp=sig_lambda*one_plus_tsquare;
3131 C0(state_x,state_x)=4.0;
3132 C0(state_y,state_y)=4.0;
3133 C0(state_tx,state_tx)=C0(state_ty,state_ty)=temp*temp;
3134 C0(state_q_over_p,state_q_over_p)=dp_over_p_sq*q_over_p_*q_over_p_;
3135
3136 //C0*=1.+1./tsquare;
3137
3138 // The position from the track candidate is reported just outside the
3139 // start counter for tracks containing cdc hits. Propagate to the
3140 // distance of closest approach to the beam line
3141 if (fit_type==kWireBased) ExtrapolateToVertex(S0);
3142
3143 error=ForwardCDCFit(S0,C0);
3144
3145 if (error!=FIT_FAILED){
3146 // Find the CL of the fit
3147 forward_prob=TMath::Prob(chisq_,ndf_);
3148 if (my_fdchits.size()>0){
3149 if (forward_prob>fdc_prob){
3150 // We did not end up using the fdc hits after all...
3151 fdchits_used_in_fit.clear();
3152 }
3153 else{
3154 chisq_=fdc_chisq;
3155 ndf_=fdc_ndf;
3156 D_=D;
3157 x_=x;
3158 y_=y;
3159 z_=z;
3160 phi_=phi;
3161 tanl_=tanl;
3162 q_over_pt_=q_over_pt;
3163
3164 // _DBG_ << endl;
3165 return NOERROR;
3166 }
3167 }
3168 if (forward_prob>0.001
3169 && error==FIT_SUCCEEDED) return NOERROR;
3170
3171 // Save the best values for the parameters and chi2 for now
3172 chisq_forward=chisq_;
3173 ndof_forward=ndf_;
3174 D=D_;
3175 x=x_;
3176 y=y_;
3177 z=z_;
3178 phi=phi_;
3179 tanl=tanl_;
3180 q_over_pt=q_over_pt_;
3181
3182 // Save the list of hits used in the fit
3183 forward_cdc_used_in_fit.assign(cdchits_used_in_fit.begin(),cdchits_used_in_fit.end());
3184
3185 }
3186 }
3187
3188 // Attempt to fit the track using the central parametrization.
3189 if (DEBUG_LEVEL>0){
3190 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3190<<" "
<< "Using central parameterization." <<endl;
3191 }
3192
3193 // Step size
3194 mStepSizeS=mCentralStepSize;
3195
3196 // Initialize the state vector
3197 S0(state_q_over_pt)=q_over_pt_=q_over_pt0;
3198 S0(state_phi)=phi_=phi0;
3199 S0(state_tanl)=tanl_=tanl0;
3200 S0(state_z)=z_=z0;
3201 S0(state_D)=D_=0.;
3202
3203 // Initialize the covariance matrix
3204 double dz=1.0;
3205 C0(state_z,state_z)=dz*dz;
3206 C0(state_q_over_pt,state_q_over_pt)
3207 =q_over_pt_*q_over_pt_*dpt_over_pt*dpt_over_pt;
3208 double dphi=0.02;
3209 C0(state_phi,state_phi)=dphi*dphi;
3210 C0(state_D,state_D)=1.0;
3211 double tanl2=tanl_*tanl_;
3212 double one_plus_tanl2=1.+tanl2;
3213 C0(state_tanl,state_tanl)=(one_plus_tanl2)*(one_plus_tanl2)
3214 *sig_lambda*sig_lambda;
3215
3216 //if (theta_deg>90.) C0*=1.+5.*tanl2;
3217 //else C0*=1.+5.*tanl2*tanl2;
3218
3219 // The position from the track candidate is reported just outside the
3220 // start counter for tracks containing cdc hits. Propagate to the
3221 // distance of closest approach to the beam line
3222 DVector2 xy(x0,y0);
3223 if (fit_type==kWireBased){
3224 ExtrapolateToVertex(xy,S0);
3225 }
3226
3227 cdc_error=CentralFit(xy,S0,C0);
3228 if (cdc_error==FIT_SUCCEEDED){
3229 // if the result of the fit using the forward parameterization succeeded
3230 // but the chi2 was too high, it still may provide the best estimate for
3231 // the track parameters...
3232 double central_prob=TMath::Prob(chisq_,ndf_);
3233
3234 if (central_prob<forward_prob){
3235 phi_=phi;
3236 q_over_pt_=q_over_pt;
3237 tanl_=tanl;
3238 D_=D;
3239 x_=x;
3240 y_=y;
3241 z_=z;
3242 chisq_=chisq_forward;
3243 ndf_= ndof_forward;
3244
3245 cdchits_used_in_fit.assign(forward_cdc_used_in_fit.begin(),forward_cdc_used_in_fit.end());
3246
3247 // We did not end up using any fdc hits...
3248 fdchits_used_in_fit.clear();
3249
3250 }
3251 return NOERROR;
3252
3253 }
3254 // otherwise if the fit using the forward parametrization worked, return that
3255 else if (error==FIT_SUCCEEDED || error==LOW_CL_FIT){
3256 phi_=phi;
3257 q_over_pt_=q_over_pt;
3258 tanl_=tanl;
3259 D_=D;
3260 x_=x;
3261 y_=y;
3262 z_=z;
3263 chisq_=chisq_forward;
3264 ndf_= ndof_forward;
3265
3266 cdchits_used_in_fit.assign(forward_cdc_used_in_fit.begin(),forward_cdc_used_in_fit.end());
3267
3268 // We did not end up using any fdc hits...
3269 fdchits_used_in_fit.clear();
3270
3271 return NOERROR;
3272 }
3273 else return UNRECOVERABLE_ERROR;
3274 }
3275
3276 if (ndf_==0) return UNRECOVERABLE_ERROR;
3277
3278 return NOERROR;
3279}
3280
3281#define ITMAX20 20
3282#define CGOLD0.3819660 0.3819660
3283#define ZEPS1.0e-10 1.0e-10
3284#define SHFT(a,b,c,d)(a)=(b);(b)=(c);(c)=(d); (a)=(b);(b)=(c);(c)=(d);
3285#define SIGN(a,b)((b)>=0.0?fabs(a):-fabs(a)) ((b)>=0.0?fabs(a):-fabs(a))
3286// Routine for finding the minimum of a function bracketed between two values
3287// (see Numerical Recipes in C, pp. 404-405).
3288jerror_t DTrackFitterKalmanSIMD::BrentsAlgorithm(double ds1,double ds2,
3289 double dedx,DVector2 &pos,
3290 const double z0wire,
3291 const DVector2 &origin,
3292 const DVector2 &dir,
3293 DMatrix5x1 &Sc,
3294 double &ds_out){
3295 double d=0.;
3296 double e=0.0; // will be distance moved on step before last
3297 double ax=0.;
3298 double bx=-ds1;
3299 double cx=-ds1-ds2;
3300
3301 double a=(ax<cx?ax:cx);
3302 double b=(ax>cx?ax:cx);
3303 double x=bx,w=bx,v=bx;
3304
3305 // printf("ds1 %f ds2 %f\n",ds1,ds2);
3306 // Initialize return step size
3307 ds_out=0.;
3308
3309 // Save the starting position
3310 // DVector3 pos0=pos;
3311 // DMatrix S0(Sc);
3312
3313 // Step to intermediate point
3314 Step(pos,x,Sc,dedx);
3315 // Bail if the transverse momentum has dropped below some minimum
3316 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
3317 if (DEBUG_LEVEL>2)
3318 {
3319 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3319<<" "
<< "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3320 << endl;
3321 }
3322 return VALUE_OUT_OF_RANGE;
3323 }
3324
3325 DVector2 wirepos=origin+(Sc(state_z)-z0wire)*dir;
3326 double u_old=x;
3327 double u=0.;
3328
3329 // initialization
3330 double fw=(pos-wirepos).Mod2();
3331 double fv=fw,fx=fw;
3332
3333 // main loop
3334 for (unsigned int iter=1;iter<=ITMAX20;iter++){
3335 double xm=0.5*(a+b);
3336 double tol1=EPS21.e-4*fabs(x)+ZEPS1.0e-10;
3337 double tol2=2.0*tol1;
3338
3339 if (fabs(x-xm)<=(tol2-0.5*(b-a))){
3340 if (Sc(state_z)<=cdc_origin[2]){
3341 unsigned int iter2=0;
3342 double ds_temp=0.;
3343 while (fabs(Sc(state_z)-cdc_origin[2])>EPS21.e-4 && iter2<20){
3344 u=x-(cdc_origin[2]-Sc(state_z))*sin(atan(Sc(state_tanl)));
3345 x=u;
3346 ds_temp+=u_old-u;
3347 // Bail if the transverse momentum has dropped below some minimum
3348 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
3349 if (DEBUG_LEVEL>2)
3350 {
3351 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3351<<" "
<< "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3352 << endl;
3353 }
3354 return VALUE_OUT_OF_RANGE;
3355 }
3356
3357 // Function evaluation
3358 Step(pos,u_old-u,Sc,dedx);
3359 u_old=u;
3360 iter2++;
3361 }
3362 //printf("new z %f ds %f \n",pos.z(),x);
3363 ds_out=ds_temp;
3364 return NOERROR;
3365 }
3366 else if (Sc(state_z)>=endplate_z){
3367 unsigned int iter2=0;
3368 double ds_temp=0.;
3369 while (fabs(Sc(state_z)-endplate_z)>EPS21.e-4 && iter2<20){
3370 u=x-(endplate_z-Sc(state_z))*sin(atan(Sc(state_tanl)));
3371 x=u;
3372 ds_temp+=u_old-u;
3373
3374 // Bail if the transverse momentum has dropped below some minimum
3375 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
3376 if (DEBUG_LEVEL>2)
3377 {
3378 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3378<<" "
<< "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3379 << endl;
3380 }
3381 return VALUE_OUT_OF_RANGE;
3382 }
3383
3384 // Function evaluation
3385 Step(pos,u_old-u,Sc,dedx);
3386 u_old=u;
3387 iter2++;
3388 }
3389 //printf("new z %f ds %f \n",pos.z(),x);
3390 ds_out=ds_temp;
3391 return NOERROR;
3392 }
3393 ds_out=cx-x;
3394 return NOERROR;
3395 }
3396 // trial parabolic fit
3397 if (fabs(e)>tol1){
3398 double x_minus_w=x-w;
3399 double x_minus_v=x-v;
3400 double r=x_minus_w*(fx-fv);
3401 double q=x_minus_v*(fx-fw);
3402 double p=x_minus_v*q-x_minus_w*r;
3403 q=2.0*(q-r);
3404 if (q>0.0) p=-p;
3405 q=fabs(q);
3406 double etemp=e;
3407 e=d;
3408 if (fabs(p)>=fabs(0.5*q*etemp) || p<=q*(a-x) || p>=q*(b-x))
3409 // fall back on the Golden Section technique
3410 d=CGOLD0.3819660*(e=(x>=xm?a-x:b-x));
3411 else{
3412 // parabolic step
3413 d=p/q;
3414 u=x+d;
3415 if (u-a<tol2 || b-u <tol2)
3416 d=SIGN(tol1,xm-x)((xm-x)>=0.0?fabs(tol1):-fabs(tol1));
3417 }
3418 } else{
3419 d=CGOLD0.3819660*(e=(x>=xm?a-x:b-x));
3420 }
3421 u=(fabs(d)>=tol1 ? x+d: x+SIGN(tol1,d)((d)>=0.0?fabs(tol1):-fabs(tol1)));
3422
3423 // Bail if the transverse momentum has dropped below some minimum
3424 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
3425 if (DEBUG_LEVEL>2)
3426 {
3427 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3427<<" "
<< "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3428 << endl;
3429 }
3430 return VALUE_OUT_OF_RANGE;
3431 }
3432
3433 // Function evaluation
3434 Step(pos,u_old-u,Sc,dedx);
3435 u_old=u;
3436
3437 wirepos=origin;
3438 wirepos+=(Sc(state_z)-z0wire)*dir;
3439 double fu=(pos-wirepos).Mod2();
3440
3441 //cout << "Brent: z="<<Sc(state_z) << " d="<<sqrt(fu) << endl;
3442
3443 if (fu<=fx){
3444 if (u>=x) a=x; else b=x;
3445 SHFT(v,w,x,u)(v)=(w);(w)=(x);(x)=(u);;
3446 SHFT(fv,fw,fx,fu)(fv)=(fw);(fw)=(fx);(fx)=(fu);;
3447 }
3448 else {
3449 if (u<x) a=u; else b=u;
3450 if (fu<=fw || w==x){
3451 v=w;
3452 w=u;
3453 fv=fw;
3454 fw=fu;
3455 }
3456 else if (fu<=fv || v==x || v==w){
3457 v=u;
3458 fv=fu;
3459 }
3460 }
3461 }
3462 ds_out=cx-x;
3463
3464 return NOERROR;
3465}
3466
3467// Routine for finding the minimum of a function bracketed between two values
3468// (see Numerical Recipes in C, pp. 404-405).
3469jerror_t DTrackFitterKalmanSIMD::BrentsAlgorithm(double z,double dz,
3470 double dedx,
3471 const double z0wire,
3472 const DVector2 &origin,
3473 const DVector2 &dir,
3474 DMatrix5x1 &S,
3475 double &dz_out){
3476 double d=0.,u=0.;
3477 double e=0.0; // will be distance moved on step before last
3478 double ax=0.;
3479 double bx=-dz;
3480 double cx=-2.*dz;
3481
3482 double a=(ax<cx?ax:cx);
3483 double b=(ax>cx?ax:cx);
3484 double x=bx,w=bx,v=bx;
3485
3486 // Initialize dz_out
3487 dz_out=0.;
3488
3489 // Step to intermediate point
3490 double z_new=z+x;
3491 Step(z,z_new,dedx,S);
3492 // Bail if the momentum has dropped below some minimum
3493 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX100.){
3494 if (DEBUG_LEVEL>2)
3495 {
3496 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3496<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p))
3497 << endl;
3498 }
3499 return VALUE_OUT_OF_RANGE;
3500 }
3501
3502 double dz0wire=z-z0wire;
3503 DVector2 wirepos=origin+(dz0wire+x)*dir;
3504 DVector2 pos(S(state_x),S(state_y));
3505 double z_old=z_new;
3506
3507 // initialization
3508 double fw=(pos-wirepos).Mod2();
3509 double fv=fw;
3510 double fx=fw;
3511
3512 // main loop
3513 for (unsigned int iter=1;iter<=ITMAX20;iter++){
3514 double xm=0.5*(a+b);
3515 double tol1=EPS21.e-4*fabs(x)+ZEPS1.0e-10;
3516 double tol2=2.0*tol1;
3517 if (fabs(x-xm)<=(tol2-0.5*(b-a))){
3518 if (z_new>=endplate_z){
3519 x=endplate_z-z_new;
3520
3521 // Bail if the momentum has dropped below some minimum
3522 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX100.){
3523 if (DEBUG_LEVEL>2)
3524 {
3525 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3525<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p))
3526 << endl;
3527 }
3528 return VALUE_OUT_OF_RANGE;
3529 }
3530 if (!isfinite(S(state_x)) || !isfinite(S(state_y))){
3531 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3531<<" "
<<endl;
3532 return VALUE_OUT_OF_RANGE;
3533 }
3534 Step(z_new,endplate_z,dedx,S);
3535 }
3536 dz_out=x;
3537 return NOERROR;
3538 }
3539 // trial parabolic fit
3540 if (fabs(e)>tol1){
3541 double x_minus_w=x-w;
3542 double x_minus_v=x-v;
3543 double r=x_minus_w*(fx-fv);
3544 double q=x_minus_v*(fx-fw);
3545 double p=x_minus_v*q-x_minus_w*r;
3546 q=2.0*(q-r);
3547 if (q>0.0) p=-p;
3548 q=fabs(q);
3549 double etemp=e;
3550 e=d;
3551 if (fabs(p)>=fabs(0.5*q*etemp) || p<=q*(a-x) || p>=q*(b-x))
3552 // fall back on the Golden Section technique
3553 d=CGOLD0.3819660*(e=(x>=xm?a-x:b-x));
3554 else{
3555 // parabolic step
3556 d=p/q;
3557 u=x+d;
3558 if (u-a<tol2 || b-u <tol2)
3559 d=SIGN(tol1,xm-x)((xm-x)>=0.0?fabs(tol1):-fabs(tol1));
3560 }
3561 } else{
3562 d=CGOLD0.3819660*(e=(x>=xm?a-x:b-x));
3563 }
3564 u=(fabs(d)>=tol1 ? x+d: x+SIGN(tol1,d)((d)>=0.0?fabs(tol1):-fabs(tol1)));
3565
3566 // Function evaluation
3567 //S=S0;
3568 z_new=z+u;
3569 // Bail if the momentum has dropped below some minimum
3570 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX100.){
3571 if (DEBUG_LEVEL>2)
3572 {
3573 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3573<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p))
3574 << endl;
3575 }
3576 return VALUE_OUT_OF_RANGE;
3577 }
3578
3579 Step(z_old,z_new,dedx,S);
3580 z_old=z_new;
3581
3582 wirepos=origin;
3583 wirepos+=(dz0wire+u)*dir;
3584 pos.Set(S(state_x),S(state_y));
3585 double fu=(pos-wirepos).Mod2();
3586
3587 // _DBG_ << "Brent: z="<< z+u << " d^2="<<fu << endl;
3588
3589 if (fu<=fx){
3590 if (u>=x) a=x; else b=x;
3591 SHFT(v,w,x,u)(v)=(w);(w)=(x);(x)=(u);;
3592 SHFT(fv,fw,fx,fu)(fv)=(fw);(fw)=(fx);(fx)=(fu);;
3593 }
3594 else {
3595 if (u<x) a=u; else b=u;
3596 if (fu<=fw || w==x){
3597 v=w;
3598 w=u;
3599 fv=fw;
3600 fw=fu;
3601 }
3602 else if (fu<=fv || v==x || v==w){
3603 v=u;
3604 fv=fu;
3605 }
3606 }
3607 }
3608 dz_out=x;
3609 return NOERROR;
3610}
3611
3612// Kalman engine for Central tracks; updates the position on the trajectory
3613// after the last hit (closest to the target) is added
3614kalman_error_t DTrackFitterKalmanSIMD::KalmanCentral(double anneal_factor,
3615 DMatrix5x1 &Sc,DMatrix5x5 &Cc,
3616 DVector2 &xy,double &chisq,
3617 unsigned int &my_ndf){
3618 DMatrix1x5 H; // Track projection matrix
3619 DMatrix5x1 H_T; // Transpose of track projection matrix
3620 DMatrix5x5 J; // State vector Jacobian matrix
3621 //DMatrix5x5 JT; // transpose of this matrix
3622 DMatrix5x5 Q; // Process noise covariance matrix
3623 DMatrix5x1 K; // KalmanSIMD gain matrix
3624 DMatrix5x5 Ctest; // covariance matrix
3625 //double V=0.2028; //1.56*1.56/12.; // Measurement variance
3626 double V=0.0507*1.15;
3627 double InvV; // inverse of variance
3628 //DMatrix5x1 dS; // perturbation in state vector
3629 DMatrix5x1 S0,S0_; // state vector
3630
3631 // set the used_in_fit flags to false for cdc hits
3632 unsigned int num_cdc=cdc_updates.size();
3633 for (unsigned int i=0;i<num_cdc;i++) cdc_updates[i].used_in_fit=false;
3634 for (unsigned int i=0;i<central_traj.size();i++){
3635 central_traj[i].h_id=0;
3636 }
3637
3638 // Initialize the chi2 for this part of the track
3639 chisq=0.;
3640 my_ndf=0;
3641 double var_cut=NUM_CDC_SIGMA_CUT*NUM_CDC_SIGMA_CUT;
3642 double my_anneal=anneal_factor*anneal_factor;
3643 double chi2cut=my_anneal*var_cut;
3644
3645 // path length increment
3646 double ds2=0.;
3647
3648 //printf(">>>>>>>>>>>>>>>>\n");
3649
3650 // beginning position
3651 double phi=Sc(state_phi);
3652 xy.Set(central_traj[break_point_step_index].xy.X()-Sc(state_D)*sin(phi),
3653 central_traj[break_point_step_index].xy.Y()+Sc(state_D)*cos(phi));
3654
3655 // Wire origin and direction
3656 // unsigned int cdc_index=my_cdchits.size()-1;
3657 unsigned int cdc_index=break_point_cdc_index;
3658
3659 if (cdc_index<MIN_HITS_FOR_REFIT) chi2cut=1000.0;
3660
3661 // Wire origin and direction
3662 DVector2 origin=my_cdchits[cdc_index]->origin;
3663 double z0w=my_cdchits[cdc_index]->z0wire;
3664 DVector2 dir=my_cdchits[cdc_index]->dir;
3665 DVector2 wirexy=origin+(Sc(state_z)-z0w)*dir;
3666
3667 // Save the starting values for C and S in the deque
3668 central_traj[break_point_step_index].Skk=Sc;
3669 central_traj[break_point_step_index].Ckk=Cc;
3670
3671 // doca variables
3672 double doca2,old_doca2=(xy-wirexy).Mod2();
3673
3674 // energy loss
3675 double dedx=0.;
3676
3677 // Boolean for flagging when we are done with measurements
3678 bool more_measurements=true;
3679
3680 // Initialize S0_ and perform the loop over the trajectory
3681 S0_=central_traj[break_point_step_index].S;
3682
3683 for (unsigned int k=break_point_step_index+1;k<central_traj.size();k++){
3684 unsigned int k_minus_1=k-1;
3685
3686 // Check that C matrix is positive definite
3687 if (Cc(0,0)<0.0 || Cc(1,1)<0.0 || Cc(2,2)<0.0 || Cc(3,3)<0.0 || Cc(4,4)<0.0){
3688 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3688<<" "
<< "Broken covariance matrix!" <<endl;
3689 return BROKEN_COVARIANCE_MATRIX;
3690 }
3691
3692 // Get the state vector, jacobian matrix, and multiple scattering matrix
3693 // from reference trajectory
3694 S0=central_traj[k].S;
3695 J=central_traj[k].J;
3696 // JT=central_traj[k].JT;
3697 Q=central_traj[k].Q;
3698
3699 //Q.Print();
3700 //J.Print();
3701
3702 // State S is perturbation about a seed S0
3703 //dS=Sc-S0_;
3704 //dS.Zero();
3705
3706 // Update the actual state vector and covariance matrix
3707 Sc=S0+J*(Sc-S0_);
3708 // Cc=J*(Cc*JT)+Q;
3709 //Cc=Q.AddSym(J*Cc*JT);
3710 Cc=Q.AddSym(Cc.SandwichMultiply(J));
3711
3712 //Sc=central_traj[k].S+central_traj[k].J*(Sc-S0_);
3713 //Cc=central_traj[k].Q.AddSym(central_traj[k].J*Cc*central_traj[k].JT);
3714
3715 // update position based on new doca to reference trajectory
3716 xy.Set(central_traj[k].xy.X()-Sc(state_D)*sin(Sc(state_phi)),
3717 central_traj[k].xy.Y()+Sc(state_D)*cos(Sc(state_phi)));
3718
3719 // Bail if the position is grossly outside of the tracking volume
3720 if (xy.Mod2()>R2_MAX4225.0 || Sc(state_z)<Z_MIN-100. || Sc(state_z)>Z_MAX370.0){
3721 if (DEBUG_LEVEL>2)
3722 {
3723 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3723<<" "
<< "Went outside of tracking volume at z="<<Sc(state_z)
3724 << " r="<<xy.Mod()<<endl;
3725 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3725<<" "
<< " Break indexes: " << break_point_cdc_index <<","
3726 << break_point_step_index << endl;
3727 }
3728 return POSITION_OUT_OF_RANGE;
3729 }
3730 // Bail if the transverse momentum has dropped below some minimum
3731 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
3732 if (DEBUG_LEVEL>2)
3733 {
3734 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3734<<" "
<< "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3735 << " at step " << k
3736 << endl;
3737 }
3738 return MOMENTUM_OUT_OF_RANGE;
3739 }
3740
3741
3742 // Save the current state of the reference trajectory
3743 S0_=S0;
3744
3745 // Save the current state and covariance matrix in the deque
3746 central_traj[k].Skk=Sc;
3747 central_traj[k].Ckk=Cc;
3748
3749 // new wire position
3750 wirexy=origin;
3751 wirexy+=(Sc(state_z)-z0w)*dir;
3752
3753 // new doca
3754 doca2=(xy-wirexy).Mod2();
3755
3756 // Check if the doca is no longer decreasing
3757 if (more_measurements && (doca2>old_doca2 && Sc(state_z)>cdc_origin[2])){
3758 if (my_cdchits[cdc_index]->status==good_hit){
3759 // Save values at end of current step
3760 DVector2 xy0=central_traj[k].xy;
3761
3762 // dEdx for current position along trajectory
3763 double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl)));
3764 if (CORRECT_FOR_ELOSS){
3765 dedx=GetdEdx(q_over_p, central_traj[k].K_rho_Z_over_A,
3766 central_traj[k].rho_Z_over_A,central_traj[k].LnI);
3767 }
3768 // Variables for the computation of D at the doca to the wire
3769 double D=Sc(state_D);
3770 double q=(Sc(state_q_over_pt)>0.0)?1.:-1.;
3771
3772 q*=FactorForSenseOfRotation;
3773
3774 double qpt=1./Sc(state_q_over_pt) * FactorForSenseOfRotation;
3775 double sinphi=sin(Sc(state_phi));
3776 double cosphi=cos(Sc(state_phi));
3777 //double qrc_old=qpt/fabs(qBr2p*bfield->GetBz(pos.x(),pos.y(),pos.z()));
3778 double qrc_old=qpt/fabs(qBr2p0.003*central_traj[k].B);
3779 double qrc_plus_D=D+qrc_old;
3780 double lambda=atan(Sc(state_tanl));
3781 double cosl=cos(lambda);
3782 double sinl=sin(lambda);
3783
3784 // wire direction variables
3785 double ux=dir.X();
3786 double uy=dir.Y();
3787 // Variables relating wire direction and track direction
3788 double my_ux=ux*sinl-cosl*cosphi;
3789 double my_uy=uy*sinl-cosl*sinphi;
3790 double denom=my_ux*my_ux+my_uy*my_uy;
3791
3792 // if the step size is small relative to the radius of curvature,
3793 // use a linear approximation to find ds2
3794 bool do_brent=false;
3795 double step1=mStepSizeS;
3796 double step2=mStepSizeS;
3797 if (k>=2){
3798 step1=-central_traj[k].s+central_traj[k_minus_1].s;
3799 step2=-central_traj[k_minus_1].s+central_traj[k-2].s;
3800 }
3801 //printf("step1 %f step 2 %f \n",step1,step2);
3802 double two_step=step1+step2;
3803 if (two_step*cosl/fabs(qrc_old)<0.01 && denom>EPS3.0e-8){
3804 double z=Sc(state_z);
3805 double dzw=z-z0w;
3806 ds2=((xy.X()-origin.X()-ux*dzw)*my_ux
3807 +(xy.Y()-origin.Y()-uy*dzw)*my_uy)/denom;
3808
3809 if (ds2<0.0){
3810 do_brent=true;
3811 }
3812 else{
3813 if (fabs(ds2)<two_step){
3814 double my_z=Sc(state_z)+ds2*sinl;
3815 if(my_z<cdc_origin[2]){
3816 ds2=(cdc_origin[2]-z)/sinl;
3817 }
3818 else if (my_z>endplate_z){
3819 ds2=(endplate_z-z)/sinl;
3820 }
3821 // Bail if the transverse momentum has dropped below some minimum
3822 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
3823 if (DEBUG_LEVEL>2)
3824 {
3825 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3825<<" "
<< "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3826 << " at step " << k
3827 << endl;
3828 }
3829 return MOMENTUM_OUT_OF_RANGE;
3830 }
3831 Step(xy,ds2,Sc,dedx);
3832 }
3833 else{
3834 do_brent=true;
3835 }
3836 }
3837 }
3838 else do_brent=true;
3839 if (do_brent){
3840 // ... otherwise, use Brent's algorithm.
3841 // See Numerical Recipes in C, pp 404-405
3842 if (BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dedx,xy,z0w,
3843 origin,dir,Sc,ds2)!=NOERROR){
3844 return MOMENTUM_OUT_OF_RANGE;
3845 }
3846 if (fabs(ds2)<EPS31.e-2){
3847 // whoops, looks like we didn't actually bracket the minimum
3848 // after all. Swim to make sure we pass the minimum doca.
3849 double my_ds=ds2;
3850
3851 // doca
3852 old_doca2=doca2;
3853
3854 // Bail if the transverse momentum has dropped below some minimum
3855 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
3856 if (DEBUG_LEVEL>2)
3857 {
3858 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3858<<" "
<< "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3859 << " at step " << k
3860 << endl;
3861 }
3862 return MOMENTUM_OUT_OF_RANGE;
3863 }
3864
3865 // Step through the field
3866 Step(xy,mStepSizeS,Sc,dedx);
3867
3868 wirexy=origin;
3869 wirexy+=(Sc(state_z)-z0w)*dir;
3870 doca2=(xy-wirexy).Mod2();
3871
3872 ds2=my_ds+mStepSizeS;
3873 if (doca2>old_doca2){
3874 // Swim to the "true" doca
3875 double ds3=0.;
3876 if (BrentsAlgorithm(mStepSizeS,mStepSizeS,dedx,xy,z0w,
3877 origin,dir,Sc,ds3)!=NOERROR){
3878 return MOMENTUM_OUT_OF_RANGE;
3879 }
3880 ds2+=ds3;
3881 }
3882
3883 }
3884 else if (fabs(ds2)>2.*mStepSizeS-EPS31.e-2){
3885 // whoops, looks like we didn't actually bracket the minimum
3886 // after all. Swim to make sure we pass the minimum doca.
3887 double my_ds=ds2;
3888
3889 // new wire position
3890 wirexy=origin;
3891 wirexy+=(Sc(state_z)-z0w)*dir;
3892
3893 // doca
3894 old_doca2=doca2;
3895 doca2=(xy-wirexy).Mod2();
3896
3897 while(doca2<old_doca2){
3898 old_doca2=doca2;
3899
3900 // Bail if the transverse momentum has dropped below some minimum
3901 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
3902 if (DEBUG_LEVEL>2)
3903 {
3904 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3904<<" "
<< "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3905 << " at step " << k
3906 << endl;
3907 }
3908 return MOMENTUM_OUT_OF_RANGE;
3909 }
3910
3911 // Step through the field
3912 Step(xy,mStepSizeS,Sc,dedx);
3913
3914 // Find the new distance to the wire
3915 wirexy=origin;
3916 wirexy+=(Sc(state_z)-z0w)*dir;
3917 doca2=(xy-wirexy).Mod2();
3918
3919 my_ds+=mStepSizeS;
3920 }
3921 // Swim to the "true" doca
3922 double ds3=0.;
3923 if (BrentsAlgorithm(mStepSizeS,mStepSizeS,dedx,xy,z0w,
3924 origin,dir,Sc,ds3)!=NOERROR){
3925 return MOMENTUM_OUT_OF_RANGE;
3926 }
3927 ds2=my_ds+ds3;
3928 }
3929 }
3930
3931 //Step along the reference trajectory and compute the new covariance matrix
3932 StepStateAndCovariance(xy0,ds2,dedx,S0,J,Cc);
3933
3934 // Compute the value of D (signed distance to the reference trajectory)
3935 // at the doca to the wire
3936 DVector2 dxy1=xy0-central_traj[k].xy;
3937 double rc=sqrt(dxy1.Mod2()
3938 +2.*qrc_plus_D*(dxy1.X()*sinphi-dxy1.Y()*cosphi)
3939 +qrc_plus_D*qrc_plus_D);
3940 Sc(state_D)=q*rc-qrc_old;
3941
3942 // wire position
3943 wirexy=origin;
3944 wirexy+=(Sc(state_z)-z0w)*dir;
3945
3946 // prediction for measurement
3947 DVector2 diff=xy-wirexy;
3948 double doca=diff.Mod()+EPS3.0e-8;
3949 double cosstereo=my_cdchits[cdc_index]->cosstereo;
3950 double prediction=doca*cosstereo;
3951
3952 // Measurement
3953 double measurement=0.39,tdrift=0.,tcorr=0.;
3954 if (fit_type==kTimeBased || USE_PASS1_TIME_MODE){
3955 // Find offset of wire with respect to the center of the
3956 // straw at this z position
3957 const DCDCWire *mywire=my_cdchits[cdc_index]->hit->wire;
3958 int ring_index=mywire->ring-1;
3959 int straw_index=mywire->straw-1;
3960 double dz=Sc(state_z)-z0w;
3961 double phi_d=diff.Phi();
3962 double delta
3963 =max_sag[ring_index][straw_index]*(1.-dz*dz/5625.)
3964 *cos(phi_d + sag_phi_offset[ring_index][straw_index]);
3965 double dphi=phi_d-mywire->origin.Phi();
3966 while (dphi>M_PI3.14159265358979323846) dphi-=2*M_PI3.14159265358979323846;
3967 while (dphi<-M_PI3.14159265358979323846) dphi+=2*M_PI3.14159265358979323846;
3968 if (mywire->origin.Y()<0) dphi*=-1.;
3969
3970 tdrift=my_cdchits[cdc_index]->tdrift-mT0
3971 -central_traj[k_minus_1].t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
3972 double B=central_traj[k_minus_1].B;
3973 ComputeCDCDrift(dphi,delta,tdrift,B,measurement,V,tcorr);
3974
3975 //_DBG_ << tcorr << " " << dphi << " " << dm << endl;
3976
3977 }
3978
3979 // Projection matrix
3980 sinphi=sin(Sc(state_phi));
3981 cosphi=cos(Sc(state_phi));
3982 double dx=diff.X();
3983 double dy=diff.Y();
3984 double cosstereo_over_doca=cosstereo/doca;
3985 H(state_D)=H_T(state_D)=(dy*cosphi-dx*sinphi)*cosstereo_over_doca;
3986 H(state_phi)=H_T(state_phi)
3987 =-Sc(state_D)*cosstereo_over_doca*(dx*cosphi+dy*sinphi);
3988 H(state_z)=H_T(state_z)=-cosstereo_over_doca*(dx*ux+dy*uy);
3989
3990 // Difference and inverse of variance
3991 //InvV=1./(V+H*(Cc*H_T));
3992 double Vproj=Cc.SandwichMultiply(H_T);
3993 InvV=1./(V+Vproj);
3994 double dm=measurement-prediction;
3995
3996 if (InvV<0.){
3997 if (DEBUG_LEVEL>1)
3998 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3998<<" "
<< k <<" "<< central_traj.size()-1<<" Negative variance??? " << V << " " << H*(Cc*H_T) <<endl;
3999
4000 break_point_cdc_index=(3*num_cdc)/4;
4001 return NEGATIVE_VARIANCE;
4002 }
4003 /*
4004 if (fabs(cosstereo)<1.){
4005 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);
4006 }
4007 */
4008
4009 // Check how far this hit is from the expected position
4010 double chi2check=dm*dm*InvV;
4011 if (chi2check<chi2cut)
4012 {
4013 /*
4014 if (chi2check>var_cut){
4015 // Give hits that satisfy the wide cut but are still pretty far
4016 // from the projected position less weight
4017
4018 // ad hoc correction
4019 double diff = chi2check-var_cut;
4020 V*=1.+my_anneal*diff;
4021 InvV=1./(V+Vproj);
4022 }
4023 */
4024 // Compute Kalman gain matrix
4025 K=InvV*(Cc*H_T);
4026
4027 // Update state vector covariance matrix
4028 //Cc=Cc-(K*(H*Cc));
4029 Ctest=Cc.SubSym(K*(H*Cc));
4030 // Joseph form
4031 // C = (I-KH)C(I-KH)^T + KVK^T
4032 //Ctest=Cc.SandwichMultiply(I5x5-K*H)+V*MultiplyTranspose(K);
4033 // Check that Ctest is positive definite
4034 if (Ctest(0,0)>0.0 && Ctest(1,1)>0.0 && Ctest(2,2)>0.0 && Ctest(3,3)>0.0
4035 && Ctest(4,4)>0.0){
4036 bool skip_ring
4037 =(my_cdchits[cdc_index]->hit->wire->ring==RING_TO_SKIP);
4038 //Update covariance matrix and state vector
4039 if (skip_ring==false){
4040 Cc=Ctest;
4041 Sc+=dm*K;
4042 }
4043
4044 // Mark point on ref trajectory with a hit id for the straw
4045 central_traj[k].h_id=cdc_index+1;
4046
4047 // Save some updated information for this hit
4048 double scale=(skip_ring)?1.:(1.-H*K);
4049 cdc_updates[cdc_index].tcorr=tcorr;
4050 cdc_updates[cdc_index].tdrift=tdrift;
4051 cdc_updates[cdc_index].doca=measurement;
4052 cdc_updates[cdc_index].residual=dm*scale;
4053 cdc_updates[cdc_index].variance=V;
4054 cdc_updates[cdc_index].used_in_fit=true;
4055
4056 // Update chi2 for this hit
4057 if (skip_ring==false){
4058 chisq+=scale*dm*dm/V;
4059 my_ndf++;
4060 }
4061 if (DEBUG_LEVEL>10)
4062 cout
4063 << "ring " << my_cdchits[cdc_index]->hit->wire->ring
4064 << " t " << my_cdchits[cdc_index]->hit->tdrift
4065 << " Dm-Dpred " << dm
4066 << " chi2 " << (1.-H*K)*dm*dm/V
4067 << endl;
4068
4069 break_point_cdc_index=cdc_index;
4070 break_point_step_index=k_minus_1;
4071 }
4072 //else printf("Negative variance!!!\n");
4073
4074
4075 }
4076
4077 // Get the field and gradient at the point (x0,y0,z0) on the reference
4078 // trajectory
4079 bfield->GetFieldAndGradient(xy0.X(),xy0.Y(),S0(state_z),Bx,By,Bz,
4080 dBxdx,dBxdy,dBxdz,dBydx,
4081 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
4082 // Compute the Jacobian matrix
4083 StepJacobian(xy0,(-1.)*dxy1,-ds2,S0,dedx,J);
4084
4085 // Update covariance matrix
4086 //Cc=J*Cc*J.Transpose();
4087 Cc=Cc.SandwichMultiply(J);
4088
4089 // Step to the next point on the trajectory
4090 Sc=S0_+J*(Sc-S0);
4091 // Save state and covariance matrix to update vector
4092 cdc_updates[cdc_index].S=Sc;
4093 cdc_updates[cdc_index].C=Cc;
4094
4095 // update position on current trajectory based on corrected doca to
4096 // reference trajectory
4097 xy.Set(central_traj[k].xy.X()-Sc(state_D)*sin(Sc(state_phi)),
4098 central_traj[k].xy.Y()+Sc(state_D)*cos(Sc(state_phi)));
4099
4100 }
4101
4102 // new wire origin and direction
4103 if (cdc_index>0){
4104 cdc_index--;
4105 origin=my_cdchits[cdc_index]->origin;
4106 z0w=my_cdchits[cdc_index]->z0wire;
4107 dir=my_cdchits[cdc_index]->dir;
4108 }
4109 else{
4110 more_measurements=false;
4111 }
4112
4113 // Update the wire position
4114 wirexy=origin+(Sc(state_z)-z0w)*dir;
4115
4116 //s+=ds2;
4117 // new doca
4118 doca2=(xy-wirexy).Mod2();
4119 }
4120
4121 old_doca2=doca2;
4122 }
4123
4124 // If there are not enough degrees of freedom, something went wrong...
4125 if (my_ndf<6){
4126 chisq=MAX_CHI21e16;
4127 my_ndf=0;
4128
4129 return INVALID_FIT;
4130 }
4131 else my_ndf-=5;
4132
4133 // Check if the momentum is unphysically large
4134 double p=cos(atan(Sc(state_tanl)))/fabs(Sc(state_q_over_pt));
4135 if (p>12.0){
4136 if (DEBUG_LEVEL>2)
4137 {
4138 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4138<<" "
<< "Unphysical momentum: P = " << p <<endl;
4139 }
4140 return MOMENTUM_OUT_OF_RANGE;
4141 }
4142
4143 // Check if we have a kink in the track or threw away too many cdc hits
4144 if (num_cdc>=MIN_HITS_FOR_REFIT){
4145 if (break_point_cdc_index>1){
4146 if (break_point_cdc_index<num_cdc/2){
4147 break_point_cdc_index=(3*num_cdc)/4;
4148 }
4149 return BREAK_POINT_FOUND;
4150 }
4151
4152 unsigned int num_good=0;
4153 for (unsigned int j=0;j<num_cdc;j++){
4154 if (cdc_updates[j].used_in_fit) num_good++;
4155 }
4156 if (double(num_good)/double(num_cdc)<MINIMUM_HIT_FRACTION0.5){
4157 return PRUNED_TOO_MANY_HITS;
4158 }
4159 }
4160
4161 return FIT_SUCCEEDED;
4162}
4163
4164// Kalman engine for forward tracks
4165kalman_error_t DTrackFitterKalmanSIMD::KalmanForward(double anneal_factor,
4166 double cdc_anneal,
4167 DMatrix5x1 &S,
4168 DMatrix5x5 &C,
4169 double &chisq,
4170 unsigned int &numdof){
4171 DMatrix2x1 Mdiff; // difference between measurement and prediction
4172 DMatrix2x5 H; // Track projection matrix
4173 DMatrix5x2 H_T; // Transpose of track projection matrix
4174 DMatrix1x5 Hc; // Track projection matrix for cdc hits
4175 DMatrix5x1 Hc_T; // Transpose of track projection matrix for cdc hits
4176 DMatrix5x5 J; // State vector Jacobian matrix
4177 //DMatrix5x5 J_T; // transpose of this matrix
4178 DMatrix5x5 Q; // Process noise covariance matrix
4179 DMatrix5x2 K; // Kalman gain matrix
4180 DMatrix5x1 Kc; // Kalman gain matrix for cdc hits
4181 DMatrix2x2 V(0.0833,0.,0.,FDC_CATHODE_VARIANCE0.000225); // Measurement covariance matrix
4182 DMatrix2x1 R; // Filtered residual
4183 DMatrix2x2 RC; // Covariance of filtered residual
4184 DMatrix5x1 S0,S0_; //State vector
4185 //DMatrix5x1 dS; // perturbation in state vector
4186 DMatrix2x2 InvV; // Inverse of error matrix
4187
4188 // Save the starting values for C and S in the deque
4189 forward_traj[0].Skk=S;
4190 forward_traj[0].Ckk=C;
4191
4192 // Initialize chi squared
4193 chisq=0;
4194
4195 // Initialize number of degrees of freedom
4196 numdof=0;
4197 // Variables for estimating t0 from tracking
4198 //mInvVarT0=mT0MinimumDriftTime=0.;
4199
4200 unsigned int num_fdc_hits=my_fdchits.size();
4201 unsigned int num_cdc_hits=my_cdchits.size();
4202 unsigned int cdc_index=0;
4203 if (num_cdc_hits>0) cdc_index=num_cdc_hits-1;
4204 double old_doca2=1e6;
4205
4206 S0_=(forward_traj[0].S);
4207 for (unsigned int k=1;k<forward_traj.size();k++){
4208 unsigned int k_minus_1=k-1;
4209
4210 // Check that C matrix is positive definite
4211 if (C(0,0)<0.0 || C(1,1)<0.0 || C(2,2)<0.0 || C(3,3)<0.0 || C(4,4)<0.0){
4212 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4212<<" "
<< "Broken covariance matrix!" <<endl;
4213 return BROKEN_COVARIANCE_MATRIX;
4214 }
4215
4216 // Get the state vector, jacobian matrix, and multiple scattering matrix
4217 // from reference trajectory
4218 S0=(forward_traj[k].S);
4219 J=(forward_traj[k].J);
4220 //J_T=(forward_traj[k].JT);
4221 Q=(forward_traj[k].Q);
4222
4223 // State S is perturbation about a seed S0
4224 //dS=S-S0_;
4225
4226 // Update the actual state vector and covariance matrix
4227 S=S0+J*(S-S0_);
4228
4229 // Bail if the position is grossly outside of the tracking volume
4230 /*
4231 if (sqrt(S(state_x)*S(state_x)+S(state_y)*S(state_y))>R_MAX_FORWARD){
4232 if (DEBUG_LEVEL>2)
4233 {
4234 _DBG_<< "Went outside of tracking volume at z="<<forward_traj[k].pos.z()<<endl;
4235 }
4236 return POSITION_OUT_OF_RANGE;
4237 }
4238 */
4239 // Bail if the momentum has dropped below some minimum
4240 if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX100.){
4241 if (DEBUG_LEVEL>2)
4242 {
4243 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4243<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p)) << endl;
4244 }
4245 return MOMENTUM_OUT_OF_RANGE;
4246 }
4247
4248
4249
4250 //C=J*(C*J_T)+Q;
4251 //C=Q.AddSym(J*C*J_T);
4252 C=Q.AddSym(C.SandwichMultiply(J));
4253
4254 // Save the current state and covariance matrix in the deque
4255 forward_traj[k].Skk=S;
4256 forward_traj[k].Ckk=C;
4257
4258 // Save the current state of the reference trajectory
4259 S0_=S0;
4260
4261 // Add the hit
4262 if (num_fdc_hits>0){
4263 if (forward_traj[k].h_id>0 && forward_traj[k].h_id<1000){
4264 unsigned int id=forward_traj[k].h_id-1;
4265
4266 double cosa=my_fdchits[id]->cosa;
4267 double sina=my_fdchits[id]->sina;
4268 double u=my_fdchits[id]->uwire;
4269 double v=my_fdchits[id]->vstrip;
4270 double x=S(state_x);
4271 double y=S(state_y);
4272 double tx=S(state_tx);
4273 double ty=S(state_ty);
4274 double du=x*cosa-y*sina-u;
4275 double tu=tx*cosa-ty*sina;
4276 double one_plus_tu2=1.+tu*tu;
4277 double alpha=atan(tu);
4278 double cosalpha=cos(alpha);
4279 double sinalpha=sin(alpha);
4280 // (signed) distance of closest approach to wire
4281 double doca=du*cosalpha;
4282 // Correction for lorentz effect
4283 double nz=my_fdchits[id]->nz;
4284 double nr=my_fdchits[id]->nr;
4285 double nz_sinalpha_plus_nr_cosalpha=nz*sinalpha+nr*cosalpha;
4286
4287 // Variance in coordinate along wire
4288 V(1,1)=anneal_factor*fdc_y_variance(my_fdchits[id]->dE);
4289
4290 // Difference between measurement and projection
4291 Mdiff(1)=v-(y*cosa+x*sina+doca*nz_sinalpha_plus_nr_cosalpha);
4292 if (fit_type==kWireBased){
4293 Mdiff(0)=-doca;
4294 }
4295 else{
4296 // Compute drift distance
4297 double drift_time=my_fdchits[id]->t-mT0
4298 -forward_traj[k].t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
4299 double drift=(du>0.0?1.:-1.)*fdc_drift_distance(drift_time,forward_traj[k].B);
4300
4301 Mdiff(0)=drift-doca;
4302
4303 // Variance in drift distance
4304 V(0,0)=anneal_factor*fdc_drift_variance(drift_time);
4305 }
4306
4307 // To transform from (x,y) to (u,v), need to do a rotation:
4308 // u = x*cosa-y*sina
4309 // v = y*cosa+x*sina
4310 H(0,state_x)=cosa*cosalpha;
4311 H_T(state_x,0)=H(0,state_x);
4312 H(1,state_x)=sina;
4313 H_T(state_x,1)=H(1,state_x);
4314 H(0,state_y)=-sina*cosalpha;
4315 H_T(state_y,0)=H(0,state_y);
4316 H(1,state_y)=cosa;
4317 H_T(state_y,1)=H(1,state_y);
4318 double factor=du*tu/sqrt(one_plus_tu2)/one_plus_tu2;
4319 H(0,state_ty)=sina*factor;
4320 H_T(state_ty,0)=H(0,state_y);
4321 H(0,state_tx)=-cosa*factor;
4322 H_T(state_tx,0)=H(0,state_tx);
4323
4324 // Terms that depend on the correction for the Lorentz effect
4325 H(1,state_x)=sina+cosa*cosalpha*nz_sinalpha_plus_nr_cosalpha;
4326 H_T(state_x,1)=H(1,state_x);
4327 H(1,state_y)=cosa-sina*cosalpha*nz_sinalpha_plus_nr_cosalpha;
4328 H_T(state_y,1)=H(1,state_y);
4329 double temp=(du/one_plus_tu2)*(nz*(cosalpha*cosalpha-sinalpha*sinalpha)
4330 -2.*nr*cosalpha*sinalpha);
4331 H(1,state_tx)=cosa*temp;
4332 H_T(state_tx,1)=H(1,state_tx);
4333 H(1,state_ty)=-sina*temp;
4334 H_T(state_y,1)=H(1,state_ty);
4335
4336 // Check to see if we have multiple hits in the same plane
4337 if (forward_traj[k].num_hits>1){
4338 // If we do have multiple hits, then all of the hits within some
4339 // validation region are included with weights determined by how
4340 // close the hits are to the track projection of the state to the
4341 // "hit space".
4342 vector<DMatrix5x2> Klist;
4343 vector<DMatrix2x1> Mlist;
4344 vector<DMatrix2x5> Hlist;
4345 vector<DMatrix2x2> Vlist;
4346 vector<double>probs;
4347 DMatrix2x2 Vtemp;
4348
4349 // Deal with the first hit:
4350 Vtemp=V+H*C*H_T;
4351 InvV=Vtemp.Invert();
4352
4353 //probability
4354 double chi2_hit=Vtemp.Chi2(Mdiff);
4355 double prob_hit=exp(-0.5*chi2_hit)
4356 /(M_TWO_PI6.28318530717958647692*sqrt(Vtemp.Determinant()));
4357
4358 // Cut out outliers
4359 if (sqrt(chi2_hit)<NUM_FDC_SIGMA_CUT){
4360 probs.push_back(prob_hit);
4361 Vlist.push_back(V);
4362 Hlist.push_back(H);
4363 Mlist.push_back(Mdiff);
4364 Klist.push_back(C*H_T*InvV); // Kalman gain
4365 }
4366
4367 // loop over the remaining hits
4368 for (unsigned int m=1;m<forward_traj[k].num_hits;m++){
4369 unsigned int my_id=id-m;
4370 u=my_fdchits[my_id]->uwire;
4371 v=my_fdchits[my_id]->vstrip;
4372 double du=x*cosa-y*sina-u;
4373 doca=du*cosalpha;
4374
4375 // variance for coordinate along the wire
4376 V(1,1)=anneal_factor*fdc_y_variance(my_fdchits[my_id]->dE);
4377
4378 // Difference between measurement and projection
4379 Mdiff(1)=v-(y*cosa+x*sina+doca*nz_sinalpha_plus_nr_cosalpha);
4380 if (fit_type==kWireBased){
4381 Mdiff(0)=-doca;
4382 }
4383 else{
4384 // Compute drift distance
4385 double drift_time=my_fdchits[id]->t-mT0
4386 -forward_traj[k].t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
4387 //double drift=DRIFT_SPEED*drift_time*(du>0?1.:-1.);
4388 double drift=(du>0.0?1.:-1.)*fdc_drift_distance(drift_time,forward_traj[k].B);
4389
4390 Mdiff(0)=drift-doca;
4391
4392 // Variance in drift distance
4393 V(0,0)=anneal_factor*fdc_drift_variance(drift_time);
4394 }
4395
4396 // Update the terms in H/H_T that depend on the particular hit
4397 factor=du*tu/sqrt(one_plus_tu2)/one_plus_tu2;
4398 H_T(state_ty,0)=sina*factor;
4399 H(0,state_ty)=H_T(state_ty,0);
4400 H_T(state_tx,0)=-cosa*factor;
4401 H(0,state_tx)=H_T(state_tx,0);
4402 temp=(du/one_plus_tu2)*(nz*(cosalpha*cosalpha-sinalpha*sinalpha)
4403 -2.*nr*cosalpha*sinalpha);
4404 H_T(state_tx,1)=cosa*temp;
4405 H(1,state_tx)=H_T(state_tx,1);
4406 H_T(state_ty,1)=-sina*temp;
4407 H(1,state_ty)=H_T(state_ty,1);
4408
4409 // Calculate the kalman gain for this hit
4410 Vtemp=V+H*C*H_T;
4411 InvV=Vtemp.Invert();
4412
4413 // probability
4414 chi2_hit=Vtemp.Chi2(Mdiff);
4415 prob_hit=exp(-0.5*chi2_hit)/(M_TWO_PI6.28318530717958647692*sqrt(Vtemp.Determinant()));
4416
4417 // Cut out outliers
4418 if(sqrt(chi2_hit)<NUM_FDC_SIGMA_CUT){
4419 probs.push_back(prob_hit);
4420 Mlist.push_back(Mdiff);
4421 Vlist.push_back(V);
4422 Hlist.push_back(H);
4423 Klist.push_back(C*H_T*InvV);
4424 }
4425 }
4426 double prob_tot=1e-100;
4427 for (unsigned int m=0;m<probs.size();m++){
4428 prob_tot+=probs[m];
4429 }
4430
4431 // Adjust the state vector and the covariance using the hit
4432 //information
4433 DMatrix5x5 sum=I5x5;
4434 DMatrix5x5 sum2;
4435 for (unsigned int m=0;m<Klist.size();m++){
4436 double my_prob=probs[m]/prob_tot;
4437 S+=my_prob*(Klist[m]*Mlist[m]);
4438 sum+=my_prob*(Klist[m]*Hlist[m]);
4439 sum2+=(my_prob*my_prob)*(Klist[m]*Vlist[m]*Transpose(Klist[m]));
4440 }
4441 C=C.SandwichMultiply(sum)+sum2;
4442
4443 if (fit_type==kTimeBased){
4444 for (unsigned int m=0;m<forward_traj[k].num_hits;m++){
4445 unsigned int my_id=id-m;
4446 if (fdc_updates[my_id].used_in_fit){
4447 fdc_updates[my_id].S=S;
4448 fdc_updates[my_id].C=C;
4449 }
4450 }
4451 }
4452
4453 // update number of degrees of freedom
4454 numdof+=2;
4455
4456 }
4457 else{
4458 // Variance for this hit
4459 DMatrix2x2 Vtemp=V+H*C*H_T;
4460 InvV=Vtemp.Invert();
4461
4462 // Check if this hit is an outlier
4463 double chi2_hit=Vtemp.Chi2(Mdiff);
4464 /*
4465 if(fit_type==kTimeBased && sqrt(chi2_hit)>NUM_FDC_SIGMA_CUT){
4466 printf("outlier %d du %f dv %f sigu %f sigv %f sqrt(chi2) %f z %f \n",
4467 id, Mdiff(0),Mdiff(1),sqrt(Vtemp(0,0)),sqrt(V(1,1)),
4468 sqrt(chi2_hit),forward_traj[k].pos.z());
4469 }
4470 */
4471 if (sqrt(chi2_hit)<NUM_FDC_SIGMA_CUT)
4472 {
4473 // Compute Kalman gain matrix
4474 K=C*H_T*InvV;
4475
4476 // Update the state vector
4477 S+=K*Mdiff;
4478
4479 // Update state vector covariance matrix
4480 C=C.SubSym(K*(H*C));
4481 // Joseph form
4482 // C = (I-KH)C(I-KH)^T + KVK^T
4483 //DMatrix2x5 KT=Transpose(K);
4484 //C=C.SandwichMultiply(I5x5-K*H)+K*V*KT;
4485
4486 //C=C.SubSym(K*(H*C));
4487
4488 //C.Print();
4489
4490 if (fit_type==kTimeBased){
4491 fdc_updates[id].S=S;
4492 fdc_updates[id].C=C;
4493 }
4494 fdc_updates[id].used_in_fit=true;
4495
4496 // Filtered residual and covariance of filtered residual
4497 R=Mdiff-H*K*Mdiff;
4498 RC=V-H*(C*H_T);
4499
4500 // Update chi2 for this segment
4501 chisq+=RC.Chi2(R);
4502
4503 // update number of degrees of freedom
4504 numdof+=2;
4505 }
4506 }
4507 if (num_fdc_hits>=forward_traj[k].num_hits)
4508 num_fdc_hits-=forward_traj[k].num_hits;
4509 }
4510 }
4511 else if (num_cdc_hits>0){
4512 DVector2 origin=my_cdchits[cdc_index]->origin;
4513 double z0w=my_cdchits[cdc_index]->z0wire;
4514 DVector2 dir=my_cdchits[cdc_index]->dir;
4515 double z=forward_traj[k].z;
4516 DVector2 wirepos=origin+(z-z0w)*dir;
4517
4518 // doca variables
4519 double dx=S(state_x)-wirepos.X();
4520 double dy=S(state_y)-wirepos.Y();
4521 double doca2=dx*dx+dy*dy;
4522
4523 // Check if the doca is no longer decreasing
4524 if (doca2>old_doca2){
4525 if(true /*my_cdchits[cdc_index]->status==0*/){
4526 // Get energy loss
4527 double dedx=0.;
4528 if (CORRECT_FOR_ELOSS){
4529 dedx=GetdEdx(S(state_q_over_p),
4530 forward_traj[k].K_rho_Z_over_A,
4531 forward_traj[k].rho_Z_over_A,
4532 forward_traj[k].LnI);
4533 }
4534 double tx=S(state_tx);
4535 double ty=S(state_ty);
4536 double tanl=1./sqrt(tx*tx+ty*ty);
4537 double sinl=sin(atan(tanl));
4538
4539 // Wire direction variables
4540 double ux=dir.X();
4541 double uy=dir.Y();
4542 // Variables relating wire direction and track direction
4543 double my_ux=tx-ux;
4544 double my_uy=ty-uy;
4545 double denom=my_ux*my_ux+my_uy*my_uy;
4546 double dz=0.;
4547
4548 // if the path length increment is small relative to the radius
4549 // of curvature, use a linear approximation to find dz
4550 bool do_brent=false;
4551 double step1=mStepSizeZ;
4552 double step2=mStepSizeZ;
4553 if (k>=2){
4554 step1=-forward_traj[k].z+forward_traj[k_minus_1].z;
4555 step2=-forward_traj[k_minus_1].z+forward_traj[k-2].z;
4556 }
4557 //printf("step1 %f step 2 %f \n",step1,step2);
4558 double two_step=step1+step2;
4559 if (fabs(qBr2p0.003*S(state_q_over_p)
4560 //*bfield->GetBz(S(state_x),S(state_y),z)
4561 *forward_traj[k].B
4562 *two_step/sinl)<0.01
4563 && denom>EPS3.0e-8){
4564 double dzw=(z-z0w);
4565 dz=-((S(state_x)-origin.X()-ux*dzw)*my_ux
4566 +(S(state_y)-origin.Y()-uy*dzw)*my_uy)
4567 /(my_ux*my_ux+my_uy*my_uy);
4568
4569 if (fabs(dz)>two_step){
4570 do_brent=true;
4571 }
4572 }
4573 else do_brent=true;
4574 if (do_brent){
4575 // We have bracketed the minimum doca: use Brent's agorithm
4576 /*
4577 double step_size
4578 =forward_traj[k].pos.z()-forward_traj[k_minus_1].pos.z();
4579 dz=BrentsAlgorithm(z,step_size,dedx,origin,dir,S);
4580 */
4581 BrentsAlgorithm(z,-0.5*two_step,dedx,z0w,origin,dir,S,dz);
4582 }
4583 double newz=z+dz;
4584 // Check for exiting the straw
4585 if (newz>endplate_z){
4586 newz=endplate_z;
4587 dz=endplate_z-z;
4588 }
4589
4590 // Step the state and covariance through the field
4591 int num_steps=0;
4592 double dz3=0.;
4593 double my_dz=0.;
4594 double t=forward_traj[k_minus_1].t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
4595 if (fabs(dz)>mStepSizeZ){
4596 my_dz=(dz>0.0?1.0:-1.)*mStepSizeZ;
4597 num_steps=int(fabs(dz/my_dz));
4598 dz3=dz-num_steps*my_dz;
4599
4600 double my_z=z;
4601 for (int m=0;m<num_steps;m++){
4602 newz=my_z+my_dz;
4603
4604 // Step current state by my_dz
4605 double ds=Step(z,newz,dedx,S);
4606
4607 //Adjust time-of-flight
4608 double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
4609 double one_over_beta2=1.+mass2*q_over_p_sq;
4610 if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8;
4611 t+=ds*sqrt(one_over_beta2); // in units where c=1
4612
4613 // propagate error matrix to z-position of hit
4614 StepJacobian(z,newz,S0,dedx,J);
4615 //C=J*C*J.Transpose();
4616 C=C.SandwichMultiply(J);
4617
4618 // Step reference trajectory by my_dz
4619 Step(z,newz,dedx,S0);
4620
4621 my_z=newz;
4622 }
4623
4624 newz=my_z+dz3;
4625
4626 // Step current state by dz3
4627 Step(my_z,newz,dedx,S);
4628
4629 // propagate error matrix to z-position of hit
4630 StepJacobian(my_z,newz,S0,dedx,J);
4631 //C=J*C*J.Transpose();
4632 C=C.SandwichMultiply(J);
4633
4634 // Step reference trajectory by dz3
4635 Step(my_z,newz,dedx,S0);
4636 }
4637 else{
4638 // Step current state by dz
4639 Step(z,newz,dedx,S);
4640
4641 // propagate error matrix to z-position of hit
4642 StepJacobian(z,newz,S0,dedx,J);
4643 //C=J*C*J.Transpose();
4644 C=C.SandwichMultiply(J);
4645
4646 // Step reference trajectory by dz
4647 Step(z,newz,dedx,S0);
4648 }
4649
4650 // Wire position at current z
4651 wirepos=origin+(newz-z0w)*dir;
4652 double xw=wirepos.X();
4653 double yw=wirepos.Y();
4654
4655 // predicted doca taking into account the orientation of the wire
4656 dy=S(state_y)-yw;
4657 dx=S(state_x)-xw;
4658 double cosstereo=my_cdchits[cdc_index]->cosstereo;
4659 double d=sqrt(dx*dx+dy*dy)*cosstereo;
4660
4661 // Track projection
4662 double cosstereo2_over_d=cosstereo*cosstereo/d;
4663 Hc_T(state_x)=dx*cosstereo2_over_d;
4664 Hc(state_x)=Hc_T(state_x);
4665 Hc_T(state_y)=dy*cosstereo2_over_d;
4666 Hc(state_y)=Hc_T(state_y);
4667
4668 //H.Print();
4669
4670 // The next measurement
4671 double dm=0.;
4672 double Vc=0.2133; //1.6*1.6/12.;
4673 //double V=0.05332; // 0.8*0.8/12.;
4674
4675 //V=4.*0.8*0.8; // Testing ideas...
4676
4677 if (fit_type==kTimeBased){
4678 double tdrift=my_cdchits[cdc_index]->tdrift-mT0-t;
4679 double B=forward_traj[k].B;
4680 dm=cdc_drift_distance(tdrift,B);
4681
4682 // variance
4683 Vc=cdc_variance(B,tdrift);
4684
4685 }
4686
4687 // Residual
4688 double res=dm-d;
4689
4690 // inverse variance including prediction
4691 double InvV1=1./(Vc+Hc*(C*Hc_T));
4692 if (InvV1<0.){
4693 if (DEBUG_LEVEL>0)
4694 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4694<<" "
<< "Negative variance???" << endl;
4695 return NEGATIVE_VARIANCE;
4696 }
4697
4698 if (DEBUG_LEVEL>10)
4699 printf("Ring %d straw %d pred %f meas %f V %f %f sig %f t %f %f t0 %f\n",
4700 my_cdchits[cdc_index]->hit->wire->ring,
4701 my_cdchits[cdc_index]->hit->wire->straw,
4702 d,dm,Vc,1./InvV1,1./sqrt(InvV1),
4703 my_cdchits[cdc_index]->hit->tdrift,
4704 forward_traj[k_minus_1].t,
4705 mT0
4706 );
4707 // Check if this hit is an outlier
4708 double chi2_hit=res*res*InvV1;
4709 if (sqrt(chi2_hit)<NUM_CDC_SIGMA_CUT){
4710 // Flag place along the reference trajectory with hit id
4711 forward_traj[k_minus_1].h_id=1000+cdc_index;
4712
4713 // Compute KalmanSIMD gain matrix
4714 Kc=InvV1*(C*Hc_T);
4715
4716 // Update the state vector
4717 S+=res*Kc;
4718
4719 // Update state vector covariance matrix
4720 C=C.SubSym(K*(H*C));
4721 // Joseph form
4722 // C = (I-KH)C(I-KH)^T + KVK^T
4723 //C=C.SandwichMultiply(I5x5-Kc*Hc)+Vc*MultiplyTranspose(Kc);
4724
4725 // Store the "improved" values of the state and covariance matrix
4726 if (fit_type==kTimeBased){
4727 cdc_updates[cdc_index].S=S;
4728 cdc_updates[cdc_index].C=C;
4729 }
4730 cdc_updates[cdc_index].used_in_fit=true;
4731
4732 // Residual
4733 res*=1.-Hc*Kc;
4734
4735 // Update chi2 for this segment
4736 double err2 = Vc-Hc*(C*Hc_T)+1e-100;
4737 chisq+=anneal_factor*res*res/err2;
4738
4739 // update number of degrees of freedom
4740 numdof++;
4741
4742 }
4743
4744 if (num_steps==0){
4745 // Step C back to the z-position on the reference trajectory
4746 StepJacobian(newz,z,S0,dedx,J);
4747 //C=J*C*J.Transpose();
4748 C=C.SandwichMultiply(J);
4749
4750 // Step S to current position on the reference trajectory
4751 Step(newz,z,dedx,S);
4752 }
4753 else{
4754 double my_z=newz;
4755 for (int m=0;m<num_steps;m++){
4756 newz=my_z-my_dz;
4757
4758 // Step C along z
4759 StepJacobian(my_z,newz,S0,dedx,J);
4760 //C=J*C*J.Transpose();
4761 C=C.SandwichMultiply(J);
4762
4763 // Step S along z
4764 Step(my_z,newz,dedx,S);
4765
4766 // Step S0 along z
4767 Step(my_z,newz,dedx,S0);
4768
4769 my_z=newz;
4770 }
4771
4772 // Step C back to the z-position on the reference trajectory
4773 StepJacobian(my_z,z,S0,dedx,J);
4774 //C=J*C*J.Transpose();
4775 C=C.SandwichMultiply(J);
4776
4777 // Step S to current position on the reference trajectory
4778 Step(my_z,z,dedx,S);
4779 }
4780 }
4781
4782 // new wire origin and direction
4783 if (cdc_index>0){
4784 cdc_index--;
4785 origin=my_cdchits[cdc_index]->origin;
4786 z0w=my_cdchits[cdc_index]->z0wire;
4787 dir=my_cdchits[cdc_index]->dir;
4788 }
4789
4790 // Update the wire position
4791 wirepos=origin+(z-z0w)*dir;
4792
4793 // new doca
4794 dx=S(state_x)-wirepos.X();
4795 dy=S(state_y)-wirepos.Y();
4796 doca2=dx*dx+dy*dy;
4797
4798 if (num_cdc_hits>0) num_cdc_hits--;
4799 if (cdc_index==0 && num_cdc_hits>1) num_cdc_hits=0;
4800 }
4801 old_doca2=doca2;
4802 }
4803
4804 }
4805
4806 // If chisq is still zero after the fit, something went wrong...
4807 if (numdof<6){
4808 numdof=0;
4809 return INVALID_FIT;
4810 }
4811
4812 chisq*=anneal_factor;
4813 numdof-=5;
4814
4815 // Final position for this leg
4816 x_=S(state_x);
4817 y_=S(state_y);
4818 z_=forward_traj[forward_traj.size()-1].z;
4819
4820 return FIT_SUCCEEDED;
4821}
4822
4823
4824
4825// Kalman engine for forward tracks -- this routine adds CDC hits
4826kalman_error_t DTrackFitterKalmanSIMD::KalmanForwardCDC(double anneal,DMatrix5x1 &S,
4827 DMatrix5x5 &C,double &chisq,
4828 unsigned int &numdof){
4829 DMatrix1x5 H; // Track projection matrix
4830 DMatrix5x1 H_T; // Transpose of track projection matrix
4831 DMatrix5x5 J; // State vector Jacobian matrix
4832 //DMatrix5x5 J_T; // transpose of this matrix
4833 DMatrix5x5 Q; // Process noise covariance matrix
4834 DMatrix5x1 K; // KalmanSIMD gain matrix
4835 DMatrix5x1 S0,S0_,Stest; //State vector
4836 DMatrix5x5 Ctest; // covariance matrix
4837 //DMatrix5x1 dS; // perturbation in state vector
4838 double V=0.0507*1.15;
4839
4840 // set used_in_fit flags to false for cdc hits
4841 unsigned int num_cdc=cdc_updates.size();
4842 for (unsigned int i=0;i<num_cdc;i++) cdc_updates[i].used_in_fit=false;
4843 for (unsigned int i=0;i<forward_traj.size();i++){
4844 forward_traj[i].h_id=0;
4845 }
4846
4847 // initialize chi2 info
4848 chisq=0.;
4849 numdof=0;
4850 double var_cut=NUM_CDC_SIGMA_CUT*NUM_CDC_SIGMA_CUT;
4851 double my_anneal=anneal*anneal;
4852 double chi2cut=my_anneal*var_cut;
4853
4854 // Save the starting values for C and S in the deque
4855 forward_traj[break_point_step_index].Skk=S;
4856 forward_traj[break_point_step_index].Ckk=C;
4857
4858 // z-position
4859 double z=forward_traj[break_point_step_index].z;
4860
4861 // Step size variables
4862 double step1=mStepSizeZ;
4863 double step2=mStepSizeZ;
4864
4865 // wire information
4866 unsigned int cdc_index=break_point_cdc_index;
4867
4868 if (cdc_index<MIN_HITS_FOR_REFIT) chi2cut=100.0;
4869
4870 DVector2 origin=my_cdchits[cdc_index]->origin;
4871 double z0w=my_cdchits[cdc_index]->z0wire;
4872 DVector2 dir=my_cdchits[cdc_index]->dir;
4873 DVector2 wirepos=origin+(z-z0w)*dir;
4874 bool more_measurements=true;
4875
4876 // doca variables
4877 double dx=S(state_x)-wirepos.X();
4878 double dy=S(state_y)-wirepos.Y();
4879 double doca2=0.,old_doca2=dx*dx+dy*dy;
4880
4881 // loop over entries in the trajectory
4882 S0_=(forward_traj[break_point_step_index].S);
4883 for (unsigned int k=break_point_step_index+1;k<forward_traj.size()/*-1*/;k++){
4884 unsigned int k_minus_1=k-1;
4885
4886 // Check that C matrix is positive definite
4887 if (C(0,0)<0.0 || C(1,1)<0.0 || C(2,2)<0.0 || C(3,3)<0.0 || C(4,4)<0.0){
4888 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4888<<" "
<< "Broken covariance matrix!" <<endl;
4889 return BROKEN_COVARIANCE_MATRIX;
4890 }
4891
4892 z=forward_traj[k].z;
4893
4894 // Get the state vector, jacobian matrix, and multiple scattering matrix
4895 // from reference trajectory
4896 S0=(forward_traj[k].S);
4897 J=(forward_traj[k].J);
4898 //J_T=(forward_traj[k].JT);
4899 Q=(forward_traj[k].Q);
4900
4901 // State S is perturbation about a seed S0
4902 //dS=S-S0_;
4903 /*
4904 dS.Print();
4905 J.Print();
4906 */
4907
4908 // Update the actual state vector and covariance matrix
4909 S=S0+J*(S-S0_);
4910
4911 // Bail if the position is grossly outside of the tracking volume
4912 if (S(state_x)*S(state_x)+S(state_y)*S(state_y)>R2_MAX4225.0){
4913 if (DEBUG_LEVEL>2)
4914 {
4915 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4915<<" "
<< "Went outside of tracking volume at x=" << S(state_x)
4916 << " y=" << S(state_y) <<" z="<<z<<endl;
4917 }
4918 return POSITION_OUT_OF_RANGE;
4919 }
4920 // Bail if the momentum has dropped below some minimum
4921 if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX100.){
4922 if (DEBUG_LEVEL>2)
4923 {
4924 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4924<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p)) << endl;
4925 }
4926 return MOMENTUM_OUT_OF_RANGE;
4927 }
4928
4929
4930
4931 //C=J*(C*J_T)+Q;
4932 //C=Q.AddSym(J*C*J_T);
4933 C=Q.AddSym(C.SandwichMultiply(J));
4934
4935 // Save the current state of the reference trajectory
4936 S0_=S0;
4937
4938 // new wire position
4939 wirepos=origin;
4940 wirepos+=(z-z0w)*dir;
4941
4942 // new doca
4943 dx=S(state_x)-wirepos.X();
4944 dy=S(state_y)-wirepos.Y();
4945 doca2=dx*dx+dy*dy;
4946
4947 // Check if the doca is no longer decreasing
4948 if (more_measurements && doca2>old_doca2 && z<endplate_z){
4949 if (my_cdchits[cdc_index]->status==good_hit){
4950 double dz=0.,newz=z;
4951
4952 // Get energy loss
4953 double dedx=0.;
4954 if (CORRECT_FOR_ELOSS){
4955 dedx=GetdEdx(S(state_q_over_p),
4956 forward_traj[k].K_rho_Z_over_A,
4957 forward_traj[k].rho_Z_over_A,
4958 forward_traj[k].LnI);
4959 }
4960
4961 // Last 2 step sizes
4962 if (k>=2){
4963 double z1=forward_traj[k_minus_1].z;
4964 step1=-forward_traj[k].z+z1;
4965 step2=-z1+forward_traj[k-2].z;
4966 }
4967
4968 // Track direction variables
4969 double tx=S(state_tx);
4970 double ty=S(state_ty);
4971 double tanl=1./sqrt(tx*tx+ty*ty);
4972 double sinl=sin(atan(tanl));
4973
4974 // Wire direction variables
4975 double ux=dir.X();
4976 double uy=dir.Y();
4977 // Variables relating wire direction and track direction
4978 double my_ux=tx-ux;
4979 double my_uy=ty-uy;
4980 double denom=my_ux*my_ux+my_uy*my_uy;
4981
4982 // if the path length increment is small relative to the radius
4983 // of curvature, use a linear approximation to find dz
4984 bool do_brent=false;
4985 //printf("step1 %f step 2 %f \n",step1,step2);
4986 double two_step=step1+step2;
4987 if (fabs(qBr2p0.003*S(state_q_over_p)
4988 //*bfield->GetBz(S(state_x),S(state_y),z)
4989 *forward_traj[k].B
4990 *two_step/sinl)<0.01
4991 && denom>EPS3.0e-8){
4992 double dzw=z-z0w;
4993 dz=-((S(state_x)-origin.X()-ux*dzw)*my_ux
4994 +(S(state_y)-origin.Y()-uy*dzw)*my_uy)/denom;
4995
4996 if (fabs(dz)>two_step || dz<0.0){
4997 do_brent=true;
4998 }
4999 else{
5000 newz=z+dz;
5001 // Check for exiting the straw
5002 if (newz>endplate_z){
5003 newz=endplate_z;
5004 dz=endplate_z-z;
5005 }
5006 // Step the state and covariance through the field
5007 if (dz>mStepSizeZ){
5008 double my_z=z;
5009 int my_steps=int(dz/mStepSizeZ);
5010 double dz2=dz-my_steps*mStepSizeZ;
5011 for (int m=0;m<my_steps;m++){
5012 newz=my_z+mStepSizeZ;
5013
5014 // Bail if the momentum has dropped below some minimum
5015 if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX100.){
5016 if (DEBUG_LEVEL>2)
5017 {
5018 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5018<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p)) << endl;
5019 }
5020 return MOMENTUM_OUT_OF_RANGE;
5021 }
5022
5023 // Step current state by step size
5024 Step(my_z,newz,dedx,S);
5025
5026 my_z=newz;
5027 }
5028 newz=my_z+dz2;
5029 // Bail if the momentum has dropped below some minimum
5030 if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX100.){
5031 if (DEBUG_LEVEL>2)
5032 {
5033 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5033<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p)) << endl;
5034 }
5035 return MOMENTUM_OUT_OF_RANGE;
5036 }
5037
5038 Step(my_z,newz,dedx,S);
5039 }
5040 else{
5041 // Bail if the momentum has dropped below some minimum
5042 if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX100.){
5043 if (DEBUG_LEVEL>2)
5044 {
5045 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5045<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p)) << endl;
5046 }
5047 return MOMENTUM_OUT_OF_RANGE;
5048 }
5049 Step(z,newz,dedx,S);
5050 }
5051 }
5052 }
5053 else do_brent=true;
5054 if (do_brent){
5055 // We have bracketed the minimum doca: use Brent's agorithm
5056 if (BrentsAlgorithm(z,-mStepSizeZ,dedx,z0w,origin,dir,S,dz)
5057 !=NOERROR){
5058 return MOMENTUM_OUT_OF_RANGE;
5059 }
5060 newz=z+dz;
5061
5062 if (fabs(dz)>2.*mStepSizeZ-EPS31.e-2){
5063 // whoops, looks like we didn't actually bracket the minimum after
5064 // all. Swim to make sure we pass the minimum doca.
5065 double ztemp=newz;
5066
5067 // doca
5068 old_doca2=doca2;
5069
5070 // new wire position
5071 wirepos=origin;
5072 wirepos+=(newz-z0w)*dir;
5073
5074 // new distance to the wire
5075 dx=S(state_x)-wirepos.X();
5076 dy=S(state_y)-wirepos.Y();
5077 doca2=dx*dx+dy*dy;
5078
5079 while(doca2<old_doca2){
5080 newz=ztemp+mStepSizeZ;
5081 old_doca2=doca2;
5082
5083 // step to the next z position
5084 Step(ztemp,newz,dedx,S);
5085
5086 // new wire position
5087 wirepos=origin;
5088 wirepos+=(newz-z0w)*dir;
5089
5090 //New distance to the wire
5091
5092 dx=S(state_x)-wirepos.X();
5093 dy=S(state_y)-wirepos.Y();
5094 doca2=dx*dx+dy*dy;
5095
5096 ztemp=newz;
5097 }
5098 // Find the true doca
5099 double dz2=0.;
5100 if (BrentsAlgorithm(newz,mStepSizeZ,dedx,z0w,origin,dir,S,dz2)!=NOERROR){
5101 return MOMENTUM_OUT_OF_RANGE;
5102 }
5103 newz=ztemp+dz2;
5104
5105 // Change in z relative to where we started for this wire
5106 dz=newz-z;
5107 }
5108 }
5109
5110 // Step the state and covariance through the field
5111 int num_steps=0;
5112 double dz3=0.;
5113 double my_dz=0.;
5114 if (fabs(dz)>mStepSizeZ){
5115 my_dz=(dz>0.0?1.0:-1.)*mStepSizeZ;
5116 num_steps=int(fabs(dz/my_dz));
5117 dz3=dz-num_steps*my_dz;
5118
5119 double my_z=z;
5120 for (int m=0;m<num_steps;m++){
5121 newz=my_z+my_dz;
5122
5123 // Step current state by my_dz
5124 //Step(z,newz,dedx,S);
5125
5126 // propagate error matrix to z-position of hit
5127 StepJacobian(z,newz,S0,dedx,J);
5128 //C=J*C*J.Transpose();
5129 C=C.SandwichMultiply(J);
5130
5131 // Step reference trajectory by my_dz
5132 Step(z,newz,dedx,S0);
5133
5134 my_z=newz;
5135 }
5136
5137 newz=my_z+dz3;
5138
5139 // Step current state by dz3
5140 // Step(my_z,newz,dedx,S);
5141
5142 // propagate error matrix to z-position of hit
5143 StepJacobian(my_z,newz,S0,dedx,J);
5144 //C=J*C*J.Transpose();
5145 C=C.SandwichMultiply(J);
5146
5147 // Step reference trajectory by dz3
5148 Step(my_z,newz,dedx,S0);
5149 }
5150 else{
5151 // Step current state by dz
5152 //Step(z,newz,dedx,S);
5153
5154 // propagate error matrix to z-position of hit
5155 StepJacobian(z,newz,S0,dedx,J);
5156 //C=J*C*J.Transpose();
5157 C=C.SandwichMultiply(J);
5158
5159 // Step reference trajectory by dz
5160 Step(z,newz,dedx,S0);
5161 }
5162
5163 // Wire position at current z
5164 wirepos=origin;
5165 wirepos+=(newz-z0w)*dir;
5166
5167 double xw=wirepos.X();
5168 double yw=wirepos.Y();
5169
5170 // predicted doca taking into account the orientation of the wire
5171 dy=S(state_y)-yw;
5172 dx=S(state_x)-xw;
5173 double cosstereo=my_cdchits[cdc_index]->cosstereo;
5174 double d=sqrt(dx*dx+dy*dy)*cosstereo+EPS3.0e-8;
5175
5176 //printf("z %f d %f z-1 %f\n",newz,d,forward_traj[k_minus_1].z);
5177
5178 // Track projection
5179 double cosstereo2_over_d=cosstereo*cosstereo/d;
5180 H(state_x)=H_T(state_x)=dx*cosstereo2_over_d;
5181 H(state_y)=H_T(state_y)=dy*cosstereo2_over_d;
5182
5183 //H.Print();
5184
5185 // The next measurement
5186 double dm=0.39,tdrift=0.,tcorr=0.;
5187 if (fit_type==kTimeBased || USE_PASS1_TIME_MODE){
5188 // Find offset of wire with respect to the center of the
5189 // straw at this z position
5190 const DCDCWire *mywire=my_cdchits[cdc_index]->hit->wire;
5191 int ring_index=mywire->ring-1;
5192 int straw_index=mywire->straw-1;
5193 double dz=newz-z0w;
5194 double phi_d=atan2(dy,dx);
5195 double delta
5196 =max_sag[ring_index][straw_index]*(1.-dz*dz/5625.)
5197 *cos(phi_d + sag_phi_offset[ring_index][straw_index]);
5198 double dphi=phi_d-mywire->origin.Phi();
5199 while (dphi>M_PI3.14159265358979323846) dphi-=2*M_PI3.14159265358979323846;
5200 while (dphi<-M_PI3.14159265358979323846) dphi+=2*M_PI3.14159265358979323846;
5201 if (mywire->origin.Y()<0) dphi*=-1.;
5202
5203 tdrift=my_cdchits[cdc_index]->tdrift-mT0
5204 -forward_traj[k_minus_1].t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
5205 double B=forward_traj[k_minus_1].B;
5206 ComputeCDCDrift(dphi,delta,tdrift,B,dm,V,tcorr);
5207
5208 //_DBG_ << tcorr << " " << dphi << " " << dm << endl;
5209 }
5210 // residual
5211 double res=dm-d;
5212
5213 // inverse of variance including prediction
5214 //InvV=1./(V+H*(C*H_T));
5215 double Vproj=C.SandwichMultiply(H_T);
5216 double InvV=1./(V+Vproj);
5217 if (InvV<0.){
5218 if (DEBUG_LEVEL>0)
5219 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5219<<" "
<< "Negative variance???" << endl;
5220 break_point_cdc_index=(3*num_cdc)/4;
5221 return NEGATIVE_VARIANCE;
5222 }
5223
5224 // Check how far this hit is from the expected position
5225 double chi2check=res*res*InvV;
5226 //if (sqrt(chi2check)>NUM_CDC_SIGMA_CUT) InvV*=0.8;
5227 if (chi2check<chi2cut)
5228 {
5229 /*
5230 if (chi2check>var_cut){
5231 // Give hits that satisfy the wide cut but are still pretty far
5232 // from the projected position less weight
5233 //_DBG_ << my_anneal << endl;
5234
5235 // ad hoc correction
5236 double diff = chi2check-var_cut;
5237 V*=1.+my_anneal*diff*diff;
5238 InvV=1./(V+Vproj);
5239 }
5240 */
5241
5242 // Compute KalmanSIMD gain matrix
5243 K=InvV*(C*H_T);
5244
5245 // Update state vector covariance matrix
5246 Ctest=C.SubSym(K*(H*C));
5247 // Joseph form
5248 // C = (I-KH)C(I-KH)^T + KVK^T
5249 //Ctest=C.SandwichMultiply(I5x5-K*H)+V*MultiplyTranspose(K);
5250 // Check that Ctest is positive definite
5251 if (Ctest(0,0)>0.0 && Ctest(1,1)>0.0 && Ctest(2,2)>0.0 && Ctest(3,3)>0.0
5252 && Ctest(4,4)>0.0){
5253 bool skip_ring
5254 =(my_cdchits[cdc_index]->hit->wire->ring==RING_TO_SKIP);
5255 // update covariance matrix and state vector
5256 if (skip_ring==false){
5257 C=Ctest;
5258 S+=res*K;
5259 }
5260 // Mark point on ref trajectory with a hit id for the straw
5261 forward_traj[k].h_id=cdc_index+1;
5262
5263 // Store some updated values related to the hit
5264 double scale=(skip_ring)?1.:(1.-H*K);
5265 cdc_updates[cdc_index].tcorr=tcorr;
5266 cdc_updates[cdc_index].tdrift=tdrift;
5267 cdc_updates[cdc_index].doca=dm;
5268 cdc_updates[cdc_index].residual=res*scale;
5269 cdc_updates[cdc_index].variance=V;
5270 cdc_updates[cdc_index].used_in_fit=true;
5271
5272 // Update chi2 for this segment
5273 if (skip_ring==false){
5274 chisq+=scale*res*res/V;
5275 numdof++;
5276 }
5277 break_point_cdc_index=cdc_index;
5278 break_point_step_index=k_minus_1;
5279
5280 if (DEBUG_LEVEL>9)
5281 printf("Ring %d straw %d pred %f meas %f chi2 %f\n",
5282 my_cdchits[cdc_index]->hit->wire->ring,
5283 my_cdchits[cdc_index]->hit->wire->straw,
5284 d,dm,(1.-H*K)*res*res/V);
5285
5286 }
5287 }
5288
5289 if (num_steps==0){
5290 // Step C back to the z-position on the reference trajectory
5291 StepJacobian(newz,z,S0,dedx,J);
5292 //C=J*C*J.Transpose();
5293 C=C.SandwichMultiply(J);
5294
5295 // Step S to current position on the reference trajectory
5296 Step(newz,z,dedx,S);
5297 }
5298 else{
5299 double my_z=newz;
5300 for (int m=0;m<num_steps;m++){
5301 z=my_z-my_dz;
5302
5303 // Step C along z
5304 StepJacobian(my_z,z,S0,dedx,J);
5305 //C=J*C*J.Transpose();
5306 C=C.SandwichMultiply(J);
5307
5308 // Step S along z
5309 Step(my_z,z,dedx,S);
5310
5311 // Step S0 along z
5312 Step(my_z,z,dedx,S0);
5313
5314 my_z=z;
5315 }
5316 z=my_z-dz3;
5317
5318 // Step C back to the z-position on the reference trajectory
5319 StepJacobian(my_z,z,S0,dedx,J);
5320 //C=J*C*J.Transpose();
5321 C=C.SandwichMultiply(J);
5322
5323 // Step S to current position on the reference trajectory
5324 Step(my_z,z,dedx,S);
5325
5326 }
5327
5328 cdc_updates[cdc_index].S=S;
5329 cdc_updates[cdc_index].C=C;
5330 }
5331 else {
5332 if (cdc_index>0) cdc_index--;
5333 else cdc_index=0;
5334
5335 }
5336
5337 // new wire origin and direction
5338 if (cdc_index>0){
5339 cdc_index--;
5340 origin=my_cdchits[cdc_index]->origin;
5341 z0w=my_cdchits[cdc_index]->z0wire;
5342 dir=my_cdchits[cdc_index]->dir;
5343 }
5344 else{
5345 more_measurements=false;
5346 }
5347
5348 // Update the wire position
5349 wirepos=origin;
5350 wirepos+=(z-z0w)*dir;
5351
5352 // new doca
5353 dx=S(state_x)-wirepos.X();
5354 dy=S(state_y)-wirepos.Y();
5355 doca2=dx*dx+dy*dy;
5356 }
5357 old_doca2=doca2;
5358
5359 // Save the current state and covariance matrix in the deque
5360 forward_traj[k].Skk=S;
5361 forward_traj[k].Ckk=C;
5362
5363 }
5364
5365 // Check that there were enough hits to make this a valid fit
5366 if (numdof<6){
5367 chisq=MAX_CHI21e16;
5368 numdof=0;
5369
5370 return INVALID_FIT;
5371 }
5372 numdof-=5;
5373
5374 // Final position for this leg
5375 x_=S(state_x);
5376 y_=S(state_y);
5377 z_=forward_traj[forward_traj.size()-1].z;
5378
5379 // Check if the momentum is unphysically large
5380 if (1./fabs(S(state_q_over_p))>12.0){
5381 if (DEBUG_LEVEL>2)
5382 {
5383 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5383<<" "
<< "Unphysical momentum: P = " << 1./fabs(S(state_q_over_p))
5384 <<endl;
5385 }
5386 return MOMENTUM_OUT_OF_RANGE;
5387 }
5388
5389 // Check if we have a kink in the track or threw away too many cdc hits
5390 if (num_cdc>=MIN_HITS_FOR_REFIT){
5391 if (break_point_cdc_index>1){
5392 if (break_point_cdc_index<num_cdc/2){
5393 break_point_cdc_index=(3*num_cdc)/4;
5394 }
5395 return BREAK_POINT_FOUND;
5396 }
5397
5398 unsigned int num_good=0;
5399 for (unsigned int j=0;j<num_cdc;j++){
5400 if (cdc_updates[j].used_in_fit) num_good++;
5401 }
5402 if (double(num_good)/double(num_cdc)<MINIMUM_HIT_FRACTION0.5){
5403 return PRUNED_TOO_MANY_HITS;
5404 }
5405 }
5406
5407 return FIT_SUCCEEDED;
5408}
5409
5410// Extrapolate to the point along z of closest approach to the beam line using
5411// the forward track state vector parameterization. Converts to the central
5412// track representation at the end.
5413jerror_t DTrackFitterKalmanSIMD::ExtrapolateToVertex(DMatrix5x1 &S,
5414 DMatrix5x5 &C){
5415 DMatrix5x5 J; // Jacobian matrix
5416 DMatrix5x5 Q; // multiple scattering matrix
5417 DMatrix5x1 S1(S); // copy of S
5418
5419 // Direction and origin of beam line
5420 DVector2 dir;
5421 DVector2 origin;
5422
5423 // position variables
5424 double z=z_,newz=z_;
5425 double r2_old=S(state_x)*S(state_x)+S(state_y)*S(state_y);
5426 double dz_old=0.;
5427 double dEdx=0.;
5428 double sign=1.;
5429
5430 // material properties
5431 double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.;
5432 double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.;
5433
5434 // if (fit_type==kTimeBased)printf("------Extrapolating\n");
5435
5436 // printf("-----------\n");
5437 // Current position
5438 DVector3 pos(S(state_x),S(state_y),z);
5439
5440 // get material properties from the Root Geometry
5441 if (geom->FindMatKalman(pos,K_rho_Z_over_A,rho_Z_over_A,LnI,
5442 chi2c_factor,chi2a_factor,chi2a_corr,
5443 last_material_map)
5444 !=NOERROR){
5445 if (DEBUG_LEVEL>1)
5446 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5446<<" "
<< "Material error in ExtrapolateToVertex at (x,y,z)=("
5447 << pos.X() <<"," << pos.y()<<","<< pos.z()<<")"<< endl;
5448 return UNRECOVERABLE_ERROR;
5449 }
5450
5451 // Adjust the step size
5452 double ds_dz=sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
5453 double dz=-mStepSizeS/ds_dz;
5454 if (fabs(dEdx)>EPS3.0e-8){
5455 dz=(-1.)*DE_PER_STEP0.0005/fabs(dEdx)/ds_dz;
5456 }
5457 if(fabs(dz)>mStepSizeZ) dz=-mStepSizeZ;
5458 if(fabs(dz)<MIN_STEP_SIZE0.1)dz=-MIN_STEP_SIZE0.1;
5459
5460 // Get dEdx for the upcoming step
5461 if (CORRECT_FOR_ELOSS){
5462 dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI);
5463 }
5464
5465
5466 double ztest=endplate_z;
5467 if (my_fdchits.size()>0){
5468 ztest =my_fdchits[0]->z-1.;
5469 }
5470 if (z<ztest)
5471 {
5472 // Check direction of propagation
5473 DMatrix5x1 S2(S); // second copy of S
5474
5475 // Step test states through the field and compute squared radii
5476 Step(z,z-dz,dEdx,S1);
5477 // Bail if the momentum has dropped below some minimum
5478 if (fabs(S1(state_q_over_p))>Q_OVER_P_MAX100.){
5479 if (DEBUG_LEVEL>2)
5480 {
5481 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5481<<" "
<< "Bailing: P = " << 1./fabs(S1(state_q_over_p))
5482 << endl;
5483 }
5484 return UNRECOVERABLE_ERROR;
5485 }
5486 double r2minus=S1(state_x)*S1(state_x)+S1(state_y)*S1(state_y);
5487 Step(z,z+dz,dEdx,S2);
5488 // Bail if the momentum has dropped below some minimum
5489 if (fabs(S2(state_q_over_p))>Q_OVER_P_MAX100.){
5490 if (DEBUG_LEVEL>2)
5491 {
5492 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5492<<" "
<< "Bailing: P = " << 1./fabs(S2(state_q_over_p))
5493 << endl;
5494 }
5495 return UNRECOVERABLE_ERROR;
5496 }
5497 double r2plus=S2(state_x)*S2(state_x)+S2(state_y)*S2(state_y);
5498 // Check to see if we have already bracketed the minimum
5499 if (r2plus>r2_old && r2minus>r2_old){
5500 newz=z+dz;
5501 DVector2 dir;
5502 DVector2 origin;
5503 double dz2=0.;
5504 if (BrentsAlgorithm(newz,dz,dEdx,0.,origin,dir,S2,dz2)!=NOERROR){
5505 if (DEBUG_LEVEL>2)
5506 {
5507 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5507<<" "
<< "Bailing: P = " << 1./fabs(S2(state_q_over_p))
5508 << endl;
5509 }
5510 return UNRECOVERABLE_ERROR;
5511 }
5512 z_=newz+dz2;
5513
5514 // Compute the Jacobian matrix
5515 StepJacobian(z,z_,S,dEdx,J);
5516
5517 // Propagate the covariance matrix
5518 //C=Q.AddSym(J*C*J.Transpose());
5519 C=C.SandwichMultiply(J);
5520
5521 // Step to the position of the doca
5522 Step(z,z_,dEdx,S);
5523
5524 // update internal variables
5525 x_=S(state_x);
5526 y_=S(state_y);
5527
5528 return NOERROR;
5529 }
5530
5531 // Find direction to propagate toward minimum doca
5532 if (r2minus<r2_old && r2_old<r2plus){
5533 newz=z-dz;
5534
5535 // Compute the Jacobian matrix
5536 StepJacobian(z,newz,S,dEdx,J);
5537
5538 // Propagate the covariance matrix
5539 //C=Q.AddSym(J*C*J.Transpose());
5540 C=C.SandwichMultiply(J);
5541
5542 S2=S;
5543 S=S1;
5544 S1=S2;
5545 dz*=-1.;
5546 sign=-1.;
5547 dz_old=dz;
5548 r2_old=r2minus;
5549 z=z+dz;
5550 }
5551 if (r2minus>r2_old && r2_old>r2plus){
5552 newz=z+dz;
5553
5554 // Compute the Jacobian matrix
5555 StepJacobian(z,newz,S,dEdx,J);
5556
5557 // Propagate the covariance matrix
5558 //C=Q.AddSym(J*C*J.Transpose());
5559 C=C.SandwichMultiply(J);
5560
5561 S1=S;
5562 S=S2;
5563 dz_old=dz;
5564 r2_old=r2plus;
5565 z=z+dz;
5566 }
5567 }
5568
5569 double r2=r2_old;
5570 while (z>Z_MIN-100. && r2<R2_MAX4225.0 && z<ztest && r2>EPS3.0e-8){
5571 // Bail if the momentum has dropped below some minimum
5572 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX100.){
5573 if (DEBUG_LEVEL>2)
5574 {
5575 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5575<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p))
5576 << endl;
5577 }
5578 return UNRECOVERABLE_ERROR;
5579 }
5580
5581 // Relationship between arc length and z
5582 double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
5583
5584 // get material properties from the Root Geometry
5585 pos.SetXYZ(S(state_x),S(state_y),z);
5586 double s_to_boundary=1.e6;
5587 if (ENABLE_BOUNDARY_CHECK && fit_type==kTimeBased){
5588 DVector3 mom(S(state_tx),S(state_ty),1.);
5589 if (geom->FindMatKalman(pos,mom,K_rho_Z_over_A,rho_Z_over_A,LnI,
5590 chi2c_factor,chi2a_factor,chi2a_corr,
5591 last_material_map,&s_to_boundary)
5592 !=NOERROR){
5593 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5593<<" "
<< "Material error in ExtrapolateToVertex! " << endl;
5594 return UNRECOVERABLE_ERROR;
5595 }
5596 }
5597 else{
5598 if (geom->FindMatKalman(pos,K_rho_Z_over_A,rho_Z_over_A,LnI,
5599 chi2c_factor,chi2a_factor,chi2a_corr,
5600 last_material_map)
5601 !=NOERROR){
5602 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5602<<" "
<< "Material error in ExtrapolateToVertex! " << endl;
5603 break;
5604 }
5605 }
5606
5607 // Get dEdx for the upcoming step
5608 if (CORRECT_FOR_ELOSS){
5609 dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI);
5610 }
5611
5612 // Adjust the step size
5613 //dz=-sign*mStepSizeS*dz_ds;
5614 double ds=mStepSizeS;
5615 if (fabs(dEdx)>EPS3.0e-8){
5616 ds=DE_PER_STEP0.0005/fabs(dEdx);
5617 }
5618 /*
5619 if(fabs(dz)>mStepSizeZ) dz=-sign*mStepSizeZ;
5620 if (fabs(dz)<z_to_boundary) dz=-sign*z_to_boundary;
5621 if(fabs(dz)<MIN_STEP_SIZE)dz=-sign*MIN_STEP_SIZE;
5622 */
5623 if (ds>mStepSizeS) ds=mStepSizeS;
5624 if (ds>s_to_boundary) ds=s_to_boundary;
5625 if (ds<MIN_STEP_SIZE0.1) ds=MIN_STEP_SIZE0.1;
5626 dz=-sign*ds*dz_ds;
5627
5628 // Get the contribution to the covariance matrix due to multiple
5629 // scattering
5630 GetProcessNoise(ds,chi2c_factor,chi2a_factor,chi2a_corr,S,Q);
5631
5632 if (CORRECT_FOR_ELOSS){
5633 double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
5634 double one_over_beta2=1.+mass2*q_over_p_sq;
5635 double varE=GetEnergyVariance(ds,one_over_beta2,K_rho_Z_over_A);
5636 Q(state_q_over_p,state_q_over_p)=varE*q_over_p_sq*q_over_p_sq*one_over_beta2;
5637 }
5638
5639
5640 newz=z+dz;
5641 // Compute the Jacobian matrix
5642 StepJacobian(z,newz,S,dEdx,J);
5643
5644 // Propagate the covariance matrix
5645 //C=Q.AddSym(J*C*J.Transpose());
5646 C=Q.AddSym(C.SandwichMultiply(J));
5647
5648 // Step through field
5649 Step(z,newz,dEdx,S);
5650
5651 // Check if we passed the minimum doca to the beam line
5652 r2=S(state_x)*S(state_x)+S(state_y)*S(state_y);
5653 if (r2>r2_old){
5654 double two_step=dz+dz_old;
5655
5656 // Find the increment/decrement in z to get to the minimum doca to the
5657 // beam line
5658 S1=S;
5659 if (BrentsAlgorithm(newz,0.5*two_step,dEdx,0.,origin,dir,S,dz)!=NOERROR){
5660 //_DBG_<<endl;
5661 return UNRECOVERABLE_ERROR;
5662 }
5663
5664 // Compute the Jacobian matrix
5665 z_=newz+dz;
5666 StepJacobian(newz,z_,S1,dEdx,J);
5667
5668 // Propagate the covariance matrix
5669 //C=J*C*J.Transpose()+(dz/(newz-z))*Q;
5670 //C=((dz/newz-z)*Q).AddSym(C.SandwichMultiply(J));
5671 C=C.SandwichMultiply(J);
5672
5673 // update internal variables
5674 x_=S(state_x);
5675 y_=S(state_y);
5676
5677 return NOERROR;
5678 }
5679 r2_old=r2;
5680 dz_old=dz;
5681 S1=S;
5682 z=newz;
5683 }
5684 // update internal variables
5685 x_=S(state_x);
5686 y_=S(state_y);
5687 z_=newz;
5688
5689 return NOERROR;
5690}
5691
5692
5693// Extrapolate to the point along z of closest approach to the beam line using
5694// the forward track state vector parameterization.
5695jerror_t DTrackFitterKalmanSIMD::ExtrapolateToVertex(DMatrix5x1 &S){
5696 DMatrix5x5 J; // Jacobian matrix
5697 DMatrix5x1 S1(S); // copy of S
5698
5699 // position variables
5700 double z=z_,newz=z_;
5701 double dz=-mStepSizeZ;
Value stored to 'dz' during its initialization is never read
5702 double r2_old=S(state_x)*S(state_x)+S(state_y)*S(state_y);
5703 double dz_old=0.;
5704 double dEdx=0.;
5705
5706 // Direction and origin for beam line
5707 DVector2 dir;
5708 DVector2 origin;
5709
5710 // material properties
5711 double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.;
5712 double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.;
5713 DVector3 pos; // current position along trajectory
5714
5715 double r2=r2_old;
5716 while (z>Z_MIN-100. && r2<R2_MAX4225.0 && z<Z_MAX370.0 && r2>EPS3.0e-8){
5717 // Bail if the momentum has dropped below some minimum
5718 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX100.){
5719 if (DEBUG_LEVEL>2)
5720 {
5721 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5721<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p))
5722 << endl;
5723 }
5724 return UNRECOVERABLE_ERROR;
5725 }
5726
5727 // Relationship between arc length and z
5728 double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
5729
5730 // get material properties from the Root Geometry
5731 pos.SetXYZ(S(state_x),S(state_y),z);
5732 if (geom->FindMatKalman(pos,K_rho_Z_over_A,rho_Z_over_A,LnI,
5733 chi2c_factor,chi2a_factor,chi2a_corr,
5734 last_material_map)
5735 !=NOERROR){
5736 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5736<<" "
<< "Material error in ExtrapolateToVertex! " << endl;
5737 break;
5738 }
5739
5740 // Get dEdx for the upcoming step
5741 if (CORRECT_FOR_ELOSS){
5742 dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI);
5743 }
5744
5745 // Adjust the step size
5746 double ds=mStepSizeS;
5747 if (fabs(dEdx)>EPS3.0e-8){
5748 ds=DE_PER_STEP0.0005/fabs(dEdx);
5749 }
5750 if (ds>mStepSizeS) ds=mStepSizeS;
5751 if (ds<MIN_STEP_SIZE0.1) ds=MIN_STEP_SIZE0.1;
5752 dz=-ds*dz_ds;
5753
5754 newz=z+dz;
5755
5756
5757 // Step through field
5758 Step(z,newz,dEdx,S);
5759
5760 // Check if we passed the minimum doca to the beam line
5761 r2=S(state_x)*S(state_x)+S(state_y)*S(state_y);
5762
5763 if (r2>r2_old){
5764 double two_step=dz+dz_old;
5765
5766 // Find the increment/decrement in z to get to the minimum doca to the
5767 // beam line
5768 if (BrentsAlgorithm(newz,0.5*two_step,dEdx,0.,origin,dir,S,dz)!=NOERROR){
5769 return UNRECOVERABLE_ERROR;
5770 }
5771 // update internal variables
5772 x_=S(state_x);
5773 y_=S(state_y);
5774 z_=newz+dz;
5775
5776 return NOERROR;
5777 }
5778 r2_old=r2;
5779 dz_old=dz;
5780 S1=S;
5781 z=newz;
5782 }
5783 // update internal variables
5784 x_=S(state_x);
5785 y_=S(state_y);
5786 z_=newz;
5787
5788
5789 return NOERROR;
5790}
5791
5792
5793
5794
5795// Propagate track to point of distance of closest approach to origin
5796jerror_t DTrackFitterKalmanSIMD::ExtrapolateToVertex(DVector2 &xy,
5797 DMatrix5x1 &Sc,DMatrix5x5 &Cc){
5798 DMatrix5x5 Jc=I5x5; //Jacobian matrix
5799 DMatrix5x5 Q; // multiple scattering matrix
5800
5801 // Initialize the beam position = center of target, and the direction
5802 DVector2 origin;
5803 DVector2 dir;
5804
5805 // Position and step variables
5806 double r2=xy.Mod2();
5807 double ds=-mStepSizeS; // step along path in cm
5808 double r2_old=r2;
5809
5810 // Energy loss
5811 double dedx=0.;
5812
5813 // Check direction of propagation
5814 DMatrix5x1 S0;
5815 S0=Sc;
5816 DVector2 xy0=xy;
5817 DVector2 xy1=xy;
5818 Step(xy0,ds,S0,dedx);
5819 // Bail if the transverse momentum has dropped below some minimum
5820 if (fabs(S0(state_q_over_pt))>Q_OVER_PT_MAX100.){
5821 if (DEBUG_LEVEL>2)
5822 {
5823 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5823<<" "
<< "Bailing: PT = " << 1./fabs(S0(state_q_over_pt))
5824 << endl;
5825 }
5826 return UNRECOVERABLE_ERROR;
5827 }
5828 r2=xy0.Mod2();
5829 if (r2>r2_old) ds*=-1.;
5830 double ds_old=ds;
5831
5832 // if (fit_type==kTimeBased)printf("------Extrapolating\n");
5833
5834 if (central_traj.size()==0){
5835 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5835<<" "
<< "Central trajectory size==0!" << endl;
5836 return UNRECOVERABLE_ERROR;
5837 }
5838
5839 // D is now on the actual trajectory itself
5840 Sc(state_D)=0.;
5841
5842 // Track propagation loop
5843 while (Sc(state_z)>Z_MIN-100. && Sc(state_z)<Z_MAX370.0
5844 && r2<R2_MAX4225.0){
5845 // Bail if the transverse momentum has dropped below some minimum
5846 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
5847 if (DEBUG_LEVEL>2)
5848 {
5849 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5849<<" "
<< "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
5850 << endl;
5851 }
5852 return UNRECOVERABLE_ERROR;
5853 }
5854
5855 // get material properties from the Root Geometry
5856 double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.;
5857 double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.;
5858 DVector3 pos3d(xy.X(),xy.Y(),Sc(state_z));
5859 if (geom->FindMatKalman(pos3d,K_rho_Z_over_A,rho_Z_over_A,LnI,
5860 chi2c_factor,chi2a_factor,chi2a_corr,
5861 last_material_map)
5862 !=NOERROR){
5863 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5863<<" "
<< "Material error in ExtrapolateToVertex! " << endl;
5864 break;
5865 }
5866
5867 // Get dEdx for the upcoming step
5868 double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl)));
5869 if (CORRECT_FOR_ELOSS){
5870 dedx=-GetdEdx(q_over_p,K_rho_Z_over_A,rho_Z_over_A,LnI);
5871 }
5872 // Adjust the step size
5873 double sign=(ds>0.0)?1.:-1.;
5874 if (fabs(dedx)>EPS3.0e-8){
5875 ds=sign*DE_PER_STEP0.0005/fabs(dedx);
5876 }
5877 if(fabs(ds)>mStepSizeS) ds=sign*mStepSizeS;
5878 if(fabs(ds)<MIN_STEP_SIZE0.1)ds=sign*MIN_STEP_SIZE0.1;
5879
5880 // Multiple scattering
5881 GetProcessNoiseCentral(ds,chi2c_factor,chi2a_factor,chi2a_corr,Sc,Q);
5882
5883 if (CORRECT_FOR_ELOSS){
5884 double q_over_p_sq=q_over_p*q_over_p;
5885 double one_over_beta2=1.+mass2*q_over_p*q_over_p;
5886 double varE=GetEnergyVariance(ds,one_over_beta2,K_rho_Z_over_A);
5887 Q(state_q_over_p,state_q_over_p)=varE*q_over_p_sq*q_over_p_sq*one_over_beta2;
5888 }
5889
5890 // Propagate the state and covariance through the field
5891 S0=Sc;
5892 DVector2 old_xy=xy;
5893 StepStateAndCovariance(xy,ds,dedx,Sc,Jc,Cc);
5894
5895 // Add contribution due to multiple scattering
5896 Cc=Q.AddSym(Cc);
5897
5898 r2=xy.Mod2();
5899 //printf("r %f r_old %f \n",sqrt(r2),sqrt(r2_old));
5900 if (r2>r2_old) {
5901 // We've passed the true minimum; backtrack to find the "vertex"
5902 // position
5903 double cosl=cos(atan(Sc(state_tanl)));
5904 double my_ds=0.;
5905 if (fabs((ds+ds_old)*cosl*Sc(state_q_over_pt)*Bz*qBr2p0.003)<0.01){
5906 my_ds=-(xy.X()*cos(Sc(state_phi))+xy.Y()*sin(Sc(state_phi)))
5907 /cosl;
5908 Step(xy,my_ds,Sc,dedx);
5909 // Bail if the transverse momentum has dropped below some minimum
5910 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
5911 if (DEBUG_LEVEL>2)
5912 {
5913 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5913<<" "
<< "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
5914 << endl;
5915 }
5916 return UNRECOVERABLE_ERROR;
5917 }
5918 //printf ("min r %f\n",xy.Mod());
5919 }
5920 else{
5921 if (BrentsAlgorithm(ds,ds_old,dedx,xy,0.,origin,dir,Sc,my_ds)!=NOERROR){
5922 //_DBG_ <<endl;
5923 return UNRECOVERABLE_ERROR;
5924 }
5925 //printf ("Brent min r %f\n",xy.Mod());
5926 }
5927 // Find the field and gradient at (old_x,old_y,old_z)
5928 bfield->GetFieldAndGradient(old_xy.X(),old_xy.Y(),S0(state_z),Bx,By,Bz,
5929 dBxdx,dBxdy,dBxdz,dBydx,
5930 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
5931
5932 // Compute the Jacobian matrix
5933 my_ds-=ds_old;
5934 StepJacobian(old_xy,xy-old_xy,my_ds,S0,dedx,Jc);
5935
5936 // Propagate the covariance matrix
5937 //Cc=Jc*Cc*Jc.Transpose()+(my_ds/ds_old)*Q;
5938 Cc=((my_ds/ds_old)*Q).AddSym(Cc.SandwichMultiply(Jc));
5939
5940 break;
5941 }
5942 r2_old=r2;
5943 ds_old=ds;
5944 }
5945
5946 return NOERROR;
5947}
5948
5949// Propagate track to point of distance of closest approach to origin
5950jerror_t DTrackFitterKalmanSIMD::ExtrapolateToVertex(DVector2 &xy,
5951 DMatrix5x1 &Sc){
5952
5953 // Initialize the beam position = center of target, and the direction
5954 DVector2 origin;
5955 DVector2 dir;
5956
5957 // Position and step variables
5958 double r2=xy.Mod2();
5959 double ds=-mStepSizeS; // step along path in cm
5960 double r2_old=r2;
5961
5962 // Energy loss
5963 double dedx=0.;
5964
5965 // Check direction of propagation
5966 DMatrix5x1 S0;
5967 S0=Sc;
5968 DVector2 xy0=xy;
5969 DVector2 xy1=xy;
5970 Step(xy0,ds,S0,dedx);
5971 r2=xy0.Mod2();
5972 if (r2>r2_old) ds*=-1.;
5973 double ds_old=ds;
5974
5975 // Track propagation loop
5976 while (Sc(state_z)>Z_MIN-100. && Sc(state_z)<Z_MAX370.0
5977 && r2<R2_MAX4225.0){
5978 // get material properties from the Root Geometry
5979 double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.;
5980 double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.;
5981 DVector3 pos3d(xy.X(),xy.Y(),Sc(state_z));
5982 if (geom->FindMatKalman(pos3d,K_rho_Z_over_A,rho_Z_over_A,LnI,
5983 chi2c_factor,chi2a_factor,chi2a_corr,
5984 last_material_map)
5985 !=NOERROR){
5986 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5986<<" "
<< "Material error in ExtrapolateToVertex! " << endl;
5987 break;
5988 }
5989
5990 // Get dEdx for the upcoming step
5991 double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl)));
5992 if (CORRECT_FOR_ELOSS){
5993 dedx=GetdEdx(q_over_p,K_rho_Z_over_A,rho_Z_over_A,LnI);
5994 }
5995 // Adjust the step size
5996 double sign=(ds>0.0)?1.:-1.;
5997 if (fabs(dedx)>EPS3.0e-8){
5998 ds=sign*DE_PER_STEP0.0005/fabs(dedx);
5999 }
6000 if(fabs(ds)>mStepSizeS) ds=sign*mStepSizeS;
6001 if(fabs(ds)<MIN_STEP_SIZE0.1)ds=sign*MIN_STEP_SIZE0.1;
6002
6003 // Propagate the state through the field
6004 Step(xy,ds,Sc,dedx);
6005
6006 r2=xy.Mod2();
6007 //printf("r %f r_old %f \n",r,r_old);
6008 if (r2>r2_old) {
6009 // We've passed the true minimum; backtrack to find the "vertex"
6010 // position
6011 double cosl=cos(atan(Sc(state_tanl)));
6012 double my_ds=0.;
6013 if (fabs((ds+ds_old)*cosl*Sc(state_q_over_pt)*Bz*qBr2p0.003)<0.01){
6014 my_ds=-(xy.X()*cos(Sc(state_phi))+xy.Y()*sin(Sc(state_phi)))
6015 /cosl;
6016 Step(xy,my_ds,Sc,dedx);
6017 //printf ("min r %f\n",pos.Perp());
6018 }
6019 else{
6020 BrentsAlgorithm(ds,ds_old,dedx,xy,0.,origin,dir,Sc,my_ds);
6021 //printf ("Brent min r %f\n",pos.Perp());
6022 }
6023 break;
6024 }
6025 r2_old=r2;
6026 ds_old=ds;
6027 }
6028
6029 return NOERROR;
6030}
6031
6032
6033
6034
6035// Transform the 5x5 tracking error matrix into a 7x7 error matrix in cartesian
6036// coordinates
6037DMatrixDSym DTrackFitterKalmanSIMD::Get7x7ErrorMatrixForward(DMatrixDSym C){
6038 DMatrixDSym C7x7(7);
6039 DMatrix J(7,5);
6040
6041 double p=1./fabs(q_over_p_);
6042 double tanl=1./sqrt(tx_*tx_+ty_*ty_);
6043 double tanl2=tanl*tanl;
6044 double lambda=atan(tanl);
6045 double sinl=sin(lambda);
6046 double sinl3=sinl*sinl*sinl;
6047
6048 J(state_X,state_x)=J(state_Y,state_y)=1.;
6049 J(state_Pz,state_ty)=-p*ty_*sinl3;
6050 J(state_Pz,state_tx)=-p*tx_*sinl3;
6051 J(state_Px,state_ty)=J(state_Py,state_tx)=-p*tx_*ty_*sinl3;
6052 J(state_Px,state_tx)=p*(1.+ty_*ty_)*sinl3;
6053 J(state_Py,state_ty)=p*(1.+tx_*tx_)*sinl3;
6054 J(state_Pz,state_q_over_p)=-p*sinl/q_over_p_;
6055 J(state_Px,state_q_over_p)=tx_*J(state_Pz,state_q_over_p);
6056 J(state_Py,state_q_over_p)=ty_*J(state_Pz,state_q_over_p);
6057 J(state_Z,state_x)=-tx_*tanl2;
6058 J(state_Z,state_y)=-ty_*tanl2;
6059 double diff=tx_*tx_-ty_*ty_;
6060 double frac=tanl2*tanl2;
6061 J(state_Z,state_tx)=(x_*diff+2.*tx_*ty_*y_)*frac;
6062 J(state_Z,state_ty)=(2.*tx_*ty_*x_-y_*diff)*frac;
6063
6064 // C'= JCJ^T
6065 C7x7=C.Similarity(J);
6066
6067 return C7x7;
6068
6069}
6070
6071
6072
6073// Transform the 5x5 tracking error matrix into a 7x7 error matrix in cartesian
6074// coordinates
6075DMatrixDSym DTrackFitterKalmanSIMD::Get7x7ErrorMatrix(DMatrixDSym C){
6076 DMatrixDSym C7x7(7);
6077 DMatrix J(7,5);
6078 //double cosl=cos(atan(tanl_));
6079 double pt=1./fabs(q_over_pt_);
6080 //double p=pt/cosl;
6081 // double p_sq=p*p;
6082 // double E=sqrt(mass2+p_sq);
6083 double pt_sq=1./(q_over_pt_*q_over_pt_);
6084 double cosphi=cos(phi_);
6085 double sinphi=sin(phi_);
6086 double q=(q_over_pt_>0.0)?1.:-1.;
6087
6088 J(state_Px,state_q_over_pt)=-q*pt_sq*cosphi;
6089 J(state_Px,state_phi)=-pt*sinphi;
6090
6091 J(state_Py,state_q_over_pt)=-q*pt_sq*sinphi;
6092 J(state_Py,state_phi)=pt*cosphi;
6093
6094 J(state_Pz,state_q_over_pt)=-q*pt_sq*tanl_;
6095 J(state_Pz,state_tanl)=pt;
6096
6097 J(state_X,state_phi)=-D_*cosphi;
6098 J(state_X,state_D)=-sinphi;
6099
6100 J(state_Y,state_phi)=-D_*sinphi;
6101 J(state_Y,state_D)=cosphi;
6102
6103 J(state_Z,state_z)=1.;
6104
6105 // C'= JCJ^T
6106 C7x7=C.Similarity(J);
6107
6108 return C7x7;
6109}
6110
6111// Track recovery for Central tracks
6112//-----------------------------------
6113// This code attempts to recover tracks that are "broken". Sometimes the fit fails because too many hits were pruned
6114// such that the number of surviving hits is less than the minimum number of degrees of freedom for a five-parameter fit.
6115// This condition is flagged as an INVALID_FIT. It may also be the case that even if we used enough hits for the fit to
6116// be valid (i.e., make sense in terms of the number of degrees of freedom for the number of parameters (5) we are trying
6117// to determine), we throw away a number of hits near the target because the projected trajectory deviates too far away from
6118// the actual hits. This may be an indication of a kink in the trajectory. This condition is flagged as BREAK_POINT_FOUND.
6119// Sometimes the fit may succeed and no break point is found, but the pruning threw out a large number of hits. This
6120// condition is flagged as PRUNED_TOO_MANY_HITS. The recovery code proceeds by truncating the reference trajectory to
6121// to a point just after the hit where a break point was found and all hits are ignored beyond this point subject to a
6122// minimum number of hits set by MIN_HITS_FOR_REFIT. The recovery code always attempts to use the hits closest to the
6123// target. The code is allowed to iterate; with each iteration the trajectory and list of useable hits is further truncated.
6124kalman_error_t DTrackFitterKalmanSIMD::RecoverBrokenTracks(double anneal_factor,
6125 DMatrix5x1 &S,
6126 DMatrix5x5 &C,
6127 const DMatrix5x5 &C0,
6128 DVector2 &xy,
6129 double &chisq,
6130 unsigned int &numdof){
6131 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6131<<" "
<< "Attempting to recover broken track ... " <<endl;
6132
6133 // Initialize degrees of freedom and chi^2
6134 double refit_chisq=MAX_CHI21e16;
6135 unsigned int refit_ndf=0;
6136 // State vector and covariance matrix
6137 DMatrix5x5 C1;
6138 DMatrix5x1 S1;
6139 // Position vector
6140 DVector2 refit_xy;
6141
6142 // save the status of the hits used in the fit
6143 unsigned int num_hits=cdc_updates.size();
6144 vector<int>old_cdc_used_status(num_hits);
6145 for (unsigned int j=0;j<num_hits;j++){
6146 old_cdc_used_status[j]=cdc_updates[j].used_in_fit;
6147 }
6148
6149 // Truncate the reference trajectory to just beyond the break point (or the minimum number of hits)
6150 unsigned int min_cdc_index_for_refit=MIN_HITS_FOR_REFIT-1;
6151 //if (break_point_cdc_index<num_hits/2)
6152 // break_point_cdc_index=num_hits/2;
6153 if (break_point_cdc_index<min_cdc_index_for_refit){
6154 break_point_cdc_index=min_cdc_index_for_refit;
6155 }
6156 // Next determine where we need to truncate the trajectory
6157 DVector2 origin=my_cdchits[break_point_cdc_index]->origin;
6158 DVector2 dir=my_cdchits[break_point_cdc_index]->dir;
6159 double z0=my_cdchits[break_point_cdc_index]->z0wire;
6160 unsigned int k=0;
6161 for (k=central_traj.size()-1;k>1;k--){
6162 double r2=central_traj[k].xy.Mod2();
6163 double r2next=central_traj[k-1].xy.Mod2();
6164 double r2_cdc=(origin+(central_traj[k].S(state_z)-z0)*dir).Mod2();
6165 if (r2next>r2 && r2>r2_cdc) break;
6166 }
6167 break_point_step_index=k;
6168
6169 if (break_point_step_index==central_traj.size()-1){
6170 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6170<<" "
<< "Invalid reference trajectory in track recovery..." << endl;
6171 return FIT_FAILED;
6172 }
6173
6174 kalman_error_t refit_error=FIT_NOT_DONE;
6175 unsigned int old_cdc_index=break_point_cdc_index;
6176 unsigned int old_step_index=break_point_step_index;
6177 unsigned int refit_iter=0;
6178 unsigned int num_cdchits=my_cdchits.size();
6179 while (break_point_cdc_index>4 && break_point_step_index>0
6180 && break_point_step_index<central_traj.size()){
6181 refit_iter++;
6182
6183 // Flag the cdc hits within the radius of the break point cdc index
6184 // as good, the rest as bad.
6185 for (unsigned int j=0;j<=break_point_cdc_index;j++){
6186 if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
6187 }
6188 for (unsigned int j=break_point_cdc_index+1;j<num_cdchits;j++){
6189 my_cdchits[j]->status=bad_hit;
6190 }
6191
6192 // Now refit with the truncated trajectory and list of hits
6193 //C1=4.0*C0;
6194 C1=10.0*C0;
6195 S1=central_traj[break_point_step_index].S;
6196 refit_chisq=MAX_CHI21e16;
6197 refit_ndf=0;
6198 refit_error=KalmanCentral(anneal_factor,S1,C1,refit_xy,
6199 refit_chisq,refit_ndf);
6200
6201 if (refit_error==FIT_SUCCEEDED
6202 || (refit_error==BREAK_POINT_FOUND
6203 && break_point_cdc_index==1
6204 )
6205 //|| refit_error==PRUNED_TOO_MANY_HITS
6206 ){
6207 C=C1;
6208 S=S1;
6209 xy=refit_xy;
6210 chisq=refit_chisq;
6211 numdof=refit_ndf;
6212
6213 return FIT_SUCCEEDED;
6214 }
6215
6216 break_point_cdc_index=old_cdc_index-refit_iter;
6217 break_point_step_index=old_step_index-refit_iter;
6218 }
6219
6220 // If the refit did not work, restore the old list hits used in the fit
6221 // before the track recovery was attempted.
6222 for (unsigned int k=0;k<num_hits;k++){
6223 cdc_updates[k].used_in_fit=old_cdc_used_status[k];
6224 }
6225
6226 return FIT_FAILED;
6227}
6228
6229// Track recovery for forward tracks
6230//-----------------------------------
6231// This code attempts to recover tracks that are "broken". Sometimes the fit fails because too many hits were pruned
6232// such that the number of surviving hits is less than the minimum number of degrees of freedom for a five-parameter fit.
6233// This condition is flagged as an INVALID_FIT. It may also be the case that even if we used enough hits for the fit to
6234// be valid (i.e., make sense in terms of the number of degrees of freedom for the number of parameters (5) we are trying
6235// to determine), we throw away a number of hits near the target because the projected trajectory deviates too far away from
6236// the actual hits. This may be an indication of a kink in the trajectory. This condition is flagged as BREAK_POINT_FOUND.
6237// Sometimes the fit may succeed and no break point is found, but the pruning threw out a large number of hits. This
6238// condition is flagged as PRUNED_TOO_MANY_HITS. The recovery code proceeds by truncating the reference trajectory to
6239// to a point just after the hit where a break point was found and all hits are ignored beyond this point subject to a
6240// minimum number of hits. The recovery code always attempts to use the hits closest to the target. The code is allowed to
6241// iterate; with each iteration the trajectory and list of useable hits is further truncated.
6242kalman_error_t DTrackFitterKalmanSIMD::RecoverBrokenTracks(double anneal_factor,
6243 DMatrix5x1 &S,
6244 DMatrix5x5 &C,
6245 const DMatrix5x5 &C0,
6246 double &chisq,
6247 unsigned int &numdof){
6248 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6248<<" "
<< "Attempting to recover broken track ... " <<endl;
6249
6250 unsigned int num_cdchits=my_cdchits.size();
6251
6252 // Initialize degrees of freedom and chi^2
6253 double refit_chisq=MAX_CHI21e16;
6254 unsigned int refit_ndf=0;
6255 // State vector and covariance matrix
6256 DMatrix5x5 C1;
6257 DMatrix5x1 S1;
6258
6259 // save the status of the hits used in the fit
6260 vector<int>old_cdc_used_status(num_cdchits);
6261 vector<int>old_fdc_used_status(fdc_updates.size());
6262 for (unsigned int j=0;j<fdc_updates.size();j++){
6263 old_fdc_used_status[j]=fdc_updates[j].used_in_fit;
6264 }
6265 for (unsigned int j=0;j<num_cdchits;j++){
6266 old_cdc_used_status[j]=cdc_updates[j].used_in_fit;
6267 }
6268
6269 unsigned int min_cdc_index=MIN_HITS_FOR_REFIT-1;
6270 if (my_fdchits.size()>0){
6271 if (break_point_cdc_index<5){
6272 break_point_cdc_index=0;
6273 min_cdc_index=5;
6274 }
6275 }
6276 /*else{
6277 unsigned int half_num_cdchits=num_cdchits/2;
6278 if (break_point_cdc_index<half_num_cdchits
6279 && half_num_cdchits>min_cdc_index)
6280 break_point_cdc_index=half_num_cdchits;
6281 }
6282 */
6283 if (break_point_cdc_index<min_cdc_index){
6284 break_point_cdc_index=min_cdc_index;
6285 }
6286
6287 // Find the index at which to truncate the reference trajectory
6288 DVector2 origin=my_cdchits[break_point_cdc_index]->origin;
6289 DVector2 dir=my_cdchits[break_point_cdc_index]->dir;
6290 double z0=my_cdchits[break_point_cdc_index]->z0wire;
6291 unsigned int k=forward_traj.size()-1;
6292 for (;k>1;k--){
6293 DMatrix5x1 S1=forward_traj[k].S;
6294 double x1=S1(state_x);
6295 double y1=S1(state_y);
6296 double r2=x1*x1+y1*y1;
6297 DMatrix5x1 S2=forward_traj[k-1].S;
6298 double x2=S2(state_x);
6299 double y2=S2(state_y);
6300 double r2next=x2*x2+y2*y2;
6301 double r2cdc=(origin+(forward_traj[k].z-z0)*dir).Mod2();
6302
6303 if (r2next>r2 && r2>r2cdc) break;
6304 }
6305 break_point_step_index=k;
6306
6307 if (break_point_step_index==forward_traj.size()-1){
6308 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6308<<" "
<< "Invalid reference trajectory in track recovery..." << endl;
6309 return FIT_FAILED;
6310 }
6311
6312 // Attemp to refit the track using the abreviated list of hits and the truncated
6313 // reference trajectory. Iterates if the fit fails.
6314 kalman_error_t refit_error=FIT_NOT_DONE;
6315 unsigned int old_cdc_index=break_point_cdc_index;
6316 unsigned int old_step_index=break_point_step_index;
6317 unsigned int refit_iter=0;
6318 while (break_point_cdc_index>4 && break_point_step_index>0
6319 && break_point_step_index<forward_traj.size()){
6320 refit_iter++;
6321
6322 // Flag the cdc hits within the radius of the break point cdc index
6323 // as good, the rest as bad.
6324 for (unsigned int j=0;j<=break_point_cdc_index;j++){
6325 if (my_cdchits[j]->status!=late_hit) my_cdchits[j]->status=good_hit;
6326 }
6327 for (unsigned int j=break_point_cdc_index+1;j<num_cdchits;j++){
6328 my_cdchits[j]->status=bad_hit;
6329 }
6330
6331 // Re-initialize the state vector, covariance, chisq and number of degrees of freedom
6332 //C1=4.0*C0;
6333 C1=10.0*C0;
6334 S1=forward_traj[break_point_step_index].S;
6335 refit_chisq=MAX_CHI21e16;
6336 refit_ndf=0;
6337 // Now refit with the truncated trajectory and list of hits
6338 refit_error=KalmanForwardCDC(anneal_factor,S1,C1,
6339 refit_chisq,refit_ndf);
6340 if (refit_error==FIT_SUCCEEDED
6341 || (refit_error==BREAK_POINT_FOUND
6342 && break_point_cdc_index==1
6343 )
6344 //|| refit_error==PRUNED_TOO_MANY_HITS
6345 ){
6346 C=C1;
6347 S=S1;
6348 chisq=refit_chisq;
6349 numdof=refit_ndf;
6350 return FIT_SUCCEEDED;
6351 }
6352 break_point_cdc_index=old_cdc_index-refit_iter;
6353 break_point_step_index=old_step_index-refit_iter;
6354 }
6355 // If the refit did not work, restore the old list hits used in the fit
6356 // before the track recovery was attempted.
6357 for (unsigned int k=0;k<num_cdchits;k++){
6358 cdc_updates[k].used_in_fit=old_cdc_used_status[k];
6359 }
6360 for (unsigned int k=0;k<fdc_updates.size();k++){
6361 fdc_updates[k].used_in_fit=old_fdc_used_status[k];
6362 }
6363
6364 return FIT_FAILED;
6365}
6366
6367
6368// Track recovery for forward-going tracks with hits in the FDC
6369kalman_error_t
6370DTrackFitterKalmanSIMD::RecoverBrokenForwardTracks(double fdc_anneal,
6371 double cdc_anneal,
6372 DMatrix5x1 &S,
6373 DMatrix5x5 &C,
6374 const DMatrix5x5 &C0,
6375 double &chisq,
6376 unsigned int &numdof){
6377 if (DEBUG_LEVEL>1)
6378 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6378<<" "
<< "Attempting to recover broken track ... " <<endl;
6379 unsigned int num_cdchits=my_cdchits.size();
6380 unsigned int num_fdchits=fdc_updates.size();
6381
6382 // Initialize degrees of freedom and chi^2
6383 double refit_chisq=MAX_CHI21e16;
6384 unsigned int refit_ndf=0;
6385 // State vector and covariance matrix
6386 DMatrix5x5 C1;
6387 DMatrix5x1 S1;
6388
6389 // save the status of the hits used in the fit
6390 vector<int>old_cdc_used_status(num_cdchits);
6391 vector<int>old_fdc_used_status(num_fdchits);
6392 for (unsigned int j=0;j<num_fdchits;j++){
6393 old_fdc_used_status[j]=fdc_updates[j].used_in_fit;
6394 }
6395 for (unsigned int j=0;j<num_cdchits;j++){
6396 old_cdc_used_status[j]=cdc_updates[j].used_in_fit;
6397 }
6398
6399 // Truncate the trajectory
6400 double zhit=my_fdchits[break_point_fdc_index]->z;
6401 unsigned int k=0;
6402 for (;k<forward_traj.size();k++){
6403 double z=forward_traj[k].z;
6404 if (z<zhit) break;
6405 }
6406 if (k==forward_traj.size()) return FIT_NOT_DONE;
6407
6408 break_point_step_index=k;
6409
6410 // Attemp to refit the track using the abreviated list of hits and the truncated
6411 // reference trajectory.
6412 kalman_error_t refit_error=FIT_NOT_DONE;
6413 int refit_iter=0;
6414 unsigned int break_id=break_point_fdc_index;
6415 while (break_id+num_cdchits>=MIN_HITS_FOR_REFIT && break_id>0
6416 && break_point_step_index<forward_traj.size()
6417 && break_point_step_index>1
6418 && refit_iter<10){
6419 refit_iter++;
6420
6421 // Reset status work for cdc hits
6422 for (unsigned int j=0;j<num_cdchits;j++){
6423 if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
6424 }
6425 // Re-initialize the state vector, covariance, chisq and number of degrees of freedom
6426 //C1=4.0*C0;
6427 C1=10.0*C0;
6428 S1=forward_traj[break_point_step_index].S;
6429 refit_chisq=MAX_CHI21e16;
6430 refit_ndf=0;
6431
6432 // Now refit with the truncated trajectory and list of hits
6433 refit_error=KalmanForward(fdc_anneal,cdc_anneal,S1,C1,refit_chisq,refit_ndf);
6434 if (refit_error==FIT_SUCCEEDED
6435 //|| (refit_error==PRUNED_TOO_MANY_HITS)
6436 ){
6437 C=C1;
6438 S=S1;
6439 chisq=refit_chisq;
6440 numdof=refit_ndf;
6441
6442 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6442<<" "
<< "Refit succeeded" << endl;
6443 return FIT_SUCCEEDED;
6444 }
6445 // Truncate the trajectory
6446 if (break_id>0) break_id--;
6447 else break;
6448 zhit=my_fdchits[break_id]->z;
6449 k=0;
6450 for (;k<forward_traj.size();k++){
6451 double z=forward_traj[k].z;
6452 if (z<zhit) break;
6453 }
6454 break_point_step_index=k;
6455
6456 }
6457
6458 // If the refit did not work, restore the old list hits used in the fit
6459 // before the track recovery was attempted.
6460 for (unsigned int k=0;k<num_cdchits;k++){
6461 cdc_updates[k].used_in_fit=old_cdc_used_status[k];
6462 }
6463 for (unsigned int k=0;k<num_fdchits;k++){
6464 fdc_updates[k].used_in_fit=old_fdc_used_status[k];
6465 }
6466
6467 return FIT_FAILED;
6468}
6469
6470
6471
6472// Routine to fit hits in the FDC and the CDC using the forward parametrization
6473kalman_error_t DTrackFitterKalmanSIMD::ForwardFit(const DMatrix5x1 &S0,const DMatrix5x5 &C0){
6474 unsigned int num_cdchits=my_cdchits.size();
6475 unsigned int num_fdchits=my_fdchits.size();
6476 unsigned int max_fdc_index=num_fdchits-1;
6477
6478 // Vectors to keep track of updated state vectors and covariance matrices (after
6479 // adding the hit information)
6480 vector<DKalmanUpdate_t>last_cdc_updates;
6481 vector<DKalmanUpdate_t>last_fdc_updates;
6482
6483 // Charge
6484 // double q=input_params.charge();
6485
6486 // Covariance matrix and state vector
6487 DMatrix5x5 C;
6488 DMatrix5x1 S=S0;
6489
6490 // Create matrices to store results from previous iteration
6491 DMatrix5x1 Slast(S);
6492 DMatrix5x5 Clast(C0);
6493 // last z position
6494 double last_z=z_;
6495
6496 double fdc_anneal=FORWARD_ANNEAL_SCALE+1.; // variable for scaling cut for hit pruning
6497 double my_fdc_anneal_const=FORWARD_ANNEAL_POW_CONST;
6498 // if (fit_type==kTimeBased && fabs(1./S(state_q_over_p))<1.0
6499 // && my_anneal_const>=2.0) my_anneal_const*=0.5;
6500 double cdc_anneal=(fit_type==kTimeBased?ANNEAL_SCALE+1.:2.); // variable for scaling cut for hit pruning
6501 double my_cdc_anneal_const=ANNEAL_POW_CONST;
6502
6503
6504 // Chi-squared and degrees of freedom
6505 double chisq=MAX_CHI21e16,chisq_forward=MAX_CHI21e16;
6506 unsigned int my_ndf=0;
6507 unsigned int last_ndf=1;
6508
6509 // Iterate over reference trajectories
6510 for (int iter=0;
6511 iter<(fit_type==kTimeBased?MAX_TB_PASSES20:MAX_WB_PASSES20);
6512 iter++) {
6513 // These variables provide the approximate location along the trajectory
6514 // where there is an indication of a kink in the track
6515 break_point_fdc_index=max_fdc_index;
6516 break_point_cdc_index=0;
6517 break_point_step_index=0;
6518
6519 // Reset material map index
6520 last_material_map=0;
6521
6522 // Abort if momentum is too low
6523 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX100.) break;
6524
6525 // Initialize path length variable and flight time
6526 len=0;
6527 ftime=0.;
6528 var_ftime=0.;
6529
6530 // Scale cut for pruning hits according to the iteration number
6531 if (fit_type==kTimeBased)
6532 {
6533 fdc_anneal=FORWARD_ANNEAL_SCALE/pow(my_fdc_anneal_const,iter)+1.;
6534 cdc_anneal=ANNEAL_SCALE/pow(my_cdc_anneal_const,iter)+1.;
6535 }
6536
6537 // Swim once through the field out to the most upstream FDC hit
6538 jerror_t ref_track_error=SetReferenceTrajectory(S);
6539 if (ref_track_error==NOERROR && forward_traj.size()> 1){
6540 // Reset the status of the cdc hits
6541 for (unsigned int j=0;j<num_cdchits;j++){
6542 if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
6543 }
6544
6545 // perform the kalman filter
6546 C=C0;
6547 kalman_error_t error=KalmanForward(fdc_anneal,cdc_anneal,S,C,chisq,my_ndf);
6548
6549 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6549<<" "
<< "Iter: " << iter+1 << " Chi2=" << chisq << " Ndf=" << my_ndf << " Error code: " << error << endl;
6550
6551 // Try to recover tracks that failed the first attempt at fitting
6552 if (error!=FIT_SUCCEEDED && RECOVER_BROKEN_TRACKS
6553 && num_fdchits>2 // some minimum to make this worthwhile...
6554 && break_point_fdc_index+num_cdchits>=MIN_HITS_FOR_REFIT
6555 && forward_traj.size()>2*MIN_HITS_FOR_REFIT // avoid small track stubs
6556 ){
6557 DMatrix5x5 Ctemp=C;
6558 DMatrix5x1 Stemp=S;
6559 unsigned int temp_ndf=my_ndf;
6560 double temp_chi2=chisq;
6561 double x=x_,y=y_,z=z_;
6562
6563 kalman_error_t refit_error=RecoverBrokenForwardTracks(fdc_anneal,
6564 cdc_anneal,
6565 S,C,C0,chisq,
6566 my_ndf);
6567 if (refit_error!=FIT_SUCCEEDED){
6568 if (error==PRUNED_TOO_MANY_HITS || error==BREAK_POINT_FOUND){
6569 C=Ctemp;
6570 S=Stemp;
6571 my_ndf=temp_ndf;
6572 chisq=temp_chi2;
6573 x_=x,y_=y,z_=z;
6574
6575 if (num_cdchits<6) error=FIT_SUCCEEDED;
6576 }
6577 else error=FIT_FAILED;
6578 }
6579 else error=FIT_SUCCEEDED;
6580 }
6581 if (error==FIT_FAILED || error==INVALID_FIT){
6582 if (iter==0) return FIT_FAILED; // first iteration failed
6583 break;
6584 }
6585 if (my_ndf==0) break;
6586
6587 // Check the charge relative to the hypothesis for protons
6588 /*
6589 if (MASS>0.9){
6590 double my_q=S(state_q_over_p)>0?1.:-1.;
6591 if (q!=my_q){
6592 if (DEBUG_LEVEL>0)
6593 _DBG_ << "Sign change in fit for protons" <<endl;
6594 S(state_q_over_p)=fabs(S(state_q_over_p));
6595 }
6596 }
6597 */
6598 // Break out of loop if the chisq is increasing or not changing much
6599 if (my_ndf==last_ndf
6600 && (chisq>chisq_forward ||fabs(chisq-chisq_forward)<0.1) ) break;
6601 //if (TMath::Prob(chisq,my_ndf)<TMath::Prob(chisq_forward,last_ndf)) break;
6602
6603 chisq_forward=chisq;
6604 last_ndf=my_ndf;
6605 Slast=S;
6606 Clast=C;
6607 last_z=z_;
6608
6609 if (fdc_updates.size()>0){
6610 last_fdc_updates.assign(fdc_updates.begin(),fdc_updates.end());
6611 }
6612 if (cdc_updates.size()>0){
6613 last_cdc_updates.assign(cdc_updates.begin(),cdc_updates.end());
6614 }
6615 } //iteration
6616 else{
6617 if (iter==0) return FIT_FAILED;
6618 }
6619 }
6620
6621 // total chisq and ndf
6622 chisq_=chisq_forward;
6623 ndf_=last_ndf;
6624
6625 // Source for t0 guess
6626 mT0Detector=SYS_CDC;
6627
6628 // Fill pull vector using smoothed filter results
6629 pulls.clear();
6630 if (fit_type==kTimeBased){
6631 SmoothForward();
6632 }
6633 // output lists of hits used in the fit and fill pull vector
6634 cdchits_used_in_fit.clear();
6635 for (unsigned int m=0;m<last_cdc_updates.size();m++){
6636 if (last_cdc_updates[m].used_in_fit){
6637 cdchits_used_in_fit.push_back(my_cdchits[m]->hit);
6638 }
6639 }
6640 fdchits_used_in_fit.clear();
6641 for (unsigned int m=0;m<last_fdc_updates.size();m++){
6642 if (last_fdc_updates[m].used_in_fit){
6643 fdchits_used_in_fit.push_back(my_fdchits[m]->hit);
6644 }
6645 }
6646
6647 // Extrapolate to the point of closest approach to the beam line
6648 z_=last_z;
6649 if (sqrt(Slast(state_x)*Slast(state_x)+Slast(state_y)*Slast(state_y))
6650 >EPS21.e-4){
6651 DMatrix5x5 Ctemp=Clast;
6652 DMatrix5x1 Stemp=Slast;
6653 double ztemp=z_;
6654 if (ExtrapolateToVertex(Stemp,Ctemp)==NOERROR){
6655 Clast=Ctemp;
6656 Slast=Stemp;
6657 }
6658 else{
6659 //_DBG_ << endl;
6660 z_=ztemp;
6661 }
6662 }
6663
6664 // Convert from forward rep. to central rep.
6665 DMatrix5x1 Sc;
6666 DMatrix5x5 Cc;
6667 ConvertStateVectorAndCovariance(z_,Slast,Sc,Clast,Cc);
6668
6669 // Track Parameters at "vertex"
6670 phi_=Sc(state_phi);
6671 q_over_pt_=Sc(state_q_over_pt);
6672 tanl_=Sc(state_tanl);
6673 D_=Sc(state_D);
6674
6675 // Covariance matrix
6676 vector<double>dummy;
6677 if (FORWARD_PARMS_COV==true){
6678 for (unsigned int i=0;i<5;i++){
6679 dummy.clear();
6680 for(unsigned int j=0;j<5;j++){
6681 dummy.push_back(Clast(i,j));
6682 }
6683 fcov.push_back(dummy);
6684 }
6685 }
6686 // Central parametrization
6687 for (unsigned int i=0;i<5;i++){
6688 dummy.clear();
6689 for(unsigned int j=0;j<5;j++){
6690 dummy.push_back(Cc(i,j));
6691 }
6692 cov.push_back(dummy);
6693 }
6694
6695
6696 return FIT_SUCCEEDED;
6697}
6698
6699// Routine to fit hits in the CDC using the forward parametrization
6700kalman_error_t DTrackFitterKalmanSIMD::ForwardCDCFit(const DMatrix5x1 &S0,const DMatrix5x5 &C0){
6701 unsigned int num_cdchits=my_cdchits.size();
6702 unsigned int max_cdc_index=num_cdchits-1;
6703 unsigned int min_cdc_index_for_refit=MIN_HITS_FOR_REFIT-1;
6704
6705 // Charge
6706 // double q=input_params.charge();
6707
6708 // Covariance matrix and state vector
6709 DMatrix5x5 C;
6710 DMatrix5x1 S=S0;
6711
6712 // Create matrices to store results from previous iteration
6713 DMatrix5x1 Slast(S);
6714 DMatrix5x5 Clast(C0);
6715
6716 // Vectors to keep track of updated state vectors and covariance matrices (after
6717 // adding the hit information)
6718 vector<DKalmanUpdate_t>last_cdc_updates;
6719 vector<DKalmanUpdate_t>last_fdc_updates;
6720
6721 double anneal_scale=ANNEAL_SCALE; // variable for scaling cut for hit pruning
6722 double my_anneal_const=ANNEAL_POW_CONST;
6723 /*
6724 double tsquare=S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty);
6725 double tanl=1./sqrt(tsquare);
6726 if (tanl>2.5){
6727 anneal_scale=FORWARD_ANNEAL_SCALE;
6728 my_anneal_const=FORWARD_ANNEAL_POW_CONST;
6729 }
6730 */
6731 double anneal_factor=anneal_scale+1.;
6732 /*
6733 if (fit_type==kTimeBased && fabs(1./S(state_q_over_p))<1.0
6734 && my_anneal_const>=2.0){
6735 my_anneal_const*=0.5;
6736 }
6737 */
6738 // Chi-squared and degrees of freedom
6739 double chisq=MAX_CHI21e16,chisq_forward=MAX_CHI21e16;
6740 unsigned int my_ndf=0;
6741 unsigned int last_ndf=1;
6742 // last z position
6743 double zlast=0.;
6744 // unsigned int last_break_point_index=0,last_break_point_step_index=0;
6745
6746 // Iterate over reference trajectories
6747 for (int iter2=0;
6748 iter2<(fit_type==kTimeBased?MAX_TB_PASSES20:MAX_WB_PASSES20);
6749 iter2++){
6750 if (DEBUG_LEVEL>1){
6751 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6751<<" "
<<"-------- iteration " << iter2+1 << " -----------" <<endl;
6752 }
6753
6754 // These variables provide the approximate location along the trajectory
6755 // where there is an indication of a kink in the track
6756 break_point_cdc_index=max_cdc_index;
6757 break_point_step_index=0;
6758
6759 // Reset material map index
6760 last_material_map=0;
6761
6762 // Abort if momentum is too low
6763 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX100.){
6764 //printf("Too low momentum? %f\n",1/S(state_q_over_p));
6765 break;
6766 }
6767
6768 // Scale cut for pruning hits according to the iteration number
6769 if (fit_type==kTimeBased)
6770 {
6771 anneal_factor=anneal_scale/pow(my_anneal_const,iter2)+1.;
6772 }
6773
6774 // Initialize path length variable and flight time
6775 len=0;
6776 ftime=0.;
6777 var_ftime=0.;
6778
6779 // Swim to create the reference trajectory
6780 jerror_t ref_track_error=SetCDCForwardReferenceTrajectory(S);
6781 if (ref_track_error==NOERROR && forward_traj.size()> 1){
6782 // Reset the status of the cdc hits
6783 for (unsigned int j=0;j<num_cdchits;j++){
6784 if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
6785 }
6786
6787 // perform the filter
6788 C=C0;
6789 kalman_error_t error=KalmanForwardCDC(anneal_factor,S,C,chisq,my_ndf);
6790
6791 // Try to recover tracks that failed the first attempt at fitting
6792 if (error!=FIT_SUCCEEDED && RECOVER_BROKEN_TRACKS
6793 && num_cdchits>=MIN_HITS_FOR_REFIT){
6794 DMatrix5x5 Ctemp=C;
6795 DMatrix5x1 Stemp=S;
6796 unsigned int temp_ndf=my_ndf;
6797 double temp_chi2=chisq;
6798 double x=x_,y=y_,z=z_;
6799
6800 if (error==MOMENTUM_OUT_OF_RANGE){
6801 // _DBG_ << "Momentum out of range" <<endl;
6802 unsigned int new_index=(3*max_cdc_index)/4;
6803 break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
6804 }
6805
6806 if (error==BROKEN_COVARIANCE_MATRIX){
6807 break_point_cdc_index=min_cdc_index_for_refit;
6808 //_DBG_ << "Bad Cov" <<endl;
6809 }
6810 if (error==POSITION_OUT_OF_RANGE){
6811 //_DBG_ << "Bad position" << endl;
6812 unsigned int new_index=(max_cdc_index)/2;
6813 break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
6814 }
6815 if (error==PRUNED_TOO_MANY_HITS){
6816 //_DBG_ << "Prune" << endl;
6817 unsigned int new_index=(3*max_cdc_index)/4;
6818 break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
6819 // anneal_factor*=10.;
6820 }
6821
6822 kalman_error_t refit_error=RecoverBrokenTracks(anneal_factor,S,C,C0,chisq,my_ndf);
6823
6824 if (refit_error!=FIT_SUCCEEDED){
6825 if (error==PRUNED_TOO_MANY_HITS || error==BREAK_POINT_FOUND){
6826 C=Ctemp;
6827 S=Stemp;
6828 my_ndf=temp_ndf;
6829 chisq=temp_chi2;
6830 x_=x,y_=y,z_=z;
6831
6832 error=FIT_SUCCEEDED;
6833 }
6834 else error=FIT_FAILED;
6835 }
6836 else error=FIT_SUCCEEDED;
6837 }
6838 if (error==FIT_FAILED || error==INVALID_FIT){
6839 if (iter2==0) return error;
6840 break;
6841 }
6842 if (my_ndf==0) break;
6843
6844 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6844<<" "
<< "--> Chisq " << chisq << " NDF "
6845 << my_ndf
6846 << " Prob: " << TMath::Prob(chisq,my_ndf)
6847 << endl;
6848 // Check the charge relative to the hypothesis for protons
6849 /*
6850 if (MASS>0.9){
6851 double my_q=S(state_q_over_p)>0?1.:-1.;
6852 if (q!=my_q){
6853 if (DEBUG_LEVEL>0)
6854 _DBG_ << "Sign change in fit for protons" <<endl;
6855 S(state_q_over_p)=fabs(S(state_q_over_p));
6856 }
6857 }
6858 */
6859 if (my_ndf==last_ndf
6860 && (chisq>chisq_forward || fabs(chisq-chisq_forward)<0.1) ) break;
6861 //if (TMath::Prob(chisq,my_ndf)<TMath::Prob(chisq_forward,last_ndf)) break;
6862
6863 chisq_forward=chisq;
6864 Slast=S;
6865 Clast=C;
6866 last_ndf=my_ndf;
6867 zlast=z_;
6868
6869 last_cdc_updates.assign(cdc_updates.begin(),cdc_updates.end());
6870
6871 } //iteration
6872 else{
6873 if (iter2==0) return FIT_FAILED;
6874 break;
6875 }
6876 }
6877
6878 // total chisq and ndf
6879 chisq_=chisq_forward;
6880 ndf_=last_ndf;
6881
6882 // source for t0 guess
6883 mT0Detector=SYS_CDC;
6884
6885 // Run smoother and fill pulls vector
6886 pulls.clear();
6887 if (fit_type==kTimeBased){
6888 SmoothForwardCDC();
6889 }
6890
6891 // output lists of hits used in the fit and fill the pull vector
6892 cdchits_used_in_fit.clear();
6893 for (unsigned int m=0;m<last_cdc_updates.size();m++){
6894 if (last_cdc_updates[m].used_in_fit){
6895 cdchits_used_in_fit.push_back(my_cdchits[m]->hit);
6896 }
6897 }
6898
6899 // Extrapolate to the point of closest approach to the beam line
6900 z_=zlast;
6901 if (sqrt(Slast(state_x)*Slast(state_x)+Slast(state_y)*Slast(state_y))
6902 >EPS21.e-4)
6903 if (ExtrapolateToVertex(Slast,Clast)!=NOERROR) return EXTRAPOLATION_FAILED;
6904
6905 // Convert from forward rep. to central rep.
6906 DMatrix5x1 Sc;
6907 DMatrix5x5 Cc;
6908 ConvertStateVectorAndCovariance(z_,Slast,Sc,Clast,Cc);
6909
6910 // Track Parameters at "vertex"
6911 phi_=Sc(state_phi);
6912 q_over_pt_=Sc(state_q_over_pt);
6913 tanl_=Sc(state_tanl);
6914 D_=Sc(state_D);
6915
6916 // Covariance matrix
6917 vector<double>dummy;
6918 // ... forward parameterization
6919 if (FORWARD_PARMS_COV==true){
6920 for (unsigned int i=0;i<5;i++){
6921 dummy.clear();
6922 for(unsigned int j=0;j<5;j++){
6923 dummy.push_back(Clast(i,j));
6924 }
6925 fcov.push_back(dummy);
6926 }
6927 }
6928 // Central parametrization
6929 for (unsigned int i=0;i<5;i++){
6930 dummy.clear();
6931 for(unsigned int j=0;j<5;j++){
6932 dummy.push_back(Cc(i,j));
6933 }
6934 cov.push_back(dummy);
6935 }
6936
6937
6938 return FIT_SUCCEEDED;
6939}
6940
6941// Routine to fit hits in the CDC using the central parametrization
6942kalman_error_t DTrackFitterKalmanSIMD::CentralFit(const DVector2 &startpos,
6943 const DMatrix5x1 &S0,
6944 const DMatrix5x5 &C0){
6945 // Initial position in x and y
6946 DVector2 pos(startpos);
6947
6948 // Charge
6949 // double q=input_params.charge();
6950
6951 // Covariance matrix and state vector
6952 DMatrix5x5 Cc;
6953 DMatrix5x1 Sc=S0;
6954
6955 // Variables to store values from previous iterations
6956 DMatrix5x1 Sclast(Sc);
6957 DMatrix5x5 Cclast(C0);
6958 DVector2 last_pos=pos;
6959
6960 unsigned int num_cdchits=my_cdchits.size();
6961 unsigned int max_cdc_index=num_cdchits-1;
6962 unsigned int min_cdc_index_for_refit=MIN_HITS_FOR_REFIT-1;
6963
6964 // Vectors to keep track of updated state vectors and covariance matrices (after
6965 // adding the hit information)
6966 vector<DKalmanUpdate_t>last_cdc_updates;
6967
6968 double anneal_factor=ANNEAL_SCALE+1.; // variable for scaling cut for hit pruning
6969 double my_anneal_const=ANNEAL_POW_CONST;
6970 //if (fit_type==kTimeBased && fabs(1./Sc(state_q_over_p))<1.0) my_anneal_const*=0.5;
6971
6972 //Initialization of chisq, ndf, and error status
6973 double chisq_iter=MAX_CHI21e16,chisq=MAX_CHI21e16;
6974 unsigned int my_ndf=0;
6975 ndf_=0.;
6976 unsigned int last_ndf=1;
6977 kalman_error_t error=FIT_NOT_DONE;
6978
6979 // Iterate over reference trajectories
6980 int iter2=0;
6981 for (;iter2<(fit_type==kTimeBased?MAX_TB_PASSES20:MAX_WB_PASSES20);
6982 iter2++){
6983 if (DEBUG_LEVEL>1){
6984 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6984<<" "
<<"-------- iteration " << iter2+1 << " -----------" <<endl;
6985 }
6986
6987 // These variables provide the approximate location along the trajectory
6988 // where there is an indication of a kink in the track
6989 break_point_cdc_index=max_cdc_index;
6990 break_point_step_index=0;
6991
6992 // Reset material map index
6993 last_material_map=0;
6994
6995 // Break out of loop if p is too small
6996 double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl)));
6997 if (fabs(q_over_p)>Q_OVER_P_MAX100.) break;
6998
6999 // Initialize path length variable and flight time
7000 len=0.;
7001 ftime=0.;
7002 var_ftime=0.;
7003
7004 // Scale cut for pruning hits according to the iteration number
7005 if (fit_type==kTimeBased)
7006 {
7007 anneal_factor=ANNEAL_SCALE/pow(my_anneal_const,iter2)+1.;
7008 }
7009
7010 // Initialize trajectory deque
7011 jerror_t ref_track_error=SetCDCReferenceTrajectory(last_pos,Sc);
7012 if (ref_track_error==NOERROR && central_traj.size()>1){
7013 // Reset the status of the cdc hits
7014 for (unsigned int j=0;j<num_cdchits;j++){
7015 if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
7016 }
7017
7018 // perform the fit
7019 Cc=C0;
7020 error=KalmanCentral(anneal_factor,Sc,Cc,pos,chisq,my_ndf);
7021 // Try to recover tracks that failed the first attempt at fitting
7022 if (error!=FIT_SUCCEEDED && RECOVER_BROKEN_TRACKS
7023 && num_cdchits>=MIN_HITS_FOR_REFIT){
7024 DVector2 temp_pos=pos;
7025 DMatrix5x1 Stemp=Sc;
7026 DMatrix5x5 Ctemp=Cc;
7027 unsigned int temp_ndf=my_ndf;
7028 double temp_chi2=chisq;
7029
7030 if (error==MOMENTUM_OUT_OF_RANGE){
7031 //_DBG_ << "Momentum out of range" <<endl;
7032 unsigned int new_index=(3*max_cdc_index)/4;
7033 break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
7034 }
7035
7036 if (error==BROKEN_COVARIANCE_MATRIX){
7037 break_point_cdc_index=min_cdc_index_for_refit;
7038 //_DBG_ << "Bad Cov" <<endl;
7039 }
7040 if (error==POSITION_OUT_OF_RANGE){
7041 //_DBG_ << "Bad position" << endl;
7042 unsigned int new_index=(max_cdc_index)/2;
7043 break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
7044 }
7045 if (error==PRUNED_TOO_MANY_HITS){
7046 unsigned int new_index=(3*max_cdc_index)/4;
7047 break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
7048 //anneal_factor*=10.;
7049 //_DBG_ << "Prune" << endl;
7050 }
7051
7052
7053 kalman_error_t refit_error=RecoverBrokenTracks(anneal_factor,Sc,Cc,C0,pos,chisq,my_ndf);
7054 if (refit_error!=FIT_SUCCEEDED){
7055 if (error==PRUNED_TOO_MANY_HITS || error==BREAK_POINT_FOUND){
7056 Cc=Ctemp;
7057 Sc=Stemp;
7058 my_ndf=temp_ndf;
7059 chisq=temp_chi2;
7060 pos=temp_pos;
7061
7062 error=FIT_SUCCEEDED;
7063 }
7064 else error=FIT_FAILED;
7065 }
7066 else error=FIT_SUCCEEDED;
7067 }
7068 if (error==FIT_FAILED || error==INVALID_FIT){
7069 if (iter2==0) return error;
7070 break;
7071 }
7072 if (my_ndf==0) break;
7073
7074
7075 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7075<<" "
<< "--> Chisq " << chisq << " Ndof " << my_ndf
7076 << " Prob: " << TMath::Prob(chisq,my_ndf)
7077 << endl;
7078 // Check the charge relative to the hypothesis for protons
7079 /*
7080 if (MASS>0.9){
7081 double my_q=Sc(state_q_over_pt)>0?1.:-1.;
7082 if (q!=my_q){
7083 if (DEBUG_LEVEL>0)
7084 _DBG_ << "Sign change in fit for protons" <<endl;
7085 Sc(state_q_over_pt)=fabs(Sc(state_q_over_pt));
7086 }
7087 }
7088 */
7089 if (my_ndf==last_ndf
7090 && (chisq>chisq_iter || fabs(chisq_iter-chisq)<0.1)) break;
7091 //if (TMath::Prob(chisq,my_ndf)<TMath::Prob(chisq_iter,last_ndf)) break;
7092
7093 // Save the current state vector and covariance matrix
7094 Cclast=Cc;
7095 Sclast=Sc;
7096 last_pos=pos;
7097 chisq_iter=chisq;
7098 last_ndf=my_ndf;
7099
7100 last_cdc_updates.assign(cdc_updates.begin(),cdc_updates.end());
7101 }
7102 else{
7103 if (iter2==0) return FIT_FAILED;
7104 break;
7105 }
7106 }
7107
7108 if (last_pos.Mod()>EPS21.e-4){
7109 if (ExtrapolateToVertex(last_pos,Sclast,Cclast)!=NOERROR) return EXTRAPOLATION_FAILED;
7110 }
7111
7112 // source for t0 guess
7113 mT0Detector=SYS_CDC;
7114
7115 // Run smoother and fill pulls vector
7116 pulls.clear();
7117 if (fit_type==kTimeBased){
7118 SmoothCentral();
7119 }
7120
7121 // output lists of hits used in the fit
7122 cdchits_used_in_fit.clear();
7123 for (unsigned int m=0;m<last_cdc_updates.size();m++){
7124 if (last_cdc_updates[m].used_in_fit){
7125 cdchits_used_in_fit.push_back(my_cdchits[m]->hit);
7126 }
7127 }
7128
7129 // Rotate covariance matrix from a coordinate system whose origin is on the track to the global coordinate system
7130 double B=sqrt(Bx*Bx+By*By+Bz*Bz);
7131 double qrc_old=1./(qBr2p0.003*B*Sclast(state_q_over_pt));
7132 double qrc_plus_D=Sclast(state_D)+qrc_old;
7133 double q=(qrc_old>0.0)?1.:-1.;
7134 double dx=-last_pos.X();
7135 double dy=-last_pos.Y();
7136 double d2=dx*dx+dy*dy;
7137 double sinphi=sin(Sclast(state_phi));
7138 double cosphi=cos(Sclast(state_phi));
7139 double dx_sinphi_minus_dy_cosphi=dx*sinphi-dy*cosphi;
7140 double rc=sqrt(d2
7141 +2.*qrc_plus_D*(dx_sinphi_minus_dy_cosphi)
7142 +qrc_plus_D*qrc_plus_D);
7143
7144 DMatrix5x5 Jc=I5x5;
7145 Jc(state_D,state_D)=q*(dx_sinphi_minus_dy_cosphi+qrc_plus_D)/rc;
7146 Jc(state_D,state_q_over_pt)=qrc_old*(Jc(state_D,state_D)-1.)/Sclast(state_q_over_pt);
7147 Jc(state_D,state_phi)=q*qrc_plus_D*(dx*cosphi+dy*sinphi)/rc;
7148
7149 Cclast=Cclast.SandwichMultiply(Jc);
7150
7151 // Track Parameters at "vertex"
7152 phi_=Sclast(state_phi);
7153 q_over_pt_=Sclast(state_q_over_pt);
7154 tanl_=Sclast(state_tanl);
7155 x_=last_pos.X();
7156 y_=last_pos.Y();
7157 z_=Sclast(state_z);
7158 D_=sqrt(d2);
7159 if ((x_>0.0 && sinphi>0.0) || (y_ <0.0 && cosphi>0.0) || (y_>0.0 && cosphi<0.0)
7160 || (x_<0.0 && sinphi<0.0)) D_*=-1.;
7161
7162 if (!isfinite(x_) || !isfinite(y_) || !isfinite(z_) || !isfinite(phi_)
7163 || !isfinite(q_over_pt_) || !isfinite(tanl_)){
7164 if (DEBUG_LEVEL>0){
7165 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7165<<" "
<< "At least one parameter is NaN or +-inf!!" <<endl;
7166 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7166<<" "
<< "x " << x_ << " y " << y_ << " z " << z_ << " phi " << phi_
7167 << " q/pt " << q_over_pt_ << " tanl " << tanl_ << endl;
7168 }
7169 return INVALID_FIT;
7170 }
7171
7172 // Covariance matrix at vertex
7173 fcov.clear();
7174 vector<double>dummy;
7175 for (unsigned int i=0;i<5;i++){
7176 dummy.clear();
7177 for(unsigned int j=0;j<5;j++){
7178 dummy.push_back(Cclast(i,j));
7179 }
7180 cov.push_back(dummy);
7181 }
7182
7183 // total chisq and ndf
7184 chisq_=chisq_iter;
7185 ndf_=last_ndf;
7186 //printf("NDof %d\n",ndf);
7187
7188 return FIT_SUCCEEDED;
7189}
7190
7191// Smoothing algorithm for the forward trajectory. Updates the state vector
7192// at each step (going in the reverse direction to the filter) based on the
7193// information from all the steps and outputs the state vector at the
7194// outermost step.
7195jerror_t DTrackFitterKalmanSIMD::SmoothForward(void){
7196 if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE;
7197
7198 unsigned int max=forward_traj.size()-1;
7199 DMatrix5x1 S=(forward_traj[max].Skk);
7200 DMatrix5x5 C=(forward_traj[max].Ckk);
7201 DMatrix5x5 JT=(forward_traj[max].JT);
7202 DMatrix5x1 Ss=S;
7203 DMatrix5x5 Cs=C;
7204 DMatrix5x5 A;
7205
7206 for (unsigned int m=max-1;m>0;m--){
7207 if (forward_traj[m].h_id>0){
7208 if (forward_traj[m].h_id<1000){
7209 unsigned int id=forward_traj[m].h_id-1;
7210 A=fdc_updates[id].C*JT*C.InvertSym();
7211 Ss=fdc_updates[id].S+A*(Ss-S);
7212 Cs=fdc_updates[id].C+A*(Cs-C)*A.Transpose();
7213
7214 }
7215 else{
7216 unsigned int id=forward_traj[m].h_id-1000;
7217 A=cdc_updates[id].C*JT*C.InvertSym();
7218 Ss=cdc_updates[id].S+A*(Ss-S);
7219 if ((!isfinite(Ss(0)))|| (!isfinite(Ss(1)))
7220 || (!isfinite(Ss(2))) || (!isfinite(Ss(3)))
7221 || (!isfinite(Ss(4)))
7222 ){
7223 if (DEBUG_LEVEL>5)
7224 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7224<<" "
<< "Invalid values for smoothed parameters..." << endl;
7225 return VALUE_OUT_OF_RANGE;
7226 }
7227 Cs=cdc_updates[id].C+A*(Cs-C)*A.Transpose();
7228
7229
7230 // Fill in pulls information for cdc hits
7231 FillPullsVectorEntry(Ss,Cs,forward_traj[m],my_cdchits[id],
7232 cdc_updates[id]);
7233 }
7234 }
7235 else{
7236 A=forward_traj[m].Ckk*JT*C.InvertSym();
7237 Ss=forward_traj[m].Skk+A*(Ss-S);
7238 Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose();
7239 }
7240
7241 S=forward_traj[m].Skk;
7242 C=forward_traj[m].Ckk;
7243 JT=forward_traj[m].JT;
7244 }
7245 A=forward_traj[0].Ckk*JT*C.InvertSym();
7246 Ss=forward_traj[0].Skk+A*(Ss-S);
7247 Cs=forward_traj[0].Ckk+A*(Cs-C)*A.Transpose();
7248
7249 return NOERROR;
7250}
7251
7252// Smoothing algorithm for the central trajectory. Updates the state vector
7253// at each step (going in the reverse direction to the filter) based on the
7254// information from all the steps.
7255jerror_t DTrackFitterKalmanSIMD::SmoothCentral(void){
7256 if (central_traj.size()<2) return RESOURCE_UNAVAILABLE;
7257
7258 unsigned int max=central_traj.size()-1;
7259 DMatrix5x1 S=(central_traj[max].Skk);
7260 DMatrix5x5 C=(central_traj[max].Ckk);
7261 DMatrix5x5 JT=(central_traj[max].JT);
7262 DMatrix5x1 Ss=S;
7263 DMatrix5x5 Cs=C;
7264 DMatrix5x5 A,AT,dC;
7265
7266 for (unsigned int m=max-1;m>0;m--){
7267 if (central_traj[m].h_id>0){
7268 unsigned int id=central_traj[m].h_id-1;
7269 A=cdc_updates[id].C*JT*C.InvertSym();
7270 AT=A.Transpose();
7271 Ss=cdc_updates[id].S+A*(Ss-S);
7272 if ((!isfinite(Ss(0)))|| (!isfinite(Ss(1)))
7273 || (!isfinite(Ss(2))) || (!isfinite(Ss(3)))
7274 || (!isfinite(Ss(4)))
7275 ){
7276 if (DEBUG_LEVEL>5)
7277 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7277<<" "
<< "Invalid values for smoothed parameters..." << endl;
7278 return VALUE_OUT_OF_RANGE;
7279 }
7280
7281 dC=Cs-C;
7282 Cs=cdc_updates[id].C+dC.SandwichMultiply(AT);
7283
7284 // Get estimate for energy loss
7285 double q_over_p=Ss(state_q_over_pt)*cos(atan(Ss(state_tanl)));
7286 double dEdx=GetdEdx(q_over_p,central_traj[m].K_rho_Z_over_A,
7287 central_traj[m].rho_Z_over_A,
7288 central_traj[m].LnI);
7289
7290 // Use Brent's algorithm to find doca to the wire
7291 DVector2 xy(central_traj[m].xy.X()-Ss(state_D)*sin(Ss(state_phi)),
7292 central_traj[m].xy.Y()+Ss(state_D)*cos(Ss(state_phi)));
7293 DVector2 old_xy=xy;
7294 DMatrix5x1 myS=Ss;
7295 double myds;
7296 DVector2 origin=my_cdchits[id]->origin;
7297 DVector2 dir=my_cdchits[id]->dir;
7298 double z0wire=my_cdchits[id]->z0wire;
7299 BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy,z0wire,origin,dir,myS,myds);
7300 DVector2 wirepos=origin+(myS(state_z)-z0wire)*dir;
7301 double cosstereo=my_cdchits[id]->cosstereo;
7302 DVector2 diff=xy-wirepos;
7303 double d=cosstereo*diff.Mod()+EPS3.0e-8;
7304 // here we add a small number to avoid division by zero errors
7305
7306 // Find the field and gradient at (old_x,old_y,old_z)
7307 bfield->GetFieldAndGradient(old_xy.X(),old_xy.Y(),Ss(state_z),
7308 Bx,By,Bz,
7309 dBxdx,dBxdy,dBxdz,dBydx,
7310 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
7311 DMatrix5x5 Jc;
7312 StepJacobian(old_xy,xy-old_xy,myds,Ss,dEdx,Jc);
7313
7314 dC=dC.SandwichMultiply(Jc*AT);
7315 // Compute the Jacobian matrix
7316 // Projection matrix
7317 DMatrix5x1 H_T;
7318 double sinphi=sin(myS(state_phi));
7319 double cosphi=cos(myS(state_phi));
7320 double dx=diff.X();
7321 double dy=diff.Y();
7322 double cosstereo_over_doca=cosstereo*cosstereo/d;
7323 H_T(state_D)=(dy*cosphi-dx*sinphi)*cosstereo_over_doca;
7324 H_T(state_phi)
7325 =-myS(state_D)*cosstereo_over_doca*(dx*cosphi+dy*sinphi);
7326 H_T(state_z)=-cosstereo_over_doca*(dx*dir.X()+dy*dir.Y());
7327 double V=cdc_updates[id].variance;
7328 V+=Cs.SandwichMultiply(Jc*H_T);
7329
7330 pulls.push_back(pull_t(cdc_updates[id].doca-d,sqrt(V),
7331 central_traj[m].s,cdc_updates[id].tdrift,
7332 d,my_cdchits[id]->hit,NULL__null,
7333 diff.Phi(),myS(state_z),
7334 cdc_updates[id].tcorr));
7335
7336 }
7337 else{
7338 A=central_traj[m].Ckk*JT*C.InvertSym();
7339 Ss=central_traj[m].Skk+A*(Ss-S);
7340 Cs=central_traj[m].Ckk+A*(Cs-C)*A.Transpose();
7341 }
7342 S=central_traj[m].Skk;
7343 C=central_traj[m].Ckk;
7344 JT=(central_traj[m].JT);
7345 }
7346
7347 // ... last entries?
7348
7349 return NOERROR;
7350
7351}
7352
7353// Smoothing algorithm for the forward_traj_cdc trajectory.
7354// Updates the state vector
7355// at each step (going in the reverse direction to the filter) based on the
7356// information from all the steps and outputs the state vector at the
7357// outermost step.
7358jerror_t DTrackFitterKalmanSIMD::SmoothForwardCDC(void){
7359 if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE;
7360
7361 unsigned int max=forward_traj.size()-1;
7362 DMatrix5x1 S=(forward_traj[max].Skk);
7363 DMatrix5x5 C=(forward_traj[max].Ckk);
7364 DMatrix5x5 JT=(forward_traj[max].JT);
7365 DMatrix5x1 Ss=S;
7366 DMatrix5x5 Cs=C;
7367 DMatrix5x5 A;
7368
7369 for (unsigned int m=max-1;m>0;m--){
7370 if (forward_traj[m].h_id>0){
7371 unsigned int cdc_index=forward_traj[m].h_id-1;
7372
7373 A=cdc_updates[cdc_index].C*JT*C.InvertSym();
7374 Ss=cdc_updates[cdc_index].S+A*(Ss-S);
7375 if ((!isfinite(Ss(0)))|| (!isfinite(Ss(1)))
7376 || (!isfinite(Ss(2))) || (!isfinite(Ss(3)))
7377 || (!isfinite(Ss(4)))
7378 ){
7379 if (DEBUG_LEVEL>5)
7380 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7380<<" "
<< "Invalid values for smoothed parameters..." << endl;
7381 return VALUE_OUT_OF_RANGE;
7382 }
7383
7384 Cs=cdc_updates[cdc_index].C+A*(Cs-C)*A.Transpose();
7385
7386 FillPullsVectorEntry(Ss,Cs,forward_traj[m],my_cdchits[cdc_index],
7387 cdc_updates[cdc_index]);
7388
7389 }
7390 else{
7391 A=forward_traj[m].Ckk*JT*C.InvertSym();
7392 Ss=forward_traj[m].Skk+A*(Ss-S);
7393 Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose();
7394 }
7395
7396 S=forward_traj[m].Skk;
7397 C=forward_traj[m].Ckk;
7398 JT=forward_traj[m].JT;
7399 }
7400 A=forward_traj[0].Ckk*JT*C.InvertSym();
7401 Ss=forward_traj[0].Skk+A*(Ss-S);
7402 Cs=forward_traj[0].Ckk+A*(Cs-C)*A.Transpose();
7403
7404 return NOERROR;
7405}
7406
7407// Fill the pulls vector with the best residual information using the smoothed
7408// filter results. Uses Brent's algorithm to find the distance of closest
7409// approach to the wire hit.
7410void DTrackFitterKalmanSIMD::FillPullsVectorEntry(const DMatrix5x1 &Ss,
7411 const DMatrix5x5 &Cs,
7412 const DKalmanForwardTrajectory_t &traj,const DKalmanSIMDCDCHit_t *hit,const DKalmanUpdate_t &update){
7413
7414 // Get estimate for energy loss
7415 double dEdx=GetdEdx(Ss(state_q_over_p),traj.K_rho_Z_over_A,traj.rho_Z_over_A,
7416 traj.LnI);
7417
7418 // Use Brent's algorithm to find the doca to the wire
7419 DMatrix5x1 myS=Ss;
7420 DMatrix5x5 myC=Cs;
7421 double mydz;
7422 double z=traj.z;
7423 DVector2 origin=hit->origin;
7424 DVector2 dir=hit->dir;
7425 double z0wire=hit->z0wire;
7426 BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0wire,origin,dir,myS,mydz);
7427 double new_z=z+mydz;
7428 DVector2 wirepos=origin+(new_z-z0wire)*dir;
7429 double cosstereo=hit->cosstereo;
7430 DVector2 xy(myS(state_x),myS(state_y));
7431
7432 DVector2 diff=xy-wirepos;
7433 double d=cosstereo*diff.Mod();
7434
7435 // Find the field and gradient at (old_x,old_y,old_z) and compute the
7436 // Jacobian matrix for transforming from S to myS
7437 bfield->GetFieldAndGradient(Ss(state_x),Ss(state_y),z,
7438 Bx,By,Bz,dBxdx,dBxdy,dBxdz,dBydx,
7439 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
7440 DMatrix5x5 Jc;
7441 StepJacobian(z,new_z,Ss,dEdx,Jc);
7442
7443 // Find the projection matrix
7444 DMatrix5x1 H_T;
7445 double cosstereo2_over_d=cosstereo*cosstereo/d;
7446 H_T(state_x)=diff.X()*cosstereo2_over_d;
7447 H_T(state_y)=diff.Y()*cosstereo2_over_d;
7448
7449 // Find the variance for this hit
7450 double V=update.variance;
7451 V+=myC.SandwichMultiply(Jc*H_T);
7452
7453 pulls.push_back(pull_t(update.doca-d,sqrt(V),traj.s,update.tdrift,d,hit->hit,
7454 NULL__null,diff.Phi(),new_z,update.tcorr));
7455}
7456
7457/*---------------------------------------------------------------------------*/