Bug Summary

File:/volatile/halld/gluex/nightly/2024-03-18/Linux_CentOS7.7-x86_64-gcc4.8.5/halld_recon/src/libraries/TRACKING/DTrackFitterKalmanSIMD.cc
Location:line 9071, column 30
Description:Value stored to 'newz' 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#include "PID/DParticleID.h"
13
14#include <TH2F.h>
15#include <TH1I.h>
16#include <TROOT.h>
17#include <TMath.h>
18#include <DMatrix.h>
19
20#include <iomanip>
21#include <math.h>
22
23#define MAX_TB_PASSES20 20
24#define MAX_WB_PASSES20 20
25
26#define ALPHA1./137. 1./137.
27#define CHISQ_DELTA0.01 0.01
28#define MIN_ITER3 3
29
30// Only print messages for one thread whenever run number change
31static pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } };
32static set<int> runs_announced;
33
34// Local boolean routines for sorting
35//bool static DKalmanSIMDHit_cmp(DKalmanSIMDHit_t *a, DKalmanSIMDHit_t *b){
36// return a->z<b->z;
37//}
38
39inline bool static DKalmanSIMDFDCHit_cmp(DKalmanSIMDFDCHit_t *a, DKalmanSIMDFDCHit_t *b){
40 if (fabs(a->z-b->z)<EPS3.0e-8){
41 if (a->hit!=NULL__null && b->hit!=NULL__null && fabs(a->t-b->t)<EPS3.0e-8){
42 double tsum_1=a->hit->t_u+a->hit->t_v;
43 double tsum_2=b->hit->t_u+b->hit->t_v;
44 if (fabs(tsum_1-tsum_2)<EPS3.0e-8){
45 return (a->dE>b->dE);
46 }
47 return (tsum_1<tsum_2);
48 }
49 return(a->t<b->t);
50 }
51 return a->z<b->z;
52}
53inline bool static DKalmanSIMDCDCHit_cmp(DKalmanSIMDCDCHit_t *a, DKalmanSIMDCDCHit_t *b){
54 if (a==NULL__null || b==NULL__null){
55 cout << "Null pointer in CDC hit list??" << endl;
56 return false;
57 }
58 const DCDCWire *wire_a= a->hit->wire;
59 const DCDCWire *wire_b= b->hit->wire;
60 if(wire_b->ring == wire_a->ring){
61 return wire_b->straw < wire_a->straw;
62 }
63
64 return (wire_b->ring>wire_a->ring);
65}
66
67
68// Locate a position in array xx given x
69void DTrackFitterKalmanSIMD::locate(const double *xx,int n,double x,int *j){
70 int jl=-1;
71 int ju=n;
72 int ascnd=(xx[n-1]>=xx[0]);
73 while(ju-jl>1){
74 int jm=(ju+jl)>>1;
75 if ( (x>=xx[jm])==ascnd)
76 jl=jm;
77 else
78 ju=jm;
79 }
80 if (x==xx[0]) *j=0;
81 else if (x==xx[n-1]) *j=n-2;
82 else *j=jl;
83}
84
85
86
87// Locate a position in vector xx given x
88unsigned int DTrackFitterKalmanSIMD::locate(vector<double>&xx,double x){
89 int n=xx.size();
90 if (x==xx[0]) return 0;
91 else if (x==xx[n-1]) return n-2;
92
93 int jl=-1;
94 int ju=n;
95 int ascnd=(xx[n-1]>=xx[0]);
96 while(ju-jl>1){
97 int jm=(ju+jl)>>1;
98 if ( (x>=xx[jm])==ascnd)
99 jl=jm;
100 else
101 ju=jm;
102 }
103 return jl;
104}
105
106// Crude approximation for the variance in drift distance due to smearing
107double DTrackFitterKalmanSIMD::fdc_drift_variance(double t) const {
108 //return FDC_ANODE_VARIANCE;
109 double dt=0.;
110 double t_lo=DRIFT_RES_PARMS[3];
111 double t_hi=DRIFT_RES_PARMS[4];
112 if (t<t_lo) t=t_lo;
113 if (t>t_hi){
114 t=t_hi;
115 dt=t-t_hi;
116 }
117 double sigma=DRIFT_RES_PARMS[0]/(t+1.)+DRIFT_RES_PARMS[1]+DRIFT_RES_PARMS[2]*t*t;
118 if (dt>0){
119 sigma+=DRIFT_RES_PARMS[5]*dt;
120 }
121
122 return sigma*sigma;
123}
124
125// Convert time to distance for the cdc and compute variance
126void DTrackFitterKalmanSIMD::ComputeCDCDrift(double dphi,double delta,double t,
127 double B,
128 double &d, double &V, double &tcorr){
129 //d=0.39; // initialize at half-cell
130 //V=0.0507; // initialize with (cell size)/12.
131 tcorr = t; // Need this value even when t is negative for calibration
132 if (t>0){
133 double dtc =(CDC_DRIFT_BSCALE_PAR1 + CDC_DRIFT_BSCALE_PAR2 * B)* t;
134 tcorr=t-dtc;
135
136 // CDC_RES_PAR2=0.005;
137 double sigma=CDC_RES_PAR1/(tcorr+1.) + CDC_RES_PAR2 + CDC_RES_PAR3*tcorr;
138
139 // Variables to store values for time-to-distance functions for delta=0
140 // and delta!=0
141 double f_0=0.;
142 double f_delta=0.;
143 // Derivative of d with respect to t, needed to add t0 variance
144 // dependence to sigma
145 double dd_dt=0;
146 // Scale factor to account for effect of B-field on maximum drift time
147 //double Bscale=long_drift_Bscale_par1+long_drift_Bscale_par2*B;
148 // tcorr=t*Bscale;
149
150 // NSJ 26 May 2020 included long side a3, b3 and short side c1, c2, c3
151 // Previously these parameters were not used (0 in ccdb) for production runs
152 // except intensity scan run 72312 by accident 5 May 2020, superseded 8 May.
153 // They were used in 2015 for runs 0-3050.
154
155 // if (delta>0)
156 if (delta>-EPS21.e-4){
157 double a1=long_drift_func[0][0];
158 double a2=long_drift_func[0][1];
159 double a3=long_drift_func[0][2];
160 double b1=long_drift_func[1][0];
161 double b2=long_drift_func[1][1];
162 double b3=long_drift_func[1][2];
163 double c1=long_drift_func[2][0];
164 double c2=long_drift_func[2][1];
165 double c3=long_drift_func[2][2];
166
167 // use "long side" functional form
168 double my_t=0.001*tcorr;
169 double sqrt_t=sqrt(my_t);
170 double t3=my_t*my_t*my_t;
171 double delta_mag=fabs(delta);
172
173 double delta_sq=delta*delta;
174 double a=a1+a2*delta_mag+a3*delta_sq;
175 double b=b1+b2*delta_mag+b3*delta_sq;
176 double c=c1+c2*delta_mag+c3*delta_sq;
177
178 f_delta=a*sqrt_t+b*my_t+c*t3;
179 f_0=a1*sqrt_t+b1*my_t+c1*t3;
180
181 dd_dt=0.001*(0.5*a/sqrt_t+b+3.*c*my_t*my_t);
182 }
183 else{
184 double my_t=0.001*tcorr;
185 double sqrt_t=sqrt(my_t);
186 double t3=my_t*my_t*my_t;
187 double delta_mag=fabs(delta);
188
189 // use "short side" functional form
190 double a1=short_drift_func[0][0];
191 double a2=short_drift_func[0][1];
192 double a3=short_drift_func[0][2];
193 double b1=short_drift_func[1][0];
194 double b2=short_drift_func[1][1];
195 double b3=short_drift_func[1][2];
196 double c1=short_drift_func[2][0];
197 double c2=short_drift_func[2][1];
198 double c3=short_drift_func[2][2];
199
200 double delta_sq=delta*delta;
201 double a=a1+a2*delta_mag+a3*delta_sq;
202 double b=b1+b2*delta_mag+b3*delta_sq;
203 double c=c1+c2*delta_mag+c3*delta_sq;
204
205 f_delta=a*sqrt_t+b*my_t+c*t3;
206 f_0=a1*sqrt_t+b1*my_t+c1*t3;
207
208 dd_dt=0.001*(0.5*a/sqrt_t+b+3.*c*my_t*my_t);
209
210 }
211
212 unsigned int max_index=cdc_drift_table.size()-1;
213 if (tcorr>cdc_drift_table[max_index]){
214 //_DBG_ << "t: " << tcorr <<" d " << f_delta <<endl;
215 d=f_delta;
216 V=sigma*sigma+mVarT0*dd_dt*dd_dt;
217
218 return;
219 }
220
221 // Drift time is within range of table -- interpolate...
222 unsigned int index=0;
223 index=locate(cdc_drift_table,tcorr);
224 double dt=cdc_drift_table[index+1]-cdc_drift_table[index];
225 double frac=(tcorr-cdc_drift_table[index])/dt;
226 double d_0=0.01*(double(index)+frac);
227
228 if (fabs(delta) < EPS21.e-4){
229 d=d_0;
230 V=sigma*sigma+mVarT0*dd_dt*dd_dt;
231 }
232 else{
233 double P=0.;
234 double tcut=250.0; // ns
235 if (tcorr<tcut) {
236 P=(tcut-tcorr)/tcut;
237 }
238 d=f_delta*(d_0/f_0*P+1.-P);
239 V=sigma*sigma+mVarT0*dd_dt*dd_dt;
240 }
241 }
242 else { // Time is negative, or exactly zero, choose position at wire, with error of t=0 hit
243 d=0.;
244 double sigma = CDC_RES_PAR1+CDC_RES_PAR2;
245 double dt=cdc_drift_table[1]-cdc_drift_table[0];
246 V=sigma*sigma+mVarT0*0.0001/(dt*dt);
247 //V=0.0507; // straw radius^2 / 12
248 }
249
250}
251
252#define FDC_T0_OFFSET17.6 17.6
253// Interpolate on a table to convert time to distance for the fdc
254/*
255 double DTrackFitterKalmanSIMD::fdc_drift_distance(double t,double Bz) const {
256 double a=93.31,b=4.614,Bref=2.143;
257 t*=(a+b*Bref)/(a+b*Bz);
258 int id=int((t+FDC_T0_OFFSET)/2.);
259 if (id<0) id=0;
260 if (id>138) id=138;
261 double d=fdc_drift_table[id];
262 if (id!=138){
263 double frac=0.5*(t+FDC_T0_OFFSET-2.*double(id));
264 double dd=fdc_drift_table[id+1]-fdc_drift_table[id];
265 d+=frac*dd;
266 }
267
268 return d;
269 }
270 */
271
272// parametrization of time-to-distance for FDC
273double DTrackFitterKalmanSIMD::fdc_drift_distance(double time,double Bz) const {
274 if (time<0.) return 0.;
275 double d=0.;
276 time/=1.+FDC_DRIFT_BSCALE_PAR1+FDC_DRIFT_BSCALE_PAR2*Bz*Bz;
277 double tsq=time*time;
278 double t_high=DRIFT_FUNC_PARMS[4];
279
280 if (time<t_high){
281 d=DRIFT_FUNC_PARMS[0]*sqrt(time)+DRIFT_FUNC_PARMS[1]*time
282 +DRIFT_FUNC_PARMS[2]*tsq+DRIFT_FUNC_PARMS[3]*tsq*time;
283 }
284 else{
285 double t_high_sq=t_high*t_high;
286 d=DRIFT_FUNC_PARMS[0]*sqrt(t_high)+DRIFT_FUNC_PARMS[1]*t_high
287 +DRIFT_FUNC_PARMS[2]*t_high_sq+DRIFT_FUNC_PARMS[3]*t_high_sq*t_high;
288 d+=DRIFT_FUNC_PARMS[5]*(time-t_high);
289 }
290
291 return d;
292}
293
294
295DTrackFitterKalmanSIMD::DTrackFitterKalmanSIMD(JEventLoop *loop):DTrackFitter(loop){
296 FactorForSenseOfRotation=(bfield->GetBz(0.,0.,65.)>0.)?-1.:1.;
297
298 // keep track of which runs we print out messages for
299 int32_t runnumber = loop->GetJEvent().GetRunNumber();
300 pthread_mutex_lock(&print_mutex);
301 bool print_messages = false;
302 if(runs_announced.find(runnumber) == runs_announced.end()){
303 print_messages = true;
304 runs_announced.insert(runnumber);
305 }
306 pthread_mutex_unlock(&print_mutex);
307
308 // Some useful values
309 two_m_e=2.*ELECTRON_MASS0.000511;
310 m_e_sq=ELECTRON_MASS0.000511*ELECTRON_MASS0.000511;
311
312 // Get the position of the CDC downstream endplate from DGeometry
313 double endplate_rmin,endplate_rmax;
314 geom->GetCDCEndplate(endplate_z,endplate_dz,endplate_rmin,endplate_rmax);
315 endplate_z-=0.5*endplate_dz;
316 endplate_z_downstream=endplate_z+endplate_dz;
317 endplate_rmin+=0.1; // put just inside CDC
318 endplate_r2min=endplate_rmin*endplate_rmin;
319 endplate_r2max=endplate_rmax*endplate_rmax;
320
321 // Beginning of the cdc
322 vector<double>cdc_center;
323 vector<double>cdc_upstream_endplate_pos;
324 vector<double>cdc_endplate_dim;
325 geom->Get("//posXYZ[@volume='CentralDC'/@X_Y_Z",cdc_origin);
326 geom->Get("//posXYZ[@volume='centralDC']/@X_Y_Z",cdc_center);
327 geom->Get("//posXYZ[@volume='CDPU']/@X_Y_Z",cdc_upstream_endplate_pos);
328 geom->Get("//tubs[@name='CDPU']/@Rio_Z",cdc_endplate_dim);
329 cdc_origin[2]+=cdc_center[2]+cdc_upstream_endplate_pos[2]
330 +0.5*cdc_endplate_dim[2];
331
332 // Outer detector geometry parameters
333 geom->GetFCALZ(dFCALz);
334 dFCALzBack=dFCALz+45.;
335 if (geom->GetDIRCZ(dDIRCz)==false) dDIRCz=1000.;
336 geom->GetFMWPCZ_vec(dFMWPCz_vec);
337 geom->GetFMWPCSize(dFMWPCsize);
338 geom->GetCTOFZ(dCTOFz);
339
340 vector<double>tof_face;
341 geom->Get("//section/composition/posXYZ[@volume='ForwardTOF']/@X_Y_Z",
342 tof_face);
343 vector<double>tof_plane;
344 geom->Get("//composition[@name='ForwardTOF']/posXYZ[@volume='forwardTOF']/@X_Y_Z/plane[@value='0']", tof_plane);
345 dTOFz=tof_face[2]+tof_plane[2];
346 geom->Get("//composition[@name='ForwardTOF']/posXYZ[@volume='forwardTOF']/@X_Y_Z/plane[@value='1']", tof_plane);
347 dTOFz+=tof_face[2]+tof_plane[2];
348 dTOFz*=0.5; // mid plane between tof planes
349 geom->GetTRDZ(dTRDz_vec); // TRD planes
350
351 // Get start counter geometry;
352 if (geom->GetStartCounterGeom(sc_pos, sc_norm)){
353 // Create vector of direction vectors in scintillator planes
354 for (int i=0;i<30;i++){
355 vector<DVector3>temp;
356 for (unsigned int j=0;j<sc_pos[i].size()-1;j++){
357 double dx=sc_pos[i][j+1].x()-sc_pos[i][j].x();
358 double dy=sc_pos[i][j+1].y()-sc_pos[i][j].y();
359 double dz=sc_pos[i][j+1].z()-sc_pos[i][j].z();
360 temp.push_back(DVector3(dx/dz,dy/dz,1.));
361 }
362 sc_dir.push_back(temp);
363 }
364 SC_END_NOSE_Z=sc_pos[0][12].z();
365 SC_BARREL_R2=sc_pos[0][0].Perp2();
366 SC_PHI_SECTOR1=sc_pos[0][0].Phi();
367 }
368
369 // Get z positions of fdc wire planes
370 geom->GetFDCZ(fdc_z_wires);
371
372 ADD_VERTEX_POINT=false;
373 gPARMS->SetDefaultParameter("KALMAN:ADD_VERTEX_POINT", ADD_VERTEX_POINT);
374
375 THETA_CUT=60.0;
376 gPARMS->SetDefaultParameter("KALMAN:THETA_CUT", THETA_CUT);
377
378 RING_TO_SKIP=0;
379 gPARMS->SetDefaultParameter("KALMAN:RING_TO_SKIP",RING_TO_SKIP);
380
381 PLANE_TO_SKIP=0;
382 gPARMS->SetDefaultParameter("KALMAN:PLANE_TO_SKIP",PLANE_TO_SKIP);
383
384 MINIMUM_HIT_FRACTION=0.7;
385 gPARMS->SetDefaultParameter("KALMAN:MINIMUM_HIT_FRACTION",MINIMUM_HIT_FRACTION);
386 MIN_HITS_FOR_REFIT=6;
387 gPARMS->SetDefaultParameter("KALMAN:MIN_HITS_FOR_REFIT", MIN_HITS_FOR_REFIT);
388 PHOTON_ENERGY_CUTOFF=0.125;
389 gPARMS->SetDefaultParameter("KALMAN:PHOTON_ENERGY_CUTOFF",
390 PHOTON_ENERGY_CUTOFF);
391
392 USE_FDC_HITS=true;
393 gPARMS->SetDefaultParameter("TRKFIT:USE_FDC_HITS",USE_FDC_HITS);
394 USE_CDC_HITS=true;
395 gPARMS->SetDefaultParameter("TRKFIT:USE_CDC_HITS",USE_CDC_HITS);
396 USE_TRD_HITS=false;
397 gPARMS->SetDefaultParameter("TRKFIT:USE_TRD_HITS",USE_TRD_HITS);
398 USE_TRD_DRIFT_TIMES=true;
399 gPARMS->SetDefaultParameter("TRKFIT:USE_TRD_DRIFT_TIMES",USE_TRD_DRIFT_TIMES);
400 USE_GEM_HITS=false;
401 gPARMS->SetDefaultParameter("TRKFIT:USE_GEM_HITS",USE_GEM_HITS);
402
403
404 // Flag to enable calculation of alignment derivatives
405 ALIGNMENT=false;
406 gPARMS->SetDefaultParameter("TRKFIT:ALIGNMENT",ALIGNMENT);
407
408 ALIGNMENT_FORWARD=false;
409 gPARMS->SetDefaultParameter("TRKFIT:ALIGNMENT_FORWARD",ALIGNMENT_FORWARD);
410
411 ALIGNMENT_CENTRAL=false;
412 gPARMS->SetDefaultParameter("TRKFIT:ALIGNMENT_CENTRAL",ALIGNMENT_CENTRAL);
413
414 if(ALIGNMENT){ALIGNMENT_FORWARD=true;ALIGNMENT_CENTRAL=true;}
415
416 DEBUG_HISTS=false;
417 gPARMS->SetDefaultParameter("KALMAN:DEBUG_HISTS", DEBUG_HISTS);
418
419 DEBUG_LEVEL=0;
420 gPARMS->SetDefaultParameter("KALMAN:DEBUG_LEVEL", DEBUG_LEVEL);
421
422 USE_T0_FROM_WIRES=0;
423 gPARMS->SetDefaultParameter("KALMAN:USE_T0_FROM_WIRES", USE_T0_FROM_WIRES);
424
425 ESTIMATE_T0_TB=false;
426 gPARMS->SetDefaultParameter("KALMAN:ESTIMATE_T0_TB",ESTIMATE_T0_TB);
427
428 ENABLE_BOUNDARY_CHECK=true;
429 gPARMS->SetDefaultParameter("GEOM:ENABLE_BOUNDARY_CHECK",
430 ENABLE_BOUNDARY_CHECK);
431
432 USE_MULS_COVARIANCE=true;
433 gPARMS->SetDefaultParameter("TRKFIT:USE_MULS_COVARIANCE",
434 USE_MULS_COVARIANCE);
435
436 USE_PASS1_TIME_MODE=false;
437 gPARMS->SetDefaultParameter("KALMAN:USE_PASS1_TIME_MODE",USE_PASS1_TIME_MODE);
438
439 USE_FDC_DRIFT_TIMES=true;
440 gPARMS->SetDefaultParameter("TRKFIT:USE_FDC_DRIFT_TIMES",
441 USE_FDC_DRIFT_TIMES);
442
443 RECOVER_BROKEN_TRACKS=true;
444 gPARMS->SetDefaultParameter("KALMAN:RECOVER_BROKEN_TRACKS",RECOVER_BROKEN_TRACKS);
445
446 NUM_CDC_SIGMA_CUT=5.0;
447 NUM_FDC_SIGMA_CUT=5.0;
448 gPARMS->SetDefaultParameter("KALMAN:NUM_CDC_SIGMA_CUT",NUM_CDC_SIGMA_CUT,
449 "maximum distance in number of sigmas away from projection to accept cdc hit");
450 gPARMS->SetDefaultParameter("KALMAN:NUM_FDC_SIGMA_CUT",NUM_FDC_SIGMA_CUT,
451 "maximum distance in number of sigmas away from projection to accept fdc hit");
452
453 ANNEAL_SCALE=9.0;
454 ANNEAL_POW_CONST=1.5;
455 gPARMS->SetDefaultParameter("KALMAN:ANNEAL_SCALE",ANNEAL_SCALE,
456 "Scale factor for annealing");
457 gPARMS->SetDefaultParameter("KALMAN:ANNEAL_POW_CONST",ANNEAL_POW_CONST,
458 "Annealing parameter");
459 FORWARD_ANNEAL_SCALE=9.;
460 FORWARD_ANNEAL_POW_CONST=1.5;
461 gPARMS->SetDefaultParameter("KALMAN:FORWARD_ANNEAL_SCALE",
462 FORWARD_ANNEAL_SCALE,
463 "Scale factor for annealing");
464 gPARMS->SetDefaultParameter("KALMAN:FORWARD_ANNEAL_POW_CONST",
465 FORWARD_ANNEAL_POW_CONST,
466 "Annealing parameter");
467
468 FORWARD_PARMS_COV=false;
469 gPARMS->SetDefaultParameter("KALMAN:FORWARD_PARMS_COV",FORWARD_PARMS_COV);
470
471 CDC_VAR_SCALE_FACTOR=1.;
472 gPARMS->SetDefaultParameter("KALMAN:CDC_VAR_SCALE_FACTOR",CDC_VAR_SCALE_FACTOR);
473 CDC_T_DRIFT_MIN=-12.; // One f125 clock = 8 ns
474 gPARMS->SetDefaultParameter("KALMAN:CDC_T_DRIFT_MIN",CDC_T_DRIFT_MIN);
475
476 MOLIERE_FRACTION=0.9;
477 gPARMS->SetDefaultParameter("KALMAN:MOLIERE_FRACTION",MOLIERE_FRACTION);
478 MS_SCALE_FACTOR=2.0;
479 gPARMS->SetDefaultParameter("KALMAN:MS_SCALE_FACTOR",MS_SCALE_FACTOR);
480 MOLIERE_RATIO1=0.5/(1.-MOLIERE_FRACTION);
481 MOLIERE_RATIO2=MS_SCALE_FACTOR*1.e-6/(1.+MOLIERE_FRACTION*MOLIERE_FRACTION); //scale_factor/(1+F*F)
482
483 COVARIANCE_SCALE_FACTOR_CENTRAL=2.0;
484 gPARMS->SetDefaultParameter("KALMAN:COVARIANCE_SCALE_FACTOR_CENTRAL",
485 COVARIANCE_SCALE_FACTOR_CENTRAL);
486
487 COVARIANCE_SCALE_FACTOR_FORWARD=2.0;
488 gPARMS->SetDefaultParameter("KALMAN:COVARIANCE_SCALE_FACTOR_FORWARD",
489 COVARIANCE_SCALE_FACTOR_FORWARD);
490
491 WRITE_ML_TRAINING_OUTPUT=false;
492 gPARMS->SetDefaultParameter("KALMAN:WRITE_ML_TRAINING_OUTPUT",
493 WRITE_ML_TRAINING_OUTPUT);
494
495 if (WRITE_ML_TRAINING_OUTPUT){
496 mlfile.open("mltraining.dat");
497 }
498
499
500 DApplication* dapp = dynamic_cast<DApplication*>(loop->GetJApplication());
501 JCalibration *jcalib = dapp->GetJCalibration((loop->GetJEvent()).GetRunNumber());
502 vector< map<string, double> > tvals;
503 cdc_drift_table.clear();
504 if (jcalib->Get("CDC/cdc_drift_table", tvals)==false){
505 for(unsigned int i=0; i<tvals.size(); i++){
506 map<string, double> &row = tvals[i];
507 cdc_drift_table.push_back(1000.*row["t"]);
508 }
509 }
510 else{
511 jerr << " CDC time-to-distance table not available... bailing..." << endl;
512 exit(0);
513 }
514
515 int straw_number[28]={42,42,54,54,66,66,80,80,93,93,106,106,
516 123,123,135,135,146,146,158,158,170,170,
517 182,182,197,197,209,209};
518 max_sag.clear();
519 sag_phi_offset.clear();
520 int straw_count=0,ring_count=0;
521 if (jcalib->Get("CDC/sag_parameters", tvals)==false){
522 vector<double>temp,temp2;
523 for(unsigned int i=0; i<tvals.size(); i++){
524 map<string, double> &row = tvals[i];
525
526 temp.push_back(row["offset"]);
527 temp2.push_back(row["phi"]);
528
529 straw_count++;
530 if (straw_count==straw_number[ring_count]){
531 max_sag.push_back(temp);
532 sag_phi_offset.push_back(temp2);
533 temp.clear();
534 temp2.clear();
535 straw_count=0;
536 ring_count++;
537 }
538 }
539 }
540
541 if (jcalib->Get("CDC/drift_parameters", tvals)==false){
542 map<string, double> &row = tvals[0]; // long drift side
543 long_drift_func[0][0]=row["a1"];
544 long_drift_func[0][1]=row["a2"];
545 long_drift_func[0][2]=row["a3"];
546 long_drift_func[1][0]=row["b1"];
547 long_drift_func[1][1]=row["b2"];
548 long_drift_func[1][2]=row["b3"];
549 long_drift_func[2][0]=row["c1"];
550 long_drift_func[2][1]=row["c2"];
551 long_drift_func[2][2]=row["c3"];
552 long_drift_Bscale_par1=row["B1"];
553 long_drift_Bscale_par2=row["B2"];
554
555 row = tvals[1]; // short drift side
556 short_drift_func[0][0]=row["a1"];
557 short_drift_func[0][1]=row["a2"];
558 short_drift_func[0][2]=row["a3"];
559 short_drift_func[1][0]=row["b1"];
560 short_drift_func[1][1]=row["b2"];
561 short_drift_func[1][2]=row["b3"];
562 short_drift_func[2][0]=row["c1"];
563 short_drift_func[2][1]=row["c2"];
564 short_drift_func[2][2]=row["c3"];
565 short_drift_Bscale_par1=row["B1"];
566 short_drift_Bscale_par2=row["B2"];
567 }
568
569 map<string, double> cdc_drift_parms;
570 jcalib->Get("CDC/cdc_drift_parms", cdc_drift_parms);
571 CDC_DRIFT_BSCALE_PAR1 = cdc_drift_parms["bscale_par1"];
572 CDC_DRIFT_BSCALE_PAR2 = cdc_drift_parms["bscale_par2"];
573
574 map<string, double> cdc_res_parms;
575 jcalib->Get("CDC/cdc_resolution_parms_v2", cdc_res_parms);
576 CDC_RES_PAR1 = cdc_res_parms["res_par1"];
577 CDC_RES_PAR2 = cdc_res_parms["res_par2"];
578 CDC_RES_PAR3 = cdc_res_parms["res_par3"];
579
580 // Parameters for correcting for deflection due to Lorentz force
581 map<string,double>lorentz_parms;
582 jcalib->Get("FDC/lorentz_deflection_parms",lorentz_parms);
583 LORENTZ_NR_PAR1=lorentz_parms["nr_par1"];
584 LORENTZ_NR_PAR2=lorentz_parms["nr_par2"];
585 LORENTZ_NZ_PAR1=lorentz_parms["nz_par1"];
586 LORENTZ_NZ_PAR2=lorentz_parms["nz_par2"];
587
588 // Parameters for accounting for variation in drift distance from FDC
589 map<string,double>drift_res_parms;
590 jcalib->Get("FDC/drift_resolution_parms",drift_res_parms);
591 DRIFT_RES_PARMS[0]=drift_res_parms["p0"];
592 DRIFT_RES_PARMS[1]=drift_res_parms["p1"];
593 DRIFT_RES_PARMS[2]=drift_res_parms["p2"];
594 map<string,double>drift_res_ext;
595 jcalib->Get("FDC/drift_resolution_ext",drift_res_ext);
596 DRIFT_RES_PARMS[3]=drift_res_ext["t_low"];
597 DRIFT_RES_PARMS[4]=drift_res_ext["t_high"];
598 DRIFT_RES_PARMS[5]=drift_res_ext["res_slope"];
599
600 // Time-to-distance function parameters for FDC
601 map<string,double>drift_func_parms;
602 jcalib->Get("FDC/drift_function_parms",drift_func_parms);
603 DRIFT_FUNC_PARMS[0]=drift_func_parms["p0"];
604 DRIFT_FUNC_PARMS[1]=drift_func_parms["p1"];
605 DRIFT_FUNC_PARMS[2]=drift_func_parms["p2"];
606 DRIFT_FUNC_PARMS[3]=drift_func_parms["p3"];
607 DRIFT_FUNC_PARMS[4]=1000.;
608 DRIFT_FUNC_PARMS[5]=0.;
609 map<string,double>drift_func_ext;
610 if (jcalib->Get("FDC/drift_function_ext",drift_func_ext)==false){
611 DRIFT_FUNC_PARMS[4]=drift_func_ext["p4"];
612 DRIFT_FUNC_PARMS[5]=drift_func_ext["p5"];
613 }
614 // Factors for taking care of B-dependence of drift time for FDC
615 map<string, double> fdc_drift_parms;
616 jcalib->Get("FDC/fdc_drift_parms", fdc_drift_parms);
617 FDC_DRIFT_BSCALE_PAR1 = fdc_drift_parms["bscale_par1"];
618 FDC_DRIFT_BSCALE_PAR2 = fdc_drift_parms["bscale_par2"];
619
620
621 /*
622 if (jcalib->Get("FDC/fdc_drift2", tvals)==false){
623 for(unsigned int i=0; i<tvals.size(); i++){
624 map<string, float> &row = tvals[i];
625 iter_float iter = row.begin();
626 fdc_drift_table[i] = iter->second;
627 }
628 }
629 else{
630 jerr << " FDC time-to-distance table not available... bailing..." << endl;
631 exit(0);
632 }
633 */
634
635 for (unsigned int i=0;i<5;i++)I5x5(i,i)=1.;
636
637
638 // center of the target
639 map<string, double> targetparms;
640 if (jcalib->Get("TARGET/target_parms",targetparms)==false){
641 TARGET_Z = targetparms["TARGET_Z_POSITION"];
642 }
643 else{
644 geom->GetTargetZ(TARGET_Z);
645 }
646 if (ADD_VERTEX_POINT){
647 gPARMS->SetDefaultParameter("KALMAN:VERTEX_POSITION",TARGET_Z);
648 }
649
650 // Beam position and direction
651 map<string, double> beam_vals;
652 jcalib->Get("PHOTON_BEAM/beam_spot",beam_vals);
653 beam_center.Set(beam_vals["x"],beam_vals["y"]);
654 beam_dir.Set(beam_vals["dxdz"],beam_vals["dydz"]);
655
656 if(print_messages)
657 jout << " Beam spot: x=" << beam_center.X() << " y=" << beam_center.Y()
658 << " z=" << beam_vals["z"]
659 << " dx/dz=" << beam_dir.X() << " dy/dz=" << beam_dir.Y() << endl;
660 beam_z0=beam_vals["z"];
661
662 // Inform user of some configuration settings
663 static bool config_printed = false;
664 if(!config_printed){
665 config_printed = true;
666 stringstream ss;
667 ss << "vertex constraint: " ;
668 if(ADD_VERTEX_POINT){
669 ss << "z = " << TARGET_Z << "cm" << endl;
670 }else{
671 ss << "<none>" << endl;
672 }
673 jout << ss.str();
674 } // config_printed
675
676 if(DEBUG_HISTS){
677 for (auto i=0; i < 46; i++){
678 double min = -10., max=10.;
679 if(i%23<12) {min=-5; max=5;}
680 if(i<23)alignDerivHists[i]=new TH1I(Form("CentralDeriv%i",i),Form("CentralDeriv%i",i),200, min, max);
681 else alignDerivHists[i]=new TH1I(Form("ForwardDeriv%i",i%23),Form("ForwardDeriv%i",i%23),200, min, max);
682 }
683 brentCheckHists[0]=new TH2I("ForwardBrentCheck","DOCA vs ds", 100, -5., 5., 100, 0.0, 1.5);
684 brentCheckHists[1]=new TH2I("CentralBrentCheck","DOCA vs ds", 100, -5., 5., 100, 0.0, 1.5);
685 }
686
687 dResourcePool_TMatrixFSym = std::make_shared<DResourcePool<TMatrixFSym>>();
688 dResourcePool_TMatrixFSym->Set_ControlParams(20, 20, 50);
689
690 my_fdchits.reserve(24);
691 my_cdchits.reserve(28);
692 fdc_updates.reserve(24);
693 cdc_updates.reserve(28);
694 cdc_used_in_fit.reserve(28);
695 fdc_used_in_fit.reserve(24);
696}
697
698//-----------------
699// ResetKalmanSIMD
700//-----------------
701void DTrackFitterKalmanSIMD::ResetKalmanSIMD(void)
702{
703 last_material_map=0;
704
705 for (unsigned int i=0;i<my_cdchits.size();i++){
706 delete my_cdchits[i];
707 }
708 for (unsigned int i=0;i<my_fdchits.size();i++){
709 delete my_fdchits[i];
710 }
711 central_traj.clear();
712 forward_traj.clear();
713 my_fdchits.clear();
714 my_cdchits.clear();
715 fdc_updates.clear();
716 cdc_updates.clear();
717 fdc_used_in_fit.clear();
718 cdc_used_in_fit.clear();
719 got_trd_gem_hits=false;
720
721 cov.clear();
722 fcov.clear();
723
724 len = 0.0;
725 ftime=0.0;
726 var_ftime=0.0;
727 x_=0.,y_=0.,tx_=0.,ty_=0.,q_over_p_ = 0.0;
728 z_=0.,phi_=0.,tanl_=0.,q_over_pt_ =0, D_= 0.0;
729 chisq_ = 0.0;
730 ndf_ = 0;
731 MASS=0.13957;
732 mass2=MASS*MASS;
733 Bx=By=0.;
734 Bz=2.;
735 dBxdx=0.,dBxdy=0.,dBxdz=0.,dBydx=0.,dBydy=0.,dBydy=0.,dBzdx=0.,dBzdy=0.,dBzdz=0.;
736 // Step sizes
737 mStepSizeS=2.0;
738 mStepSizeZ=2.0;
739 //mStepSizeZ=0.5;
740
741 //if (fit_type==kTimeBased){
742 // mStepSizeS=0.5;
743 // mStepSizeZ=0.5;
744 // }
745
746
747 mT0=0.,mT0MinimumDriftTime=1e6;
748 mVarT0=25.;
749
750 mCDCInternalStepSize=0.5;
751 //mCDCInternalStepSize=1.0;
752 //mCentralStepSize=0.75;
753 mCentralStepSize=0.75;
754
755 mT0Detector=SYS_CDC;
756
757 IsHadron=true;
758 IsElectron=false;
759 IsPositron=false;
760
761 PT_MIN=0.01;
762 Q_OVER_P_MAX=100.;
763
764 // These variables provide the approximate location along the trajectory
765 // where there is an indication of a kink in the track
766 break_point_fdc_index=0;
767 break_point_cdc_index=0;
768 break_point_step_index=0;
769
770}
771
772//-----------------
773// FitTrack
774//-----------------
775DTrackFitter::fit_status_t DTrackFitterKalmanSIMD::FitTrack(void)
776{
777 // Reset member data and free an memory associated with the last fit,
778 // but some of which only for wire-based fits
779 ResetKalmanSIMD();
780
781 // Check that we have enough FDC and CDC hits to proceed
782 if (cdchits.size()==0 && fdchits.size()<4) return kFitNotDone;
783 if (cdchits.size()+fdchits.size() < 6) return kFitNotDone;
784
785 // Copy hits from base class into structures specific to DTrackFitterKalmanSIMD
786 if (USE_CDC_HITS)
787 for(unsigned int i=0; i<cdchits.size(); i++)AddCDCHit(cdchits[i]);
788 if (USE_FDC_HITS)
789 for(unsigned int i=0; i<fdchits.size(); i++)AddFDCHit(fdchits[i]);
790 if (USE_TRD_HITS){
791 for(unsigned int i=0; i<trdhits.size(); i++)AddTRDHit(trdhits[i]);
792 if (trdhits.size()>0){
793 //_DBG_ << "Got TRD" <<endl;
794 got_trd_gem_hits=true;
795 }
796 }
797 if (USE_GEM_HITS){
798 for(unsigned int i=0; i<gemhits.size(); i++)AddGEMHit(gemhits[i]);
799 if (gemhits.size()>0){
800 //_DBG_ << " Got GEM" << endl;
801 got_trd_gem_hits=true;
802 }
803 }
804
805 unsigned int num_good_cdchits=my_cdchits.size();
806 unsigned int num_good_fdchits=my_fdchits.size();
807
808 // keep track of the range of detector elements that could be hit
809 // for calculating the number of expected hits later on
810 //int min_cdc_ring=-1, max_cdc_ring=-1;
811
812 // Order the cdc hits by ring number
813 if (num_good_cdchits>0){
814 stable_sort(my_cdchits.begin(),my_cdchits.end(),DKalmanSIMDCDCHit_cmp);
815
816 //min_cdc_ring = my_cdchits[0]->hit->wire->ring;
817 //max_cdc_ring = my_cdchits[my_cdchits.size()-1]->hit->wire->ring;
818
819 // Look for multiple hits on the same wire
820 for (unsigned int i=0;i<my_cdchits.size()-1;i++){
821 if (my_cdchits[i]->hit->wire->ring==my_cdchits[i+1]->hit->wire->ring &&
822 my_cdchits[i]->hit->wire->straw==my_cdchits[i+1]->hit->wire->straw){
823 num_good_cdchits--;
824 if (my_cdchits[i]->tdrift<my_cdchits[i+1]->tdrift){
825 my_cdchits[i+1]->status=late_hit;
826 }
827 else{
828 my_cdchits[i]->status=late_hit;
829 }
830 }
831 }
832
833 }
834 // Order the fdc hits by z
835 if (num_good_fdchits>0){
836 stable_sort(my_fdchits.begin(),my_fdchits.end(),DKalmanSIMDFDCHit_cmp);
837
838 // Look for multiple hits on the same wire
839 for (unsigned int i=0;i<my_fdchits.size()-1;i++){
840 if (my_fdchits[i]->hit==NULL__null || my_fdchits[i+1]->hit==NULL__null) continue;
841 if (my_fdchits[i]->hit->wire->layer==my_fdchits[i+1]->hit->wire->layer &&
842 my_fdchits[i]->hit->wire->wire==my_fdchits[i+1]->hit->wire->wire){
843 num_good_fdchits--;
844 if (fabs(my_fdchits[i]->t-my_fdchits[i+1]->t)<EPS3.0e-8){
845 double tsum_1=my_fdchits[i]->hit->t_u+my_fdchits[i]->hit->t_v;
846 double tsum_2=my_fdchits[i+1]->hit->t_u+my_fdchits[i+1]->hit->t_v;
847 if (tsum_1<tsum_2){
848 my_fdchits[i+1]->status=late_hit;
849 }
850 else{
851 my_fdchits[i]->status=late_hit;
852 }
853 }
854 else if (my_fdchits[i]->t<my_fdchits[i+1]->t){
855 my_fdchits[i+1]->status=late_hit;
856 }
857 else{
858 my_fdchits[i]->status=late_hit;
859 }
860 }
861 }
862 }
863 if (num_good_cdchits==0 && num_good_fdchits<4) return kFitNotDone;
864 if (num_good_cdchits+num_good_fdchits < 6) return kFitNotDone;
865
866 // Create vectors of updates (from hits) to S and C
867 if (my_cdchits.size()>0){
868 cdc_updates=vector<DKalmanUpdate_t>(my_cdchits.size());
869 // Initialize vector to keep track of whether or not a hit is used in
870 // the fit
871 cdc_used_in_fit=vector<bool>(my_cdchits.size());
872 }
873 if (my_fdchits.size()>0){
874 fdc_updates=vector<DKalmanUpdate_t>(my_fdchits.size());
875 // Initialize vector to keep track of whether or not a hit is used in
876 // the fit
877 fdc_used_in_fit=vector<bool>(my_fdchits.size());
878 }
879
880 // start time and variance
881 if (fit_type==kTimeBased){
882 mT0=input_params.t0();
883 switch(input_params.t0_detector()){
884 case SYS_TOF:
885 mVarT0=0.01;
886 break;
887 case SYS_CDC:
888 mVarT0=7.5;
889 break;
890 case SYS_FDC:
891 mVarT0=7.5;
892 break;
893 case SYS_BCAL:
894 mVarT0=0.25;
895 break;
896 default:
897 mVarT0=0.09;
898 break;
899 }
900 }
901
902 //_DBG_ << SystemName(input_params.t0_detector()) << " " << mT0 <<endl;
903
904 //Set the mass
905 MASS=input_params.mass();
906 mass2=MASS*MASS;
907 m_ratio=ELECTRON_MASS0.000511/MASS;
908 m_ratio_sq=m_ratio*m_ratio;
909
910 // Is this particle an electron or positron?
911 if (MASS<0.001){
912 IsHadron=false;
913 if (input_params.charge()<0.) IsElectron=true;
914 else IsPositron=true;
915 }
916 if (DEBUG_LEVEL>0)
917 {
918 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<918<<" "
<< "------Starting "
919 <<(fit_type==kTimeBased?"Time-based":"Wire-based")
920 << " Fit with " << my_fdchits.size() << " FDC hits and "
921 << my_cdchits.size() << " CDC hits.-------" <<endl;
922 if (fit_type==kTimeBased){
923 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<923<<" "
<< " Using t0=" << mT0 << " from DET="
924 << input_params.t0_detector() <<endl;
925 }
926 }
927 // Do the fit
928 jerror_t error = KalmanLoop();
929 if (error!=NOERROR){
930 if (DEBUG_LEVEL>0)
931 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<931<<" "
<< "Fit failed with Error = " << error <<endl;
932 return kFitFailed;
933 }
934
935 // Copy fit results into DTrackFitter base-class data members
936 DVector3 mom,pos;
937 GetPosition(pos);
938 GetMomentum(mom);
939 double charge = GetCharge();
940 fit_params.setPosition(pos);
941 fit_params.setMomentum(mom);
942 fit_params.setTime(mT0MinimumDriftTime);
943 fit_params.setPID(IDTrack(charge, MASS));
944 fit_params.setT0(mT0MinimumDriftTime,4.,mT0Detector);
945
946 if (DEBUG_LEVEL>0){
947 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<947<<" "
<< "----- Pass: "
948 << (fit_type==kTimeBased?"Time-based ---":"Wire-based ---")
949 << " Mass: " << MASS
950 << " p=" << mom.Mag()
951 << " theta=" << 90.0-180./M_PI3.14159265358979323846*atan(tanl_)
952 << " vertex=(" << x_ << "," << y_ << "," << z_<<")"
953 << " chi2=" << chisq_
954 <<endl;
955 if(DEBUG_LEVEL>3){
956 //Dump pulls
957 for (unsigned int iPull = 0; iPull < pulls.size(); iPull++){
958 if (pulls[iPull].cdc_hit != NULL__null){
959 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<959<<" "
<< " ring: " << pulls[iPull].cdc_hit->wire->ring
960 << " straw: " << pulls[iPull].cdc_hit->wire->straw
961 << " Residual: " << pulls[iPull].resi
962 << " Err: " << pulls[iPull].err
963 << " tdrift: " << pulls[iPull].tdrift
964 << " doca: " << pulls[iPull].d
965 << " docaphi: " << pulls[iPull].docaphi
966 << " z: " << pulls[iPull].z
967 << " cos(theta_rel): " << pulls[iPull].cosThetaRel
968 << " tcorr: " << pulls[iPull].tcorr
969 << endl;
970 }
971 }
972 }
973 }
974
975 DMatrixDSym errMatrix(5);
976 // Fill the tracking error matrix and the one needed for kinematic fitting
977 if (fcov.size()!=0){
978 // We MUST fill the entire matrix (not just upper right) even though
979 // this is a DMatrixDSym
980 for (unsigned int i=0;i<5;i++){
981 for (unsigned int j=0;j<5;j++){
982 errMatrix(i,j)=fcov[i][j];
983 }
984 }
985 if (FORWARD_PARMS_COV){
986 fit_params.setForwardParmFlag(true);
987 fit_params.setTrackingStateVector(x_,y_,tx_,ty_,q_over_p_);
988
989 // Compute and fill the error matrix needed for kinematic fitting
990 fit_params.setErrorMatrix(Get7x7ErrorMatrixForward(errMatrix));
991 }
992 else {
993 fit_params.setForwardParmFlag(false);
994 fit_params.setTrackingStateVector(q_over_pt_,phi_,tanl_,D_,z_);
995
996 // Compute and fill the error matrix needed for kinematic fitting
997 fit_params.setErrorMatrix(Get7x7ErrorMatrix(errMatrix));
998 }
999 }
1000 else if (cov.size()!=0){
1001 fit_params.setForwardParmFlag(false);
1002
1003 // We MUST fill the entire matrix (not just upper right) even though
1004 // this is a DMatrixDSym
1005 for (unsigned int i=0;i<5;i++){
1006 for (unsigned int j=0;j<5;j++){
1007 errMatrix(i,j)=cov[i][j];
1008 }
1009 }
1010 fit_params.setTrackingStateVector(q_over_pt_,phi_,tanl_,D_,z_);
1011
1012 // Compute and fill the error matrix needed for kinematic fitting
1013 fit_params.setErrorMatrix(Get7x7ErrorMatrix(errMatrix));
1014 }
1015 auto locTrackingCovarianceMatrix = dResourcePool_TMatrixFSym->Get_SharedResource();
1016 locTrackingCovarianceMatrix->ResizeTo(5, 5);
1017 for(unsigned int loc_i = 0; loc_i < 5; ++loc_i)
1018 {
1019 for(unsigned int loc_j = 0; loc_j < 5; ++loc_j)
1020 (*locTrackingCovarianceMatrix)(loc_i, loc_j) = errMatrix(loc_i, loc_j);
1021
1022 }
1023 fit_params.setTrackingErrorMatrix(locTrackingCovarianceMatrix);
1024 this->chisq = GetChiSq();
1025 this->Ndof = GetNDF();
1026 fit_status = kFitSuccess;
1027
1028 //_DBG_ << "========= done!" << endl;
1029
1030 return fit_status;
1031}
1032
1033//-----------------
1034// ChiSq
1035//-----------------
1036double DTrackFitterKalmanSIMD::ChiSq(fit_type_t fit_type, DReferenceTrajectory *rt, double *chisq_ptr, int *dof_ptr, vector<pull_t> *pulls_ptr)
1037{
1038 // This simply returns whatever was left in for the chisq/NDF from the last fit.
1039 // Using a DReferenceTrajectory is not really appropriate here so the base class'
1040 // requirement of it should be reviewed.
1041 double chisq = GetChiSq();
1042 unsigned int ndf = GetNDF();
1043
1044 if(chisq_ptr)*chisq_ptr = chisq;
1045 if(dof_ptr)*dof_ptr = int(ndf);
1046 if(pulls_ptr)*pulls_ptr = pulls;
1047
1048 return chisq/double(ndf);
1049}
1050
1051// Return the momentum at the distance of closest approach to the origin.
1052inline void DTrackFitterKalmanSIMD::GetMomentum(DVector3 &mom){
1053 double pt=1./fabs(q_over_pt_);
1054 mom.SetXYZ(pt*cos(phi_),pt*sin(phi_),pt*tanl_);
1055}
1056
1057// Return the "vertex" position (position at which track crosses beam line)
1058inline void DTrackFitterKalmanSIMD::GetPosition(DVector3 &pos){
1059 DVector2 beam_pos=beam_center+(z_-beam_z0)*beam_dir;
1060 pos.SetXYZ(x_+beam_pos.X(),y_+beam_pos.Y(),z_);
1061}
1062
1063// Add GEM points
1064void DTrackFitterKalmanSIMD::AddGEMHit(const DGEMPoint *gemhit){
1065 DKalmanSIMDFDCHit_t *hit= new DKalmanSIMDFDCHit_t;
1066
1067 hit->t=gemhit->time;
1068 hit->uwire=gemhit->x;
1069 hit->vstrip=gemhit->y;
1070 // From Justin (12/12/19):
1071 // DGEMPoint (GEM2 SRS, plane closest to the DIRC):
1072 // sigma_X = sigma_Y = 100 um
1073 hit->vvar=0.01*0.01;
1074 hit->uvar=hit->vvar;
1075 hit->z=gemhit->z;
1076 hit->cosa=1.;
1077 hit->sina=0.;
1078 hit->phiX=0.;
1079 hit->phiY=0.;
1080 hit->phiZ=0.;
1081 hit->nr=0.;
1082 hit->nz=0.;
1083 hit->status=gem_hit;
1084 hit->hit=NULL__null;
1085
1086 my_fdchits.push_back(hit);
1087}
1088
1089
1090
1091// Add TRD points
1092void DTrackFitterKalmanSIMD::AddTRDHit(const DTRDPoint *trdhit){
1093 DKalmanSIMDFDCHit_t *hit= new DKalmanSIMDFDCHit_t;
1094
1095 hit->t=trdhit->time;
1096 hit->uwire=trdhit->x;
1097 hit->vstrip=trdhit->y;
1098 // From Justin (12/12/19):
1099 // sigma_X = 1 mm / sqrt(12)
1100 // sigma_Y = 300 um
1101 hit->vvar=0.03*0.03;
1102 hit->uvar=0.1*0.1/12.;
1103 hit->z=trdhit->z;
1104 hit->cosa=1.;
1105 hit->sina=0.;
1106 hit->phiX=0.;
1107 hit->phiY=0.;
1108 hit->phiZ=0.;
1109 hit->nr=0.;
1110 hit->nz=0.;
1111 hit->status=trd_hit;
1112 hit->hit=NULL__null;
1113
1114 my_fdchits.push_back(hit);
1115}
1116
1117// Add FDC hits
1118void DTrackFitterKalmanSIMD::AddFDCHit(const DFDCPseudo *fdchit){
1119 DKalmanSIMDFDCHit_t *hit= new DKalmanSIMDFDCHit_t;
1120
1121 hit->t=fdchit->time;
1122 hit->uwire=fdchit->w;
1123 hit->vstrip=fdchit->s;
1124 hit->uvar=0.0833;
1125 hit->vvar=fdchit->ds*fdchit->ds;
1126 hit->z=fdchit->wire->origin.z();
1127 hit->cosa=cos(fdchit->wire->angle);
1128 hit->sina=sin(fdchit->wire->angle);
1129 hit->phiX=fdchit->wire->angles.X();
1130 hit->phiY=fdchit->wire->angles.Y();
1131 hit->phiZ=fdchit->wire->angles.Z();
1132
1133 hit->nr=0.;
1134 hit->nz=0.;
1135 hit->dE=1e6*fdchit->dE;
1136 hit->hit=fdchit;
1137 hit->status=good_hit;
1138
1139 my_fdchits.push_back(hit);
1140}
1141
1142// Add CDC hits
1143void DTrackFitterKalmanSIMD::AddCDCHit (const DCDCTrackHit *cdchit){
1144 DKalmanSIMDCDCHit_t *hit= new DKalmanSIMDCDCHit_t;
1145
1146 hit->hit=cdchit;
1147 hit->status=good_hit;
1148 hit->origin.Set(cdchit->wire->origin.x(),cdchit->wire->origin.y());
1149 double one_over_uz=1./cdchit->wire->udir.z();
1150 hit->dir.Set(one_over_uz*cdchit->wire->udir.x(),
1151 one_over_uz*cdchit->wire->udir.y());
1152 hit->z0wire=cdchit->wire->origin.z();
1153 hit->cosstereo=cos(cdchit->wire->stereo);
1154 hit->tdrift=cdchit->tdrift;
1155 my_cdchits.push_back(hit);
1156}
1157
1158// Calculate the derivative of the state vector with respect to z
1159jerror_t DTrackFitterKalmanSIMD::CalcDeriv(double z,
1160 const DMatrix5x1 &S,
1161 double dEdx,
1162 DMatrix5x1 &D){
1163 double tx=S(state_tx),ty=S(state_ty);
1164 double q_over_p=S(state_q_over_p);
1165
1166 // Turn off dEdx if the magnitude of the momentum drops below some cutoff
1167 if (fabs(q_over_p)>Q_OVER_P_MAX){
1168 dEdx=0.;
1169 }
1170 // Try to keep the direction tangents from heading towards 90 degrees
1171 if (fabs(tx)>TAN_MAX10.) tx=TAN_MAX10.*(tx>0.0?1.:-1.);
1172 if (fabs(ty)>TAN_MAX10.) ty=TAN_MAX10.*(ty>0.0?1.:-1.);
1173
1174 // useful combinations of terms
1175 double kq_over_p=qBr2p0.003*q_over_p;
1176 double tx2=tx*tx;
1177 double ty2=ty*ty;
1178 double txty=tx*ty;
1179 double one_plus_tx2=1.+tx2;
1180 double dsdz=sqrt(one_plus_tx2+ty2);
1181 double dtx_Bfac=ty*Bz+txty*Bx-one_plus_tx2*By;
1182 double dty_Bfac=Bx*(1.+ty2)-txty*By-tx*Bz;
1183 double kq_over_p_dsdz=kq_over_p*dsdz;
1184
1185 // Derivative of S with respect to z
1186 D(state_x)=tx;
1187 D(state_y)=ty;
1188 D(state_tx)=kq_over_p_dsdz*dtx_Bfac;
1189 D(state_ty)=kq_over_p_dsdz*dty_Bfac;
1190
1191 D(state_q_over_p)=0.;
1192 if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS3.0e-8){
1193 double q_over_p_sq=q_over_p*q_over_p;
1194 double E=sqrt(1./q_over_p_sq+mass2);
1195 D(state_q_over_p)=-q_over_p_sq*q_over_p*E*dEdx*dsdz;
1196 }
1197 return NOERROR;
1198}
1199
1200// Reference trajectory for forward tracks in CDC region
1201// At each point we store the state vector and the Jacobian needed to get to
1202//this state along z from the previous state.
1203jerror_t DTrackFitterKalmanSIMD::SetCDCForwardReferenceTrajectory(DMatrix5x1 &S){
1204 int i=0,forward_traj_length=forward_traj.size();
1205 double z=z_;
1206 double r2=0.;
1207 bool stepped_to_boundary=false;
1208
1209 // Magnetic field and gradient at beginning of trajectory
1210 //bfield->GetField(x_,y_,z_,Bx,By,Bz);
1211 bfield->GetFieldAndGradient(x_,y_,z_,Bx,By,Bz,
1212 dBxdx,dBxdy,dBxdz,dBydx,
1213 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
1214
1215 // Reset cdc status flags
1216 for (unsigned int i=0;i<my_cdchits.size();i++){
1217 if (my_cdchits[i]->status!=late_hit) my_cdchits[i]->status=good_hit;
1218 }
1219
1220 // Continue adding to the trajectory until we have reached the endplate
1221 // or the maximum radius
1222 while(z<endplate_z_downstream && z>cdc_origin[2] &&
1223 r2<endplate_r2max && fabs(S(state_q_over_p))<Q_OVER_P_MAX
1224 && fabs(S(state_tx))<TAN_MAX10.
1225 && fabs(S(state_ty))<TAN_MAX10.
1226 ){
1227 if (PropagateForwardCDC(forward_traj_length,i,z,r2,S,stepped_to_boundary)
1228 !=NOERROR) return UNRECOVERABLE_ERROR;
1229 }
1230
1231 // Only use hits that would fall within the range of the reference trajectory
1232 /*
1233 for (unsigned int i=0;i<my_cdchits.size();i++){
1234 DKalmanSIMDCDCHit_t *hit=my_cdchits[i];
1235 double my_r2=(hit->origin+(z-hit->z0wire)*hit->dir).Mod2();
1236 if (my_r2>r2) hit->status=bad_hit;
1237 }
1238 */
1239
1240 // If the current length of the trajectory deque is less than the previous
1241 // trajectory deque, remove the extra elements and shrink the deque
1242 if (i<(int)forward_traj.size()){
1243 forward_traj_length=forward_traj.size();
1244 for (int j=0;j<forward_traj_length-i;j++){
1245 forward_traj.pop_front();
1246 }
1247 }
1248
1249 // return an error if there are not enough entries in the trajectory
1250 if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE;
1251
1252 if (DEBUG_LEVEL>20)
1253 {
1254 cout << "--- Forward cdc trajectory ---" <<endl;
1255 for (unsigned int m=0;m<forward_traj.size();m++){
1256 // DMatrix5x1 S=*(forward_traj[m].S);
1257 DMatrix5x1 S=(forward_traj[m].S);
1258 double tx=S(state_tx),ty=S(state_ty);
1259 double phi=atan2(ty,tx);
1260 double cosphi=cos(phi);
1261 double sinphi=sin(phi);
1262 double p=fabs(1./S(state_q_over_p));
1263 double tanl=1./sqrt(tx*tx+ty*ty);
1264 double sinl=sin(atan(tanl));
1265 double cosl=cos(atan(tanl));
1266 cout
1267 << setiosflags(ios::fixed)<< "pos: " << setprecision(4)
1268 << forward_traj[m].S(state_x) << ", "
1269 << forward_traj[m].S(state_y) << ", "
1270 << forward_traj[m].z << " mom: "
1271 << p*cosphi*cosl<< ", " << p*sinphi*cosl << ", "
1272 << p*sinl << " -> " << p
1273 <<" s: " << setprecision(3)
1274 << forward_traj[m].s
1275 <<" t: " << setprecision(3)
1276 << forward_traj[m].t/SPEED_OF_LIGHT29.9792458
1277 <<" B: " << forward_traj[m].B
1278 << endl;
1279 }
1280 }
1281
1282 // Current state vector
1283 S=forward_traj[0].S;
1284
1285 // position at the end of the swim
1286 x_=forward_traj[0].S(state_x);
1287 y_=forward_traj[0].S(state_y);
1288 z_=forward_traj[0].z;
1289
1290 return NOERROR;
1291}
1292
1293// Routine that extracts the state vector propagation part out of the reference
1294// trajectory loop
1295jerror_t DTrackFitterKalmanSIMD::PropagateForwardCDC(int length,int &index,
1296 double &z,double &r2,
1297 DMatrix5x1 &S,
1298 bool &stepped_to_boundary){
1299 DMatrix5x5 J,Q;
1300 DKalmanForwardTrajectory_t temp;
1301 int my_i=0;
1302 temp.h_id=0;
1303 temp.num_hits=0;
1304 double dEdx=0.;
1305 double s_to_boundary=1e6;
1306 double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
1307
1308 // current position
1309 DVector3 pos(S(state_x),S(state_y),z);
1310 temp.z=z;
1311 // squared radius
1312 r2=pos.Perp2();
1313
1314 temp.s=len;
1315 temp.t=ftime;
1316 temp.S=S;
1317
1318 // Kinematic variables
1319 double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
1320 double one_over_beta2=1.+mass2*q_over_p_sq;
1321 if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8;
1322
1323 // get material properties from the Root Geometry
1324 if (ENABLE_BOUNDARY_CHECK && fit_type==kTimeBased){
1325 DVector3 mom(S(state_tx),S(state_ty),1.);
1326 if(geom->FindMatKalman(pos,mom,temp.K_rho_Z_over_A,
1327 temp.rho_Z_over_A,temp.LnI,temp.Z,
1328 temp.chi2c_factor,temp.chi2a_factor,
1329 temp.chi2a_corr,
1330 last_material_map,
1331 &s_to_boundary)!=NOERROR){
1332 return UNRECOVERABLE_ERROR;
1333 }
1334 }
1335 else
1336 {
1337 if(geom->FindMatKalman(pos,temp.K_rho_Z_over_A,
1338 temp.rho_Z_over_A,temp.LnI,temp.Z,
1339 temp.chi2c_factor,temp.chi2a_factor,
1340 temp.chi2a_corr,
1341 last_material_map)!=NOERROR){
1342 return UNRECOVERABLE_ERROR;
1343 }
1344 }
1345
1346 // Get dEdx for the upcoming step
1347 if (CORRECT_FOR_ELOSS){
1348 dEdx=GetdEdx(S(state_q_over_p),temp.K_rho_Z_over_A,temp.rho_Z_over_A,
1349 temp.LnI,temp.Z);
1350 }
1351
1352 index++;
1353 if (index<=length){
1354 my_i=length-index;
1355 forward_traj[my_i].s=temp.s;
1356 forward_traj[my_i].t=temp.t;
1357 forward_traj[my_i].h_id=temp.h_id;
1358 forward_traj[my_i].num_hits=0;
1359 forward_traj[my_i].z=temp.z;
1360 forward_traj[my_i].rho_Z_over_A=temp.rho_Z_over_A;
1361 forward_traj[my_i].K_rho_Z_over_A=temp.K_rho_Z_over_A;
1362 forward_traj[my_i].LnI=temp.LnI;
1363 forward_traj[my_i].Z=temp.Z;
1364 forward_traj[my_i].S=S;
1365 }
1366
1367 // Determine the step size based on energy loss
1368 //double step=mStepSizeS*dz_ds;
1369 double max_step_size
1370 =(z<endplate_z&& r2>endplate_r2min)?mCDCInternalStepSize:mStepSizeS;
1371 double ds=mStepSizeS;
1372 if (z<endplate_z && r2<endplate_r2max && z>cdc_origin[2]){
1373 if (!stepped_to_boundary){
1374 stepped_to_boundary=false;
1375 if (fabs(dEdx)>EPS3.0e-8){
1376 ds=DE_PER_STEP0.001/fabs(dEdx);
1377 }
1378 if (ds>max_step_size) ds=max_step_size;
1379 if (s_to_boundary<ds){
1380 ds=s_to_boundary+EPS31.e-2;
1381 stepped_to_boundary=true;
1382 }
1383 if(ds<MIN_STEP_SIZE0.1)ds=MIN_STEP_SIZE0.1;
1384 }
1385 else{
1386 ds=MIN_STEP_SIZE0.1;
1387 stepped_to_boundary=false;
1388 }
1389 }
1390 double newz=z+ds*dz_ds; // new z position
1391
1392 // Store magnetic field
1393 temp.B=sqrt(Bx*Bx+By*By+Bz*Bz);
1394
1395 // Step through field
1396 ds=FasterStep(z,newz,dEdx,S);
1397
1398 // update path length
1399 len+=fabs(ds);
1400
1401 // Update flight time
1402 ftime+=ds*sqrt(one_over_beta2);// in units where c=1
1403
1404 // Get the contribution to the covariance matrix due to multiple
1405 // scattering
1406 GetProcessNoise(z,ds,temp.chi2c_factor,temp.chi2a_factor,temp.chi2a_corr,
1407 temp.S,Q);
1408
1409 // Energy loss straggling
1410 if (CORRECT_FOR_ELOSS){
1411 double varE=GetEnergyVariance(ds,one_over_beta2,temp.K_rho_Z_over_A);
1412 Q(state_q_over_p,state_q_over_p)=varE*q_over_p_sq*q_over_p_sq*one_over_beta2;
1413 }
1414
1415 // Compute the Jacobian matrix and its transpose
1416 StepJacobian(newz,z,S,dEdx,J);
1417
1418 // update the trajectory
1419 if (index<=length){
1420 forward_traj[my_i].B=temp.B;
1421 forward_traj[my_i].Q=Q;
1422 forward_traj[my_i].J=J;
1423 }
1424 else{
1425 temp.Q=Q;
1426 temp.J=J;
1427 temp.Ckk=Zero5x5;
1428 temp.Skk=Zero5x1;
1429 forward_traj.push_front(temp);
1430 }
1431
1432 //update z
1433 z=newz;
1434
1435 return NOERROR;
1436}
1437
1438// Routine that extracts the state vector propagation part out of the reference
1439// trajectory loop
1440jerror_t DTrackFitterKalmanSIMD::PropagateCentral(int length, int &index,
1441 DVector2 &my_xy,
1442 double &var_t_factor,
1443 DMatrix5x1 &Sc,
1444 bool &stepped_to_boundary){
1445 DKalmanCentralTrajectory_t temp;
1446 DMatrix5x5 J; // State vector Jacobian matrix
1447 DMatrix5x5 Q; // Process noise covariance matrix
1448
1449 //Initialize some variables needed later
1450 double dEdx=0.;
1451 double s_to_boundary=1e6;
1452 int my_i=0;
1453 // Kinematic variables
1454 double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl)));
1455 double q_over_p_sq=q_over_p*q_over_p;
1456 double one_over_beta2=1.+mass2*q_over_p_sq;
1457 if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8;
1458
1459 // Reset D to zero
1460 Sc(state_D)=0.;
1461
1462 temp.xy=my_xy;
1463 temp.s=len;
1464 temp.t=ftime;
1465 temp.h_id=0;
1466 temp.S=Sc;
1467
1468 // Store magnitude of magnetic field
1469 temp.B=sqrt(Bx*Bx+By*By+Bz*Bz);
1470
1471 // get material properties from the Root Geometry
1472 DVector3 pos3d(my_xy.X(),my_xy.Y(),Sc(state_z));
1473 if (ENABLE_BOUNDARY_CHECK && fit_type==kTimeBased){
1474 DVector3 mom(cos(Sc(state_phi)),sin(Sc(state_phi)),Sc(state_tanl));
1475 if(geom->FindMatKalman(pos3d,mom,temp.K_rho_Z_over_A,
1476 temp.rho_Z_over_A,temp.LnI,temp.Z,
1477 temp.chi2c_factor,temp.chi2a_factor,
1478 temp.chi2a_corr,
1479 last_material_map,
1480 &s_to_boundary)
1481 !=NOERROR){
1482 return UNRECOVERABLE_ERROR;
1483 }
1484 }
1485 else if(geom->FindMatKalman(pos3d,temp.K_rho_Z_over_A,
1486 temp.rho_Z_over_A,temp.LnI,temp.Z,
1487 temp.chi2c_factor,temp.chi2a_factor,
1488 temp.chi2a_corr,
1489 last_material_map)!=NOERROR){
1490 return UNRECOVERABLE_ERROR;
1491 }
1492
1493 if (CORRECT_FOR_ELOSS){
1494 dEdx=GetdEdx(q_over_p,temp.K_rho_Z_over_A,temp.rho_Z_over_A,temp.LnI,
1495 temp.Z);
1496 }
1497
1498 // If the deque already exists, update it
1499 index++;
1500 if (index<=length){
1501 my_i=length-index;
1502 central_traj[my_i].B=temp.B;
1503 central_traj[my_i].s=temp.s;
1504 central_traj[my_i].t=temp.t;
1505 central_traj[my_i].h_id=0;
1506 central_traj[my_i].xy=temp.xy;
1507 central_traj[my_i].rho_Z_over_A=temp.rho_Z_over_A;
1508 central_traj[my_i].K_rho_Z_over_A=temp.K_rho_Z_over_A;
1509 central_traj[my_i].LnI=temp.LnI;
1510 central_traj[my_i].Z=temp.Z;
1511 central_traj[my_i].S=Sc;
1512 }
1513
1514 // Adjust the step size
1515 double step_size=mStepSizeS;
1516 if (stepped_to_boundary){
1517 step_size=MIN_STEP_SIZE0.1;
1518 stepped_to_boundary=false;
1519 }
1520 else{
1521 if (fabs(dEdx)>EPS3.0e-8){
1522 step_size=DE_PER_STEP0.001/fabs(dEdx);
1523 }
1524 if(step_size>mStepSizeS) step_size=mStepSizeS;
1525 if (s_to_boundary<step_size){
1526 step_size=s_to_boundary+EPS31.e-2;
1527 stepped_to_boundary=true;
1528 }
1529 if(step_size<MIN_STEP_SIZE0.1)step_size=MIN_STEP_SIZE0.1;
1530 }
1531 double r2=my_xy.Mod2();
1532 if (r2>endplate_r2min
1533 && step_size>mCDCInternalStepSize) step_size=mCDCInternalStepSize;
1534 // Propagate the state through the field
1535 FasterStep(my_xy,step_size,Sc,dEdx);
1536
1537 // update path length
1538 len+=step_size;
1539
1540 // Update flight time
1541 double dt=step_size*sqrt(one_over_beta2); // in units of c=1
1542 double one_minus_beta2=1.-1./one_over_beta2;
1543 ftime+=dt;
1544 var_ftime+=dt*dt*one_minus_beta2*one_minus_beta2*0.0004;
1545 var_t_factor=dt*dt*one_minus_beta2*one_minus_beta2;
1546
1547 //printf("t %f sigt %f\n",TIME_UNIT_CONVERSION*ftime,TIME_UNIT_CONVERSION*sqrt(var_ftime));
1548
1549 // Multiple scattering
1550 GetProcessNoiseCentral(step_size,temp.chi2c_factor,temp.chi2a_factor,
1551 temp.chi2a_corr,temp.S,Q);
1552
1553 // Energy loss straggling in the approximation of thick absorbers
1554 if (CORRECT_FOR_ELOSS){
1555 double varE
1556 =GetEnergyVariance(step_size,one_over_beta2,temp.K_rho_Z_over_A);
1557 Q(state_q_over_pt,state_q_over_pt)
1558 +=varE*temp.S(state_q_over_pt)*temp.S(state_q_over_pt)*one_over_beta2
1559 *q_over_p_sq;
1560 }
1561
1562 // B-field and gradient at current (x,y,z)
1563 bfield->GetFieldAndGradient(my_xy.X(),my_xy.Y(),Sc(state_z),Bx,By,Bz,
1564 dBxdx,dBxdy,dBxdz,dBydx,
1565 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
1566
1567 // Compute the Jacobian matrix and its transpose
1568 StepJacobian(my_xy,temp.xy-my_xy,-step_size,Sc,dEdx,J);
1569
1570 // Update the trajectory info
1571 if (index<=length){
1572 central_traj[my_i].Q=Q;
1573 central_traj[my_i].J=J;
1574 }
1575 else{
1576 temp.Q=Q;
1577 temp.J=J;
1578 temp.Ckk=Zero5x5;
1579 temp.Skk=Zero5x1;
1580 central_traj.push_front(temp);
1581 }
1582
1583 return NOERROR;
1584}
1585
1586
1587
1588// Reference trajectory for central tracks
1589// At each point we store the state vector and the Jacobian needed to get to this state
1590// along s from the previous state.
1591// The tricky part is that we swim out from the target to find Sc and pos along the trajectory
1592// but we need the Jacobians for the opposite direction, because the filter proceeds from
1593// the outer hits toward the target.
1594jerror_t DTrackFitterKalmanSIMD::SetCDCReferenceTrajectory(const DVector2 &xy,
1595 DMatrix5x1 &Sc){
1596 bool stepped_to_boundary=false;
1597 int i=0,central_traj_length=central_traj.size();
1598 // factor for scaling momentum resolution to propagate variance in flight
1599 // time
1600 double var_t_factor=0;
1601
1602 // Magnetic field and gradient at beginning of trajectory
1603 //bfield->GetField(x_,y_,z_,Bx,By,Bz);
1604 bfield->GetFieldAndGradient(x_,y_,z_,Bx,By,Bz,
1605 dBxdx,dBxdy,dBxdz,dBydx,
1606 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
1607
1608 // Copy of initial position in xy
1609 DVector2 my_xy=xy;
1610 double r2=xy.Mod2(),z=z_;
1611
1612 // Reset cdc status flags
1613 for (unsigned int j=0;j<my_cdchits.size();j++){
1614 if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
1615 }
1616
1617 // Continue adding to the trajectory until we have reached the endplate
1618 // or the maximum radius
1619 while(z<endplate_z && z>=Z_MIN-100. && r2<endplate_r2max
1620 && fabs(Sc(state_q_over_pt))<Q_OVER_PT_MAX100.
1621 ){
1622 if (PropagateCentral(central_traj_length,i,my_xy,var_t_factor,Sc,stepped_to_boundary)
1623 !=NOERROR) return UNRECOVERABLE_ERROR;
1624 z=Sc(state_z);
1625 r2=my_xy.Mod2();
1626 }
1627
1628 // If the current length of the trajectory deque is less than the previous
1629 // trajectory deque, remove the extra elements and shrink the deque
1630 if (i<(int)central_traj.size()){
1631 int central_traj_length=central_traj.size();
1632 for (int j=0;j<central_traj_length-i;j++){
1633 central_traj.pop_front();
1634 }
1635 }
1636
1637 // Only use hits that would fall within the range of the reference trajectory
1638 /*for (unsigned int j=0;j<my_cdchits.size();j++){
1639 DKalmanSIMDCDCHit_t *hit=my_cdchits[j];
1640 double my_r2=(hit->origin+(z-hit->z0wire)*hit->dir).Mod2();
1641 if (my_r2>r2) hit->status=bad_hit;
1642 }
1643 */
1644
1645 // return an error if there are not enough entries in the trajectory
1646 if (central_traj.size()<2) return RESOURCE_UNAVAILABLE;
1647
1648 if (DEBUG_LEVEL>20)
1649 {
1650 cout << "---------" << central_traj.size() <<" entries------" <<endl;
1651 for (unsigned int m=0;m<central_traj.size();m++){
1652 DMatrix5x1 S=central_traj[m].S;
1653 double cosphi=cos(S(state_phi));
1654 double sinphi=sin(S(state_phi));
1655 double pt=fabs(1./S(state_q_over_pt));
1656 double tanl=S(state_tanl);
1657
1658 cout
1659 << m << "::"
1660 << setiosflags(ios::fixed)<< "pos: " << setprecision(4)
1661 << central_traj[m].xy.X() << ", "
1662 << central_traj[m].xy.Y() << ", "
1663 << central_traj[m].S(state_z) << " mom: "
1664 << pt*cosphi << ", " << pt*sinphi << ", "
1665 << pt*tanl << " -> " << pt/cos(atan(tanl))
1666 <<" s: " << setprecision(3)
1667 << central_traj[m].s
1668 <<" t: " << setprecision(3)
1669 << central_traj[m].t/SPEED_OF_LIGHT29.9792458
1670 <<" B: " << central_traj[m].B
1671 << endl;
1672 }
1673 }
1674
1675 // State at end of swim
1676 Sc=central_traj[0].S;
1677
1678 return NOERROR;
1679}
1680
1681// Routine that extracts the state vector propagation part out of the reference
1682// trajectory loop
1683jerror_t DTrackFitterKalmanSIMD::PropagateForward(int length,int &i,
1684 double &z,double zhit,
1685 DMatrix5x1 &S, bool &done,
1686 bool &stepped_to_boundary,
1687 bool &stepped_to_endplate){
1688 DMatrix5x5 J,Q;
1689 DKalmanForwardTrajectory_t temp;
1690
1691 // Initialize some variables
1692 temp.h_id=0;
1693 temp.num_hits=0;
1694 int my_i=0;
1695 double s_to_boundary=1e6;
1696 double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
1697
1698 // current position
1699 DVector3 pos(S(state_x),S(state_y),z);
1700 double r2=pos.Perp2();
1701
1702 temp.s=len;
1703 temp.t=ftime;
1704 temp.z=z;
1705 temp.S=S;
1706
1707 // Kinematic variables
1708 double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
1709 double one_over_beta2=1.+mass2*q_over_p_sq;
1710 if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8;
1711
1712 // get material properties from the Root Geometry
1713 if (ENABLE_BOUNDARY_CHECK && fit_type==kTimeBased){
1714 DVector3 mom(S(state_tx),S(state_ty),1.);
1715 if (geom->FindMatKalman(pos,mom,temp.K_rho_Z_over_A,
1716 temp.rho_Z_over_A,temp.LnI,temp.Z,
1717 temp.chi2c_factor,temp.chi2a_factor,
1718 temp.chi2a_corr,
1719 last_material_map,
1720 &s_to_boundary)
1721 !=NOERROR){
1722 return UNRECOVERABLE_ERROR;
1723 }
1724 }
1725 else
1726 {
1727 if (geom->FindMatKalman(pos,temp.K_rho_Z_over_A,
1728 temp.rho_Z_over_A,temp.LnI,temp.Z,
1729 temp.chi2c_factor,temp.chi2a_factor,
1730 temp.chi2a_corr,
1731 last_material_map)!=NOERROR){
1732 return UNRECOVERABLE_ERROR;
1733 }
1734 }
1735
1736 // Get dEdx for the upcoming step
1737 double dEdx=0.;
1738 if (CORRECT_FOR_ELOSS){
1739 dEdx=GetdEdx(S(state_q_over_p),temp.K_rho_Z_over_A,
1740 temp.rho_Z_over_A,temp.LnI,temp.Z);
1741 }
1742 i++;
1743 my_i=length-i;
1744 if (i<=length){
1745 forward_traj[my_i].s=temp.s;
1746 forward_traj[my_i].t=temp.t;
1747 forward_traj[my_i].h_id=temp.h_id;
1748 forward_traj[my_i].num_hits=temp.num_hits;
1749 forward_traj[my_i].z=temp.z;
1750 forward_traj[my_i].rho_Z_over_A=temp.rho_Z_over_A;
1751 forward_traj[my_i].K_rho_Z_over_A=temp.K_rho_Z_over_A;
1752 forward_traj[my_i].LnI=temp.LnI;
1753 forward_traj[my_i].Z=temp.Z;
1754 forward_traj[my_i].S=S;
1755 }
1756 else{
1757 temp.S=S;
1758 }
1759
1760 // Determine the step size based on energy loss
1761 // step=mStepSizeS*dz_ds;
1762 double max_step_size
1763 =(z<endplate_z&& r2>endplate_r2min)?mCentralStepSize:mStepSizeS;
1764 double ds=mStepSizeS;
1765 if (z>cdc_origin[2]){
1766 if (!stepped_to_boundary){
1767 stepped_to_boundary=false;
1768 if (fabs(dEdx)>EPS3.0e-8){
1769 ds=DE_PER_STEP0.001/fabs(dEdx);
1770 }
1771 if (ds>max_step_size) ds=max_step_size;
1772 if (s_to_boundary<ds){
1773 ds=s_to_boundary+EPS31.e-2;
1774 stepped_to_boundary=true;
1775 }
1776 if(ds<MIN_STEP_SIZE0.1)ds=MIN_STEP_SIZE0.1;
1777
1778 }
1779 else{
1780 ds=MIN_STEP_SIZE0.1;
1781 stepped_to_boundary=false;
1782 }
1783 }
1784
1785 double dz=stepped_to_endplate ? endplate_dz : ds*dz_ds;
1786 double newz=z+dz; // new z position
1787 // Check if we are stepping through the CDC endplate
1788 if (newz>endplate_z && z<endplate_z){
1789 // _DBG_ << endl;
1790 newz=endplate_z+EPS31.e-2;
1791 stepped_to_endplate=true;
1792 }
1793
1794 // Check if we are about to step to one of the wire planes
1795 done=false;
1796 if (newz>zhit){
1797 newz=zhit;
1798 done=true;
1799 }
1800
1801 // Store magnitude of magnetic field
1802 temp.B=sqrt(Bx*Bx+By*By+Bz*Bz);
1803
1804 // Step through field
1805 ds=FasterStep(z,newz,dEdx,S);
1806
1807 // update path length
1808 len+=ds;
1809
1810 // update flight time
1811 ftime+=ds*sqrt(one_over_beta2); // in units where c=1
1812
1813 // Get the contribution to the covariance matrix due to multiple
1814 // scattering
1815 GetProcessNoise(z,ds,temp.chi2c_factor,temp.chi2a_factor,temp.chi2a_corr,
1816 temp.S,Q);
1817
1818 // Energy loss straggling
1819 if (CORRECT_FOR_ELOSS){
1820 double varE=GetEnergyVariance(ds,one_over_beta2,temp.K_rho_Z_over_A);
1821 Q(state_q_over_p,state_q_over_p)=varE*q_over_p_sq*q_over_p_sq*one_over_beta2;
1822 }
1823
1824 // Compute the Jacobian matrix and its transpose
1825 StepJacobian(newz,z,S,dEdx,J);
1826
1827 // update the trajectory data
1828 if (i<=length){
1829 forward_traj[my_i].B=temp.B;
1830 forward_traj[my_i].Q=Q;
1831 forward_traj[my_i].J=J;
1832 }
1833 else{
1834 temp.Q=Q;
1835 temp.J=J;
1836 temp.Ckk=Zero5x5;
1837 temp.Skk=Zero5x1;
1838 forward_traj.push_front(temp);
1839 }
1840
1841 // update z
1842 z=newz;
1843
1844 return NOERROR;
1845}
1846
1847// Reference trajectory for trajectories with hits in the forward direction
1848// At each point we store the state vector and the Jacobian needed to get to this state
1849// along z from the previous state.
1850jerror_t DTrackFitterKalmanSIMD::SetReferenceTrajectory(DMatrix5x1 &S){
1851
1852 // Magnetic field and gradient at beginning of trajectory
1853 //bfield->GetField(x_,y_,z_,Bx,By,Bz);
1854 bfield->GetFieldAndGradient(x_,y_,z_,Bx,By,Bz,
1855 dBxdx,dBxdy,dBxdz,dBydx,
1856 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
1857
1858 // progress in z from hit to hit
1859 double z=z_;
1860 int i=0;
1861
1862 int forward_traj_length=forward_traj.size();
1863 // loop over the fdc hits
1864 double zhit=0.,old_zhit=0.;
1865 bool stepped_to_boundary=false;
1866 bool stepped_to_endplate=false;
1867 unsigned int m=0;
1868 double z_max=400.;
1869 double r2max=50.*50.;
1870 if (got_trd_gem_hits){
1871 z_max=600.;
1872 r2max=100.*100.;
1873 }
1874 for (m=0;m<my_fdchits.size();m++){
1875 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX
1876 || fabs(S(state_tx))>TAN_MAX10.
1877 || fabs(S(state_ty))>TAN_MAX10.
1878 || S(state_x)*S(state_x)+S(state_y)*S(state_y)>r2max
1879 || z>z_max || z<Z_MIN-100.
1880 ){
1881 break;
1882 }
1883
1884 zhit=my_fdchits[m]->z;
1885 if (fabs(old_zhit-zhit)>EPS3.0e-8){
1886 bool done=false;
1887 while (!done){
1888 if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX
1889 || fabs(S(state_tx))>TAN_MAX10.
1890 || fabs(S(state_ty))>TAN_MAX10.
1891 || S(state_x)*S(state_x)+S(state_y)*S(state_y)>r2max
1892 || z>z_max || z< Z_MIN-100.
1893 ){
1894 break;
1895 }
1896
1897 if (PropagateForward(forward_traj_length,i,z,zhit,S,done,
1898 stepped_to_boundary,stepped_to_endplate)
1899 !=NOERROR)
1900 return UNRECOVERABLE_ERROR;
1901 }
1902 }
1903 old_zhit=zhit;
1904 }
1905
1906 // If m<2 then no useable FDC hits survived the check on the magnitude on the
1907 // momentum
1908 if (m<2) return UNRECOVERABLE_ERROR;
1909
1910 // Make sure the reference trajectory goes one step beyond the most
1911 // downstream hit plane
1912 if (m==my_fdchits.size()){
1913 bool done=false;
1914 if (PropagateForward(forward_traj_length,i,z,z_max,S,done,
1915 stepped_to_boundary,stepped_to_endplate)
1916 !=NOERROR)
1917 return UNRECOVERABLE_ERROR;
1918 if (PropagateForward(forward_traj_length,i,z,z_max,S,done,
1919 stepped_to_boundary,stepped_to_endplate)
1920 !=NOERROR)
1921 return UNRECOVERABLE_ERROR;
1922 }
1923
1924 // Shrink the deque if the new trajectory has less points in it than the
1925 // old trajectory
1926 if (i<(int)forward_traj.size()){
1927 int mylen=forward_traj.size();
1928 //_DBG_ << "Shrinking: " << mylen << " to " << i << endl;
1929 for (int j=0;j<mylen-i;j++){
1930 forward_traj.pop_front();
1931 }
1932 // _DBG_ << " Now " << forward_traj.size() << endl;
1933 }
1934
1935 // If we lopped off some hits on the downstream end, truncate the trajectory to
1936 // the point in z just beyond the last valid hit
1937 unsigned int my_id=my_fdchits.size();
1938 if (m<my_id){
1939 if (zhit<z) my_id=m;
1940 else my_id=m-1;
1941 zhit=my_fdchits[my_id-1]->z;
1942 //_DBG_ << "Shrinking: " << forward_traj.size()<< endl;
1943 for (;;){
1944 z=forward_traj[0].z;
1945 if (z<zhit+EPS21.e-4) break;
1946 forward_traj.pop_front();
1947 }
1948 //_DBG_ << " Now " << forward_traj.size() << endl;
1949
1950 // Temporory structure keeping state and trajectory information
1951 DKalmanForwardTrajectory_t temp;
1952 temp.h_id=0;
1953 temp.num_hits=0;
1954 temp.B=0.;
1955 temp.K_rho_Z_over_A=temp.rho_Z_over_A=temp.LnI=0.;
1956 temp.Z=0.;
1957 temp.Q=Zero5x5;
1958
1959 // last S vector
1960 S=forward_traj[0].S;
1961
1962 // Step just beyond the last hit
1963 double newz=z+0.01;
1964 double ds=Step(z,newz,0.,S); // ignore energy loss for this small step
1965 temp.s=forward_traj[0].s+ds;
1966 temp.z=newz;
1967 temp.S=S;
1968
1969 // Flight time
1970 double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
1971 double one_over_beta2=1.+mass2*q_over_p_sq;
1972 if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8;
1973 temp.t=forward_traj[0].t+ds*sqrt(one_over_beta2); // in units where c=1
1974
1975 // Covariance and state vector needed for smoothing code
1976 temp.Ckk=Zero5x5;
1977 temp.Skk=Zero5x1;
1978
1979 // Jacobian matrices
1980 temp.J=I5x5;
1981
1982 forward_traj.push_front(temp);
1983 }
1984
1985 // return an error if there are not enough entries in the trajectory
1986 if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE;
1987
1988 // Fill in Lorentz deflection parameters
1989 for (unsigned int m=0;m<forward_traj.size();m++){
1990 if (my_id>0){
1991 unsigned int hit_id=my_id-1;
1992 double z=forward_traj[m].z;
1993 if (fabs(z-my_fdchits[hit_id]->z)<EPS21.e-4){
1994 forward_traj[m].h_id=my_id;
1995
1996 if (my_fdchits[hit_id]->hit!=NULL__null){
1997 // Get the magnetic field at this position along the trajectory
1998 bfield->GetField(forward_traj[m].S(state_x),forward_traj[m].S(state_y),
1999 z,Bx,By,Bz);
2000 double Br=sqrt(Bx*Bx+By*By);
2001
2002 // Angle between B and wire
2003 double my_phi=0.;
2004 if (Br>0.) my_phi=acos((Bx*my_fdchits[hit_id]->sina
2005 +By*my_fdchits[hit_id]->cosa)/Br);
2006 /*
2007 lorentz_def->GetLorentzCorrectionParameters(forward_traj[m].pos.x(),
2008 forward_traj[m].pos.y(),
2009 forward_traj[m].pos.z(),
2010 tanz,tanr);
2011 my_fdchits[hit_id]->nr=tanr;
2012 my_fdchits[hit_id]->nz=tanz;
2013 */
2014
2015 my_fdchits[hit_id]->nr=LORENTZ_NR_PAR1*Bz*(1.+LORENTZ_NR_PAR2*Br);
2016 my_fdchits[hit_id]->nz=(LORENTZ_NZ_PAR1+LORENTZ_NZ_PAR2*Bz)*(Br*cos(my_phi));
2017 }
2018
2019 my_id--;
2020
2021 unsigned int num=1;
2022 while (hit_id>0
2023 && fabs(my_fdchits[hit_id]->z-my_fdchits[hit_id-1]->z)<EPS3.0e-8){
2024 hit_id=my_id-1;
2025 num++;
2026 my_id--;
2027 }
2028 forward_traj[m].num_hits=num;
2029 }
2030
2031 }
2032 }
2033
2034 if (DEBUG_LEVEL>20)
2035 {
2036 cout << "--- Forward fdc trajectory ---" <<endl;
2037 for (unsigned int m=0;m<forward_traj.size();m++){
2038 DMatrix5x1 S=(forward_traj[m].S);
2039 double tx=S(state_tx),ty=S(state_ty);
2040 double phi=atan2(ty,tx);
2041 double cosphi=cos(phi);
2042 double sinphi=sin(phi);
2043 double p=fabs(1./S(state_q_over_p));
2044 double tanl=1./sqrt(tx*tx+ty*ty);
2045 double sinl=sin(atan(tanl));
2046 double cosl=cos(atan(tanl));
2047 cout
2048 << setiosflags(ios::fixed)<< "pos: " << setprecision(4)
2049 << forward_traj[m].S(state_x) << ", "
2050 << forward_traj[m].S(state_y) << ", "
2051 << forward_traj[m].z << " mom: "
2052 << p*cosphi*cosl<< ", " << p*sinphi*cosl << ", "
2053 << p*sinl << " -> " << p
2054 <<" s: " << setprecision(3)
2055 << forward_traj[m].s
2056 <<" t: " << setprecision(3)
2057 << forward_traj[m].t/SPEED_OF_LIGHT29.9792458
2058 <<" id: " << forward_traj[m].h_id
2059 << endl;
2060 }
2061 }
2062
2063
2064 // position at the end of the swim
2065 z_=z;
2066 x_=S(state_x);
2067 y_=S(state_y);
2068
2069 return NOERROR;
2070}
2071
2072// Step the state vector through the field from oldz to newz.
2073// Uses the 4th-order Runga-Kutte algorithm.
2074double DTrackFitterKalmanSIMD::Step(double oldz,double newz, double dEdx,
2075 DMatrix5x1 &S){
2076 double delta_z=newz-oldz;
2077 if (fabs(delta_z)<EPS3.0e-8) return 0.; // skip if the step is too small
2078
2079 // Direction tangents
2080 double tx=S(state_tx);
2081 double ty=S(state_ty);
2082 double ds=sqrt(1.+tx*tx+ty*ty)*delta_z;
2083
2084 double delta_z_over_2=0.5*delta_z;
2085 double midz=oldz+delta_z_over_2;
2086 DMatrix5x1 D1,D2,D3,D4;
2087
2088 //B-field and gradient at at (x,y,z)
2089 bfield->GetFieldAndGradient(S(state_x),S(state_y),oldz,Bx,By,Bz,
2090 dBxdx,dBxdy,dBxdz,dBydx,
2091 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
2092 double Bx0=Bx,By0=By,Bz0=Bz;
2093
2094 // Calculate the derivative and propagate the state to the next point
2095 CalcDeriv(oldz,S,dEdx,D1);
2096 DMatrix5x1 S1=S+delta_z_over_2*D1;
2097
2098 // Calculate the field at the first intermediate point
2099 double dx=S1(state_x)-S(state_x);
2100 double dy=S1(state_y)-S(state_y);
2101 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z_over_2;
2102 By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z_over_2;
2103 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z_over_2;
2104
2105 // Calculate the derivative and propagate the state to the next point
2106 CalcDeriv(midz,S1,dEdx,D2);
2107 S1=S+delta_z_over_2*D2;
2108
2109 // Calculate the field at the second intermediate point
2110 dx=S1(state_x)-S(state_x);
2111 dy=S1(state_y)-S(state_y);
2112 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z_over_2;
2113 By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z_over_2;
2114 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z_over_2;
2115
2116 // Calculate the derivative and propagate the state to the next point
2117 CalcDeriv(midz,S1,dEdx,D3);
2118 S1=S+delta_z*D3;
2119
2120 // Calculate the field at the final point
2121 dx=S1(state_x)-S(state_x);
2122 dy=S1(state_y)-S(state_y);
2123 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z;
2124 By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z;
2125 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z;
2126
2127 // Final derivative
2128 CalcDeriv(newz,S1,dEdx,D4);
2129
2130 // S+=delta_z*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4);
2131 double dz_over_6=delta_z*ONE_SIXTH0.16666666666666667;
2132 double dz_over_3=delta_z*ONE_THIRD0.33333333333333333;
2133 S+=dz_over_6*D1;
2134 S+=dz_over_3*D2;
2135 S+=dz_over_3*D3;
2136 S+=dz_over_6*D4;
2137
2138 // Don't let the magnitude of the momentum drop below some cutoff
2139 //if (fabs(S(state_q_over_p))>Q_OVER_P_MAX)
2140 // S(state_q_over_p)=Q_OVER_P_MAX*(S(state_q_over_p)>0.0?1.:-1.);
2141 // Try to keep the direction tangents from heading towards 90 degrees
2142 //if (fabs(S(state_tx))>TAN_MAX)
2143 // S(state_tx)=TAN_MAX*(S(state_tx)>0.0?1.:-1.);
2144 //if (fabs(S(state_ty))>TAN_MAX)
2145 // S(state_ty)=TAN_MAX*(S(state_ty)>0.0?1.:-1.);
2146
2147 return ds;
2148}
2149// Step the state vector through the field from oldz to newz.
2150// Uses the 4th-order Runga-Kutte algorithm.
2151// Uses the gradient to compute the field at the intermediate and last
2152// points.
2153double DTrackFitterKalmanSIMD::FasterStep(double oldz,double newz, double dEdx,
2154 DMatrix5x1 &S){
2155 double delta_z=newz-oldz;
2156 if (fabs(delta_z)<EPS3.0e-8) return 0.; // skip if the step is too small
2157
2158 // Direction tangents
2159 double tx=S(state_tx);
2160 double ty=S(state_ty);
2161 double ds=sqrt(1.+tx*tx+ty*ty)*delta_z;
2162
2163 double delta_z_over_2=0.5*delta_z;
2164 double midz=oldz+delta_z_over_2;
2165 DMatrix5x1 D1,D2,D3,D4;
2166 double Bx0=Bx,By0=By,Bz0=Bz;
2167
2168 // The magnetic field at the beginning of the step is assumed to be
2169 // obtained at the end of the previous step through StepJacobian
2170
2171 // Calculate the derivative and propagate the state to the next point
2172 CalcDeriv(oldz,S,dEdx,D1);
2173 DMatrix5x1 S1=S+delta_z_over_2*D1;
2174
2175 // Calculate the field at the first intermediate point
2176 double dx=S1(state_x)-S(state_x);
2177 double dy=S1(state_y)-S(state_y);
2178 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z_over_2;
2179 By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z_over_2;
2180 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z_over_2;
2181
2182 // Calculate the derivative and propagate the state to the next point
2183 CalcDeriv(midz,S1,dEdx,D2);
2184 S1=S+delta_z_over_2*D2;
2185
2186 // Calculate the field at the second intermediate point
2187 dx=S1(state_x)-S(state_x);
2188 dy=S1(state_y)-S(state_y);
2189 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z_over_2;
2190 By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z_over_2;
2191 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z_over_2;
2192
2193 // Calculate the derivative and propagate the state to the next point
2194 CalcDeriv(midz,S1,dEdx,D3);
2195 S1=S+delta_z*D3;
2196
2197 // Calculate the field at the final point
2198 dx=S1(state_x)-S(state_x);
2199 dy=S1(state_y)-S(state_y);
2200 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z;
2201 By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z;
2202 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z;
2203
2204 // Final derivative
2205 CalcDeriv(newz,S1,dEdx,D4);
2206
2207 // S+=delta_z*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4);
2208 double dz_over_6=delta_z*ONE_SIXTH0.16666666666666667;
2209 double dz_over_3=delta_z*ONE_THIRD0.33333333333333333;
2210 S+=dz_over_6*D1;
2211 S+=dz_over_3*D2;
2212 S+=dz_over_3*D3;
2213 S+=dz_over_6*D4;
2214
2215 // Don't let the magnitude of the momentum drop below some cutoff
2216 //if (fabs(S(state_q_over_p))>Q_OVER_P_MAX)
2217 // S(state_q_over_p)=Q_OVER_P_MAX*(S(state_q_over_p)>0.0?1.:-1.);
2218 // Try to keep the direction tangents from heading towards 90 degrees
2219 //if (fabs(S(state_tx))>TAN_MAX)
2220 // S(state_tx)=TAN_MAX*(S(state_tx)>0.0?1.:-1.);
2221 //if (fabs(S(state_ty))>TAN_MAX)
2222 // S(state_ty)=TAN_MAX*(S(state_ty)>0.0?1.:-1.);
2223
2224 return ds;
2225}
2226
2227
2228
2229// Compute the Jacobian matrix for the forward parametrization.
2230jerror_t DTrackFitterKalmanSIMD::StepJacobian(double oldz,double newz,
2231 const DMatrix5x1 &S,
2232 double dEdx,DMatrix5x5 &J){
2233 // Initialize the Jacobian matrix
2234 //J.Zero();
2235 //for (int i=0;i<5;i++) J(i,i)=1.;
2236 J=I5x5;
2237
2238 // Step in z
2239 double delta_z=newz-oldz;
2240 if (fabs(delta_z)<EPS3.0e-8) return NOERROR; //skip if the step is too small
2241
2242 // Current values of state vector variables
2243 double x=S(state_x), y=S(state_y),tx=S(state_tx),ty=S(state_ty);
2244 double q_over_p=S(state_q_over_p);
2245
2246 //B-field and field gradient at (x,y,z)
2247 //if (get_field)
2248 bfield->GetFieldAndGradient(x,y,oldz,Bx,By,Bz,dBxdx,dBxdy,
2249 dBxdz,dBydx,dBydy,
2250 dBydz,dBzdx,dBzdy,dBzdz);
2251
2252 // Don't let the magnitude of the momentum drop below some cutoff
2253 if (fabs(q_over_p)>Q_OVER_P_MAX){
2254 q_over_p=Q_OVER_P_MAX*(q_over_p>0.0?1.:-1.);
2255 dEdx=0.;
2256 }
2257 // Try to keep the direction tangents from heading towards 90 degrees
2258 if (fabs(tx)>TAN_MAX10.) tx=TAN_MAX10.*(tx>0.0?1.:-1.);
2259 if (fabs(ty)>TAN_MAX10.) ty=TAN_MAX10.*(ty>0.0?1.:-1.);
2260 // useful combinations of terms
2261 double kq_over_p=qBr2p0.003*q_over_p;
2262 double tx2=tx*tx;
2263 double twotx2=2.*tx2;
2264 double ty2=ty*ty;
2265 double twoty2=2.*ty2;
2266 double txty=tx*ty;
2267 double one_plus_tx2=1.+tx2;
2268 double one_plus_ty2=1.+ty2;
2269 double one_plus_twotx2_plus_ty2=one_plus_ty2+twotx2;
2270 double one_plus_twoty2_plus_tx2=one_plus_tx2+twoty2;
2271 double dsdz=sqrt(1.+tx2+ty2);
2272 double ds=dsdz*delta_z;
2273 double kds=qBr2p0.003*ds;
2274 double kqdz_over_p_over_dsdz=kq_over_p*delta_z/dsdz;
2275 double kq_over_p_ds=kq_over_p*ds;
2276 double dtx_Bdep=ty*Bz+txty*Bx-one_plus_tx2*By;
2277 double dty_Bdep=Bx*one_plus_ty2-txty*By-tx*Bz;
2278 double Bxty=Bx*ty;
2279 double Bytx=By*tx;
2280 double Bztxty=Bz*txty;
2281 double Byty=By*ty;
2282 double Bxtx=Bx*tx;
2283
2284 // Jacobian
2285 J(state_x,state_tx)=J(state_y,state_ty)=delta_z;
2286 J(state_tx,state_q_over_p)=kds*dtx_Bdep;
2287 J(state_ty,state_q_over_p)=kds*dty_Bdep;
2288 J(state_tx,state_tx)+=kqdz_over_p_over_dsdz*(Bxty*(one_plus_twotx2_plus_ty2)
2289 -Bytx*(3.*one_plus_tx2+twoty2)
2290 +Bztxty);
2291 J(state_tx,state_x)=kq_over_p_ds*(ty*dBzdx+txty*dBxdx-one_plus_tx2*dBydx);
2292 J(state_ty,state_ty)+=kqdz_over_p_over_dsdz*(Bxty*(3.*one_plus_ty2+twotx2)
2293 -Bytx*(one_plus_twoty2_plus_tx2)
2294 -Bztxty);
2295 J(state_ty,state_y)= kq_over_p_ds*(one_plus_ty2*dBxdy-txty*dBydy-tx*dBzdy);
2296 J(state_tx,state_ty)=kqdz_over_p_over_dsdz
2297 *((Bxtx+Bz)*(one_plus_twoty2_plus_tx2)-Byty*one_plus_tx2);
2298 J(state_tx,state_y)= kq_over_p_ds*(tx*dBzdy+txty*dBxdy-one_plus_tx2*dBydy);
2299 J(state_ty,state_tx)=-kqdz_over_p_over_dsdz*((Byty+Bz)*(one_plus_twotx2_plus_ty2)
2300 -Bxtx*one_plus_ty2);
2301 J(state_ty,state_x)=kq_over_p_ds*(one_plus_ty2*dBxdx-txty*dBydx-tx*dBzdx);
2302 if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS3.0e-8){
2303 double one_over_p_sq=q_over_p*q_over_p;
2304 double E=sqrt(1./one_over_p_sq+mass2);
2305 J(state_q_over_p,state_q_over_p)-=dEdx*ds/E*(2.+3.*mass2*one_over_p_sq);
2306 double temp=-(q_over_p*one_over_p_sq/dsdz)*E*dEdx*delta_z;
2307 J(state_q_over_p,state_tx)=tx*temp;
2308 J(state_q_over_p,state_ty)=ty*temp;
2309 }
2310
2311 return NOERROR;
2312}
2313
2314// Calculate the derivative for the alternate set of parameters {q/pT, phi,
2315// tan(lambda),D,z}
2316jerror_t DTrackFitterKalmanSIMD::CalcDeriv(DVector2 &dpos,const DMatrix5x1 &S,
2317 double dEdx,DMatrix5x1 &D1){
2318 //Direction at current point
2319 double tanl=S(state_tanl);
2320 // Don't let tanl exceed some maximum
2321 if (fabs(tanl)>TAN_MAX10.) tanl=TAN_MAX10.*(tanl>0.0?1.:-1.);
2322
2323 double phi=S(state_phi);
2324 double cosphi=cos(phi);
2325 double sinphi=sin(phi);
2326 double lambda=atan(tanl);
2327 double sinl=sin(lambda);
2328 double cosl=cos(lambda);
2329 // Other parameters
2330 double q_over_pt=S(state_q_over_pt);
2331 double pt=fabs(1./q_over_pt);
2332
2333 // Turn off dEdx if the pt drops below some minimum
2334 if (pt<PT_MIN) {
2335 dEdx=0.;
2336 }
2337 double kq_over_pt=qBr2p0.003*q_over_pt;
2338
2339 // Derivative of S with respect to s
2340 double By_cosphi_minus_Bx_sinphi=By*cosphi-Bx*sinphi;
2341 D1(state_q_over_pt)
2342 =kq_over_pt*q_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2343 double one_over_cosl=1./cosl;
2344 if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS3.0e-8){
2345 double p=pt*one_over_cosl;
2346 double p_sq=p*p;
2347 double E=sqrt(p_sq+mass2);
2348 D1(state_q_over_pt)-=q_over_pt*E*dEdx/p_sq;
2349 }
2350 // D1(state_phi)
2351 // =kq_over_pt*(Bx*cosphi*sinl+By*sinphi*sinl-Bz*cosl);
2352 D1(state_phi)=kq_over_pt*((Bx*cosphi+By*sinphi)*sinl-Bz*cosl);
2353 D1(state_tanl)=kq_over_pt*By_cosphi_minus_Bx_sinphi*one_over_cosl;
2354 D1(state_z)=sinl;
2355
2356 // New direction
2357 dpos.Set(cosl*cosphi,cosl*sinphi);
2358
2359 return NOERROR;
2360}
2361
2362// Calculate the derivative and Jacobian matrices for the alternate set of
2363// parameters {q/pT, phi, tan(lambda),D,z}
2364jerror_t DTrackFitterKalmanSIMD::CalcDerivAndJacobian(const DVector2 &xy,
2365 DVector2 &dxy,
2366 const DMatrix5x1 &S,
2367 double dEdx,
2368 DMatrix5x5 &J1,
2369 DMatrix5x1 &D1){
2370 //Direction at current point
2371 double tanl=S(state_tanl);
2372 // Don't let tanl exceed some maximum
2373 if (fabs(tanl)>TAN_MAX10.) tanl=TAN_MAX10.*(tanl>0.0?1.:-1.);
2374
2375 double phi=S(state_phi);
2376 double cosphi=cos(phi);
2377 double sinphi=sin(phi);
2378 double lambda=atan(tanl);
2379 double sinl=sin(lambda);
2380 double cosl=cos(lambda);
2381 double cosl2=cosl*cosl;
2382 double cosl3=cosl*cosl2;
2383 double one_over_cosl=1./cosl;
2384 // Other parameters
2385 double q_over_pt=S(state_q_over_pt);
2386 double pt=fabs(1./q_over_pt);
2387 double q=pt*q_over_pt;
2388
2389 // Turn off dEdx if pt drops below some minimum
2390 if (pt<PT_MIN) {
2391 dEdx=0.;
2392 }
2393 double kq_over_pt=qBr2p0.003*q_over_pt;
2394
2395 // B-field and gradient at (x,y,z)
2396 bfield->GetFieldAndGradient(xy.X(),xy.Y(),S(state_z),Bx,By,Bz,
2397 dBxdx,dBxdy,dBxdz,dBydx,
2398 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
2399
2400 // Derivative of S with respect to s
2401 double By_cosphi_minus_Bx_sinphi=By*cosphi-Bx*sinphi;
2402 double By_sinphi_plus_Bx_cosphi=By*sinphi+Bx*cosphi;
2403 D1(state_q_over_pt)=kq_over_pt*q_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2404 D1(state_phi)=kq_over_pt*(By_sinphi_plus_Bx_cosphi*sinl-Bz*cosl);
2405 D1(state_tanl)=kq_over_pt*By_cosphi_minus_Bx_sinphi*one_over_cosl;
2406 D1(state_z)=sinl;
2407
2408 // New direction
2409 dxy.Set(cosl*cosphi,cosl*sinphi);
2410
2411 // Jacobian matrix elements
2412 J1(state_phi,state_phi)=kq_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2413 J1(state_phi,state_q_over_pt)
2414 =qBr2p0.003*(By_sinphi_plus_Bx_cosphi*sinl-Bz*cosl);
2415 J1(state_phi,state_tanl)=kq_over_pt*(By_sinphi_plus_Bx_cosphi*cosl
2416 +Bz*sinl)*cosl2;
2417 J1(state_phi,state_z)
2418 =kq_over_pt*(dBxdz*cosphi*sinl+dBydz*sinphi*sinl-dBzdz*cosl);
2419
2420 J1(state_tanl,state_phi)=-kq_over_pt*By_sinphi_plus_Bx_cosphi*one_over_cosl;
2421 J1(state_tanl,state_q_over_pt)=qBr2p0.003*By_cosphi_minus_Bx_sinphi*one_over_cosl;
2422 J1(state_tanl,state_tanl)=kq_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2423 J1(state_tanl,state_z)=kq_over_pt*(dBydz*cosphi-dBxdz*sinphi)*one_over_cosl;
2424 J1(state_q_over_pt,state_phi)
2425 =-kq_over_pt*q_over_pt*sinl*By_sinphi_plus_Bx_cosphi;
2426 J1(state_q_over_pt,state_q_over_pt)
2427 =2.*kq_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2428 J1(state_q_over_pt,state_tanl)
2429 =kq_over_pt*q_over_pt*cosl3*By_cosphi_minus_Bx_sinphi;
2430 if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS3.0e-8){
2431 double p=pt*one_over_cosl;
2432 double p_sq=p*p;
2433 double m2_over_p2=mass2/p_sq;
2434 double E=sqrt(p_sq+mass2);
2435
2436 D1(state_q_over_pt)-=q_over_pt*E/p_sq*dEdx;
2437 J1(state_q_over_pt,state_q_over_pt)-=dEdx*(2.+3.*m2_over_p2)/E;
2438 J1(state_q_over_pt,state_tanl)+=q*dEdx*sinl*(1.+2.*m2_over_p2)/(p*E);
2439 }
2440 J1(state_q_over_pt,state_z)
2441 =kq_over_pt*q_over_pt*sinl*(dBydz*cosphi-dBxdz*sinphi);
2442 J1(state_z,state_tanl)=cosl3;
2443
2444 return NOERROR;
2445}
2446
2447// Step the state and the covariance matrix through the field
2448jerror_t DTrackFitterKalmanSIMD::StepStateAndCovariance(DVector2 &xy,
2449 double ds,
2450 double dEdx,
2451 DMatrix5x1 &S,
2452 DMatrix5x5 &J,
2453 DMatrix5x5 &C){
2454 //Initialize the Jacobian matrix
2455 J=I5x5;
2456 if (fabs(ds)<EPS3.0e-8) return NOERROR; // break out if ds is too small
2457
2458 // B-field and gradient at current (x,y,z)
2459 bfield->GetFieldAndGradient(xy.X(),xy.Y(),S(state_z),Bx,By,Bz,
2460 dBxdx,dBxdy,dBxdz,dBydx,
2461 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
2462 double Bx0=Bx,By0=By,Bz0=Bz;
2463
2464 // Matrices for intermediate steps
2465 DMatrix5x1 D1,D2,D3,D4;
2466 DMatrix5x1 S1;
2467 DMatrix5x5 J1;
2468 DVector2 dxy1,dxy2,dxy3,dxy4;
2469 double ds_2=0.5*ds;
2470
2471 // Find the derivative at the first point, propagate the state to the
2472 // first intermediate point and start filling the Jacobian matrix
2473 CalcDerivAndJacobian(xy,dxy1,S,dEdx,J1,D1);
2474 S1=S+ds_2*D1;
2475
2476 // Calculate the field at the first intermediate point
2477 double dz=S1(state_z)-S(state_z);
2478 double dx=ds_2*dxy1.X();
2479 double dy=ds_2*dxy1.Y();
2480 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2481 By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2482 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2483
2484 // Calculate the derivative and propagate the state to the next point
2485 CalcDeriv(dxy2,S1,dEdx,D2);
2486 S1=S+ds_2*D2;
2487
2488 // Calculate the field at the second intermediate point
2489 dz=S1(state_z)-S(state_z);
2490 dx=ds_2*dxy2.X();
2491 dy=ds_2*dxy2.Y();
2492 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2493 By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2494 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2495
2496 // Calculate the derivative and propagate the state to the next point
2497 CalcDeriv(dxy3,S1,dEdx,D3);
2498 S1=S+ds*D3;
2499
2500 // Calculate the field at the final point
2501 dz=S1(state_z)-S(state_z);
2502 dx=ds*dxy3.X();
2503 dy=ds*dxy3.Y();
2504 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2505 By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2506 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2507
2508 // Final derivative
2509 CalcDeriv(dxy4,S1,dEdx,D4);
2510
2511 // Position vector increment
2512 //DVector3 dpos
2513 // =ds*(ONE_SIXTH*dpos1+ONE_THIRD*dpos2+ONE_THIRD*dpos3+ONE_SIXTH*dpos4);
2514 double ds_over_6=ds*ONE_SIXTH0.16666666666666667;
2515 double ds_over_3=ds*ONE_THIRD0.33333333333333333;
2516 DVector2 dxy=ds_over_6*dxy1;
2517 dxy+=ds_over_3*dxy2;
2518 dxy+=ds_over_3*dxy3;
2519 dxy+=ds_over_6*dxy4;
2520
2521 // New Jacobian matrix
2522 J+=ds*J1;
2523
2524 // Deal with changes in D
2525 double B=sqrt(Bx0*Bx0+By0*By0+Bz0*Bz0);
2526 //double qrc_old=qpt/(qBr2p*Bz_);
2527 double qpt=1./S(state_q_over_pt);
2528 double q=(qpt>0.)?1.:-1.;
2529 double qrc_old=qpt/(qBr2p0.003*B);
2530 double sinphi=sin(S(state_phi));
2531 double cosphi=cos(S(state_phi));
2532 double qrc_plus_D=S(state_D)+qrc_old;
2533 dx=dxy.X();
2534 dy=dxy.Y();
2535 double dx_sinphi_minus_dy_cosphi=dx*sinphi-dy*cosphi;
2536 double rc=sqrt(dxy.Mod2()
2537 +2.*qrc_plus_D*(dx_sinphi_minus_dy_cosphi)
2538 +qrc_plus_D*qrc_plus_D);
2539 double q_over_rc=q/rc;
2540
2541 J(state_D,state_D)=q_over_rc*(dx_sinphi_minus_dy_cosphi+qrc_plus_D);
2542 J(state_D,state_q_over_pt)=qpt*qrc_old*(J(state_D,state_D)-1.);
2543 J(state_D,state_phi)=q_over_rc*qrc_plus_D*(dx*cosphi+dy*sinphi);
2544
2545 // New xy vector
2546 xy+=dxy;
2547
2548 // New state vector
2549 //S+=ds*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4);
2550 S+=ds_over_6*D1;
2551 S+=ds_over_3*D2;
2552 S+=ds_over_3*D3;
2553 S+=ds_over_6*D4;
2554
2555 // Don't let the pt drop below some minimum
2556 //if (fabs(1./S(state_q_over_pt))<PT_MIN) {
2557 // S(state_q_over_pt)=(1./PT_MIN)*(S(state_q_over_pt)>0.0?1.:-1.);
2558 // }
2559 // Don't let tanl exceed some maximum
2560 if (fabs(S(state_tanl))>TAN_MAX10.){
2561 S(state_tanl)=TAN_MAX10.*(S(state_tanl)>0.0?1.:-1.);
2562 }
2563
2564 // New covariance matrix
2565 // C=J C J^T
2566 //C=C.SandwichMultiply(J);
2567 C=J*C*J.Transpose();
2568
2569 return NOERROR;
2570}
2571
2572// Runga-Kutte for alternate parameter set {q/pT,phi,tanl(lambda),D,z}
2573// Uses the gradient to compute the field at the intermediate and last
2574// points.
2575jerror_t DTrackFitterKalmanSIMD::FasterStep(DVector2 &xy,double ds,
2576 DMatrix5x1 &S,
2577 double dEdx){
2578 if (fabs(ds)<EPS3.0e-8) return NOERROR; // break out if ds is too small
2579
2580 // Matrices for intermediate steps
2581 DMatrix5x1 D1,D2,D3,D4;
2582 DMatrix5x1 S1;
2583 DVector2 dxy1,dxy2,dxy3,dxy4;
2584 double ds_2=0.5*ds;
2585 double Bx0=Bx,By0=By,Bz0=Bz;
2586
2587 // The magnetic field at the beginning of the step is assumed to be
2588 // obtained at the end of the previous step through StepJacobian
2589
2590 // Calculate the derivative and propagate the state to the next point
2591 CalcDeriv(dxy1,S,dEdx,D1);
2592 S1=S+ds_2*D1;
2593
2594 // Calculate the field at the first intermediate point
2595 double dz=S1(state_z)-S(state_z);
2596 double dx=ds_2*dxy1.X();
2597 double dy=ds_2*dxy1.Y();
2598 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2599 By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2600 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2601
2602 // Calculate the derivative and propagate the state to the next point
2603 CalcDeriv(dxy2,S1,dEdx,D2);
2604 S1=S+ds_2*D2;
2605
2606 // Calculate the field at the second intermediate point
2607 dz=S1(state_z)-S(state_z);
2608 dx=ds_2*dxy2.X();
2609 dy=ds_2*dxy2.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(dxy3,S1,dEdx,D3);
2616 S1=S+ds*D3;
2617
2618 // Calculate the field at the final point
2619 dz=S1(state_z)-S(state_z);
2620 dx=ds*dxy3.X();
2621 dy=ds*dxy3.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 // Final derivative
2627 CalcDeriv(dxy4,S1,dEdx,D4);
2628
2629 // New state vector
2630 // S+=ds*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4);
2631 double ds_over_6=ds*ONE_SIXTH0.16666666666666667;
2632 double ds_over_3=ds*ONE_THIRD0.33333333333333333;
2633 S+=ds_over_6*D1;
2634 S+=ds_over_3*D2;
2635 S+=ds_over_3*D3;
2636 S+=ds_over_6*D4;
2637
2638 // New position
2639 //pos+=ds*(ONE_SIXTH*dpos1+ONE_THIRD*dpos2+ONE_THIRD*dpos3+ONE_SIXTH*dpos4);
2640 xy+=ds_over_6*dxy1;
2641 xy+=ds_over_3*dxy2;
2642 xy+=ds_over_3*dxy3;
2643 xy+=ds_over_6*dxy4;
2644
2645 // Don't let the pt drop below some minimum
2646 //if (fabs(1./S(state_q_over_pt))<PT_MIN) {
2647 // S(state_q_over_pt)=(1./PT_MIN)*(S(state_q_over_pt)>0.0?1.:-1.);
2648 //}
2649 // Don't let tanl exceed some maximum
2650 if (fabs(S(state_tanl))>TAN_MAX10.){
2651 S(state_tanl)=TAN_MAX10.*(S(state_tanl)>0.0?1.:-1.);
2652 }
2653
2654 return NOERROR;
2655}
2656
2657// Runga-Kutte for alternate parameter set {q/pT,phi,tanl(lambda),D,z}
2658jerror_t DTrackFitterKalmanSIMD::Step(DVector2 &xy,double ds,
2659 DMatrix5x1 &S,
2660 double dEdx){
2661 if (fabs(ds)<EPS3.0e-8) return NOERROR; // break out if ds is too small
2662
2663 // B-field and gradient at current (x,y,z)
2664 bfield->GetFieldAndGradient(xy.X(),xy.Y(),S(state_z),Bx,By,Bz,
2665 dBxdx,dBxdy,dBxdz,dBydx,
2666 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
2667 double Bx0=Bx,By0=By,Bz0=Bz;
2668
2669 // Matrices for intermediate steps
2670 DMatrix5x1 D1,D2,D3,D4;
2671 DMatrix5x1 S1;
2672 DVector2 dxy1,dxy2,dxy3,dxy4;
2673 double ds_2=0.5*ds;
2674
2675 // Find the derivative at the first point, propagate the state to the
2676 // first intermediate point
2677 CalcDeriv(dxy1,S,dEdx,D1);
2678 S1=S+ds_2*D1;
2679
2680 // Calculate the field at the first intermediate point
2681 double dz=S1(state_z)-S(state_z);
2682 double dx=ds_2*dxy1.X();
2683 double dy=ds_2*dxy1.Y();
2684 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2685 By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2686 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2687
2688 // Calculate the derivative and propagate the state to the next point
2689 CalcDeriv(dxy2,S1,dEdx,D2);
2690 S1=S+ds_2*D2;
2691
2692 // Calculate the field at the second intermediate point
2693 dz=S1(state_z)-S(state_z);
2694 dx=ds_2*dxy2.X();
2695 dy=ds_2*dxy2.Y();
2696 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2697 By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2698 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2699
2700 // Calculate the derivative and propagate the state to the next point
2701 CalcDeriv(dxy3,S1,dEdx,D3);
2702 S1=S+ds*D3;
2703
2704 // Calculate the field at the final point
2705 dz=S1(state_z)-S(state_z);
2706 dx=ds*dxy3.X();
2707 dy=ds*dxy3.Y();
2708 Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz;
2709 By=By0+dBydx*dx+dBydy*dy+dBydz*dz;
2710 Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz;
2711
2712 // Final derivative
2713 CalcDeriv(dxy4,S1,dEdx,D4);
2714
2715 // New state vector
2716 // S+=ds*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4);
2717 double ds_over_6=ds*ONE_SIXTH0.16666666666666667;
2718 double ds_over_3=ds*ONE_THIRD0.33333333333333333;
2719 S+=ds_over_6*D1;
2720 S+=ds_over_3*D2;
2721 S+=ds_over_3*D3;
2722 S+=ds_over_6*D4;
2723
2724 // New position
2725 //pos+=ds*(ONE_SIXTH*dpos1+ONE_THIRD*dpos2+ONE_THIRD*dpos3+ONE_SIXTH*dpos4);
2726 xy+=ds_over_6*dxy1;
2727 xy+=ds_over_3*dxy2;
2728 xy+=ds_over_3*dxy3;
2729 xy+=ds_over_6*dxy4;
2730
2731 // Don't let the pt drop below some minimum
2732 //if (fabs(1./S(state_q_over_pt))<PT_MIN) {
2733 // S(state_q_over_pt)=(1./PT_MIN)*(S(state_q_over_pt)>0.0?1.:-1.);
2734 //}
2735 // Don't let tanl exceed some maximum
2736 if (fabs(S(state_tanl))>TAN_MAX10.){
2737 S(state_tanl)=TAN_MAX10.*(S(state_tanl)>0.0?1.:-1.);
2738 }
2739
2740 return NOERROR;
2741}
2742
2743// Assuming that the magnetic field is constant over the step, use a helical
2744// model to step directly to the next point along the trajectory.
2745void DTrackFitterKalmanSIMD::FastStep(double &z,double ds, double dEdx,
2746 DMatrix5x1 &S){
2747
2748 // Compute convenience terms involving Bx, By, Bz
2749 double one_over_p=fabs(S(state_q_over_p));
2750 double p=1./one_over_p;
2751 double tx=S(state_tx),ty=S(state_ty);
2752 double denom=sqrt(1.+tx*tx+ty*ty);
2753 double px=p*tx/denom;
2754 double py=p*ty/denom;
2755 double pz=p/denom;
2756 double q=S(state_q_over_p)>0?1.:-1.;
2757 double k_q=qBr2p0.003*q;
2758 double ds_over_p=ds*one_over_p;
2759 double factor=k_q*(0.25*ds_over_p);
2760 double Ax=factor*Bx,Ay=factor*By,Az=factor*Bz;
2761 double Ax2=Ax*Ax,Ay2=Ay*Ay,Az2=Az*Az;
2762 double AxAy=Ax*Ay,AxAz=Ax*Az,AyAz=Ay*Az;
2763 double one_plus_Ax2=1.+Ax2;
2764 double scale=ds_over_p/(one_plus_Ax2+Ay2+Az2);
2765
2766 // Compute new position
2767 double dx=scale*(px*one_plus_Ax2+py*(AxAy+Az)+pz*(AxAz-Ay));
2768 double dy=scale*(px*(AxAy-Az)+py*(1.+Ay2)+pz*(AyAz+Ax));
2769 double dz=scale*(px*(AxAz+Ay)+py*(AyAz-Ax)+pz*(1.+Az2));
2770 S(state_x)+=dx;
2771 S(state_y)+=dy;
2772 z+=dz;
2773
2774 // Compute new momentum
2775 px+=k_q*(Bz*dy-By*dz);
2776 py+=k_q*(Bx*dz-Bz*dx);
2777 pz+=k_q*(By*dx-Bx*dy);
2778 S(state_tx)=px/pz;
2779 S(state_ty)=py/pz;
2780 if (fabs(dEdx)>EPS3.0e-8){
2781 double one_over_p_sq=one_over_p*one_over_p;
2782 double E=sqrt(1./one_over_p_sq+mass2);
2783 S(state_q_over_p)-=S(state_q_over_p)*one_over_p_sq*E*dEdx*ds;
2784 }
2785}
2786// Assuming that the magnetic field is constant over the step, use a helical
2787// model to step directly to the next point along the trajectory.
2788void DTrackFitterKalmanSIMD::FastStep(DVector2 &xy,double ds, double dEdx,
2789 DMatrix5x1 &S){
2790
2791 // Compute convenience terms involving Bx, By, Bz
2792 double pt=fabs(1./S(state_q_over_pt));
2793 double one_over_p=cos(atan(S(state_tanl)))/pt;
2794 double px=pt*cos(S(state_phi));
2795 double py=pt*sin(S(state_phi));
2796 double pz=pt*S(state_tanl);
2797 double q=S(state_q_over_pt)>0?1.:-1.;
2798 double k_q=qBr2p0.003*q;
2799 double ds_over_p=ds*one_over_p;
2800 double factor=k_q*(0.25*ds_over_p);
2801 double Ax=factor*Bx,Ay=factor*By,Az=factor*Bz;
2802 double Ax2=Ax*Ax,Ay2=Ay*Ay,Az2=Az*Az;
2803 double AxAy=Ax*Ay,AxAz=Ax*Az,AyAz=Ay*Az;
2804 double one_plus_Ax2=1.+Ax2;
2805 double scale=ds_over_p/(one_plus_Ax2+Ay2+Az2);
2806
2807 // Compute new position
2808 double dx=scale*(px*one_plus_Ax2+py*(AxAy+Az)+pz*(AxAz-Ay));
2809 double dy=scale*(px*(AxAy-Az)+py*(1.+Ay2)+pz*(AyAz+Ax));
2810 double dz=scale*(px*(AxAz+Ay)+py*(AyAz-Ax)+pz*(1.+Az2));
2811 xy.Set(xy.X()+dx,xy.Y()+dy);
2812 S(state_z)+=dz;
2813
2814 // Compute new momentum
2815 px+=k_q*(Bz*dy-By*dz);
2816 py+=k_q*(Bx*dz-Bz*dx);
2817 pz+=k_q*(By*dx-Bx*dy);
2818 pt=sqrt(px*px+py*py);
2819 S(state_q_over_pt)=q/pt;
2820 S(state_phi)=atan2(py,px);
2821 S(state_tanl)=pz/pt;
2822 if (fabs(dEdx)>EPS3.0e-8){
2823 double one_over_p_sq=one_over_p*one_over_p;
2824 double E=sqrt(1./one_over_p_sq+mass2);
2825 S(state_q_over_p)-=S(state_q_over_pt)*one_over_p_sq*E*dEdx*ds;
2826 }
2827}
2828
2829// Calculate the jacobian matrix for the alternate parameter set
2830// {q/pT,phi,tanl(lambda),D,z}
2831jerror_t DTrackFitterKalmanSIMD::StepJacobian(const DVector2 &xy,
2832 const DVector2 &dxy,
2833 double ds,const DMatrix5x1 &S,
2834 double dEdx,DMatrix5x5 &J){
2835 // Initialize the Jacobian matrix
2836 //J.Zero();
2837 //for (int i=0;i<5;i++) J(i,i)=1.;
2838 J=I5x5;
2839
2840 if (fabs(ds)<EPS3.0e-8) return NOERROR; // break out if ds is too small
2841 // B-field and gradient at current (x,y,z)
2842 //bfield->GetFieldAndGradient(xy.X(),xy.Y(),S(state_z),Bx,By,Bz,
2843 //dBxdx,dBxdy,dBxdz,dBydx,
2844 //dBydy,dBydz,dBzdx,dBzdy,dBzdz);
2845
2846 // Charge
2847 double q=(S(state_q_over_pt)>0.0)?1.:-1.;
2848
2849 //kinematic quantities
2850 double q_over_pt=S(state_q_over_pt);
2851 double sinphi=sin(S(state_phi));
2852 double cosphi=cos(S(state_phi));
2853 double D=S(state_D);
2854 double lambda=atan(S(state_tanl));
2855 double sinl=sin(lambda);
2856 double cosl=cos(lambda);
2857 double cosl2=cosl*cosl;
2858 double cosl3=cosl*cosl2;
2859 double one_over_cosl=1./cosl;
2860 double pt=fabs(1./q_over_pt);
2861
2862 // Turn off dEdx if pt drops below some minimum
2863 if (pt<PT_MIN) {
2864 dEdx=0.;
2865 }
2866 double kds=qBr2p0.003*ds;
2867 double kq_ds_over_pt=kds*q_over_pt;
2868 double By_cosphi_minus_Bx_sinphi=By*cosphi-Bx*sinphi;
2869 double By_sinphi_plus_Bx_cosphi=By*sinphi+Bx*cosphi;
2870
2871 // Jacobian matrix elements
2872 J(state_phi,state_phi)+=kq_ds_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2873 J(state_phi,state_q_over_pt)=kds*(By_sinphi_plus_Bx_cosphi*sinl-Bz*cosl);
2874 J(state_phi,state_tanl)=kq_ds_over_pt*(By_sinphi_plus_Bx_cosphi*cosl
2875 +Bz*sinl)*cosl2;
2876 J(state_phi,state_z)
2877 =kq_ds_over_pt*(dBxdz*cosphi*sinl+dBydz*sinphi*sinl-dBzdz*cosl);
2878
2879 J(state_tanl,state_phi)=-kq_ds_over_pt*By_sinphi_plus_Bx_cosphi*one_over_cosl;
2880 J(state_tanl,state_q_over_pt)=kds*By_cosphi_minus_Bx_sinphi*one_over_cosl;
2881 J(state_tanl,state_tanl)+=kq_ds_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2882 J(state_tanl,state_z)=kq_ds_over_pt*(dBydz*cosphi-dBxdz*sinphi)*one_over_cosl;
2883 J(state_q_over_pt,state_phi)
2884 =-kq_ds_over_pt*q_over_pt*sinl*By_sinphi_plus_Bx_cosphi;
2885 J(state_q_over_pt,state_q_over_pt)
2886 +=2.*kq_ds_over_pt*sinl*By_cosphi_minus_Bx_sinphi;
2887 J(state_q_over_pt,state_tanl)
2888 =kq_ds_over_pt*q_over_pt*cosl3*By_cosphi_minus_Bx_sinphi;
2889 if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS3.0e-8){
2890 double p=pt*one_over_cosl;
2891 double p_sq=p*p;
2892 double m2_over_p2=mass2/p_sq;
2893 double E=sqrt(p_sq+mass2);
2894 double dE_over_E=dEdx*ds/E;
2895
2896 J(state_q_over_pt,state_q_over_pt)-=dE_over_E*(2.+3.*m2_over_p2);
2897 J(state_q_over_pt,state_tanl)+=q*dE_over_E*sinl*(1.+2.*m2_over_p2)/p;
2898 }
2899 J(state_q_over_pt,state_z)
2900 =kq_ds_over_pt*q_over_pt*sinl*(dBydz*cosphi-dBxdz*sinphi);
2901 J(state_z,state_tanl)=cosl3*ds;
2902
2903 // Deal with changes in D
2904 double B=sqrt(Bx*Bx+By*By+Bz*Bz);
2905 //double qrc_old=qpt/(qBr2p*fabs(Bz));
2906 double qpt=FactorForSenseOfRotation/q_over_pt;
2907 double qrc_old=qpt/(qBr2p0.003*B);
2908 double qrc_plus_D=D+qrc_old;
2909 double dx=dxy.X();
2910 double dy=dxy.Y();
2911 double dx_sinphi_minus_dy_cosphi=dx*sinphi-dy*cosphi;
2912 double rc=sqrt(dxy.Mod2()
2913 +2.*qrc_plus_D*(dx_sinphi_minus_dy_cosphi)
2914 +qrc_plus_D*qrc_plus_D);
2915 double q_over_rc=FactorForSenseOfRotation*q/rc;
2916
2917 J(state_D,state_D)=q_over_rc*(dx_sinphi_minus_dy_cosphi+qrc_plus_D);
2918 J(state_D,state_q_over_pt)=qpt*qrc_old*(J(state_D,state_D)-1.);
2919 J(state_D,state_phi)=q_over_rc*qrc_plus_D*(dx*cosphi+dy*sinphi);
2920
2921 return NOERROR;
2922}
2923
2924
2925
2926
2927// Runga-Kutte for alternate parameter set {q/pT,phi,tanl(lambda),D,z}
2928jerror_t DTrackFitterKalmanSIMD::StepJacobian(const DVector2 &xy,
2929 double ds,const DMatrix5x1 &S,
2930 double dEdx,DMatrix5x5 &J){
2931 // Initialize the Jacobian matrix
2932 //J.Zero();
2933 //for (int i=0;i<5;i++) J(i,i)=1.;
2934 J=I5x5;
2935
2936 if (fabs(ds)<EPS3.0e-8) return NOERROR; // break out if ds is too small
2937
2938 // Matrices for intermediate steps
2939 DMatrix5x5 J1;
2940 DMatrix5x1 D1;
2941 DVector2 dxy1;
2942
2943 // charge
2944 double q=(S(state_q_over_pt)>0.0)?1.:-1.;
2945 q*=FactorForSenseOfRotation;
2946
2947 //kinematic quantities
2948 double qpt=1./S(state_q_over_pt) * FactorForSenseOfRotation;
2949 double sinphi=sin(S(state_phi));
2950 double cosphi=cos(S(state_phi));
2951 double D=S(state_D);
2952
2953 CalcDerivAndJacobian(xy,dxy1,S,dEdx,J1,D1);
2954 // double Bz_=fabs(Bz); // needed for computing D
2955
2956 // New Jacobian matrix
2957 J+=ds*J1;
2958
2959 // change in position
2960 DVector2 dxy =ds*dxy1;
2961
2962 // Deal with changes in D
2963 double B=sqrt(Bx*Bx+By*By+Bz*Bz);
2964 //double qrc_old=qpt/(qBr2p*Bz_);
2965 double qrc_old=qpt/(qBr2p0.003*B);
2966 double qrc_plus_D=D+qrc_old;
2967 double dx=dxy.X();
2968 double dy=dxy.Y();
2969 double dx_sinphi_minus_dy_cosphi=dx*sinphi-dy*cosphi;
2970 double rc=sqrt(dxy.Mod2()
2971 +2.*qrc_plus_D*(dx_sinphi_minus_dy_cosphi)
2972 +qrc_plus_D*qrc_plus_D);
2973 double q_over_rc=q/rc;
2974
2975 J(state_D,state_D)=q_over_rc*(dx_sinphi_minus_dy_cosphi+qrc_plus_D);
2976 J(state_D,state_q_over_pt)=qpt*qrc_old*(J(state_D,state_D)-1.);
2977 J(state_D,state_phi)=q_over_rc*qrc_plus_D*(dx*cosphi+dy*sinphi);
2978
2979 return NOERROR;
2980}
2981
2982// Compute contributions to the covariance matrix due to multiple scattering
2983// using the Lynch/Dahl empirical formulas
2984jerror_t DTrackFitterKalmanSIMD::GetProcessNoiseCentral(double ds,
2985 double chi2c_factor,
2986 double chi2a_factor,
2987 double chi2a_corr,
2988 const DMatrix5x1 &Sc,
2989 DMatrix5x5 &Q){
2990 Q.Zero();
2991 //return NOERROR;
2992 if (USE_MULS_COVARIANCE && chi2c_factor>0. && fabs(ds)>EPS3.0e-8){
2993 double tanl=Sc(state_tanl);
2994 double tanl2=tanl*tanl;
2995 double one_plus_tanl2=1.+tanl2;
2996 double one_over_pt=fabs(Sc(state_q_over_pt));
2997 double my_ds=fabs(ds);
2998 double my_ds_2=0.5*my_ds;
2999
3000 Q(state_phi,state_phi)=one_plus_tanl2;
3001 Q(state_tanl,state_tanl)=one_plus_tanl2*one_plus_tanl2;
3002 Q(state_q_over_pt,state_q_over_pt)=one_over_pt*one_over_pt*tanl2;
3003 Q(state_q_over_pt,state_tanl)=Q(state_tanl,state_q_over_pt)
3004 =Sc(state_q_over_pt)*tanl*one_plus_tanl2;
3005 Q(state_D,state_D)=ONE_THIRD0.33333333333333333*ds*ds;
3006
3007 // I am not sure the following is correct...
3008 double sign_D=(Sc(state_D)>0.0)?1.:-1.;
3009 Q(state_D,state_phi)=Q(state_phi,state_D)=sign_D*my_ds_2*sqrt(one_plus_tanl2);
3010 Q(state_D,state_tanl)=Q(state_tanl,state_D)=sign_D*my_ds_2*one_plus_tanl2;
3011 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);
3012
3013 double one_over_p_sq=one_over_pt*one_over_pt/one_plus_tanl2;
3014 double one_over_beta2=1.+mass2*one_over_p_sq;
3015 double chi2c_p_sq=chi2c_factor*my_ds*one_over_beta2;
3016 double chi2a_p_sq=chi2a_factor*(1.+chi2a_corr*one_over_beta2);
3017 // F=Fraction of Moliere distribution to be taken into account
3018 // nu=0.5*chi2c/(chi2a*(1.-F));
3019 double nu=MOLIERE_RATIO1*chi2c_p_sq/chi2a_p_sq;
3020 double one_plus_nu=1.+nu;
3021 // sig2_ms=chi2c*1e-6/(1.+F*F)*((one_plus_nu)/nu*log(one_plus_nu)-1.);
3022 double sig2_ms=chi2c_p_sq*one_over_p_sq*MOLIERE_RATIO2
3023 *(one_plus_nu/nu*log(one_plus_nu)-1.);
3024
3025 Q*=sig2_ms;
3026 }
3027
3028 return NOERROR;
3029}
3030
3031// Compute contributions to the covariance matrix due to multiple scattering
3032// using the Lynch/Dahl empirical formulas
3033jerror_t DTrackFitterKalmanSIMD::GetProcessNoise(double z, double ds,
3034 double chi2c_factor,
3035 double chi2a_factor,
3036 double chi2a_corr,
3037 const DMatrix5x1 &S,
3038 DMatrix5x5 &Q){
3039
3040 Q.Zero();
3041 //return NOERROR;
3042 if (USE_MULS_COVARIANCE && chi2c_factor>0. && fabs(ds)>EPS3.0e-8){
3043 double tx=S(state_tx),ty=S(state_ty);
3044 double one_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
3045 double my_ds=fabs(ds);
3046 double my_ds_2=0.5*my_ds;
3047 double tx2=tx*tx;
3048 double ty2=ty*ty;
3049 double one_plus_tx2=1.+tx2;
3050 double one_plus_ty2=1.+ty2;
3051 double tsquare=tx2+ty2;
3052 double one_plus_tsquare=1.+tsquare;
3053
3054 Q(state_tx,state_tx)=one_plus_tx2*one_plus_tsquare;
3055 Q(state_ty,state_ty)=one_plus_ty2*one_plus_tsquare;
3056 Q(state_tx,state_ty)=Q(state_ty,state_tx)=tx*ty*one_plus_tsquare;
3057
3058 Q(state_x,state_x)=ONE_THIRD0.33333333333333333*ds*ds;
3059 Q(state_y,state_y)=Q(state_x,state_x);
3060 Q(state_y,state_ty)=Q(state_ty,state_y)
3061 = my_ds_2*sqrt(one_plus_tsquare*one_plus_ty2);
3062 Q(state_x,state_tx)=Q(state_tx,state_x)
3063 = my_ds_2*sqrt(one_plus_tsquare*one_plus_tx2);
3064
3065 double one_over_beta2=1.+one_over_p_sq*mass2;
3066 double chi2c_p_sq=chi2c_factor*my_ds*one_over_beta2;
3067 double chi2a_p_sq=chi2a_factor*(1.+chi2a_corr*one_over_beta2);
3068 // F=MOLIERE_FRACTION =Fraction of Moliere distribution to be taken into account
3069 // nu=0.5*chi2c/(chi2a*(1.-F));
3070 double nu=MOLIERE_RATIO1*chi2c_p_sq/chi2a_p_sq;
3071 double one_plus_nu=1.+nu;
3072 double sig2_ms=chi2c_p_sq*one_over_p_sq*MOLIERE_RATIO2
3073 *(one_plus_nu/nu*log(one_plus_nu)-1.);
3074
3075 // printf("fac %f %f %f\n",chi2c_factor,chi2a_factor,chi2a_corr);
3076 //printf("omega %f\n",chi2c/chi2a);
3077
3078
3079 Q*=sig2_ms;
3080 }
3081
3082 return NOERROR;
3083}
3084
3085// Calculate the energy loss per unit length given properties of the material
3086// through which a particle of momentum p is passing
3087double DTrackFitterKalmanSIMD::GetdEdx(double q_over_p,double K_rho_Z_over_A,
3088 double rho_Z_over_A,double LnI,double Z){
3089 if (rho_Z_over_A<=0.) return 0.;
3090 //return 0.;
3091
3092 double p=fabs(1./q_over_p);
3093 double betagamma=p/MASS;
3094 double betagamma2=betagamma*betagamma;
3095 double gamma2=1.+betagamma2;
3096 double beta2=betagamma2/gamma2;
3097 if (beta2<EPS3.0e-8) beta2=EPS3.0e-8;
3098
3099 // density effect
3100 double delta=CalcDensityEffect(betagamma,rho_Z_over_A,LnI);
3101
3102 double dEdx=0.;
3103 // For particles heavier than electrons:
3104 if (IsHadron){
3105 double two_Me_betagamma_sq=two_m_e*betagamma2;
3106 double Tmax
3107 =two_Me_betagamma_sq/(1.+2.*sqrt(gamma2)*m_ratio+m_ratio_sq);
3108
3109 dEdx=K_rho_Z_over_A/beta2*(-log(two_Me_betagamma_sq*Tmax)
3110 +2.*(LnI + beta2)+delta);
3111 }
3112 else{
3113 // relativistic kinetic energy in units of M_e c^2
3114 double tau=sqrt(gamma2)-1.;
3115 double tau_sq=tau*tau;
3116 double tau_plus_1=tau+1.;
3117 double tau_plus_2=tau+2.;
3118 double tau_plus_2_sq=tau_plus_2*tau_plus_2;
3119 double f=0.; // function that depends on tau; see Leo (2nd ed.), p. 38.
3120 if (IsElectron){
3121 f=1.-beta2+(0.125*tau_sq-(2.*tau+1.)*log(2.))/(tau_plus_1*tau_plus_1);
3122 }
3123 else{
3124 f=2.*log(2.)-(beta2/12.)*(23.+14./tau_plus_2+10./tau_plus_2_sq
3125 +4./(tau_plus_2*tau_plus_2_sq));
3126 }
3127
3128 // collision loss (Leo eq. 2.66)
3129 double dEdx_coll
3130 =-K_rho_Z_over_A/beta2*(log(0.5*tau_sq*tau_plus_2*m_e_sq)-LnI+f-delta);
3131
3132 // radiation loss (Leo eqs. 2.74, 2.76 with Z^2 -> Z(Z+1)
3133 double a=Z*ALPHA1./137.;
3134 double a2=a*a;
3135 double a4=a2*a2;
3136 double epsilon=1.-PHOTON_ENERGY_CUTOFF;
3137 double epsilon2=epsilon*epsilon;
3138 double f_Z=a2*(1./(1.+a2)+0.20206-0.0369*a2+0.0083*a4-0.002*a2*a4);
3139 // The expression below is the integral of the photon energy weighted
3140 // by the bremsstrahlung cross section up to a maximum photon energy
3141 // expressed as a fraction of the incident electron energy.
3142 double dEdx_rad=-K_rho_Z_over_A*tau_plus_1*(2.*ALPHA1./137./M_PI3.14159265358979323846)*(Z+1.)
3143 *((log(183.*pow(Z,-1./3.))-f_Z)
3144 *(1.-epsilon-(1./3.)*(epsilon2-epsilon*epsilon2))
3145 +1./18.*(1.-epsilon2));
3146
3147
3148 // dEdx_rad=0.;
3149
3150 dEdx=dEdx_coll+dEdx_rad;
3151 }
3152
3153 return dEdx;
3154}
3155
3156// Calculate the variance in the energy loss in a Gaussian approximation.
3157// The standard deviation of the energy loss distribution is
3158// var=0.1535*density*(Z/A)*x*(1-0.5*beta^2)*Tmax [MeV]
3159// where Tmax is the maximum energy transfer.
3160// (derived from Leo (2nd ed.), eq. 2.100. Note that I think there is a typo
3161// in this formula in the text...)
3162double DTrackFitterKalmanSIMD::GetEnergyVariance(double ds,
3163 double one_over_beta2,
3164 double K_rho_Z_over_A){
3165 if (K_rho_Z_over_A<=0.) return 0.;
3166
3167 double betagamma2=1./(one_over_beta2-1.);
3168 double gamma2=betagamma2*one_over_beta2;
3169 double two_Me_betagamma_sq=two_m_e*betagamma2;
3170 double Tmax=two_Me_betagamma_sq/(1.+2.*sqrt(gamma2)*m_ratio+m_ratio_sq);
3171 double var=K_rho_Z_over_A*one_over_beta2*fabs(ds)*Tmax*(1.-0.5/one_over_beta2);
3172 return var;
3173}
3174
3175// Interface routine for Kalman filter
3176jerror_t DTrackFitterKalmanSIMD::KalmanLoop(void){
3177 if (z_<Z_MIN-100.) return VALUE_OUT_OF_RANGE;
3178
3179 // Vector to store the list of hits used in the fit for the forward parametrization
3180 vector<const DCDCTrackHit*>forward_cdc_used_in_fit;
3181
3182 // State vector and initial guess for covariance matrix
3183 DMatrix5x1 S0;
3184 DMatrix5x5 C0;
3185
3186 chisq_=-1.;
3187
3188 // Angle with respect to beam line
3189 double theta_deg=(180/M_PI3.14159265358979323846)*input_params.momentum().Theta();
3190 //double theta_deg_sq=theta_deg*theta_deg;
3191 double tanl0=tanl_=tan(M_PI_21.57079632679489661923-input_params.momentum().Theta());
3192
3193 // Azimuthal angle
3194 double phi0=phi_=input_params.momentum().Phi();
3195
3196 // Guess for momentum error
3197 double dpt_over_pt=0.1;
3198 /*
3199 if (theta_deg<15){
3200 dpt_over_pt=0.107-0.0178*theta_deg+0.000966*theta_deg_sq;
3201 }
3202 else {
3203 dpt_over_pt=0.0288+0.00579*theta_deg-2.77e-5*theta_deg_sq;
3204 }
3205 */
3206 /*
3207 if (theta_deg<28.){
3208 theta_deg=28.;
3209 theta_deg_sq=theta_deg*theta_deg;
3210 }
3211 else if (theta_deg>125.){
3212 theta_deg=125.;
3213 theta_deg_sq=theta_deg*theta_deg;
3214 }
3215 */
3216 double sig_lambda=0.02;
3217 double dp_over_p_sq
3218 =dpt_over_pt*dpt_over_pt+tanl_*tanl_*sig_lambda*sig_lambda;
3219
3220 // Input charge
3221 double q=input_params.charge();
3222
3223 // Input momentum
3224 DVector3 pvec=input_params.momentum();
3225 double p_mag=pvec.Mag();
3226 double px=pvec.x();
3227 double py=pvec.y();
3228 double pz=pvec.z();
3229 double q_over_p0=q_over_p_=q/p_mag;
3230 double q_over_pt0=q_over_pt_=q/pvec.Perp();
3231
3232 // Initial position
3233 double x0=x_=input_params.position().x();
3234 double y0=y_=input_params.position().y();
3235 double z0=z_=input_params.position().z();
3236
3237 if (fit_type==kWireBased && theta_deg>10.){
3238 double Bz=fabs(bfield->GetBz(x0,y0,z0));
3239 double sperp=25.; // empirical guess
3240 if (my_fdchits.size()>0 && my_fdchits[0]->hit!=NULL__null){
3241 double my_z=my_fdchits[0]->z;
3242 double my_x=my_fdchits[0]->hit->xy.X();
3243 double my_y=my_fdchits[0]->hit->xy.Y();
3244 Bz+=fabs(bfield->GetBz(my_x,my_y,my_z));
3245 Bz*=0.5; // crude average
3246 sperp=(my_z-z0)/tanl_;
3247 }
3248 double twokappa=qBr2p0.003*Bz*q_over_pt0*FactorForSenseOfRotation;
3249 double one_over_2k=1./twokappa;
3250 if (my_fdchits.size()==0){
3251 for (unsigned int i=my_cdchits.size()-1;i>1;i--){
3252 // Use outermost axial straw to estimate a resonable arc length
3253 if (my_cdchits[i]->hit->is_stereo==false){
3254 double tworc=2.*fabs(one_over_2k);
3255 double ratio=(my_cdchits[i]->hit->wire->origin
3256 -input_params.position()).Perp()/tworc;
3257 sperp=(ratio<1.)?tworc*asin(ratio):tworc*M_PI_21.57079632679489661923;
3258 if (sperp<25.) sperp=25.;
3259 break;
3260 }
3261 }
3262 }
3263 double twoks=twokappa*sperp;
3264 double cosphi=cos(phi0);
3265 double sinphi=sin(phi0);
3266 double sin2ks=sin(twoks);
3267 double cos2ks=cos(twoks);
3268 double one_minus_cos2ks=1.-cos2ks;
3269 double myx=x0+one_over_2k*(cosphi*sin2ks-sinphi*one_minus_cos2ks);
3270 double myy=y0+one_over_2k*(sinphi*sin2ks+cosphi*one_minus_cos2ks);
3271 double mypx=px*cos2ks-py*sin2ks;
3272 double mypy=py*cos2ks+px*sin2ks;
3273 double myphi=atan2(mypy,mypx);
3274 phi0=phi_=myphi;
3275 px=mypx;
3276 py=mypy;
3277 x0=x_=myx;
3278 y0=y_=myy;
3279 z0+=tanl_*sperp;
3280 z_=z0;
3281 }
3282
3283 // Check integrity of input parameters
3284 if (!isfinite(x0) || !isfinite(y0) || !isfinite(q_over_p0)){
3285 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3285<<" "
<< "Invalid input parameters!" <<endl;
3286 return UNRECOVERABLE_ERROR;
3287 }
3288
3289 // Initial direction tangents
3290 double tx0=tx_=px/pz;
3291 double ty0=ty_=py/pz;
3292 double one_plus_tsquare=1.+tx_*tx_+ty_*ty_;
3293
3294 // deal with hits in FDC
3295 double fdc_prob=0.,fdc_chisq=-1.;
3296 unsigned int fdc_ndf=0;
3297 if (my_fdchits.size()>0
3298 && // Make sure that these parameters are valid for forward-going tracks
3299 (isfinite(tx0) && isfinite(ty0))
3300 ){
3301 if (DEBUG_LEVEL>0){
3302 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3302<<" "
<< "Using forward parameterization." <<endl;
3303 }
3304
3305 // Initial guess for the state vector
3306 S0(state_x)=x_;
3307 S0(state_y)=y_;
3308 S0(state_tx)=tx_;
3309 S0(state_ty)=ty_;
3310 S0(state_q_over_p)=q_over_p_;
3311
3312 // Initial guess for forward representation covariance matrix
3313 C0(state_x,state_x)=2.0;
3314 C0(state_y,state_y)=2.0;
3315 double temp=sig_lambda*one_plus_tsquare;
3316 C0(state_tx,state_tx)=C0(state_ty,state_ty)=temp*temp;
3317 C0(state_q_over_p,state_q_over_p)=dp_over_p_sq*q_over_p_*q_over_p_;
3318 C0*=COVARIANCE_SCALE_FACTOR_FORWARD;
3319
3320 if (my_cdchits.size()>0){
3321 mCDCInternalStepSize=0.25;
3322 }
3323
3324 // The position from the track candidate is reported just outside the
3325 // start counter for tracks containing cdc hits. Propagate to the distance
3326 // of closest approach to the beam line
3327 if (fit_type==kWireBased) ExtrapolateToVertex(S0);
3328
3329 kalman_error_t error=ForwardFit(S0,C0);
3330 if (error==FIT_SUCCEEDED) return NOERROR;
3331 if ((error==FIT_FAILED || ndf_==0) && my_cdchits.size()<6){
3332 return UNRECOVERABLE_ERROR;
3333 }
3334
3335 fdc_prob=TMath::Prob(chisq_,ndf_);
3336 fdc_ndf=ndf_;
3337 fdc_chisq=chisq_;
3338 }
3339
3340 // Deal with hits in the CDC
3341 if (my_cdchits.size()>5){
3342 kalman_error_t error=FIT_NOT_DONE;
3343 kalman_error_t cdc_error=FIT_NOT_DONE;
3344
3345 // Save the current state of the extrapolation vector if it exists
3346 map<DetectorSystem_t,vector<Extrapolation_t> >saved_extrapolations;
3347 if (!extrapolations.empty()){
3348 saved_extrapolations=extrapolations;
3349 ClearExtrapolations();
3350 }
3351 bool save_IsSmoothed=IsSmoothed;
3352
3353 // Chi-squared, degrees of freedom, and probability
3354 double forward_prob=0.;
3355 double chisq_forward=-1.;
3356 unsigned int ndof_forward=0;
3357
3358 // Parameters at "vertex"
3359 double phi=phi_,q_over_pt=q_over_pt_,tanl=tanl_,x=x_,y=y_,z=z_;
3360 vector< vector <double> > fcov_save;
3361 vector<pull_t>pulls_save;
3362 pulls_save.assign(pulls.begin(),pulls.end());
3363 if (!fcov.empty()){
3364 fcov_save.assign(fcov.begin(),fcov.end());
3365 }
3366 if (my_fdchits.size()>0){
3367 if (error==INVALID_FIT) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3367<<" "
<< "Invalid fit " << fcov.size() << " " << fdc_ndf <<endl;
3368 }
3369
3370 // Use forward parameters for CDC-only tracks with theta<THETA_CUT degrees
3371 if (theta_deg<THETA_CUT){
3372 if (DEBUG_LEVEL>0){
3373 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3373<<" "
<< "Using forward parameterization." <<endl;
3374 }
3375
3376 // Step size
3377 mStepSizeS=mCentralStepSize;
3378
3379 // Initialize the state vector
3380 S0(state_x)=x_=x0;
3381 S0(state_y)=y_=y0;
3382 S0(state_tx)=tx_=tx0;
3383 S0(state_ty)=ty_=ty0;
3384 S0(state_q_over_p)=q_over_p_=q_over_p0;
3385 z_=z0;
3386
3387 // Initial guess for forward representation covariance matrix
3388 double temp=sig_lambda*one_plus_tsquare;
3389 C0(state_x,state_x)=2.0;
3390 C0(state_y,state_y)=2.0;
3391 C0(state_tx,state_tx)=C0(state_ty,state_ty)=temp*temp;
3392 C0(state_q_over_p,state_q_over_p)=dp_over_p_sq*q_over_p_*q_over_p_;
3393 C0*=COVARIANCE_SCALE_FACTOR_FORWARD;
3394
3395 //C0*=1.+1./tsquare;
3396
3397 // The position from the track candidate is reported just outside the
3398 // start counter for tracks containing cdc hits. Propagate to the
3399 // distance of closest approach to the beam line
3400 if (fit_type==kWireBased) ExtrapolateToVertex(S0);
3401
3402 error=ForwardCDCFit(S0,C0);
3403 if (error==FIT_SUCCEEDED) return NOERROR;
3404
3405 // Find the CL of the fit
3406 forward_prob=TMath::Prob(chisq_,ndf_);
3407 if (my_fdchits.size()>0){
3408 if (fdc_ndf==0 || forward_prob>fdc_prob){
3409 // We did not end up using the fdc hits after all...
3410 fdchits_used_in_fit.clear();
3411 }
3412 else{
3413 chisq_=fdc_chisq;
3414 ndf_=fdc_ndf;
3415 x_=x;
3416 y_=y;
3417 z_=z;
3418 phi_=phi;
3419 tanl_=tanl;
3420 q_over_pt_=q_over_pt;
3421 if (!fcov_save.empty()){
3422 fcov.assign(fcov_save.begin(),fcov_save.end());
3423 }
3424 if (!saved_extrapolations.empty()){
3425 extrapolations=saved_extrapolations;
3426 }
3427 IsSmoothed=save_IsSmoothed;
3428 pulls.assign(pulls_save.begin(),pulls_save.end());
3429
3430 // _DBG_ << endl;
3431 return NOERROR;
3432 }
3433
3434 // Save the best values for the parameters and chi2 for now
3435 chisq_forward=chisq_;
3436 ndof_forward=ndf_;
3437 x=x_;
3438 y=y_;
3439 z=z_;
3440 phi=phi_;
3441 tanl=tanl_;
3442 q_over_pt=q_over_pt_;
3443 fcov_save.assign(fcov.begin(),fcov.end());
3444 pulls_save.assign(pulls.begin(),pulls.end());
3445 save_IsSmoothed=IsSmoothed;
3446 if (!extrapolations.empty()){
3447 saved_extrapolations=extrapolations;
3448 ClearExtrapolations();
3449 }
3450
3451 // Save the list of hits used in the fit
3452 forward_cdc_used_in_fit.assign(cdchits_used_in_fit.begin(),cdchits_used_in_fit.end());
3453
3454 }
3455 }
3456
3457 // Attempt to fit the track using the central parametrization.
3458 if (DEBUG_LEVEL>0){
3459 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3459<<" "
<< "Using central parameterization." <<endl;
3460 }
3461
3462 // Step size
3463 mStepSizeS=mCentralStepSize;
3464
3465 // Initialize the state vector
3466 S0(state_q_over_pt)=q_over_pt_=q_over_pt0;
3467 S0(state_phi)=phi_=phi0;
3468 S0(state_tanl)=tanl_=tanl0;
3469 S0(state_z)=z_=z0;
3470 S0(state_D)=0.;
3471
3472 // Initialize the covariance matrix
3473 double dz=1.0;
3474 C0(state_z,state_z)=dz*dz;
3475 C0(state_q_over_pt,state_q_over_pt)
3476 =q_over_pt_*q_over_pt_*dpt_over_pt*dpt_over_pt;
3477 double dphi=0.02;
3478 C0(state_phi,state_phi)=dphi*dphi;
3479 C0(state_D,state_D)=1.0;
3480 double tanl2=tanl_*tanl_;
3481 double one_plus_tanl2=1.+tanl2;
3482 C0(state_tanl,state_tanl)=(one_plus_tanl2)*(one_plus_tanl2)
3483 *sig_lambda*sig_lambda;
3484 C0*=COVARIANCE_SCALE_FACTOR_CENTRAL;
3485
3486 //if (theta_deg>90.) C0*=1.+5.*tanl2;
3487 //else C0*=1.+5.*tanl2*tanl2;
3488
3489 mCentralStepSize=0.4;
3490 mCDCInternalStepSize=0.2;
3491
3492 // The position from the track candidate is reported just outside the
3493 // start counter for tracks containing cdc hits. Propagate to the
3494 // distance of closest approach to the beam line
3495 DVector2 xy(x0,y0);
3496 if (fit_type==kWireBased){
3497 ExtrapolateToVertex(xy,S0);
3498 }
3499
3500 cdc_error=CentralFit(xy,S0,C0);
3501 if (cdc_error==FIT_SUCCEEDED){
3502 // if the result of the fit using the forward parameterization succeeded
3503 // but the chi2 was too high, it still may provide the best estimate
3504 // for the track parameters...
3505 double central_prob=TMath::Prob(chisq_,ndf_);
3506
3507 if (central_prob<forward_prob){
3508 phi_=phi;
3509 q_over_pt_=q_over_pt;
3510 tanl_=tanl;
3511 x_=x;
3512 y_=y;
3513 z_=z;
3514 chisq_=chisq_forward;
3515 ndf_= ndof_forward;
3516 fcov.assign(fcov_save.begin(),fcov_save.end());
3517 pulls.assign(pulls_save.begin(),pulls_save.end());
3518 IsSmoothed=save_IsSmoothed;
3519 if (!saved_extrapolations.empty()){
3520 extrapolations=saved_extrapolations;
3521 }
3522
3523 cdchits_used_in_fit.assign(forward_cdc_used_in_fit.begin(),forward_cdc_used_in_fit.end());
3524
3525 // We did not end up using any fdc hits...
3526 fdchits_used_in_fit.clear();
3527
3528 }
3529 return NOERROR;
3530
3531 }
3532 // otherwise if the fit using the forward parametrization worked, return that
3533 else if (error!=FIT_FAILED){
3534 phi_=phi;
3535 q_over_pt_=q_over_pt;
3536 tanl_=tanl;
3537 x_=x;
3538 y_=y;
3539 z_=z;
3540 chisq_=chisq_forward;
3541 ndf_= ndof_forward;
3542
3543 if (!saved_extrapolations.empty()){
3544 extrapolations=saved_extrapolations;
3545 }
3546 IsSmoothed=save_IsSmoothed;
3547 fcov.assign(fcov_save.begin(),fcov_save.end());
3548 pulls.assign(pulls_save.begin(),pulls_save.end());
3549 cdchits_used_in_fit.assign(forward_cdc_used_in_fit.begin(),forward_cdc_used_in_fit.end());
3550
3551 // We did not end up using any fdc hits...
3552 fdchits_used_in_fit.clear();
3553
3554 return NOERROR;
3555 }
3556 else return UNRECOVERABLE_ERROR;
3557 }
3558
3559 if (ndf_==0) return UNRECOVERABLE_ERROR;
3560
3561 return NOERROR;
3562}
3563
3564#define ITMAX20 20
3565#define CGOLD0.3819660 0.3819660
3566#define ZEPS1.0e-10 1.0e-10
3567#define SHFT(a,b,c,d)(a)=(b);(b)=(c);(c)=(d); (a)=(b);(b)=(c);(c)=(d);
3568#define SIGN(a,b)((b)>=0.0?fabs(a):-fabs(a)) ((b)>=0.0?fabs(a):-fabs(a))
3569// Routine for finding the minimum of a function bracketed between two values
3570// (see Numerical Recipes in C, pp. 404-405).
3571jerror_t DTrackFitterKalmanSIMD::BrentsAlgorithm(double ds1,double ds2,
3572 double dedx,DVector2 &pos,
3573 const double z0wire,
3574 const DVector2 &origin,
3575 const DVector2 &dir,
3576 DMatrix5x1 &Sc,
3577 double &ds_out){
3578 double d=0.;
3579 double e=0.0; // will be distance moved on step before last
3580 double ax=0.;
3581 double bx=-ds1;
3582 double cx=-ds1-ds2;
3583
3584 double a=(ax<cx?ax:cx);
3585 double b=(ax>cx?ax:cx);
3586 double x=bx,w=bx,v=bx;
3587
3588 // printf("ds1 %f ds2 %f\n",ds1,ds2);
3589 // Initialize return step size
3590 ds_out=0.;
3591
3592 // Save the starting position
3593 // DVector3 pos0=pos;
3594 // DMatrix S0(Sc);
3595
3596 // Step to intermediate point
3597 Step(pos,x,Sc,dedx);
3598 // Bail if the transverse momentum has dropped below some minimum
3599 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
3600 if (DEBUG_LEVEL>2)
3601 {
3602 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3602<<" "
<< "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3603 << endl;
3604 }
3605 return VALUE_OUT_OF_RANGE;
3606 }
3607
3608 DVector2 wirepos=origin+(Sc(state_z)-z0wire)*dir;
3609 double u_old=x;
3610 double u=0.;
3611
3612 // initialization
3613 double fw=(pos-wirepos).Mod2();
3614 double fv=fw,fx=fw;
3615
3616 // main loop
3617 for (unsigned int iter=1;iter<=ITMAX20;iter++){
3618 double xm=0.5*(a+b);
3619 double tol1=EPS21.e-4*fabs(x)+ZEPS1.0e-10;
3620 double tol2=2.0*tol1;
3621
3622 if (fabs(x-xm)<=(tol2-0.5*(b-a))){
3623 if (Sc(state_z)<=cdc_origin[2]){
3624 unsigned int iter2=0;
3625 double ds_temp=0.;
3626 while (fabs(Sc(state_z)-cdc_origin[2])>EPS21.e-4 && iter2<20){
3627 u=x-(cdc_origin[2]-Sc(state_z))*sin(atan(Sc(state_tanl)));
3628 x=u;
3629 ds_temp+=u_old-u;
3630 // Bail if the transverse momentum has dropped below some minimum
3631 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
3632 if (DEBUG_LEVEL>2)
3633 {
3634 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3634<<" "
<< "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3635 << endl;
3636 }
3637 return VALUE_OUT_OF_RANGE;
3638 }
3639
3640 // Function evaluation
3641 Step(pos,u_old-u,Sc,dedx);
3642 u_old=u;
3643 iter2++;
3644 }
3645 //printf("new z %f ds %f \n",pos.z(),x);
3646 ds_out=ds_temp;
3647 return NOERROR;
3648 }
3649 else if (Sc(state_z)>=endplate_z){
3650 unsigned int iter2=0;
3651 double ds_temp=0.;
3652 while (fabs(Sc(state_z)-endplate_z)>EPS21.e-4 && iter2<20){
3653 u=x-(endplate_z-Sc(state_z))*sin(atan(Sc(state_tanl)));
3654 x=u;
3655 ds_temp+=u_old-u;
3656
3657 // Bail if the transverse momentum has dropped below some minimum
3658 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
3659 if (DEBUG_LEVEL>2)
3660 {
3661 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3661<<" "
<< "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3662 << endl;
3663 }
3664 return VALUE_OUT_OF_RANGE;
3665 }
3666
3667 // Function evaluation
3668 Step(pos,u_old-u,Sc,dedx);
3669 u_old=u;
3670 iter2++;
3671 }
3672 //printf("new z %f ds %f \n",pos.z(),x);
3673 ds_out=ds_temp;
3674 return NOERROR;
3675 }
3676 ds_out=cx-x;
3677 return NOERROR;
3678 }
3679 // trial parabolic fit
3680 if (fabs(e)>tol1){
3681 double x_minus_w=x-w;
3682 double x_minus_v=x-v;
3683 double r=x_minus_w*(fx-fv);
3684 double q=x_minus_v*(fx-fw);
3685 double p=x_minus_v*q-x_minus_w*r;
3686 q=2.0*(q-r);
3687 if (q>0.0) p=-p;
3688 q=fabs(q);
3689 double etemp=e;
3690 e=d;
3691 if (fabs(p)>=fabs(0.5*q*etemp) || p<=q*(a-x) || p>=q*(b-x))
3692 // fall back on the Golden Section technique
3693 d=CGOLD0.3819660*(e=(x>=xm?a-x:b-x));
3694 else{
3695 // parabolic step
3696 d=p/q;
3697 u=x+d;
3698 if (u-a<tol2 || b-u <tol2)
3699 d=SIGN(tol1,xm-x)((xm-x)>=0.0?fabs(tol1):-fabs(tol1));
3700 }
3701 } else{
3702 d=CGOLD0.3819660*(e=(x>=xm?a-x:b-x));
3703 }
3704 u=(fabs(d)>=tol1 ? x+d: x+SIGN(tol1,d)((d)>=0.0?fabs(tol1):-fabs(tol1)));
3705
3706 // Bail if the transverse momentum has dropped below some minimum
3707 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
3708 if (DEBUG_LEVEL>2)
3709 {
3710 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3710<<" "
<< "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
3711 << endl;
3712 }
3713 return VALUE_OUT_OF_RANGE;
3714 }
3715
3716 // Function evaluation
3717 Step(pos,u_old-u,Sc,dedx);
3718 u_old=u;
3719
3720 wirepos=origin;
3721 wirepos+=(Sc(state_z)-z0wire)*dir;
3722 double fu=(pos-wirepos).Mod2();
3723
3724 //cout << "Brent: z="<<Sc(state_z) << " d="<<sqrt(fu) << endl;
3725
3726 if (fu<=fx){
3727 if (u>=x) a=x; else b=x;
3728 SHFT(v,w,x,u)(v)=(w);(w)=(x);(x)=(u);;
3729 SHFT(fv,fw,fx,fu)(fv)=(fw);(fw)=(fx);(fx)=(fu);;
3730 }
3731 else {
3732 if (u<x) a=u; else b=u;
3733 if (fu<=fw || w==x){
3734 v=w;
3735 w=u;
3736 fv=fw;
3737 fw=fu;
3738 }
3739 else if (fu<=fv || v==x || v==w){
3740 v=u;
3741 fv=fu;
3742 }
3743 }
3744 }
3745 ds_out=cx-x;
3746
3747 return NOERROR;
3748}
3749
3750// Routine for finding the minimum of a function bracketed between two values
3751// (see Numerical Recipes in C, pp. 404-405).
3752jerror_t DTrackFitterKalmanSIMD::BrentsAlgorithm(double z,double dz,
3753 double dedx,
3754 const double z0wire,
3755 const DVector2 &origin,
3756 const DVector2 &dir,
3757 DMatrix5x1 &S,
3758 double &dz_out){
3759 double d=0.,u=0.;
3760 double e=0.0; // will be distance moved on step before last
3761 double ax=0.;
3762 double bx=-dz;
3763 double cx=-2.*dz;
3764
3765 double a=(ax<cx?ax:cx);
3766 double b=(ax>cx?ax:cx);
3767 double x=bx,w=bx,v=bx;
3768
3769 // Initialize dz_out
3770 dz_out=0.;
3771
3772 // Step to intermediate point
3773 double z_new=z+x;
3774 Step(z,z_new,dedx,S);
3775 // Bail if the momentum has dropped below some minimum
3776 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){
3777 if (DEBUG_LEVEL>2)
3778 {
3779 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3779<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p))
3780 << endl;
3781 }
3782 return VALUE_OUT_OF_RANGE;
3783 }
3784
3785 double dz0wire=z-z0wire;
3786 DVector2 wirepos=origin+(dz0wire+x)*dir;
3787 DVector2 pos(S(state_x),S(state_y));
3788 double z_old=z_new;
3789
3790 // initialization
3791 double fw=(pos-wirepos).Mod2();
3792 double fv=fw;
3793 double fx=fw;
3794
3795 // main loop
3796 for (unsigned int iter=1;iter<=ITMAX20;iter++){
3797 double xm=0.5*(a+b);
3798 double tol1=EPS21.e-4*fabs(x)+ZEPS1.0e-10;
3799 double tol2=2.0*tol1;
3800 if (fabs(x-xm)<=(tol2-0.5*(b-a))){
3801 if (z_new>=endplate_z){
3802 x=endplate_z-z_new;
3803
3804 // Bail if the momentum has dropped below some minimum
3805 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){
3806 if (DEBUG_LEVEL>2)
3807 {
3808 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3808<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p))
3809 << endl;
3810 }
3811 return VALUE_OUT_OF_RANGE;
3812 }
3813 if (!isfinite(S(state_x)) || !isfinite(S(state_y))){
3814 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3814<<" "
<<endl;
3815 return VALUE_OUT_OF_RANGE;
3816 }
3817 Step(z_new,endplate_z,dedx,S);
3818 }
3819 dz_out=x;
3820 return NOERROR;
3821 }
3822 // trial parabolic fit
3823 if (fabs(e)>tol1){
3824 double x_minus_w=x-w;
3825 double x_minus_v=x-v;
3826 double r=x_minus_w*(fx-fv);
3827 double q=x_minus_v*(fx-fw);
3828 double p=x_minus_v*q-x_minus_w*r;
3829 q=2.0*(q-r);
3830 if (q>0.0) p=-p;
3831 q=fabs(q);
3832 double etemp=e;
3833 e=d;
3834 if (fabs(p)>=fabs(0.5*q*etemp) || p<=q*(a-x) || p>=q*(b-x))
3835 // fall back on the Golden Section technique
3836 d=CGOLD0.3819660*(e=(x>=xm?a-x:b-x));
3837 else{
3838 // parabolic step
3839 d=p/q;
3840 u=x+d;
3841 if (u-a<tol2 || b-u <tol2)
3842 d=SIGN(tol1,xm-x)((xm-x)>=0.0?fabs(tol1):-fabs(tol1));
3843 }
3844 } else{
3845 d=CGOLD0.3819660*(e=(x>=xm?a-x:b-x));
3846 }
3847 u=(fabs(d)>=tol1 ? x+d: x+SIGN(tol1,d)((d)>=0.0?fabs(tol1):-fabs(tol1)));
3848
3849 // Function evaluation
3850 //S=S0;
3851 z_new=z+u;
3852 // Bail if the momentum has dropped below some minimum
3853 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){
3854 if (DEBUG_LEVEL>2)
3855 {
3856 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<3856<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p))
3857 << endl;
3858 }
3859 return VALUE_OUT_OF_RANGE;
3860 }
3861
3862 Step(z_old,z_new,dedx,S);
3863 z_old=z_new;
3864
3865 wirepos=origin;
3866 wirepos+=(dz0wire+u)*dir;
3867 pos.Set(S(state_x),S(state_y));
3868 double fu=(pos-wirepos).Mod2();
3869
3870 // _DBG_ << "Brent: z="<< z+u << " d^2="<<fu << endl;
3871
3872 if (fu<=fx){
3873 if (u>=x) a=x; else b=x;
3874 SHFT(v,w,x,u)(v)=(w);(w)=(x);(x)=(u);;
3875 SHFT(fv,fw,fx,fu)(fv)=(fw);(fw)=(fx);(fx)=(fu);;
3876 }
3877 else {
3878 if (u<x) a=u; else b=u;
3879 if (fu<=fw || w==x){
3880 v=w;
3881 w=u;
3882 fv=fw;
3883 fw=fu;
3884 }
3885 else if (fu<=fv || v==x || v==w){
3886 v=u;
3887 fv=fu;
3888 }
3889 }
3890 }
3891 dz_out=x;
3892 return NOERROR;
3893}
3894
3895// Kalman engine for Central tracks; updates the position on the trajectory
3896// after the last hit (closest to the target) is added
3897kalman_error_t DTrackFitterKalmanSIMD::KalmanCentral(double anneal_factor,
3898 DMatrix5x1 &Sc,
3899 DMatrix5x5 &Cc,
3900 DVector2 &xy,double &chisq,
3901 unsigned int &my_ndf
3902 ){
3903 DMatrix1x5 H; // Track projection matrix
3904 DMatrix5x1 H_T; // Transpose of track projection matrix
3905 DMatrix5x5 J; // State vector Jacobian matrix
3906 DMatrix5x5 Q; // Process noise covariance matrix
3907 DMatrix5x1 K; // KalmanSIMD gain matrix
3908 DMatrix5x5 Ctest; // covariance matrix
3909 // double V=0.2028; //1.56*1.56/12.; // Measurement variance
3910 double V=0.0507;
3911 double InvV; // inverse of variance
3912 //DMatrix5x1 dS; // perturbation in state vector
3913 DMatrix5x1 S0,S0_; // state vector
3914
3915 // set the used_in_fit flags to false for cdc hits
3916 unsigned int num_cdc=cdc_used_in_fit.size();
3917 for (unsigned int i=0;i<num_cdc;i++) cdc_used_in_fit[i]=false;
3918 for (unsigned int i=0;i<central_traj.size();i++){
3919 central_traj[i].h_id=0;
3920 }
3921
3922 // Initialize the chi2 for this part of the track
3923 chisq=0.;
3924 my_ndf=0;
3925
3926 double chi2cut=NUM_CDC_SIGMA_CUT*NUM_CDC_SIGMA_CUT;
3927
3928 // path length increment
3929 double ds2=0.;
3930
3931 //printf(">>>>>>>>>>>>>>>>\n");
3932
3933 // beginning position
3934 double phi=Sc(state_phi);
3935 xy.Set(central_traj[break_point_step_index].xy.X()-Sc(state_D)*sin(phi),
3936 central_traj[break_point_step_index].xy.Y()+Sc(state_D)*cos(phi));
3937
3938 // Wire origin and direction
3939 // unsigned int cdc_index=my_cdchits.size()-1;
3940 unsigned int cdc_index=break_point_cdc_index;
3941 if (break_point_cdc_index<num_cdc-1){
3942 num_cdc=break_point_cdc_index+1;
3943 }
3944
3945 if (num_cdc<MIN_HITS_FOR_REFIT) chi2cut=BIG1.0e8;
3946
3947 // Wire origin and direction
3948 DVector2 origin=my_cdchits[cdc_index]->origin;
3949 double z0w=my_cdchits[cdc_index]->z0wire;
3950 DVector2 dir=my_cdchits[cdc_index]->dir;
3951 DVector2 wirexy=origin+(Sc(state_z)-z0w)*dir;
3952
3953 // Save the starting values for C and S in the deque
3954 central_traj[break_point_step_index].Skk=Sc;
3955 central_traj[break_point_step_index].Ckk=Cc;
3956
3957 // doca variables
3958 double doca2,old_doca2=(xy-wirexy).Mod2();
3959
3960 // energy loss
3961 double dedx=0.;
3962
3963 // Boolean for flagging when we are done with measurements
3964 bool more_measurements=true;
3965
3966 // Initialize S0_ and perform the loop over the trajectory
3967 S0_=central_traj[break_point_step_index].S;
3968
3969 for (unsigned int k=break_point_step_index+1;k<central_traj.size();k++){
3970 unsigned int k_minus_1=k-1;
3971
3972 // Get the state vector, jacobian matrix, and multiple scattering matrix
3973 // from reference trajectory
3974 S0=central_traj[k].S;
3975 J=central_traj[k].J;
3976 Q=central_traj[k].Q;
3977
3978 //Q.Print();
3979 //J.Print();
3980
3981 // State S is perturbation about a seed S0
3982 //dS=Sc-S0_;
3983 //dS.Zero();
3984
3985 // Update the actual state vector and covariance matrix
3986 Sc=S0+J*(Sc-S0_);
3987 // Cc=J*(Cc*JT)+Q;
3988 // Cc=Q.AddSym(Cc.SandwichMultiply(J));
3989 Cc=Q.AddSym(J*Cc*J.Transpose());
3990
3991 // Save the current state and covariance matrix in the deque
3992 if (fit_type==kTimeBased){
3993 central_traj[k].Skk=Sc;
3994 central_traj[k].Ckk=Cc;
3995 }
3996
3997 // update position based on new doca to reference trajectory
3998 xy.Set(central_traj[k].xy.X()-Sc(state_D)*sin(Sc(state_phi)),
3999 central_traj[k].xy.Y()+Sc(state_D)*cos(Sc(state_phi)));
4000
4001 // Bail if the position is grossly outside of the tracking volume
4002 if (xy.Mod2()>R2_MAX4225.0 || Sc(state_z)<Z_MIN-100. || Sc(state_z)>Z_MAX370.0){
4003 if (DEBUG_LEVEL>2)
4004 {
4005 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4005<<" "
<< "Went outside of tracking volume at z="<<Sc(state_z)
4006 << " r="<<xy.Mod()<<endl;
4007 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4007<<" "
<< " Break indexes: " << break_point_cdc_index <<","
4008 << break_point_step_index << endl;
4009 }
4010 return POSITION_OUT_OF_RANGE;
4011 }
4012 // Bail if the transverse momentum has dropped below some minimum
4013 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
4014 if (DEBUG_LEVEL>2)
4015 {
4016 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4016<<" "
<< "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
4017 << " at step " << k
4018 << endl;
4019 }
4020 return MOMENTUM_OUT_OF_RANGE;
4021 }
4022
4023
4024 // Save the current state of the reference trajectory
4025 S0_=S0;
4026
4027 // new wire position
4028 wirexy=origin;
4029 wirexy+=(Sc(state_z)-z0w)*dir;
4030
4031 // new doca
4032 doca2=(xy-wirexy).Mod2();
4033
4034 // Check if the doca is no longer decreasing
4035 if (more_measurements && (doca2>old_doca2 && Sc(state_z)>cdc_origin[2])){
4036 if (my_cdchits[cdc_index]->status==good_hit){
4037 if (DEBUG_LEVEL>9) {
4038 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4038<<" "
<< " Good Hit Ring " << my_cdchits[cdc_index]->hit->wire->ring << " Straw " << my_cdchits[cdc_index]->hit->wire->straw << endl;
4039 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4039<<" "
<< " doca " << sqrt(doca2) << endl;
4040 }
4041
4042 // Save values at end of current step
4043 DVector2 xy0=central_traj[k].xy;
4044
4045 // Variables for the computation of D at the doca to the wire
4046 double D=Sc(state_D);
4047 double q=(Sc(state_q_over_pt)>0.0)?1.:-1.;
4048
4049 q*=FactorForSenseOfRotation;
4050
4051 double qpt=1./Sc(state_q_over_pt) * FactorForSenseOfRotation;
4052 double sinphi=sin(Sc(state_phi));
4053 double cosphi=cos(Sc(state_phi));
4054 //double qrc_old=qpt/fabs(qBr2p*bfield->GetBz(pos.x(),pos.y(),pos.z()));
4055 double qrc_old=qpt/fabs(qBr2p0.003*central_traj[k].B);
4056 double qrc_plus_D=D+qrc_old;
4057
4058 // wire direction variable
4059 double ux=dir.X();
4060 double uy=dir.Y();
4061 double cosstereo=my_cdchits[cdc_index]->cosstereo;
4062 // Variables relating wire direction and track direction
4063 //double my_ux=ux*sinl-cosl*cosphi;
4064 //double my_uy=uy*sinl-cosl*sinphi;
4065 //double denom=my_ux*my_ux+my_uy*my_uy;
4066 // distance variables
4067 DVector2 diff,dxy1;
4068
4069 // use Brent's algorithm to find the poca to the wire
4070 // See Numerical Recipes in C, pp 404-405
4071
4072 // dEdx for current position along trajectory
4073 double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl)));
4074 if (CORRECT_FOR_ELOSS){
4075 dedx=GetdEdx(q_over_p, central_traj[k].K_rho_Z_over_A,
4076 central_traj[k].rho_Z_over_A,
4077 central_traj[k].LnI,central_traj[k].Z);
4078 }
4079
4080 if (BrentCentral(dedx,xy,z0w,origin,dir,Sc,ds2)!=NOERROR) return MOMENTUM_OUT_OF_RANGE;
4081
4082 //Step along the reference trajectory and compute the new covariance matrix
4083 StepStateAndCovariance(xy0,ds2,dedx,S0,J,Cc);
4084
4085 // Compute the value of D (signed distance to the reference trajectory)
4086 // at the doca to the wire
4087 dxy1=xy0-central_traj[k].xy;
4088 double rc=sqrt(dxy1.Mod2()
4089 +2.*qrc_plus_D*(dxy1.X()*sinphi-dxy1.Y()*cosphi)
4090 +qrc_plus_D*qrc_plus_D);
4091 Sc(state_D)=q*rc-qrc_old;
4092
4093 // wire position
4094 wirexy=origin;
4095 wirexy+=(Sc(state_z)-z0w)*dir;
4096 diff=xy-wirexy;
4097
4098 // prediction for measurement
4099 double doca=diff.Mod()+EPS3.0e-8;
4100 double prediction=doca*cosstereo;
4101
4102 // Measurement
4103 double measurement=0.39,tdrift=0.,tcorr=0.,dDdt0=0.;
4104 if (fit_type==kTimeBased || USE_PASS1_TIME_MODE){
4105 // Find offset of wire with respect to the center of the
4106 // straw at this z position
4107 const DCDCWire *mywire=my_cdchits[cdc_index]->hit->wire;
4108 int ring_index=mywire->ring-1;
4109 int straw_index=mywire->straw-1;
4110 double dz=Sc(state_z)-z0w;
4111 double phi_d=diff.Phi();
4112 double delta
4113 =max_sag[ring_index][straw_index]*(1.-dz*dz/5625.)
4114 *cos(phi_d + sag_phi_offset[ring_index][straw_index]);
4115 double dphi=phi_d-mywire->origin.Phi();
4116 while (dphi>M_PI3.14159265358979323846) dphi-=2*M_PI3.14159265358979323846;
4117 while (dphi<-M_PI3.14159265358979323846) dphi+=2*M_PI3.14159265358979323846;
4118 if (mywire->origin.Y()<0) dphi*=-1.;
4119
4120 tdrift=my_cdchits[cdc_index]->tdrift-mT0
4121 -central_traj[k_minus_1].t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
4122 double B=central_traj[k_minus_1].B;
4123 ComputeCDCDrift(dphi,delta,tdrift,B,measurement,V,tcorr);
4124 V*=anneal_factor;
4125 if (ALIGNMENT_CENTRAL){
4126 double myV=0.;
4127 double mytcorr=0.;
4128 double d_shifted;
4129 double dt=2.0;
4130 ComputeCDCDrift(dphi,delta,tdrift+dt,B,d_shifted,myV,mytcorr);
4131 dDdt0=(d_shifted-measurement)/dt;
4132 }
4133
4134 //_DBG_ << tcorr << " " << dphi << " " << dm << endl;
4135
4136 }
4137
4138 // Projection matrix
4139 sinphi=sin(Sc(state_phi));
4140 cosphi=cos(Sc(state_phi));
4141 double dx=diff.X();
4142 double dy=diff.Y();
4143 double cosstereo_over_doca=cosstereo/doca;
4144 H_T(state_D)=(dy*cosphi-dx*sinphi)*cosstereo_over_doca;
4145 H_T(state_phi)
4146 =-Sc(state_D)*cosstereo_over_doca*(dx*cosphi+dy*sinphi);
4147 H_T(state_z)=-cosstereo_over_doca*(dx*ux+dy*uy);
4148 H(state_tanl)=0.;
4149 H_T(state_tanl)=0.;
4150 H(state_D)=H_T(state_D);
4151 H(state_z)=H_T(state_z);
4152 H(state_phi)=H_T(state_phi);
4153
4154 // Difference and inverse of variance
4155 //InvV=1./(V+H*(Cc*H_T));
4156 //double Vproj=Cc.SandwichMultiply(H_T);
4157 double Vproj=H*Cc*H_T;
4158 InvV=1./(V+Vproj);
4159 double dm=measurement-prediction;
4160
4161 if (InvV<0.){
4162 if (DEBUG_LEVEL>1)
4163 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4163<<" "
<< k <<" "<< central_traj.size()-1<<" Negative variance??? " << V << " " << H*(Cc*H_T) <<endl;
4164
4165 break_point_cdc_index=(3*num_cdc)/4;
4166 return NEGATIVE_VARIANCE;
4167 }
4168 /*
4169 if (fabs(cosstereo)<1.){
4170 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);
4171 }
4172 */
4173
4174 // Check how far this hit is from the expected position
4175 double chi2check=dm*dm*InvV;
4176 if (DEBUG_LEVEL>9) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4176<<" "
<< " Prediction " << prediction << " Measurement " << measurement << " Chi2 " << chi2check << endl;
4177 if (chi2check<chi2cut)
4178 {
4179 if (DEBUG_LEVEL>9) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4179<<" "
<< " Passed Chi^2 check Ring " << my_cdchits[cdc_index]->hit->wire->ring << " Straw " << my_cdchits[cdc_index]->hit->wire->straw << endl;
4180
4181 // Compute Kalman gain matrix
4182 K=InvV*(Cc*H_T);
4183
4184 // Update state vector covariance matrix
4185 //Cc=Cc-(K*(H*Cc));
4186 Ctest=Cc.SubSym(K*(H*Cc));
4187 // Joseph form
4188 // C = (I-KH)C(I-KH)^T + KVK^T
4189 //Ctest=Cc.SandwichMultiply(I5x5-K*H)+V*MultiplyTranspose(K);
4190 // Check that Ctest is positive definite
4191 if (!Ctest.IsPosDef()){
4192 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4192<<" "
<< "Broken covariance matrix!" <<endl;
4193 return BROKEN_COVARIANCE_MATRIX;
4194 }
4195 bool skip_ring
4196 =(my_cdchits[cdc_index]->hit->wire->ring==RING_TO_SKIP);
4197 //Update covariance matrix and state vector
4198 if (skip_ring==false && tdrift >= CDC_T_DRIFT_MIN){
4199 Cc=Ctest;
4200 Sc+=dm*K;
4201 }
4202
4203 // Mark point on ref trajectory with a hit id for the straw
4204 central_traj[k].h_id=cdc_index+1;
4205 if (DEBUG_LEVEL>9) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4205<<" "
<< " Marked Trajectory central_traj[k].h_id=cdc_index+1 (k cdc_index)" << k << " " << cdc_index << endl;
4206
4207 // Save some updated information for this hit
4208 double scale=(skip_ring)?1.:(1.-H*K);
4209 cdc_updates[cdc_index].tcorr=tcorr;
4210 cdc_updates[cdc_index].tdrift=tdrift;
4211 cdc_updates[cdc_index].doca=measurement;
4212 cdc_updates[cdc_index].variance=V;
4213 cdc_updates[cdc_index].dDdt0=dDdt0;
4214 cdc_used_in_fit[cdc_index]=true;
4215 if (tdrift < CDC_T_DRIFT_MIN) cdc_used_in_fit[cdc_index]=false;
4216
4217 // Update chi2 for this hit
4218 if (skip_ring==false && tdrift >= CDC_T_DRIFT_MIN){
4219 chisq+=scale*dm*dm/V;
4220 my_ndf++;
4221 }
4222 if (DEBUG_LEVEL>10)
4223 cout
4224 << "ring " << my_cdchits[cdc_index]->hit->wire->ring
4225 << " t " << my_cdchits[cdc_index]->hit->tdrift
4226 << " Dm-Dpred " << dm
4227 << " chi2 " << (1.-H*K)*dm*dm/V
4228 << endl;
4229
4230 break_point_cdc_index=cdc_index;
4231 break_point_step_index=k_minus_1;
4232
4233 //else printf("Negative variance!!!\n");
4234
4235
4236 }
4237
4238 // Move back to the right step along the reference trajectory.
4239 StepStateAndCovariance(xy,-ds2,dedx,Sc,J,Cc);
4240
4241 // Save state and covariance matrix to update vector
4242 cdc_updates[cdc_index].S=Sc;
4243 cdc_updates[cdc_index].C=Cc;
4244
4245 //Sc.Print();
4246 //Cc.Print();
4247
4248 // update position on current trajectory based on corrected doca to
4249 // reference trajectory
4250 xy.Set(central_traj[k].xy.X()-Sc(state_D)*sin(Sc(state_phi)),
4251 central_traj[k].xy.Y()+Sc(state_D)*cos(Sc(state_phi)));
4252
4253 }
4254
4255 // new wire origin and direction
4256 if (cdc_index>0){
4257 cdc_index--;
4258 origin=my_cdchits[cdc_index]->origin;
4259 z0w=my_cdchits[cdc_index]->z0wire;
4260 dir=my_cdchits[cdc_index]->dir;
4261 }
4262 else{
4263 more_measurements=false;
4264 }
4265
4266 // Update the wire position
4267 wirexy=origin+(Sc(state_z)-z0w)*dir;
4268
4269 //s+=ds2;
4270 // new doca
4271 doca2=(xy-wirexy).Mod2();
4272 }
4273
4274 old_doca2=doca2;
4275
4276 }
4277
4278 // If there are not enough degrees of freedom, something went wrong...
4279 if (my_ndf<6){
4280 chisq=-1.;
4281 my_ndf=0;
4282 return PRUNED_TOO_MANY_HITS;
4283 }
4284 else my_ndf-=5;
4285
4286 // Check if we have a kink in the track or threw away too many cdc hits
4287 if (num_cdc>=MIN_HITS_FOR_REFIT){
4288 if (break_point_cdc_index>1){
4289 if (break_point_cdc_index<num_cdc/2){
4290 break_point_cdc_index=(3*num_cdc)/4;
4291 }
4292 return BREAK_POINT_FOUND;
4293 }
4294
4295 unsigned int num_good=0;
4296 for (unsigned int j=0;j<num_cdc;j++){
4297 if (cdc_used_in_fit[j]) num_good++;
4298 }
4299 if (double(num_good)/double(num_cdc)<MINIMUM_HIT_FRACTION){
4300 return PRUNED_TOO_MANY_HITS;
4301 }
4302 }
4303
4304 return FIT_SUCCEEDED;
4305}
4306
4307// Kalman engine for forward tracks
4308kalman_error_t DTrackFitterKalmanSIMD::KalmanForward(double fdc_anneal_factor,
4309 double cdc_anneal_factor,
4310 DMatrix5x1 &S,
4311 DMatrix5x5 &C,
4312 double &chisq,
4313 unsigned int &numdof){
4314 DMatrix2x1 Mdiff; // difference between measurement and prediction
4315 DMatrix2x5 H; // Track projection matrix
4316 DMatrix5x2 H_T; // Transpose of track projection matrix
4317 DMatrix1x5 Hc; // Track projection matrix for cdc hits
4318 DMatrix5x1 Hc_T; // Transpose of track projection matrix for cdc hits
4319 DMatrix5x5 J; // State vector Jacobian matrix
4320 //DMatrix5x5 J_T; // transpose of this matrix
4321 DMatrix5x5 Q; // Process noise covariance matrix
4322 DMatrix5x2 K; // Kalman gain matrix
4323 DMatrix5x1 Kc; // Kalman gain matrix for cdc hits
4324 DMatrix2x2 V(0.0833,0.,0.,FDC_CATHODE_VARIANCE0.000225); // Measurement covariance matrix
4325 DMatrix2x1 R; // Filtered residual
4326 DMatrix2x2 RC; // Covariance of filtered residual
4327 DMatrix5x1 S0,S0_; //State vector
4328 DMatrix5x5 Ctest; // Covariance matrix
4329 DMatrix2x2 InvV; // Inverse of error matrix
4330
4331 double Vc=0.0507;
4332
4333 // Vectors for cdc wires
4334 DVector2 origin,dir,wirepos;
4335 double z0w=0.; // origin in z for wire
4336
4337 // Set used_in_fit flags to false for fdc and cdc hits
4338 unsigned int num_cdc=cdc_used_in_fit.size();
4339 unsigned int num_fdc=fdc_used_in_fit.size();
4340 for (unsigned int i=0;i<num_cdc;i++) cdc_used_in_fit[i]=false;
4341 for (unsigned int i=0;i<num_fdc;i++) fdc_used_in_fit[i]=false;
4342 for (unsigned int i=0;i<forward_traj.size();i++){
4343 if (forward_traj[i].h_id>999)
4344 forward_traj[i].h_id=0;
4345 }
4346
4347 // Save the starting values for C and S in the deque
4348 forward_traj[break_point_step_index].Skk=S;
4349 forward_traj[break_point_step_index].Ckk=C;
4350
4351 // Initialize chi squared
4352 chisq=0;
4353
4354 // Initialize number of degrees of freedom
4355 numdof=0;
4356
4357 double fdc_chi2cut=NUM_FDC_SIGMA_CUT*NUM_FDC_SIGMA_CUT;
4358 double cdc_chi2cut=NUM_CDC_SIGMA_CUT*NUM_CDC_SIGMA_CUT;
4359
4360 unsigned int num_fdc_hits=break_point_fdc_index+1;
4361 unsigned int max_num_fdc_used_in_fit=num_fdc_hits;
4362 unsigned int num_cdc_hits=my_cdchits.size();
4363 unsigned int cdc_index=0;
4364 if (num_cdc_hits>0) cdc_index=num_cdc_hits-1;
4365 bool more_cdc_measurements=(num_cdc_hits>0);
4366 double old_doca2=1e6;
4367
4368 if (num_fdc_hits+num_cdc_hits<MIN_HITS_FOR_REFIT){
4369 cdc_chi2cut=BIG1.0e8;
4370 fdc_chi2cut=BIG1.0e8;
4371 }
4372
4373 if (more_cdc_measurements){
4374 origin=my_cdchits[cdc_index]->origin;
4375 dir=my_cdchits[cdc_index]->dir;
4376 z0w=my_cdchits[cdc_index]->z0wire;
4377 wirepos=origin+(forward_traj[break_point_step_index].z-z0w)*dir;
4378 }
4379
4380 S0_=(forward_traj[break_point_step_index].S);
4381
4382 if (DEBUG_LEVEL > 25){
4383 jout << "Entering DTrackFitterKalmanSIMD::KalmanForward ================================" << endl;
4384 jout << " We have the following starting parameters for our fit. S = State vector, C = Covariance matrix" << endl;
4385 S.Print();
4386 C.Print();
4387 jout << setprecision(6);
4388 jout << " There are " << num_cdc << " CDC Updates and " << num_fdc << " FDC Updates on this track" << endl;
4389 jout << " There are " << num_cdc_hits << " CDC Hits and " << num_fdc_hits << " FDC Hits on this track" << endl;
4390 jout << " With NUM_FDC_SIGMA_CUT = " << NUM_FDC_SIGMA_CUT << " and NUM_CDC_SIGMA_CUT = " << NUM_CDC_SIGMA_CUT << endl;
4391 jout << " fdc_anneal_factor = " << fdc_anneal_factor << " cdc_anneal_factor = " << cdc_anneal_factor << endl;
4392 jout << " yields fdc_chi2cut = " << fdc_chi2cut << " cdc_chi2cut = " << cdc_chi2cut << endl;
4393 jout << " Starting from break_point_step_index " << break_point_step_index << endl;
4394 jout << " S0_ which is the state vector of the reference trajectory at the break point step:" << endl;
4395 S0_.Print();
4396 jout << " ===== Beginning pass over reference trajectory ======== " << endl;
4397 }
4398
4399 for (unsigned int k=break_point_step_index+1;k<forward_traj.size();k++){
4400 unsigned int k_minus_1=k-1;
4401
4402 // Get the state vector, jacobian matrix, and multiple scattering matrix
4403 // from reference trajectory
4404 S0=(forward_traj[k].S);
4405 J=(forward_traj[k].J);
4406 Q=(forward_traj[k].Q);
4407
4408 // State S is perturbation about a seed S0
4409 //dS=S-S0_;
4410
4411 // Update the actual state vector and covariance matrix
4412 S=S0+J*(S-S0_);
4413
4414 // Bail if the momentum has dropped below some minimum
4415 if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX){
4416 if (DEBUG_LEVEL>2)
4417 {
4418 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4418<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p)) << endl;
4419 }
4420 break_point_fdc_index=(3*num_fdc)/4;
4421 return MOMENTUM_OUT_OF_RANGE;
4422 }
4423
4424
4425 //C=J*(C*J_T)+Q;
4426 //C=Q.AddSym(C.SandwichMultiply(J));
4427 C=Q.AddSym(J*C*J.Transpose());
4428
4429 // Save the current state and covariance matrix in the deque
4430 forward_traj[k].Skk=S;
4431 forward_traj[k].Ckk=C;
4432
4433 // Save the current state of the reference trajectory
4434 S0_=S0;
4435
4436 // Z position along the trajectory
4437 double z=forward_traj[k].z;
4438
4439 if (DEBUG_LEVEL > 25){
4440 jout << " At reference trajectory index " << k << " at z=" << z << endl;
4441 jout << " The State vector from the reference trajectory" << endl;
4442 S0.Print();
4443 jout << " The Jacobian matrix " << endl;
4444 J.Print();
4445 jout << " The Q matrix "<< endl;
4446 Q.Print();
4447 jout << " The updated State vector S=S0+J*(S-S0_)" << endl;
4448 S.Print();
4449 jout << " The updated Covariance matrix C=J*(C*J_T)+Q;" << endl;
4450 C.Print();
4451 }
4452
4453 // Add the hit
4454 if (num_fdc_hits>0){
4455 if (forward_traj[k].h_id>0 && forward_traj[k].h_id<1000){
4456 unsigned int id=forward_traj[k].h_id-1;
4457 // Check if this is a plane we want to skip in the fit (we still want
4458 // to store track and hit info at this plane, however).
4459 bool skip_plane=(my_fdchits[id]->hit!=NULL__null
4460 &&my_fdchits[id]->hit->wire->layer==PLANE_TO_SKIP);
4461 double upred=0,vpred=0.,doca=0.,cosalpha=0.,lorentz_factor=0.;
4462 FindDocaAndProjectionMatrix(my_fdchits[id],S,upred,vpred,doca,cosalpha,
4463 lorentz_factor,H_T);
4464 // Matrix transpose H_T -> H
4465 H=Transpose(H_T);
4466
4467 // Variance in coordinate transverse to wire
4468 V(0,0)=my_fdchits[id]->uvar;
4469 if (my_fdchits[id]->hit==NULL__null&&my_fdchits[id]->status!=trd_hit){
4470 V(0,0)*=fdc_anneal_factor;
4471 }
4472
4473 // Variance in coordinate along wire
4474 V(1,1)=my_fdchits[id]->vvar*fdc_anneal_factor;
4475
4476 // Residual for coordinate along wire
4477 Mdiff(1)=my_fdchits[id]->vstrip-vpred-doca*lorentz_factor;
4478
4479 // Residual for coordinate transverse to wire
4480 Mdiff(0)=-doca;
4481 double drift_time=my_fdchits[id]->t-mT0-forward_traj[k].t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
4482 if (fit_type==kTimeBased && USE_FDC_DRIFT_TIMES){
4483 if (my_fdchits[id]->hit!=NULL__null){
4484 double drift=(doca>0.0?1.:-1.)
4485 *fdc_drift_distance(drift_time,forward_traj[k].B);
4486 Mdiff(0)+=drift;
4487
4488 // Variance in drift distance
4489 V(0,0)=fdc_drift_variance(drift_time)*fdc_anneal_factor;
4490 }
4491 else if (USE_TRD_DRIFT_TIMES&&my_fdchits[id]->status==trd_hit){
4492 double drift =(doca>0.0?1.:-1.)*0.1*pow(drift_time/8./0.91,1./1.556);
4493 Mdiff(0)+=drift;
4494
4495 // Variance in drift distance
4496 V(0,0)=0.05*0.05*fdc_anneal_factor;
4497 }
4498 }
4499 // Check to see if we have multiple hits in the same plane
4500 if (!ALIGNMENT_FORWARD && forward_traj[k].num_hits>1){
4501 UpdateSandCMultiHit(forward_traj[k],upred,vpred,doca,cosalpha,
4502 lorentz_factor,V,Mdiff,H,H_T,S,C,
4503 fdc_chi2cut,skip_plane,chisq,numdof,
4504 fdc_anneal_factor);
4505 }
4506 else{
4507 if (DEBUG_LEVEL > 25) jout << " == There is a single FDC hit on this plane" << endl;
4508
4509 // Variance for this hit
4510 DMatrix2x2 Vtemp=V+H*C*H_T;
4511 InvV=Vtemp.Invert();
4512
4513 // Check if this hit is an outlier
4514 double chi2_hit=Vtemp.Chi2(Mdiff);
4515 if (chi2_hit<fdc_chi2cut){
4516 // Compute Kalman gain matrix
4517 K=C*H_T*InvV;
4518
4519 if (skip_plane==false){
4520 // Update the state vector
4521 S+=K*Mdiff;
4522
4523 // Update state vector covariance matrix
4524 //C=C-K*(H*C);
4525 C=C.SubSym(K*(H*C));
4526
4527 if (DEBUG_LEVEL > 25) {
4528 jout << "S Update: " << endl; S.Print();
4529 jout << "C Uodate: " << endl; C.Print();
4530 }
4531 }
4532
4533 // Store the "improved" values for the state vector and covariance
4534 fdc_updates[id].S=S;
4535 fdc_updates[id].C=C;
4536 fdc_updates[id].tdrift=drift_time;
4537 fdc_updates[id].tcorr=fdc_updates[id].tdrift; // temporary!
4538 fdc_updates[id].doca=doca;
4539 fdc_used_in_fit[id]=true;
4540
4541 if (skip_plane==false){
4542 // Filtered residual and covariance of filtered residual
4543 R=Mdiff-H*K*Mdiff;
4544 RC=V-H*(C*H_T);
4545
4546 fdc_updates[id].V=RC;
4547
4548 // Update chi2 for this segment
4549 chisq+=RC.Chi2(R);
4550
4551 // update number of degrees of freedom
4552 numdof+=2;
4553
4554 if (DEBUG_LEVEL>20)
4555 {
4556 printf("hit %d p %5.2f t %f dm %5.2f sig %f chi2 %5.2f z %5.2f\n",
4557 id,1./S(state_q_over_p),fdc_updates[id].tdrift,Mdiff(1),
4558 sqrt(V(1,1)),RC.Chi2(R),
4559 forward_traj[k].z);
4560
4561 }
4562 }
4563 else{
4564 fdc_updates[id].V=V;
4565 }
4566
4567 break_point_fdc_index=id;
4568 break_point_step_index=k;
4569 }
4570 }
4571 if (num_fdc_hits>=forward_traj[k].num_hits)
4572 num_fdc_hits-=forward_traj[k].num_hits;
4573 }
4574 }
4575 else if (more_cdc_measurements /* && z<endplate_z*/){
4576 // new wire position
4577 wirepos=origin;
4578 wirepos+=(z-z0w)*dir;
4579
4580 // doca variables
4581 double dx=S(state_x)-wirepos.X();
4582 double dy=S(state_y)-wirepos.Y();
4583 double doca2=dx*dx+dy*dy;
4584
4585 // Check if the doca is no longer decreasing
4586 if (doca2>old_doca2){
4587 if(my_cdchits[cdc_index]->status==good_hit){
4588 find_doca_error_t swimmed_to_doca=DOCA_NO_BRENT;
4589 double newz=endplate_z;
4590 double dz=newz-z;
4591 // Sometimes the true doca would correspond to the case where the
4592 // wire would need to extend beyond the physical volume of the straw.
4593 // In this case, find the doca at the cdc endplate.
4594 if (z>endplate_z){
4595 swimmed_to_doca=DOCA_ENDPLATE;
4596 SwimToEndplate(z,forward_traj[k],S);
4597
4598 // wire position at the endplate
4599 wirepos=origin;
4600 wirepos+=(endplate_z-z0w)*dir;
4601
4602 dx=S(state_x)-wirepos.X();
4603 dy=S(state_y)-wirepos.Y();
4604 }
4605 else{
4606 // Find the true doca to the wire. If we had to use Brent's
4607 // algorithm, the routine returns true.
4608 double step1=mStepSizeZ;
4609 double step2=mStepSizeZ;
4610 if (k>=2){
4611 step1=-forward_traj[k].z+forward_traj[k_minus_1].z;
4612 step2=-forward_traj[k_minus_1].z+forward_traj[k-2].z;
4613 }
4614 swimmed_to_doca=FindDoca(my_cdchits[cdc_index],forward_traj[k],
4615 step1,step2,S0,S,C,dx,dy,dz);
4616 if (swimmed_to_doca==BRENT_FAILED){
4617 //break_point_fdc_index=(3*num_fdc)/4;
4618 return MOMENTUM_OUT_OF_RANGE;
4619 }
4620
4621 newz=forward_traj[k].z+dz;
4622 }
4623 double cosstereo=my_cdchits[cdc_index]->cosstereo;
4624 double d=sqrt(dx*dx+dy*dy)*cosstereo+EPS3.0e-8;
4625
4626 // Track projection
4627 double cosstereo2_over_d=cosstereo*cosstereo/d;
4628 Hc_T(state_x)=dx*cosstereo2_over_d;
4629 Hc(state_x)=Hc_T(state_x);
4630 Hc_T(state_y)=dy*cosstereo2_over_d;
4631 Hc(state_y)=Hc_T(state_y);
4632 if (swimmed_to_doca==DOCA_NO_BRENT){
4633 Hc_T(state_ty)=Hc_T(state_y)*dz;
4634 Hc(state_ty)=Hc_T(state_ty);
4635 Hc_T(state_tx)=Hc_T(state_x)*dz;
4636 Hc(state_tx)=Hc_T(state_tx);
4637 }
4638 else{
4639 Hc_T(state_ty)=0.;
4640 Hc(state_ty)=0.;
4641 Hc_T(state_tx)=0.;
4642 Hc(state_tx)=0.;
4643 }
4644
4645 //H.Print();
4646
4647 // The next measurement
4648 double dm=0.39,tdrift=0.,tcorr=0.,dDdt0=0.;
4649 if (fit_type==kTimeBased){
4650 // Find offset of wire with respect to the center of the
4651 // straw at this z position
4652 double delta=0,dphi=0.;
4653 FindSag(dx,dy,newz-z0w,my_cdchits[cdc_index]->hit->wire,delta,dphi);
4654
4655 // Find drift time and distance
4656 tdrift=my_cdchits[cdc_index]->tdrift-mT0
4657 -forward_traj[k_minus_1].t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
4658 double B=forward_traj[k_minus_1].B;
4659 ComputeCDCDrift(dphi,delta,tdrift,B,dm,Vc,tcorr);
4660 Vc*=cdc_anneal_factor;
4661 if (ALIGNMENT_FORWARD){
4662 double myV=0.;
4663 double mytcorr=0.;
4664 double d_shifted;
4665 double dt=5.0;
4666 // Dont compute this for negative drift times
4667 if (tdrift < 0.) d_shifted = dm;
4668 else ComputeCDCDrift(dphi,delta,tdrift+dt,B,d_shifted,myV,mytcorr);
4669 dDdt0=(d_shifted-dm)/dt;
4670 }
4671
4672 if (max_num_fdc_used_in_fit>4)
4673 {
4674 Vc*=CDC_VAR_SCALE_FACTOR; //de-weight CDC hits
4675 }
4676 //_DBG_ << "t " << tdrift << " d " << d << " delta " << delta << " dphi " << atan2(dy,dx)-mywire->origin.Phi() << endl;
4677
4678 //_DBG_ << tcorr << " " << dphi << " " << dm << endl;
4679 }
4680
4681 // Residual
4682 double res=dm-d;
4683
4684 // inverse variance including prediction
4685 //double InvV1=1./(Vc+H*(C*H_T));
4686 //double Vproj=C.SandwichMultiply(Hc_T);
4687 double Vproj=Hc*C*Hc_T;
4688 double InvV1=1./(Vc+Vproj);
4689 if (InvV1<0.){
4690 if (DEBUG_LEVEL>0)
4691 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4691<<" "
<< "Negative variance???" << endl;
4692 return NEGATIVE_VARIANCE;
4693 }
4694
4695 // Check if this hit is an outlier
4696 double chi2_hit=res*res*InvV1;
4697 if (chi2_hit<cdc_chi2cut){
4698 // Compute KalmanSIMD gain matrix
4699 Kc=InvV1*(C*Hc_T);
4700
4701 // Update state vector covariance matrix
4702 //C=C-K*(H*C);
4703 Ctest=C.SubSym(Kc*(Hc*C));
4704 //Ctest=C.SandwichMultiply(I5x5-K*H)+Vc*MultiplyTranspose(K);
4705 // Check that Ctest is positive definite
4706 if (!Ctest.IsPosDef()){
4707 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4707<<" "
<< "Broken covariance matrix!" <<endl;
4708 return BROKEN_COVARIANCE_MATRIX;
4709 }
4710 bool skip_ring
4711 =(my_cdchits[cdc_index]->hit->wire->ring==RING_TO_SKIP);
4712 // update covariance matrix and state vector
4713 if (my_cdchits[cdc_index]->hit->wire->ring!=RING_TO_SKIP && tdrift >= CDC_T_DRIFT_MIN){
4714 C=Ctest;
4715 S+=res*Kc;
4716
4717 if (DEBUG_LEVEL > 25) {
4718 jout << " == Adding CDC Hit in Ring " << my_cdchits[cdc_index]->hit->wire->ring << endl;
4719 jout << " New S: " << endl; S.Print();
4720 jout << " New C: " << endl; C.Print();
4721 }
4722 }
4723
4724 // Flag the place along the reference trajectory with hit id
4725 forward_traj[k].h_id=1000+cdc_index;
4726
4727 // Store updated info related to this hit
4728 double scale=(skip_ring)?1.:(1.-Hc*Kc);
4729 cdc_updates[cdc_index].tdrift=tdrift;
4730 cdc_updates[cdc_index].tcorr=tcorr;
4731 cdc_updates[cdc_index].variance=Vc;
4732 cdc_updates[cdc_index].doca=dm;
4733 cdc_updates[cdc_index].dDdt0=dDdt0;
4734 cdc_used_in_fit[cdc_index]=true;
4735 if(tdrift < CDC_T_DRIFT_MIN){
4736 //_DBG_ << tdrift << endl;
4737 cdc_used_in_fit[cdc_index]=false;
4738 }
4739
4740 // Update chi2 and number of degrees of freedom for this hit
4741 if (skip_ring==false && tdrift >= CDC_T_DRIFT_MIN){
4742 chisq+=scale*res*res/Vc;
4743 numdof++;
4744 }
4745
4746 if (DEBUG_LEVEL>10)
4747 jout << "Ring " << my_cdchits[cdc_index]->hit->wire->ring
4748 << " Straw " << my_cdchits[cdc_index]->hit->wire->straw
4749 << " Pred " << d << " Meas " << dm
4750 << " Sigma meas " << sqrt(Vc)
4751 << " t " << tcorr
4752 << " Chi2 " << (1.-Hc*Kc)*res*res/Vc << endl;
4753
4754 break_point_cdc_index=cdc_index;
4755 break_point_step_index=k_minus_1;
4756
4757 }
4758
4759 // If we had to use Brent's algorithm to find the true doca or the
4760 // doca to the line corresponding to the wire is downstream of the
4761 // cdc endplate, we need to swim the state vector and covariance
4762 // matrix back to the appropriate position along the reference
4763 // trajectory.
4764 if (swimmed_to_doca!=DOCA_NO_BRENT){
4765 double dedx=0.;
4766 if (CORRECT_FOR_ELOSS){
4767 dedx=GetdEdx(S(state_q_over_p),
4768 forward_traj[k].K_rho_Z_over_A,
4769 forward_traj[k].rho_Z_over_A,
4770 forward_traj[k].LnI,forward_traj[k].Z);
4771 }
4772 StepBack(dedx,newz,forward_traj[k].z,S0,S,C);
4773 }
4774
4775 cdc_updates[cdc_index].S=S;
4776 cdc_updates[cdc_index].C=C;
4777 }
4778
4779 // new wire origin and direction
4780 if (cdc_index>0){
4781 cdc_index--;
4782 origin=my_cdchits[cdc_index]->origin;
4783 z0w=my_cdchits[cdc_index]->z0wire;
4784 dir=my_cdchits[cdc_index]->dir;
4785 }
4786 else more_cdc_measurements=false;
4787
4788 // Update the wire position
4789 wirepos=origin+(z-z0w)*dir;
4790
4791 // new doca
4792 dx=S(state_x)-wirepos.X();
4793 dy=S(state_y)-wirepos.Y();
4794 doca2=dx*dx+dy*dy;
4795 }
4796 old_doca2=doca2;
4797 }
4798 }
4799 // Save final z position
4800 z_=forward_traj[forward_traj.size()-1].z;
4801
4802 // The following code segment addes a fake point at a well-defined z position
4803 // that would correspond to a thin foil target. It should not be turned on
4804 // for an extended target.
4805 if (ADD_VERTEX_POINT){
4806 double dz_to_target=TARGET_Z-z_;
4807 double my_dz=mStepSizeZ*(dz_to_target>0?1.:-1.);
4808 int num_steps=int(fabs(dz_to_target/my_dz));
4809
4810 for (int k=0;k<num_steps;k++){
4811 double newz=z_+my_dz;
4812 // Step C along z
4813 StepJacobian(z_,newz,S,0.,J);
4814 C=J*C*J.Transpose();
4815 //C=C.SandwichMultiply(J);
4816
4817 // Step S along z
4818 Step(z_,newz,0.,S);
4819
4820 z_=newz;
4821 }
4822
4823 // Step C along z
4824 StepJacobian(z_,TARGET_Z,S,0.,J);
4825 C=J*C*J.Transpose();
4826 //C=C.SandwichMultiply(J);
4827
4828 // Step S along z
4829 Step(z_,TARGET_Z,0.,S);
4830
4831 z_=TARGET_Z;
4832
4833 // predicted doca taking into account the orientation of the wire
4834 double dy=S(state_y);
4835 double dx=S(state_x);
4836 double d=sqrt(dx*dx+dy*dy);
4837
4838 // Track projection
4839 double one_over_d=1./d;
4840 Hc_T(state_x)=dx*one_over_d;
4841 Hc(state_x)=Hc_T(state_x);
4842 Hc_T(state_y)=dy*one_over_d;
4843 Hc(state_y)=Hc_T(state_y);
4844
4845 // Variance of target point
4846 // Variance is for average beam spot size assuming triangular distribution
4847 // out to 2.2 mm from the beam line.
4848 // sigma_r = 2.2 mm/ sqrt(18)
4849 Vc=0.002689;
4850
4851 // inverse variance including prediction
4852 double InvV1=1./(Vc+Hc*(C*Hc_T));
4853 //double InvV1=1./(Vc+C.SandwichMultiply(H_T));
4854 if (InvV1<0.){
4855 if (DEBUG_LEVEL>0)
4856 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<4856<<" "
<< "Negative variance???" << endl;
4857 return NEGATIVE_VARIANCE;
4858 }
4859 // Compute KalmanSIMD gain matrix
4860 Kc=InvV1*(C*Hc_T);
4861
4862 // Update the state vector with the target point
4863 // "Measurement" is average of expected beam spot size
4864 double res=0.1466666667-d;
4865 S+=res*Kc;
4866 // Update state vector covariance matrix
4867 //C=C-K*(H*C);
4868 C=C.SubSym(Kc*(Hc*C));
4869
4870 // Update chi2 for this segment
4871 chisq+=(1.-Hc*Kc)*res*res/Vc;
4872 numdof++;
4873 }
4874
4875 // Check that there were enough hits to make this a valid fit
4876 if (numdof<6){
4877 chisq=-1.;
4878 numdof=0;
4879
4880 if (num_cdc==0){
4881 unsigned int new_index=(3*num_fdc)/4;
4882 break_point_fdc_index=(new_index>=MIN_HITS_FOR_REFIT)?new_index:(MIN_HITS_FOR_REFIT-1);
4883 }
4884 else{
4885 unsigned int new_index=(3*num_fdc)/4;
4886 if (new_index+num_cdc>=MIN_HITS_FOR_REFIT){
4887 break_point_fdc_index=new_index;
4888 }
4889 else{
4890 break_point_fdc_index=MIN_HITS_FOR_REFIT-num_cdc;
4891 }
4892 }
4893 return PRUNED_TOO_MANY_HITS;
4894 }
4895
4896 // chisq*=anneal_factor;
4897 numdof-=5;
4898
4899 // Final positions in x and y for this leg
4900 x_=S(state_x);
4901 y_=S(state_y);
4902
4903 if (DEBUG_LEVEL>1){
4904 cout << "Position after forward filter: " << x_ << ", " << y_ << ", " << z_ <<endl;
4905 cout << "Momentum " << 1./S(state_q_over_p) <<endl;
4906 }
4907
4908 if (!S.IsFinite()) return FIT_FAILED;
4909
4910 // Check if we have a kink in the track or threw away too many hits
4911 if (num_cdc>0 && break_point_fdc_index>0 && break_point_cdc_index>2){
4912 if (break_point_fdc_index+num_cdc<MIN_HITS_FOR_REFIT){
4913 //_DBG_ << endl;
4914 unsigned int new_index=(3*num_fdc)/4;
4915 if (new_index+num_cdc>=MIN_HITS_FOR_REFIT){
4916 break_point_fdc_index=new_index;
4917 }
4918 else{
4919 break_point_fdc_index=MIN_HITS_FOR_REFIT-num_cdc;
4920 }
4921 }
4922 return BREAK_POINT_FOUND;
4923 }
4924 if (num_cdc==0 && break_point_fdc_index>2){
4925 //_DBG_ << endl;
4926 if (break_point_fdc_index<num_fdc/2){
4927 break_point_fdc_index=(3*num_fdc)/4;
4928 }
4929 if (break_point_fdc_index<MIN_HITS_FOR_REFIT-1){
4930 break_point_fdc_index=MIN_HITS_FOR_REFIT-1;
4931 }
4932 return BREAK_POINT_FOUND;
4933 }
4934 if (num_cdc>5 && break_point_cdc_index>2){
4935 //_DBG_ << endl;
4936 unsigned int new_index=3*(num_fdc)/4;
4937 if (new_index+num_cdc>=MIN_HITS_FOR_REFIT){
4938 break_point_fdc_index=new_index;
4939 }
4940 else{
4941 break_point_fdc_index=MIN_HITS_FOR_REFIT-num_cdc;
4942 }
4943 return BREAK_POINT_FOUND;
4944 }
4945 unsigned int num_good=0;
4946 unsigned int num_hits=num_cdc+max_num_fdc_used_in_fit;
4947 for (unsigned int j=0;j<num_cdc;j++){
4948 if (cdc_used_in_fit[j]) num_good++;
4949 }
4950 for (unsigned int j=0;j<num_fdc;j++){
4951 if (fdc_used_in_fit[j]) num_good++;
4952 }
4953 if (double(num_good)/double(num_hits)<MINIMUM_HIT_FRACTION){
4954 //_DBG_ <<endl;
4955 if (num_cdc==0){
4956 unsigned int new_index=(3*num_fdc)/4;
4957 break_point_fdc_index=(new_index>=MIN_HITS_FOR_REFIT)?new_index:(MIN_HITS_FOR_REFIT-1);
4958 }
4959 else{
4960 unsigned int new_index=(3*num_fdc)/4;
4961 if (new_index+num_cdc>=MIN_HITS_FOR_REFIT){
4962 break_point_fdc_index=new_index;
4963 }
4964 else{
4965 break_point_fdc_index=MIN_HITS_FOR_REFIT-num_cdc;
4966 }
4967 }
4968 return PRUNED_TOO_MANY_HITS;
4969 }
4970
4971 return FIT_SUCCEEDED;
4972}
4973
4974
4975
4976// Kalman engine for forward tracks -- this routine adds CDC hits
4977kalman_error_t DTrackFitterKalmanSIMD::KalmanForwardCDC(double anneal,
4978 DMatrix5x1 &S,
4979 DMatrix5x5 &C,
4980 double &chisq,
4981 unsigned int &numdof){
4982 DMatrix1x5 H; // Track projection matrix
4983 DMatrix5x1 H_T; // Transpose of track projection matrix
4984 DMatrix5x5 J; // State vector Jacobian matrix
4985 //DMatrix5x5 J_T; // transpose of this matrix
4986 DMatrix5x5 Q; // Process noise covariance matrix
4987 DMatrix5x1 K; // KalmanSIMD gain matrix
4988 DMatrix5x1 S0,S0_,Stest; //State vector
4989 DMatrix5x5 Ctest; // covariance matrix
4990 //DMatrix5x1 dS; // perturbation in state vector
4991 double V=0.0507;
4992
4993 // set used_in_fit flags to false for cdc hits
4994 unsigned int num_cdc=cdc_used_in_fit.size();
4995 for (unsigned int i=0;i<num_cdc;i++) cdc_used_in_fit[i]=false;
4996 for (unsigned int i=0;i<forward_traj.size();i++){
4997 forward_traj[i].h_id=0;
4998 }
4999
5000 // initialize chi2 info
5001 chisq=0.;
5002 numdof=0;
5003
5004 double chi2cut=NUM_CDC_SIGMA_CUT*NUM_CDC_SIGMA_CUT;
5005
5006 // Save the starting values for C and S in the deque
5007 forward_traj[break_point_step_index].Skk=S;
5008 forward_traj[break_point_step_index].Ckk=C;
5009
5010 // z-position
5011 double z=forward_traj[break_point_step_index].z;
5012
5013 // wire information
5014 unsigned int cdc_index=break_point_cdc_index;
5015 if (cdc_index<num_cdc-1){
5016 num_cdc=cdc_index+1;
5017 }
5018
5019 if (num_cdc<MIN_HITS_FOR_REFIT) chi2cut=BIG1.0e8;
5020
5021 DVector2 origin=my_cdchits[cdc_index]->origin;
5022 double z0w=my_cdchits[cdc_index]->z0wire;
5023 DVector2 dir=my_cdchits[cdc_index]->dir;
5024 DVector2 wirepos=origin+(z-z0w)*dir;
5025 bool more_measurements=true;
5026
5027 // doca variables
5028 double dx=S(state_x)-wirepos.X();
5029 double dy=S(state_y)-wirepos.Y();
5030 double doca2=0.,old_doca2=dx*dx+dy*dy;
5031
5032 // loop over entries in the trajectory
5033 S0_=(forward_traj[break_point_step_index].S);
5034 for (unsigned int k=break_point_step_index+1;k<forward_traj.size()/*-1*/;k++){
5035 unsigned int k_minus_1=k-1;
5036
5037 z=forward_traj[k].z;
5038
5039 // Get the state vector, jacobian matrix, and multiple scattering matrix
5040 // from reference trajectory
5041 S0=(forward_traj[k].S);
5042 J=(forward_traj[k].J);
5043 Q=(forward_traj[k].Q);
5044
5045 // Update the actual state vector and covariance matrix
5046 S=S0+J*(S-S0_);
5047
5048 // Bail if the position is grossly outside of the tracking volume
5049 if (S(state_x)*S(state_x)+S(state_y)*S(state_y)>R2_MAX4225.0){
5050 if (DEBUG_LEVEL>2)
5051 {
5052 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5052<<" "
<< "Went outside of tracking volume at x=" << S(state_x)
5053 << " y=" << S(state_y) <<" z="<<z<<endl;
5054 }
5055 return POSITION_OUT_OF_RANGE;
5056 }
5057 // Bail if the momentum has dropped below some minimum
5058 if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX){
5059 if (DEBUG_LEVEL>2)
5060 {
5061 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5061<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p)) << endl;
5062 }
5063 return MOMENTUM_OUT_OF_RANGE;
5064 }
5065
5066 //C=J*(C*J_T)+Q;
5067 C=Q.AddSym(J*C*J.Transpose());
5068 //C=Q.AddSym(C.SandwichMultiply(J));
5069
5070 // Save the current state of the reference trajectory
5071 S0_=S0;
5072
5073 // new wire position
5074 wirepos=origin;
5075 wirepos+=(z-z0w)*dir;
5076
5077 // new doca
5078 dx=S(state_x)-wirepos.X();
5079 dy=S(state_y)-wirepos.Y();
5080 doca2=dx*dx+dy*dy;
5081
5082 // Save the current state and covariance matrix in the deque
5083 if (fit_type==kTimeBased){
5084 forward_traj[k].Skk=S;
5085 forward_traj[k].Ckk=C;
5086 }
5087
5088 // Check if the doca is no longer decreasing
5089 if (more_measurements && doca2>old_doca2/* && z<endplate_z_downstream*/){
5090 if (my_cdchits[cdc_index]->status==good_hit){
5091 find_doca_error_t swimmed_to_doca=DOCA_NO_BRENT;
5092 double newz=endplate_z;
5093 double dz=newz-z;
5094 // Sometimes the true doca would correspond to the case where the
5095 // wire would need to extend beyond the physical volume of the straw.
5096 // In this case, find the doca at the cdc endplate.
5097 if (z>endplate_z){
5098 swimmed_to_doca=DOCA_ENDPLATE;
5099 SwimToEndplate(z,forward_traj[k],S);
5100
5101 // wire position at the endplate
5102 wirepos=origin;
5103 wirepos+=(endplate_z-z0w)*dir;
5104
5105 dx=S(state_x)-wirepos.X();
5106 dy=S(state_y)-wirepos.Y();
5107 }
5108 else{
5109 // Find the true doca to the wire. If we had to use Brent's
5110 // algorithm, the routine returns USED_BRENT
5111 double step1=mStepSizeZ;
5112 double step2=mStepSizeZ;
5113 if (k>=2){
5114 step1=-forward_traj[k].z+forward_traj[k_minus_1].z;
5115 step2=-forward_traj[k_minus_1].z+forward_traj[k-2].z;
5116 }
5117 swimmed_to_doca=FindDoca(my_cdchits[cdc_index],forward_traj[k],
5118 step1,step2,S0,S,C,dx,dy,dz);
5119 if (swimmed_to_doca==BRENT_FAILED){
5120 break_point_cdc_index=(3*num_cdc)/4;
5121 return MOMENTUM_OUT_OF_RANGE;
5122 }
5123 newz=forward_traj[k].z+dz;
5124 }
5125 double cosstereo=my_cdchits[cdc_index]->cosstereo;
5126 double d=sqrt(dx*dx+dy*dy)*cosstereo+EPS3.0e-8;
5127
5128 // Track projection
5129 double cosstereo2_over_d=cosstereo*cosstereo/d;
5130 H_T(state_x)=dx*cosstereo2_over_d;
5131 H(state_x)=H_T(state_x);
5132 H_T(state_y)=dy*cosstereo2_over_d;
5133 H(state_y)=H_T(state_y);
5134 if (swimmed_to_doca==DOCA_NO_BRENT){
5135 H_T(state_ty)=H_T(state_y)*dz;
5136 H(state_ty)=H_T(state_ty);
5137 H_T(state_tx)=H_T(state_x)*dz;
5138 H(state_tx)=H_T(state_tx);
5139 }
5140 else{
5141 H_T(state_ty)=0.;
5142 H(state_ty)=0.;
5143 H_T(state_tx)=0.;
5144 H(state_tx)=0.;
5145 }
5146
5147 // The next measurement
5148 double dm=0.39,tdrift=0.,tcorr=0.,dDdt0=0.;
5149 if (fit_type==kTimeBased || USE_PASS1_TIME_MODE){
5150 // Find offset of wire with respect to the center of the
5151 // straw at this z position
5152 double delta=0,dphi=0.;
5153 FindSag(dx,dy,newz-z0w,my_cdchits[cdc_index]->hit->wire,delta,dphi);
5154 // Find drift time and distance
5155 tdrift=my_cdchits[cdc_index]->tdrift-mT0
5156 -forward_traj[k_minus_1].t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
5157 double B=forward_traj[k_minus_1].B;
5158 ComputeCDCDrift(dphi,delta,tdrift,B,dm,V,tcorr);
5159 V*=anneal;
5160 if (ALIGNMENT_FORWARD){
5161 double myV=0.;
5162 double mytcorr=0.;
5163 double d_shifted;
5164 double dt=2.0;
5165 if (tdrift < 0.) d_shifted = dm;
5166 else ComputeCDCDrift(dphi,delta,tdrift+dt,B,d_shifted,myV,mytcorr);
5167 dDdt0=(d_shifted-dm)/dt;
5168 }
5169 //_DBG_ << tcorr << " " << dphi << " " << dm << endl;
5170
5171 }
5172 // residual
5173 double res=dm-d;
5174
5175 // inverse of variance including prediction
5176 double Vproj=H*C*H_T;
5177 double InvV=1./(V+Vproj);
5178 if (InvV<0.){
5179 if (DEBUG_LEVEL>0)
5180 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5180<<" "
<< "Negative variance???" << endl;
5181 break_point_cdc_index=(3*num_cdc)/4;
5182 return NEGATIVE_VARIANCE;
5183 }
5184
5185 // Check how far this hit is from the expected position
5186 double chi2check=res*res*InvV;
5187 if (chi2check<chi2cut){
5188 // Compute KalmanSIMD gain matrix
5189 K=InvV*(C*H_T);
5190
5191 // Update state vector covariance matrix
5192 Ctest=C.SubSym(K*(H*C));
5193 // Joseph form
5194 // C = (I-KH)C(I-KH)^T + KVK^T
5195 //Ctest=C.SandwichMultiply(I5x5-K*H)+V*MultiplyTranspose(K);
5196 // Check that Ctest is positive definite
5197 if (!Ctest.IsPosDef()){
5198 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5198<<" "
<< "Broken covariance matrix!" <<endl;
5199 return BROKEN_COVARIANCE_MATRIX;
5200 }
5201
5202 bool skip_ring
5203 =(my_cdchits[cdc_index]->hit->wire->ring==RING_TO_SKIP);
5204 // update covariance matrix and state vector
5205 if (skip_ring==false && tdrift >= CDC_T_DRIFT_MIN){
5206 C=Ctest;
5207 S+=res*K;
5208 }
5209 // Mark point on ref trajectory with a hit id for the straw
5210 forward_traj[k].h_id=cdc_index+1000;
5211
5212 // Store some updated values related to the hit
5213 double scale=(skip_ring)?1.:(1.-H*K);
5214 cdc_updates[cdc_index].tcorr=tcorr;
5215 cdc_updates[cdc_index].tdrift=tdrift;
5216 cdc_updates[cdc_index].doca=dm;
5217 cdc_updates[cdc_index].variance=V;
5218 cdc_updates[cdc_index].dDdt0=dDdt0;
5219 cdc_used_in_fit[cdc_index]=true;
5220 if(tdrift < CDC_T_DRIFT_MIN) cdc_used_in_fit[cdc_index]=false;
5221
5222 // Update chi2 for this segment
5223 if (skip_ring==false && tdrift >= CDC_T_DRIFT_MIN){
5224 chisq+=scale*res*res/V;
5225 numdof++;
5226 }
5227 break_point_cdc_index=cdc_index;
5228 break_point_step_index=k_minus_1;
5229
5230 if (DEBUG_LEVEL>9)
5231 printf("Ring %d straw %d pred %f meas %f chi2 %f useBrent %i \n",
5232 my_cdchits[cdc_index]->hit->wire->ring,
5233 my_cdchits[cdc_index]->hit->wire->straw,
5234 d,dm,(1.-H*K)*res*res/V,swimmed_to_doca);
5235
5236 }
5237
5238 // If we had to use Brent's algorithm to find the true doca or the
5239 // doca to the line corresponding to the wire is downstream of the
5240 // cdc endplate, we need to swim the state vector and covariance
5241 // matrix back to the appropriate position along the reference
5242 // trajectory.
5243 if (swimmed_to_doca!=DOCA_NO_BRENT){
5244 double dedx=0.;
5245 if (CORRECT_FOR_ELOSS){
5246 dedx=GetdEdx(S(state_q_over_p),
5247 forward_traj[k].K_rho_Z_over_A,
5248 forward_traj[k].rho_Z_over_A,
5249 forward_traj[k].LnI,forward_traj[k].Z);
5250 }
5251 StepBack(dedx,newz,forward_traj[k].z,S0,S,C);
5252 }
5253
5254 cdc_updates[cdc_index].S=S;
5255 cdc_updates[cdc_index].C=C;
5256 }
5257
5258 // new wire origin and direction
5259 if (cdc_index>0){
5260 cdc_index--;
5261 origin=my_cdchits[cdc_index]->origin;
5262 z0w=my_cdchits[cdc_index]->z0wire;
5263 dir=my_cdchits[cdc_index]->dir;
5264 }
5265 else{
5266 more_measurements=false;
5267 }
5268
5269 // Update the wire position
5270 wirepos=origin;
5271 wirepos+=(z-z0w)*dir;
5272
5273 // new doca
5274 dx=S(state_x)-wirepos.X();
5275 dy=S(state_y)-wirepos.Y();
5276 doca2=dx*dx+dy*dy;
5277 }
5278 old_doca2=doca2;
5279 }
5280
5281 // Check that there were enough hits to make this a valid fit
5282 if (numdof<6){
5283 chisq=-1.;
5284 numdof=0;
5285 return PRUNED_TOO_MANY_HITS;
5286 }
5287 numdof-=5;
5288
5289 // Final position for this leg
5290 x_=S(state_x);
5291 y_=S(state_y);
5292 z_=forward_traj[forward_traj.size()-1].z;
5293
5294 if (!S.IsFinite()) return FIT_FAILED;
5295
5296 // Check if we have a kink in the track or threw away too many cdc hits
5297 if (num_cdc>=MIN_HITS_FOR_REFIT){
5298 if (break_point_cdc_index>1){
5299 if (break_point_cdc_index<num_cdc/2){
5300 break_point_cdc_index=(3*num_cdc)/4;
5301 }
5302 return BREAK_POINT_FOUND;
5303 }
5304
5305 unsigned int num_good=0;
5306 for (unsigned int j=0;j<num_cdc;j++){
5307 if (cdc_used_in_fit[j]) num_good++;
5308 }
5309 if (double(num_good)/double(num_cdc)<MINIMUM_HIT_FRACTION){
5310 return PRUNED_TOO_MANY_HITS;
5311 }
5312 }
5313
5314 return FIT_SUCCEEDED;
5315}
5316
5317// Extrapolate to the point along z of closest approach to the beam line using
5318// the forward track state vector parameterization. Converts to the central
5319// track representation at the end.
5320jerror_t DTrackFitterKalmanSIMD::ExtrapolateToVertex(DMatrix5x1 &S,
5321 DMatrix5x5 &C){
5322 DMatrix5x5 J; // Jacobian matrix
5323 DMatrix5x5 Q; // multiple scattering matrix
5324 DMatrix5x1 S1(S); // copy of S
5325
5326 // position variables
5327 double z=z_,newz=z_;
5328
5329 DVector2 beam_pos=beam_center+(z-beam_z0)*beam_dir;
5330 double r2_old=(DVector2(S(state_x),S(state_y))-beam_pos).Mod2();
5331 double dz_old=0.;
5332 double dEdx=0.;
5333 double sign=1.;
5334
5335 // material properties
5336 double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.;
5337 double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.;
5338
5339 // if (fit_type==kTimeBased)printf("------Extrapolating\n");
5340
5341 // printf("-----------\n");
5342 // Current position
5343 DVector3 pos(S(state_x),S(state_y),z);
5344
5345 // get material properties from the Root Geometry
5346 if (geom->FindMatKalman(pos,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
5347 chi2c_factor,chi2a_factor,chi2a_corr,
5348 last_material_map)
5349 !=NOERROR){
5350 if (DEBUG_LEVEL>1)
5351 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5351<<" "
<< "Material error in ExtrapolateToVertex at (x,y,z)=("
5352 << pos.X() <<"," << pos.y()<<","<< pos.z()<<")"<< endl;
5353 return UNRECOVERABLE_ERROR;
5354 }
5355
5356 // Adjust the step size
5357 double ds_dz=sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
5358 double dz=-mStepSizeS/ds_dz;
5359 if (fabs(dEdx)>EPS3.0e-8){
5360 dz=(-1.)*DE_PER_STEP0.001/fabs(dEdx)/ds_dz;
5361 }
5362 if(fabs(dz)>mStepSizeZ) dz=-mStepSizeZ;
5363 if(fabs(dz)<MIN_STEP_SIZE0.1)dz=-MIN_STEP_SIZE0.1;
5364
5365 // Get dEdx for the upcoming step
5366 if (CORRECT_FOR_ELOSS){
5367 dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI,Z);
5368 }
5369
5370
5371 double ztest=endplate_z;
5372 if (my_fdchits.size()>0){
5373 ztest =my_fdchits[0]->z-1.;
5374 }
5375 if (z<ztest)
5376 {
5377 // Check direction of propagation
5378 DMatrix5x1 S2(S); // second copy of S
5379
5380 // Step test states through the field and compute squared radii
5381 Step(z,z-dz,dEdx,S1);
5382 // Bail if the momentum has dropped below some minimum
5383 if (fabs(S1(state_q_over_p))>Q_OVER_P_MAX){
5384 if (DEBUG_LEVEL>2)
5385 {
5386 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5386<<" "
<< "Bailing: P = " << 1./fabs(S1(state_q_over_p))
5387 << endl;
5388 }
5389 return UNRECOVERABLE_ERROR;
5390 }
5391 beam_pos=beam_center+(z-dz-beam_z0)*beam_dir;
5392 double r2minus=(DVector2(S1(state_x),S1(state_y))-beam_pos).Mod2();
5393
5394 Step(z,z+dz,dEdx,S2);
5395 // Bail if the momentum has dropped below some minimum
5396 if (fabs(S2(state_q_over_p))>Q_OVER_P_MAX){
5397 if (DEBUG_LEVEL>2)
5398 {
5399 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5399<<" "
<< "Bailing: P = " << 1./fabs(S2(state_q_over_p))
5400 << endl;
5401 }
5402 return UNRECOVERABLE_ERROR;
5403 }
5404 beam_pos=beam_center+(z+dz-beam_z0)*beam_dir;
5405 double r2plus=(DVector2(S2(state_x),S2(state_y))-beam_pos).Mod2();
5406 // Check to see if we have already bracketed the minimum
5407 if (r2plus>r2_old && r2minus>r2_old){
5408 newz=z+dz;
5409 double dz2=0.;
5410 if (BrentsAlgorithm(newz,dz,dEdx,0.,beam_center,beam_dir,S2,dz2)!=NOERROR){
5411 if (DEBUG_LEVEL>2)
5412 {
5413 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5413<<" "
<< "Bailing: P = " << 1./fabs(S2(state_q_over_p))
5414 << endl;
5415 }
5416 return UNRECOVERABLE_ERROR;
5417 }
5418 z_=newz+dz2;
5419
5420 // Compute the Jacobian matrix
5421 StepJacobian(z,z_,S,dEdx,J);
5422
5423 // Propagate the covariance matrix
5424 C=J*C*J.Transpose();
5425 //C=C.SandwichMultiply(J);
5426
5427 // Step to the position of the doca
5428 Step(z,z_,dEdx,S);
5429
5430 // update internal variables
5431 x_=S(state_x);
5432 y_=S(state_y);
5433
5434 return NOERROR;
5435 }
5436
5437 // Find direction to propagate toward minimum doca
5438 if (r2minus<r2_old && r2_old<r2plus){
5439 newz=z-dz;
5440
5441 // Compute the Jacobian matrix
5442 StepJacobian(z,newz,S,dEdx,J);
5443
5444 // Propagate the covariance matrix
5445 C=J*C*J.Transpose();
5446 //C=C.SandwichMultiply(J);
5447
5448 S2=S;
5449 S=S1;
5450 S1=S2;
5451 dz*=-1.;
5452 sign=-1.;
5453 dz_old=dz;
5454 r2_old=r2minus;
5455 z=z+dz;
5456 }
5457 if (r2minus>r2_old && r2_old>r2plus){
5458 newz=z+dz;
5459
5460 // Compute the Jacobian matrix
5461 StepJacobian(z,newz,S,dEdx,J);
5462
5463 // Propagate the covariance matrix
5464 C=J*C*J.Transpose();
5465 //C=C.SandwichMultiply(J);
5466
5467 S1=S;
5468 S=S2;
5469 dz_old=dz;
5470 r2_old=r2plus;
5471 z=z+dz;
5472 }
5473 }
5474
5475 double r2=r2_old;
5476 while (z>Z_MIN-100. && r2<R2_MAX4225.0 && z<ztest && r2>EPS3.0e-8){
5477 // Bail if the momentum has dropped below some minimum
5478 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){
5479 if (DEBUG_LEVEL>2)
5480 {
5481 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5481<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p))
5482 << endl;
5483 }
5484 return UNRECOVERABLE_ERROR;
5485 }
5486
5487 // Relationship between arc length and z
5488 double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
5489
5490 // get material properties from the Root Geometry
5491 pos.SetXYZ(S(state_x),S(state_y),z);
5492 double s_to_boundary=1.e6;
5493 if (ENABLE_BOUNDARY_CHECK && fit_type==kTimeBased){
5494 DVector3 mom(S(state_tx),S(state_ty),1.);
5495 if (geom->FindMatKalman(pos,mom,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
5496 chi2c_factor,chi2a_factor,chi2a_corr,
5497 last_material_map,&s_to_boundary)
5498 !=NOERROR){
5499 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5499<<" "
<< "Material error in ExtrapolateToVertex! " << endl;
5500 return UNRECOVERABLE_ERROR;
5501 }
5502 }
5503 else{
5504 if (geom->FindMatKalman(pos,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
5505 chi2c_factor,chi2a_factor,chi2a_corr,
5506 last_material_map)
5507 !=NOERROR){
5508 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5508<<" "
<< "Material error in ExtrapolateToVertex! " << endl;
5509 break;
5510 }
5511 }
5512
5513 // Get dEdx for the upcoming step
5514 if (CORRECT_FOR_ELOSS){
5515 dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI,Z);
5516 }
5517
5518 // Adjust the step size
5519 //dz=-sign*mStepSizeS*dz_ds;
5520 double ds=mStepSizeS;
5521 if (fabs(dEdx)>EPS3.0e-8){
5522 ds=DE_PER_STEP0.001/fabs(dEdx);
5523 }
5524 /*
5525 if(fabs(dz)>mStepSizeZ) dz=-sign*mStepSizeZ;
5526 if (fabs(dz)<z_to_boundary) dz=-sign*z_to_boundary;
5527 if(fabs(dz)<MIN_STEP_SIZE)dz=-sign*MIN_STEP_SIZE;
5528 */
5529 if (ds>mStepSizeS) ds=mStepSizeS;
5530 if (ds>s_to_boundary) ds=s_to_boundary;
5531 if (ds<MIN_STEP_SIZE0.1) ds=MIN_STEP_SIZE0.1;
5532 dz=-sign*ds*dz_ds;
5533
5534 // Get the contribution to the covariance matrix due to multiple
5535 // scattering
5536 GetProcessNoise(z,ds,chi2c_factor,chi2a_factor,chi2a_corr,S,Q);
5537
5538 if (CORRECT_FOR_ELOSS){
5539 double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
5540 double one_over_beta2=1.+mass2*q_over_p_sq;
5541 double varE=GetEnergyVariance(ds,one_over_beta2,K_rho_Z_over_A);
5542 Q(state_q_over_p,state_q_over_p)=varE*q_over_p_sq*q_over_p_sq*one_over_beta2;
5543 }
5544
5545
5546 newz=z+dz;
5547 // Compute the Jacobian matrix
5548 StepJacobian(z,newz,S,dEdx,J);
5549
5550 // Propagate the covariance matrix
5551 C=Q.AddSym(J*C*J.Transpose());
5552 //C=Q.AddSym(C.SandwichMultiply(J));
5553
5554 // Step through field
5555 Step(z,newz,dEdx,S);
5556
5557 // Check if we passed the minimum doca to the beam line
5558 beam_pos=beam_center+(newz-beam_z0)*beam_dir;
5559 r2=(DVector2(S(state_x),S(state_y))-beam_pos).Mod2();
5560 //r2=S(state_x)*S(state_x)+S(state_y)*S(state_y);
5561 if (r2>r2_old){
5562 double two_step=dz+dz_old;
5563
5564 // Find the increment/decrement in z to get to the minimum doca to the
5565 // beam line
5566 S1=S;
5567 if (BrentsAlgorithm(newz,0.5*two_step,dEdx,0.,beam_center,beam_dir,S,dz)!=NOERROR){
5568 //_DBG_<<endl;
5569 return UNRECOVERABLE_ERROR;
5570 }
5571
5572 // Compute the Jacobian matrix
5573 z_=newz+dz;
5574 StepJacobian(newz,z_,S1,dEdx,J);
5575
5576 // Propagate the covariance matrix
5577 //C=J*C*J.Transpose()+(dz/(newz-z))*Q;
5578 //C=((dz/newz-z)*Q).AddSym(C.SandwichMultiply(J));
5579 //C=C.SandwichMultiply(J);
5580 C=J*C*J.Transpose();
5581
5582 // update internal variables
5583 x_=S(state_x);
5584 y_=S(state_y);
5585
5586 return NOERROR;
5587 }
5588 r2_old=r2;
5589 dz_old=dz;
5590 S1=S;
5591 z=newz;
5592 }
5593 // update internal variables
5594 x_=S(state_x);
5595 y_=S(state_y);
5596 z_=newz;
5597
5598 return NOERROR;
5599}
5600
5601
5602// Extrapolate to the point along z of closest approach to the beam line using
5603// the forward track state vector parameterization.
5604jerror_t DTrackFitterKalmanSIMD::ExtrapolateToVertex(DMatrix5x1 &S){
5605 DMatrix5x5 J; // Jacobian matrix
5606 DMatrix5x1 S1(S); // copy of S
5607
5608 // position variables
5609 double z=z_,newz=z_;
5610 DVector2 beam_pos=beam_center+(z-beam_z0)*beam_dir;
5611 double r2_old=(DVector2(S(state_x),S(state_y))-beam_pos).Mod2();
5612 double dz_old=0.;
5613 double dEdx=0.;
5614
5615 // Direction and origin for beam line
5616 DVector2 dir;
5617 DVector2 origin;
5618
5619 // material properties
5620 double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.;
5621 double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.;
5622 DVector3 pos; // current position along trajectory
5623
5624 double r2=r2_old;
5625 while (z>Z_MIN-100. && r2<R2_MAX4225.0 && z<Z_MAX370.0 && r2>EPS3.0e-8){
5626 // Bail if the momentum has dropped below some minimum
5627 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){
5628 if (DEBUG_LEVEL>2)
5629 {
5630 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5630<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p))
5631 << endl;
5632 }
5633 return UNRECOVERABLE_ERROR;
5634 }
5635
5636 // Relationship between arc length and z
5637 double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
5638
5639 // get material properties from the Root Geometry
5640 pos.SetXYZ(S(state_x),S(state_y),z);
5641 if (geom->FindMatKalman(pos,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
5642 chi2c_factor,chi2a_factor,chi2a_corr,
5643 last_material_map)
5644 !=NOERROR){
5645 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5645<<" "
<< "Material error in ExtrapolateToVertex! " << endl;
5646 break;
5647 }
5648
5649 // Get dEdx for the upcoming step
5650 if (CORRECT_FOR_ELOSS){
5651 dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI,Z);
5652 }
5653
5654 // Adjust the step size
5655 double ds=mStepSizeS;
5656 if (fabs(dEdx)>EPS3.0e-8){
5657 ds=DE_PER_STEP0.001/fabs(dEdx);
5658 }
5659 if (ds>mStepSizeS) ds=mStepSizeS;
5660 if (ds<MIN_STEP_SIZE0.1) ds=MIN_STEP_SIZE0.1;
5661 double dz=-ds*dz_ds;
5662
5663 newz=z+dz;
5664
5665
5666 // Step through field
5667 Step(z,newz,dEdx,S);
5668
5669 // Check if we passed the minimum doca to the beam line
5670 beam_pos=beam_center+(newz-beam_z0)*beam_dir;
5671 r2=(DVector2(S(state_x),S(state_y))-beam_pos).Mod2();
5672
5673 if (r2>r2_old && newz<endplate_z){
5674 double two_step=dz+dz_old;
5675
5676 // Find the increment/decrement in z to get to the minimum doca to the
5677 // beam line
5678 if (BrentsAlgorithm(newz,0.5*two_step,dEdx,0.,beam_center,beam_dir,S,dz)!=NOERROR){
5679 return UNRECOVERABLE_ERROR;
5680 }
5681 // update internal variables
5682 x_=S(state_x);
5683 y_=S(state_y);
5684 z_=newz+dz;
5685
5686 return NOERROR;
5687 }
5688 r2_old=r2;
5689 dz_old=dz;
5690 z=newz;
5691 }
5692
5693 // If we extrapolate beyond the fiducial volume of the detector before
5694 // finding the doca, abandon the extrapolation...
5695 if (newz<Z_MIN-100.){
5696 //_DBG_ << "Extrapolated z = " << newz << endl;
5697 // Restore old state vector
5698 S=S1;
5699 return VALUE_OUT_OF_RANGE;
5700 }
5701
5702 // update internal variables
5703 x_=S(state_x);
5704 y_=S(state_y);
5705 z_=newz;
5706
5707
5708 return NOERROR;
5709}
5710
5711
5712
5713
5714// Propagate track to point of distance of closest approach to origin
5715jerror_t DTrackFitterKalmanSIMD::ExtrapolateToVertex(DVector2 &xy,
5716 DMatrix5x1 &Sc,DMatrix5x5 &Cc){
5717 DMatrix5x5 Jc=I5x5; //Jacobian matrix
5718 DMatrix5x5 Q; // multiple scattering matrix
5719
5720 // Position and step variables
5721 DVector2 beam_pos=beam_center+(Sc(state_z)-beam_z0)*beam_dir;
5722 double r2=(xy-beam_pos).Mod2();
5723 double ds=-mStepSizeS; // step along path in cm
5724 double r2_old=r2;
5725
5726 // Energy loss
5727 double dedx=0.;
5728
5729 // Check direction of propagation
5730 DMatrix5x1 S0;
5731 S0=Sc;
5732 DVector2 xy0=xy;
5733 DVector2 xy1=xy;
5734 Step(xy0,ds,S0,dedx);
5735 // Bail if the transverse momentum has dropped below some minimum
5736 if (fabs(S0(state_q_over_pt))>Q_OVER_PT_MAX100.){
5737 if (DEBUG_LEVEL>2)
5738 {
5739 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5739<<" "
<< "Bailing: PT = " << 1./fabs(S0(state_q_over_pt))
5740 << endl;
5741 }
5742 return UNRECOVERABLE_ERROR;
5743 }
5744 beam_pos=beam_center+(S0(state_z)-beam_z0)*beam_dir;
5745 r2=(xy0-beam_pos).Mod2();
5746 if (r2>r2_old) ds*=-1.;
5747 double ds_old=ds;
5748
5749 // if (fit_type==kTimeBased)printf("------Extrapolating\n");
5750
5751 if (central_traj.size()==0){
5752 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5752<<" "
<< "Central trajectory size==0!" << endl;
5753 return UNRECOVERABLE_ERROR;
5754 }
5755
5756 // D is now on the actual trajectory itself
5757 Sc(state_D)=0.;
5758
5759 // Track propagation loop
5760 while (Sc(state_z)>Z_MIN-100. && Sc(state_z)<Z_MAX370.0
5761 && r2<R2_MAX4225.0){
5762 // Bail if the transverse momentum has dropped below some minimum
5763 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
5764 if (DEBUG_LEVEL>2)
5765 {
5766 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5766<<" "
<< "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt))
5767 << endl;
5768 }
5769 return UNRECOVERABLE_ERROR;
5770 }
5771
5772 // get material properties from the Root Geometry
5773 double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.;
5774 double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.;
5775 DVector3 pos3d(xy.X(),xy.Y(),Sc(state_z));
5776 if (geom->FindMatKalman(pos3d,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
5777 chi2c_factor,chi2a_factor,chi2a_corr,
5778 last_material_map)
5779 !=NOERROR){
5780 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5780<<" "
<< "Material error in ExtrapolateToVertex! " << endl;
5781 break;
5782 }
5783
5784 // Get dEdx for the upcoming step
5785 double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl)));
5786 if (CORRECT_FOR_ELOSS){
5787 dedx=-GetdEdx(q_over_p,K_rho_Z_over_A,rho_Z_over_A,LnI,Z);
5788 }
5789 // Adjust the step size
5790 double sign=(ds>0.0)?1.:-1.;
5791 if (fabs(dedx)>EPS3.0e-8){
5792 ds=sign*DE_PER_STEP0.001/fabs(dedx);
5793 }
5794 if(fabs(ds)>mStepSizeS) ds=sign*mStepSizeS;
5795 if(fabs(ds)<MIN_STEP_SIZE0.1)ds=sign*MIN_STEP_SIZE0.1;
5796
5797 // Multiple scattering
5798 GetProcessNoiseCentral(ds,chi2c_factor,chi2a_factor,chi2a_corr,Sc,Q);
5799
5800 if (CORRECT_FOR_ELOSS){
5801 double q_over_p_sq=q_over_p*q_over_p;
5802 double one_over_beta2=1.+mass2*q_over_p*q_over_p;
5803 double varE=GetEnergyVariance(ds,one_over_beta2,K_rho_Z_over_A);
5804 Q(state_q_over_pt,state_q_over_pt)
5805 +=varE*Sc(state_q_over_pt)*Sc(state_q_over_pt)*one_over_beta2
5806 *q_over_p_sq;
5807 }
5808
5809 // Propagate the state and covariance through the field
5810 S0=Sc;
5811 DVector2 old_xy=xy;
5812 StepStateAndCovariance(xy,ds,dedx,Sc,Jc,Cc);
5813
5814 // Add contribution due to multiple scattering
5815 Cc=(sign*Q).AddSym(Cc);
5816
5817 beam_pos=beam_center+(Sc(state_z)-beam_z0)*beam_dir;
5818 r2=(xy-beam_pos).Mod2();
5819 //printf("r %f r_old %f \n",sqrt(r2),sqrt(r2_old));
5820 if (r2>r2_old) {
5821 // We've passed the true minimum; backtrack to find the "vertex"
5822 // position
5823 double my_ds=0.;
5824 if (BrentsAlgorithm(ds,ds_old,dedx,xy,0.,beam_center,beam_dir,Sc,my_ds)!=NOERROR){
5825 //_DBG_ <<endl;
5826 return UNRECOVERABLE_ERROR;
5827 }
5828 //printf ("Brent min r %f\n",xy.Mod());
5829
5830 // Find the field and gradient at (old_x,old_y,old_z)
5831 bfield->GetFieldAndGradient(old_xy.X(),old_xy.Y(),S0(state_z),Bx,By,Bz,
5832 dBxdx,dBxdy,dBxdz,dBydx,
5833 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
5834
5835 // Compute the Jacobian matrix
5836 my_ds-=ds_old;
5837 StepJacobian(old_xy,xy-old_xy,my_ds,S0,dedx,Jc);
5838
5839 // Propagate the covariance matrix
5840 //Cc=Jc*Cc*Jc.Transpose()+(my_ds/ds_old)*Q;
5841 //Cc=((my_ds/ds_old)*Q).AddSym(Cc.SandwichMultiply(Jc));
5842 Cc=((my_ds/ds_old)*Q).AddSym(Jc*Cc*Jc.Transpose());
5843
5844 break;
5845 }
5846 r2_old=r2;
5847 ds_old=ds;
5848 }
5849
5850 return NOERROR;
5851}
5852
5853// Propagate track to point of distance of closest approach to origin
5854jerror_t DTrackFitterKalmanSIMD::ExtrapolateToVertex(DVector2 &xy,
5855 DMatrix5x1 &Sc){
5856 // Save un-extroplated quantities
5857 DMatrix5x1 S0(Sc);
5858 DVector2 xy0(xy);
5859
5860 // Initialize the beam position = center of target, and the direction
5861 DVector2 origin;
5862 DVector2 dir;
5863
5864 // Position and step variables
5865 DVector2 beam_pos=beam_center+(Sc(state_z)-beam_z0)*beam_dir;
5866 double r2=(xy-beam_pos).Mod2();
5867 double ds=-mStepSizeS; // step along path in cm
5868 double r2_old=r2;
5869
5870 // Energy loss
5871 double dedx=0.;
5872
5873 // Check direction of propagation
5874 DMatrix5x1 S1=Sc;
5875 DVector2 xy1=xy;
5876 Step(xy1,ds,S1,dedx);
5877 beam_pos=beam_center+(S1(state_z)-beam_z0)*beam_dir;
5878 r2=(xy1-beam_pos).Mod2();
5879 if (r2>r2_old) ds*=-1.;
5880 double ds_old=ds;
5881
5882 // Track propagation loop
5883 while (Sc(state_z)>Z_MIN-100. && Sc(state_z)<Z_MAX370.0
5884 && r2<R2_MAX4225.0){
5885 // get material properties from the Root Geometry
5886 double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0;
5887 double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.;
5888 DVector3 pos3d(xy.X(),xy.Y(),Sc(state_z));
5889 if (geom->FindMatKalman(pos3d,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
5890 chi2c_factor,chi2a_factor,chi2a_corr,
5891 last_material_map)
5892 !=NOERROR){
5893 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<5893<<" "
<< "Material error in ExtrapolateToVertex! " << endl;
5894 break;
5895 }
5896
5897 // Get dEdx for the upcoming step
5898 double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl)));
5899 if (CORRECT_FOR_ELOSS){
5900 dedx=GetdEdx(q_over_p,K_rho_Z_over_A,rho_Z_over_A,LnI,Z);
5901 }
5902 // Adjust the step size
5903 double sign=(ds>0.0)?1.:-1.;
5904 if (fabs(dedx)>EPS3.0e-8){
5905 ds=sign*DE_PER_STEP0.001/fabs(dedx);
5906 }
5907 if(fabs(ds)>mStepSizeS) ds=sign*mStepSizeS;
5908 if(fabs(ds)<MIN_STEP_SIZE0.1)ds=sign*MIN_STEP_SIZE0.1;
5909
5910 // Propagate the state through the field
5911 Step(xy,ds,Sc,dedx);
5912
5913 beam_pos=beam_center+(Sc(state_z)-beam_z0)*beam_dir;
5914 r2=(xy-beam_pos).Mod2();
5915 //printf("r %f r_old %f \n",r,r_old);
5916 if (r2>r2_old) {
5917 // We've passed the true minimum; backtrack to find the "vertex"
5918 // position
5919 double my_ds=0.;
5920 BrentsAlgorithm(ds,ds_old,dedx,xy,0.,beam_center,beam_dir,Sc,my_ds);
5921 //printf ("Brent min r %f\n",pos.Perp());
5922 break;
5923 }
5924 r2_old=r2;
5925 ds_old=ds;
5926 }
5927
5928 // If we extrapolate beyond the fiducial volume of the detector before
5929 // finding the doca, abandon the extrapolation...
5930 if (Sc(state_z)<Z_MIN-100.){
5931 //_DBG_ << "Extrapolated z = " << Sc(state_z) << endl;
5932 // Restore un-extrapolated values
5933 Sc=S0;
5934 xy=xy0;
5935 return VALUE_OUT_OF_RANGE;
5936 }
5937
5938 return NOERROR;
5939}
5940
5941
5942
5943
5944// Transform the 5x5 tracking error matrix into a 7x7 error matrix in cartesian
5945// coordinates
5946shared_ptr<TMatrixFSym> DTrackFitterKalmanSIMD::Get7x7ErrorMatrixForward(DMatrixDSym C){
5947 auto C7x7 = dResourcePool_TMatrixFSym->Get_SharedResource();
5948 C7x7->ResizeTo(7, 7);
5949 DMatrix J(7,5);
5950
5951 double p=1./fabs(q_over_p_);
5952 double tanl=1./sqrt(tx_*tx_+ty_*ty_);
5953 double tanl2=tanl*tanl;
5954 double lambda=atan(tanl);
5955 double sinl=sin(lambda);
5956 double sinl3=sinl*sinl*sinl;
5957
5958 J(state_X,state_x)=J(state_Y,state_y)=1.;
5959 J(state_Pz,state_ty)=-p*ty_*sinl3;
5960 J(state_Pz,state_tx)=-p*tx_*sinl3;
5961 J(state_Px,state_ty)=J(state_Py,state_tx)=-p*tx_*ty_*sinl3;
5962 J(state_Px,state_tx)=p*(1.+ty_*ty_)*sinl3;
5963 J(state_Py,state_ty)=p*(1.+tx_*tx_)*sinl3;
5964 J(state_Pz,state_q_over_p)=-p*sinl/q_over_p_;
5965 J(state_Px,state_q_over_p)=tx_*J(state_Pz,state_q_over_p);
5966 J(state_Py,state_q_over_p)=ty_*J(state_Pz,state_q_over_p);
5967 J(state_Z,state_x)=-tx_*tanl2;
5968 J(state_Z,state_y)=-ty_*tanl2;
5969 double diff=tx_*tx_-ty_*ty_;
5970 double frac=tanl2*tanl2;
5971 J(state_Z,state_tx)=(x_*diff+2.*tx_*ty_*y_)*frac;
5972 J(state_Z,state_ty)=(2.*tx_*ty_*x_-y_*diff)*frac;
5973
5974 // C'= JCJ^T
5975 *C7x7=C.Similarity(J);
5976
5977 return C7x7;
5978}
5979
5980
5981
5982// Transform the 5x5 tracking error matrix into a 7x7 error matrix in cartesian
5983// coordinates
5984shared_ptr<TMatrixFSym> DTrackFitterKalmanSIMD::Get7x7ErrorMatrix(DMatrixDSym C){
5985 auto C7x7 = dResourcePool_TMatrixFSym->Get_SharedResource();
5986 C7x7->ResizeTo(7, 7);
5987 DMatrix J(7,5);
5988 //double cosl=cos(atan(tanl_));
5989 double pt=1./fabs(q_over_pt_);
5990 //double p=pt/cosl;
5991 // double p_sq=p*p;
5992 // double E=sqrt(mass2+p_sq);
5993 double pt_sq=1./(q_over_pt_*q_over_pt_);
5994 double cosphi=cos(phi_);
5995 double sinphi=sin(phi_);
5996 double q=(q_over_pt_>0.0)?1.:-1.;
5997
5998 J(state_Px,state_q_over_pt)=-q*pt_sq*cosphi;
5999 J(state_Px,state_phi)=-pt*sinphi;
6000
6001 J(state_Py,state_q_over_pt)=-q*pt_sq*sinphi;
6002 J(state_Py,state_phi)=pt*cosphi;
6003
6004 J(state_Pz,state_q_over_pt)=-q*pt_sq*tanl_;
6005 J(state_Pz,state_tanl)=pt;
6006
6007 J(state_X,state_phi)=-D_*cosphi;
6008 J(state_X,state_D)=-sinphi;
6009
6010 J(state_Y,state_phi)=-D_*sinphi;
6011 J(state_Y,state_D)=cosphi;
6012
6013 J(state_Z,state_z)=1.;
6014
6015 // C'= JCJ^T
6016 *C7x7=C.Similarity(J);
6017 // C7x7->Print();
6018 // _DBG_ << " " << C7x7->operator()(3,3) << " " << C7x7->operator()(4,4) << endl;
6019
6020 return C7x7;
6021}
6022
6023// Track recovery for Central tracks
6024//-----------------------------------
6025// This code attempts to recover tracks that are "broken". Sometimes the fit fails because too many hits were pruned
6026// such that the number of surviving hits is less than the minimum number of degrees of freedom for a five-parameter fit.
6027// This condition is flagged as PRUNED_TOO_MANY_HITS. It may also be the case that even if we used enough hits for the fit to
6028// be valid (i.e., make sense in terms of the number of degrees of freedom for the number of parameters (5) we are trying
6029// to determine), we throw away a number of hits near the target because the projected trajectory deviates too far away from
6030// the actual hits. This may be an indication of a kink in the trajectory. This condition is flagged as BREAK_POINT_FOUND.
6031// Sometimes the fit may succeed and no break point is found, but the pruning threw out a large number of hits. This
6032// condition is flagged as PRUNED_TOO_MANY_HITS. The recovery code proceeds by truncating the reference trajectory to
6033// to a point just after the hit where a break point was found and all hits are ignored beyond this point subject to a
6034// minimum number of hits set by MIN_HITS_FOR_REFIT. The recovery code always attempts to use the hits closest to the
6035// target. The code is allowed to iterate; with each iteration the trajectory and list of useable hits is further truncated.
6036kalman_error_t DTrackFitterKalmanSIMD::RecoverBrokenTracks(double anneal_factor,
6037 DMatrix5x1 &S,
6038 DMatrix5x5 &C,
6039 const DMatrix5x5 &C0,
6040 DVector2 &xy,
6041 double &chisq,
6042 unsigned int &numdof){
6043 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6043<<" "
<< "Attempting to recover broken track ... " <<endl;
6044
6045 // Initialize degrees of freedom and chi^2
6046 double refit_chisq=-1.;
6047 unsigned int refit_ndf=0;
6048 // State vector and covariance matrix
6049 DMatrix5x5 C1;
6050 DMatrix5x1 S1;
6051 // Position vector
6052 DVector2 refit_xy;
6053
6054 // save the status of the hits used in the fit
6055 unsigned int num_hits=cdc_used_in_fit.size();
6056 vector<bool>old_cdc_used_status(num_hits);
6057 for (unsigned int j=0;j<num_hits;j++){
6058 old_cdc_used_status[j]=cdc_used_in_fit[j];
6059 }
6060
6061 // Truncate the reference trajectory to just beyond the break point (or the minimum number of hits)
6062 unsigned int min_cdc_index_for_refit=MIN_HITS_FOR_REFIT-1;
6063 //if (break_point_cdc_index<num_hits/2)
6064 // break_point_cdc_index=num_hits/2;
6065 if (break_point_cdc_index<min_cdc_index_for_refit){
6066 break_point_cdc_index=min_cdc_index_for_refit;
6067 }
6068 // Next determine where we need to truncate the trajectory
6069 DVector2 origin=my_cdchits[break_point_cdc_index]->origin;
6070 DVector2 dir=my_cdchits[break_point_cdc_index]->dir;
6071 double z0=my_cdchits[break_point_cdc_index]->z0wire;
6072 unsigned int k=0;
6073 for (k=central_traj.size()-1;k>1;k--){
6074 double r2=central_traj[k].xy.Mod2();
6075 double r2next=central_traj[k-1].xy.Mod2();
6076 double r2_cdc=(origin+(central_traj[k].S(state_z)-z0)*dir).Mod2();
6077 if (r2next>r2 && r2>r2_cdc) break;
6078 }
6079 break_point_step_index=k;
6080
6081 if (break_point_step_index==central_traj.size()-1){
6082 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6082<<" "
<< "Invalid reference trajectory in track recovery..." << endl;
6083 return FIT_FAILED;
6084 }
6085
6086 kalman_error_t refit_error=FIT_NOT_DONE;
6087 unsigned int old_cdc_index=break_point_cdc_index;
6088 unsigned int old_step_index=break_point_step_index;
6089 unsigned int refit_iter=0;
6090 unsigned int num_cdchits=my_cdchits.size();
6091 while (break_point_cdc_index>4 && break_point_step_index>0
6092 && break_point_step_index<central_traj.size()){
6093 refit_iter++;
6094
6095 // Flag the cdc hits within the radius of the break point cdc index
6096 // as good, the rest as bad.
6097 for (unsigned int j=0;j<=break_point_cdc_index;j++){
6098 if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
6099 }
6100 for (unsigned int j=break_point_cdc_index+1;j<num_cdchits;j++){
6101 my_cdchits[j]->status=bad_hit;
6102 }
6103
6104 // Now refit with the truncated trajectory and list of hits
6105 //C1=C0;
6106 //C1=4.0*C0;
6107 C1=1.0*C0;
6108 S1=central_traj[break_point_step_index].S;
6109 refit_chisq=-1.;
6110 refit_ndf=0;
6111 refit_error=KalmanCentral(anneal_factor,S1,C1,refit_xy,
6112 refit_chisq,refit_ndf);
6113 if (refit_error==FIT_SUCCEEDED
6114 || (refit_error==BREAK_POINT_FOUND
6115 && break_point_cdc_index==1
6116 )
6117 //|| refit_error==PRUNED_TOO_MANY_HITS
6118 ){
6119 C=C1;
6120 S=S1;
6121 xy=refit_xy;
6122 chisq=refit_chisq;
6123 numdof=refit_ndf;
6124
6125 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6125<<" "
<< "Fit recovery succeeded..." << endl;
6126 return FIT_SUCCEEDED;
6127 }
6128
6129 break_point_cdc_index=old_cdc_index-refit_iter;
6130 break_point_step_index=old_step_index-refit_iter;
6131 }
6132
6133 // If the refit did not work, restore the old list hits used in the fit
6134 // before the track recovery was attempted.
6135 for (unsigned int k=0;k<num_hits;k++){
6136 cdc_used_in_fit[k]=old_cdc_used_status[k];
6137 }
6138
6139 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6139<<" "
<< "Fit recovery failed..." << endl;
6140 return FIT_FAILED;
6141}
6142
6143// Track recovery for forward tracks
6144//-----------------------------------
6145// This code attempts to recover tracks that are "broken". Sometimes the fit fails because too many hits were pruned
6146// such that the number of surviving hits is less than the minimum number of degrees of freedom for a five-parameter fit.
6147// This condition is flagged as PRUNED_TOO_MANY_HITS. It may also be the case that even if we used enough hits for the fit to
6148// be valid (i.e., make sense in terms of the number of degrees of freedom for the number of parameters (5) we are trying
6149// to determine), we throw away a number of hits near the target because the projected trajectory deviates too far away from
6150// the actual hits. This may be an indication of a kink in the trajectory. This condition is flagged as BREAK_POINT_FOUND.
6151// Sometimes the fit may succeed and no break point is found, but the pruning threw out a large number of hits. This
6152// condition is flagged as PRUNED_TOO_MANY_HITS. The recovery code proceeds by truncating the reference trajectory to
6153// to a point just after the hit where a break point was found and all hits are ignored beyond this point subject to a
6154// minimum number of hits. The recovery code always attempts to use the hits closest to the target. The code is allowed to
6155// iterate; with each iteration the trajectory and list of useable hits is further truncated.
6156kalman_error_t DTrackFitterKalmanSIMD::RecoverBrokenTracks(double anneal_factor,
6157 DMatrix5x1 &S,
6158 DMatrix5x5 &C,
6159 const DMatrix5x5 &C0,
6160 double &chisq,
6161 unsigned int &numdof
6162 ){
6163 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6163<<" "
<< "Attempting to recover broken track ... " <<endl;
6164
6165 unsigned int num_cdchits=my_cdchits.size();
6166 unsigned int num_fdchits=my_fdchits.size();
6167
6168 // Initialize degrees of freedom and chi^2
6169 double refit_chisq=-1.;
6170 unsigned int refit_ndf=0;
6171 // State vector and covariance matrix
6172 DMatrix5x5 C1;
6173 DMatrix5x1 S1;
6174
6175 // save the status of the hits used in the fit
6176 vector<bool>old_cdc_used_status(num_cdchits);
6177 vector<bool>old_fdc_used_status(num_fdchits);
6178 for (unsigned int j=0;j<num_fdchits;j++){
6179 old_fdc_used_status[j]=fdc_used_in_fit[j];
6180 }
6181 for (unsigned int j=0;j<num_cdchits;j++){
6182 old_cdc_used_status[j]=cdc_used_in_fit[j];
6183 }
6184
6185 unsigned int min_cdc_index=MIN_HITS_FOR_REFIT-1;
6186 if (my_fdchits.size()>0){
6187 if (break_point_cdc_index<5){
6188 break_point_cdc_index=0;
6189 min_cdc_index=5;
6190 }
6191 }
6192 /*else{
6193 unsigned int half_num_cdchits=num_cdchits/2;
6194 if (break_point_cdc_index<half_num_cdchits
6195 && half_num_cdchits>min_cdc_index)
6196 break_point_cdc_index=half_num_cdchits;
6197 }
6198 */
6199 if (break_point_cdc_index<min_cdc_index){
6200 break_point_cdc_index=min_cdc_index;
6201 }
6202
6203 // Find the index at which to truncate the reference trajectory
6204 DVector2 origin=my_cdchits[break_point_cdc_index]->origin;
6205 DVector2 dir=my_cdchits[break_point_cdc_index]->dir;
6206 double z0=my_cdchits[break_point_cdc_index]->z0wire;
6207 unsigned int k=forward_traj.size()-1;
6208 for (;k>1;k--){
6209 DMatrix5x1 S1=forward_traj[k].S;
6210 double x1=S1(state_x);
6211 double y1=S1(state_y);
6212 double r2=x1*x1+y1*y1;
6213 DMatrix5x1 S2=forward_traj[k-1].S;
6214 double x2=S2(state_x);
6215 double y2=S2(state_y);
6216 double r2next=x2*x2+y2*y2;
6217 double r2cdc=(origin+(forward_traj[k].z-z0)*dir).Mod2();
6218
6219 if (r2next>r2 && r2>r2cdc) break;
6220 }
6221 break_point_step_index=k;
6222
6223 if (break_point_step_index==forward_traj.size()-1){
6224 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6224<<" "
<< "Invalid reference trajectory in track recovery..." << endl;
6225 return FIT_FAILED;
6226 }
6227
6228 // Attemp to refit the track using the abreviated list of hits and the truncated
6229 // reference trajectory. Iterates if the fit fails.
6230 kalman_error_t refit_error=FIT_NOT_DONE;
6231 unsigned int old_cdc_index=break_point_cdc_index;
6232 unsigned int old_step_index=break_point_step_index;
6233 unsigned int refit_iter=0;
6234 while (break_point_cdc_index>4 && break_point_step_index>0
6235 && break_point_step_index<forward_traj.size()){
6236 refit_iter++;
6237
6238 // Flag the cdc hits within the radius of the break point cdc index
6239 // as good, the rest as bad.
6240 for (unsigned int j=0;j<=break_point_cdc_index;j++){
6241 if (my_cdchits[j]->status!=late_hit) my_cdchits[j]->status=good_hit;
6242 }
6243 for (unsigned int j=break_point_cdc_index+1;j<num_cdchits;j++){
6244 my_cdchits[j]->status=bad_hit;
6245 }
6246
6247 // Re-initialize the state vector, covariance, chisq and number of degrees of freedom
6248 //C1=4.0*C0;
6249 C1=1.0*C0;
6250 S1=forward_traj[break_point_step_index].S;
6251 refit_chisq=-1.;
6252 refit_ndf=0;
6253 // Now refit with the truncated trajectory and list of hits
6254 refit_error=KalmanForwardCDC(anneal_factor,S1,C1,refit_chisq,refit_ndf);
6255 if (refit_error==FIT_SUCCEEDED
6256 || (refit_error==BREAK_POINT_FOUND
6257 && break_point_cdc_index==1
6258 )
6259 //|| refit_error==PRUNED_TOO_MANY_HITS
6260 ){
6261 C=C1;
6262 S=S1;
6263 chisq=refit_chisq;
6264 numdof=refit_ndf;
6265 return FIT_SUCCEEDED;
6266 }
6267 break_point_cdc_index=old_cdc_index-refit_iter;
6268 break_point_step_index=old_step_index-refit_iter;
6269 }
6270 // If the refit did not work, restore the old list hits used in the fit
6271 // before the track recovery was attempted.
6272 for (unsigned int k=0;k<num_cdchits;k++){
6273 cdc_used_in_fit[k]=old_cdc_used_status[k];
6274 }
6275 for (unsigned int k=0;k<num_fdchits;k++){
6276 fdc_used_in_fit[k]=old_fdc_used_status[k];
6277 }
6278
6279 return FIT_FAILED;
6280}
6281
6282
6283// Track recovery for forward-going tracks with hits in the FDC
6284kalman_error_t
6285DTrackFitterKalmanSIMD::RecoverBrokenForwardTracks(double fdc_anneal,
6286 double cdc_anneal,
6287 DMatrix5x1 &S,
6288 DMatrix5x5 &C,
6289 const DMatrix5x5 &C0,
6290 double &chisq,
6291 unsigned int &numdof){
6292 if (DEBUG_LEVEL>1)
6293 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6293<<" "
<< "Attempting to recover broken track ... " <<endl;
6294 unsigned int num_cdchits=my_cdchits.size();
6295 unsigned int num_fdchits=fdc_updates.size();
6296
6297 // Initialize degrees of freedom and chi^2
6298 double refit_chisq=-1.;
6299 unsigned int refit_ndf=0;
6300 // State vector and covariance matrix
6301 DMatrix5x5 C1;
6302 DMatrix5x1 S1;
6303
6304 // save the status of the hits used in the fit
6305 vector<int>old_cdc_used_status(num_cdchits);
6306 vector<int>old_fdc_used_status(num_fdchits);
6307 for (unsigned int j=0;j<num_fdchits;j++){
6308 old_fdc_used_status[j]=fdc_used_in_fit[j];
6309 }
6310 for (unsigned int j=0;j<num_cdchits;j++){
6311 old_cdc_used_status[j]=cdc_used_in_fit[j];
6312 }
6313
6314 // Truncate the trajectory
6315 double zhit=my_fdchits[break_point_fdc_index]->z;
6316 unsigned int k=0;
6317 for (;k<forward_traj.size();k++){
6318 double z=forward_traj[k].z;
6319 if (z<zhit) break;
6320 }
6321 for (unsigned int j=0;j<=break_point_fdc_index;j++){
6322 my_fdchits[j]->status=good_hit;
6323 }
6324 for (unsigned int j=break_point_fdc_index+1;j<num_fdchits;j++){
6325 my_fdchits[j]->status=bad_hit;
6326 }
6327
6328 if (k==forward_traj.size()) return FIT_NOT_DONE;
6329
6330 break_point_step_index=k;
6331
6332 // Attemp to refit the track using the abreviated list of hits and the truncated
6333 // reference trajectory.
6334 kalman_error_t refit_error=FIT_NOT_DONE;
6335 int refit_iter=0;
6336 unsigned int break_id=break_point_fdc_index;
6337 while (break_id+num_cdchits>=MIN_HITS_FOR_REFIT && break_id>0
6338 && break_point_step_index<forward_traj.size()
6339 && break_point_step_index>1
6340 && refit_iter<10){
6341 refit_iter++;
6342
6343 // Mark the hits as bad if they are not included
6344 if (break_id >= 0){
6345 for (unsigned int j=0;j<num_cdchits;j++){
6346 if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
6347 }
6348 for (unsigned int j=0;j<=break_id;j++){
6349 my_fdchits[j]->status=good_hit;
6350 }
6351 for (unsigned int j=break_id+1;j<num_fdchits;j++){
6352 my_fdchits[j]->status=bad_hit;
6353 }
6354 }
6355 else{
6356 // BreakID should always be 0 or positive, so this should never happen, but could be investigated in the future.
6357 for (unsigned int j=0;j<num_cdchits+break_id;j++){
6358 if (my_cdchits[j]->status!=late_hit) my_cdchits[j]->status=good_hit;
6359 }
6360 for (unsigned int j=num_cdchits+break_id;j<num_cdchits;j++){
6361 my_cdchits[j]->status=bad_hit;
6362 }
6363 for (unsigned int j=0;j<num_fdchits;j++){
6364 my_fdchits[j]->status=bad_hit;
6365 }
6366 }
6367
6368 // Re-initialize the state vector, covariance, chisq and number of degrees of freedom
6369 //C1=4.0*C0;
6370 C1=1.0*C0;
6371 S1=forward_traj[break_point_step_index].S;
6372 refit_chisq=-1.;
6373 refit_ndf=0;
6374
6375 // Now refit with the truncated trajectory and list of hits
6376 refit_error=KalmanForward(fdc_anneal,cdc_anneal,S1,C1,refit_chisq,refit_ndf);
6377 if (refit_error==FIT_SUCCEEDED
6378 //|| (refit_error==PRUNED_TOO_MANY_HITS)
6379 ){
6380 C=C1;
6381 S=S1;
6382 chisq=refit_chisq;
6383 numdof=refit_ndf;
6384
6385 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6385<<" "
<< "Refit succeeded" << endl;
6386 return FIT_SUCCEEDED;
6387 }
6388 // Truncate the trajectory
6389 if (break_id>0) break_id--;
6390 else break;
6391 zhit=my_fdchits[break_id]->z;
6392 k=0;
6393 for (;k<forward_traj.size();k++){
6394 double z=forward_traj[k].z;
6395 if (z<zhit) break;
6396 }
6397 break_point_step_index=k;
6398
6399 }
6400
6401 // If the refit did not work, restore the old list hits used in the fit
6402 // before the track recovery was attempted.
6403 for (unsigned int k=0;k<num_cdchits;k++){
6404 cdc_used_in_fit[k]=old_cdc_used_status[k];
6405 }
6406 for (unsigned int k=0;k<num_fdchits;k++){
6407 fdc_used_in_fit[k]=old_fdc_used_status[k];
6408 }
6409
6410 return FIT_FAILED;
6411}
6412
6413
6414
6415// Routine to fit hits in the FDC and the CDC using the forward parametrization
6416kalman_error_t DTrackFitterKalmanSIMD::ForwardFit(const DMatrix5x1 &S0,const DMatrix5x5 &C0){
6417 unsigned int num_cdchits=my_cdchits.size();
6418 unsigned int num_fdchits=my_fdchits.size();
6419 unsigned int max_fdc_index=num_fdchits-1;
6420
6421 // Vectors to keep track of updated state vectors and covariance matrices (after
6422 // adding the hit information)
6423 vector<bool>last_fdc_used_in_fit(num_fdchits);
6424 vector<bool>last_cdc_used_in_fit(num_cdchits);
6425 vector<pull_t>forward_pulls;
6426 vector<pull_t>last_forward_pulls;
6427
6428 // Charge
6429 // double q=input_params.charge();
6430
6431 // Covariance matrix and state vector
6432 DMatrix5x5 C;
6433 DMatrix5x1 S=S0;
6434
6435 // Create matrices to store results from previous iteration
6436 DMatrix5x1 Slast(S);
6437 DMatrix5x5 Clast(C0);
6438 // last z position
6439 double last_z=z_;
6440
6441 double fdc_anneal=FORWARD_ANNEAL_SCALE+1.; // variable for scaling cut for hit pruning
6442 double cdc_anneal=ANNEAL_SCALE+1.; // variable for scaling cut for hit pruning
6443
6444 // Chi-squared and degrees of freedom
6445 double chisq=-1.,chisq_forward=-1.;
6446 unsigned int my_ndf=0;
6447 unsigned int last_ndf=1;
6448 kalman_error_t error=FIT_NOT_DONE,last_error=FIT_NOT_DONE;
6449
6450 // Iterate over reference trajectories
6451 for (int iter=0;
6452 iter<(fit_type==kTimeBased?MAX_TB_PASSES20:MAX_WB_PASSES20);
6453 iter++) {
6454 // These variables provide the approximate location along the trajectory
6455 // where there is an indication of a kink in the track
6456 break_point_fdc_index=max_fdc_index;
6457 break_point_cdc_index=0;
6458 break_point_step_index=0;
6459
6460 // Reset material map index
6461 last_material_map=0;
6462
6463 // Abort if momentum is too low
6464 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX) break;
6465
6466 // Initialize path length variable and flight time
6467 len=0;
6468 ftime=0.;
6469 var_ftime=0.;
6470
6471 // Scale cut for pruning hits according to the iteration number
6472 fdc_anneal=(iter<MIN_ITER3)?(FORWARD_ANNEAL_SCALE/pow(FORWARD_ANNEAL_POW_CONST,iter)+1.):1.;
6473 cdc_anneal=(iter<MIN_ITER3)?(ANNEAL_SCALE/pow(ANNEAL_POW_CONST,iter)+1.):1.;
6474
6475 // Swim through the field out to the most upstream FDC hit
6476 jerror_t ref_track_error=SetReferenceTrajectory(S);
6477 if (ref_track_error!=NOERROR){
6478 if (iter==0) return FIT_FAILED;
6479 break;
6480 }
6481
6482 // Reset the status of the cdc hits
6483 for (unsigned int j=0;j<num_cdchits;j++){
6484 if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
6485 }
6486
6487 // perform the kalman filter
6488 C=C0;
6489 bool did_second_refit=false;
6490 error=KalmanForward(fdc_anneal,cdc_anneal,S,C,chisq,my_ndf);
6491 if (DEBUG_LEVEL>1){
6492 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6492<<" "
<< "Iter: " << iter+1 << " Chi2=" << chisq << " Ndf=" << my_ndf << " Error code: " << error << endl;
6493 }
6494 // Try to recover tracks that failed the first attempt at fitting by
6495 // cutting outer hits
6496 if (error!=FIT_SUCCEEDED && RECOVER_BROKEN_TRACKS
6497 && num_fdchits>2 // some minimum to make this worthwhile...
6498 && break_point_fdc_index<num_fdchits
6499 && break_point_fdc_index+num_cdchits>=MIN_HITS_FOR_REFIT
6500 && forward_traj.size()>2*MIN_HITS_FOR_REFIT // avoid small track stubs
6501 ){
6502 DMatrix5x5 Ctemp=C;
6503 DMatrix5x1 Stemp=S;
6504 unsigned int temp_ndf=my_ndf;
6505 double temp_chi2=chisq;
6506 double x=x_,y=y_,z=z_;
6507
6508 kalman_error_t refit_error=RecoverBrokenForwardTracks(fdc_anneal,
6509 cdc_anneal,
6510 S,C,C0,chisq,
6511 my_ndf);
6512 if (fit_type==kTimeBased && refit_error!=FIT_SUCCEEDED){
6513 fdc_anneal=1000.;
6514 cdc_anneal=1000.;
6515 refit_error=RecoverBrokenForwardTracks(fdc_anneal,
6516 cdc_anneal,
6517 S,C,C0,chisq,
6518 my_ndf);
6519 //chisq=1e6;
6520 did_second_refit=true;
6521 }
6522 if (refit_error!=FIT_SUCCEEDED){
6523 if (error==PRUNED_TOO_MANY_HITS || error==BREAK_POINT_FOUND){
6524 C=Ctemp;
6525 S=Stemp;
6526 my_ndf=temp_ndf;
6527 chisq=temp_chi2;
6528 x_=x,y_=y,z_=z;
6529
6530 if (num_cdchits<6) error=FIT_SUCCEEDED;
6531 }
6532 else error=FIT_FAILED;
6533 }
6534 else error=FIT_SUCCEEDED;
6535 }
6536 if ((error==POSITION_OUT_OF_RANGE || error==MOMENTUM_OUT_OF_RANGE)
6537 && iter==0){
6538 return FIT_FAILED;
6539 }
6540 if (error==FIT_FAILED || error==INVALID_FIT || my_ndf==0){
6541 if (iter==0) return FIT_FAILED; // first iteration failed
6542 break;
6543 }
6544
6545 if (iter>MIN_ITER3 && did_second_refit==false){
6546 double new_reduced_chisq=chisq/my_ndf;
6547 double old_reduced_chisq=chisq_forward/last_ndf;
6548 double new_prob=TMath::Prob(chisq,my_ndf);
6549 double old_prob=TMath::Prob(chisq_forward,last_ndf);
6550 if (new_prob<old_prob
6551 || fabs(new_reduced_chisq-old_reduced_chisq)<CHISQ_DELTA0.01){
6552 break;
6553 }
6554 }
6555
6556 chisq_forward=chisq;
6557 last_ndf=my_ndf;
6558 last_error=error;
6559 Slast=S;
6560 Clast=C;
6561 last_z=z_;
6562
6563 last_fdc_used_in_fit=fdc_used_in_fit;
6564 last_cdc_used_in_fit=cdc_used_in_fit;
6565 } //iteration
6566
6567 IsSmoothed=false;
6568 if(fit_type==kTimeBased){
6569 forward_pulls.clear();
6570 if (SmoothForward(forward_pulls) == NOERROR){
6571 IsSmoothed = true;
6572 pulls.assign(forward_pulls.begin(),forward_pulls.end());
6573 }
6574 }
6575
6576 // total chisq and ndf
6577 chisq_=chisq_forward;
6578 ndf_=last_ndf;
6579
6580 // output lists of hits used in the fit and fill pull vector
6581 cdchits_used_in_fit.clear();
6582 for (unsigned int m=0;m<last_cdc_used_in_fit.size();m++){
6583 if (last_cdc_used_in_fit[m]){
6584 cdchits_used_in_fit.push_back(my_cdchits[m]->hit);
6585 }
6586 }
6587 fdchits_used_in_fit.clear();
6588 for (unsigned int m=0;m<last_fdc_used_in_fit.size();m++){
6589 if (last_fdc_used_in_fit[m] && my_fdchits[m]->hit!=NULL__null){
6590 fdchits_used_in_fit.push_back(my_fdchits[m]->hit);
6591 }
6592 }
6593 // fill pull vector
6594 //pulls.assign(last_forward_pulls.begin(),last_forward_pulls.end());
6595
6596 // fill vector of extrapolations
6597 ClearExtrapolations();
6598 if (forward_traj.size()>1){
6599 ExtrapolateToInnerDetectors();
6600 if (fit_type==kTimeBased){
6601 double reverse_chisq=1e16,reverse_chisq_old=1e16;
6602 unsigned int reverse_ndf=0,reverse_ndf_old=0;
6603
6604 // Run the Kalman filter in the reverse direction, to get the best guess
6605 // for the state vector at the last FDC point on the track
6606 DMatrix5x5 CReverse=C;
6607 DMatrix5x1 SReverse=S,SDownstream,SBest;
6608 kalman_error_t reverse_error=FIT_NOT_DONE;
6609 for (int iter=0;iter<20;iter++){
6610 reverse_chisq_old=reverse_chisq;
6611 reverse_ndf_old=reverse_ndf;
6612 SBest=SDownstream;
6613 reverse_error=KalmanReverse(fdc_anneal,cdc_anneal,SReverse,CReverse,
6614 SDownstream,reverse_chisq,reverse_ndf);
6615 if (reverse_error!=FIT_SUCCEEDED) break;
6616
6617 SReverse=SDownstream;
6618 for (unsigned int k=0;k<forward_traj.size()-1;k++){
6619 // Get dEdx for the upcoming step
6620 double dEdx=0.;
6621 if (CORRECT_FOR_ELOSS){
6622 dEdx=GetdEdx(SReverse(state_q_over_p),
6623 forward_traj[k].K_rho_Z_over_A,
6624 forward_traj[k].rho_Z_over_A,
6625 forward_traj[k].LnI,forward_traj[k].Z);
6626 }
6627 // Step through field
6628 DMatrix5x5 J;
6629 double z=forward_traj[k].z;
6630 double newz=forward_traj[k+1].z;
6631 StepJacobian(z,newz,SReverse,dEdx,J);
6632 Step(z,newz,dEdx,SReverse);
6633
6634 CReverse=forward_traj[k].Q.AddSym(J*CReverse*J.Transpose());
6635 }
6636
6637 double reduced_chisq=reverse_chisq/double(reverse_ndf);
6638 double reduced_chisq_old=reverse_chisq_old/double(reverse_ndf_old);
6639 if (reduced_chisq>reduced_chisq_old
6640 || fabs(reduced_chisq-reduced_chisq_old)<0.01) break;
6641 }
6642
6643 if (reverse_error!=FIT_SUCCEEDED){
6644 ExtrapolateToOuterDetectors(forward_traj[0].S);
6645 }
6646 else{
6647 ExtrapolateToOuterDetectors(SBest);
6648 }
6649 }
6650 else{
6651 ExtrapolateToOuterDetectors(forward_traj[0].S);
6652 }
6653 if (extrapolations.at(SYS_BCAL).size()==1){
6654 // There needs to be some steps inside the the volume of the BCAL for
6655 // the extrapolation to be useful. If this is not the case, clear
6656 // the extrolation vector.
6657 extrapolations[SYS_BCAL].clear();
6658 }
6659 }
6660 // Extrapolate to the point of closest approach to the beam line
6661 z_=last_z;
6662 DVector2 beam_pos=beam_center+(z_-beam_z0)*beam_dir;
6663 double dx=Slast(state_x)-beam_pos.X();
6664 double dy=Slast(state_y)-beam_pos.Y();
6665 bool extrapolated=false;
6666 if (sqrt(dx*dx+dy*dy)>EPS21.e-4){
6667 DMatrix5x5 Ctemp=Clast;
6668 DMatrix5x1 Stemp=Slast;
6669 double ztemp=z_;
6670 if (ExtrapolateToVertex(Stemp,Ctemp)==NOERROR){
6671 Clast=Ctemp;
6672 Slast=Stemp;
6673 extrapolated=true;
6674 }
6675 else{
6676 //_DBG_ << endl;
6677 z_=ztemp;
6678 }
6679 }
6680
6681 // Final momentum, positions and tangents
6682 x_=Slast(state_x), y_=Slast(state_y);
6683 tx_=Slast(state_tx),ty_=Slast(state_ty);
6684 q_over_p_=Slast(state_q_over_p);
6685
6686 // Convert from forward rep. to central rep.
6687 double tsquare=tx_*tx_+ty_*ty_;
6688 tanl_=1./sqrt(tsquare);
6689 double cosl=cos(atan(tanl_));
6690 q_over_pt_=q_over_p_/cosl;
6691 phi_=atan2(ty_,tx_);
6692 if (FORWARD_PARMS_COV==false){
6693 if (extrapolated){
6694 beam_pos=beam_center+(z_-beam_z0)*beam_dir;
6695 dx=x_-beam_pos.X();
6696 dy=y_-beam_pos.Y();
6697 }
6698 D_=sqrt(dx*dx+dy*dy)+EPS3.0e-8;
6699 x_ = dx; y_ = dy;
6700 double cosphi=cos(phi_);
6701 double sinphi=sin(phi_);
6702 if ((dx>0.0 && sinphi>0.0) || (dy<0.0 && cosphi>0.0)
6703 || (dy>0.0 && cosphi<0.0) || (dx<0.0 && sinphi<0.0)) D_*=-1.;
6704 TransformCovariance(Clast);
6705 }
6706 // Covariance matrix
6707 vector<double>dummy;
6708 for (unsigned int i=0;i<5;i++){
6709 dummy.clear();
6710 for(unsigned int j=0;j<5;j++){
6711 dummy.push_back(Clast(i,j));
6712 }
6713 fcov.push_back(dummy);
6714 }
6715
6716 return last_error;
6717}
6718
6719// Routine to fit hits in the CDC using the forward parametrization
6720kalman_error_t DTrackFitterKalmanSIMD::ForwardCDCFit(const DMatrix5x1 &S0,const DMatrix5x5 &C0){
6721 unsigned int num_cdchits=my_cdchits.size();
6722 unsigned int max_cdc_index=num_cdchits-1;
6723 unsigned int min_cdc_index_for_refit=MIN_HITS_FOR_REFIT-1;
6724
6725 // Charge
6726 // double q=input_params.charge();
6727
6728 // Covariance matrix and state vector
6729 DMatrix5x5 C;
6730 DMatrix5x1 S=S0;
6731
6732 // Create matrices to store results from previous iteration
6733 DMatrix5x1 Slast(S);
6734 DMatrix5x5 Clast(C0);
6735
6736 // Vectors to keep track of updated state vectors and covariance matrices (after
6737 // adding the hit information)
6738 vector<pull_t>cdc_pulls;
6739 vector<pull_t>last_cdc_pulls;
6740 vector<bool>last_cdc_used_in_fit;
6741
6742 double anneal_factor=ANNEAL_SCALE+1.;
6743 kalman_error_t error=FIT_NOT_DONE,last_error=FIT_NOT_DONE;
6744
6745 // Chi-squared and degrees of freedom
6746 double chisq=-1.,chisq_forward=-1.;
6747 unsigned int my_ndf=0;
6748 unsigned int last_ndf=1;
6749 // last z position
6750 double zlast=0.;
6751 // unsigned int last_break_point_index=0,last_break_point_step_index=0;
6752
6753 // Iterate over reference trajectories
6754 for (int iter2=0;
6755 iter2<(fit_type==kTimeBased?MAX_TB_PASSES20:MAX_WB_PASSES20);
6756 iter2++){
6757 if (DEBUG_LEVEL>1){
6758 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6758<<" "
<<"-------- iteration " << iter2+1 << " -----------" <<endl;
6759 }
6760
6761 // These variables provide the approximate location along the trajectory
6762 // where there is an indication of a kink in the track
6763 break_point_cdc_index=max_cdc_index;
6764 break_point_step_index=0;
6765
6766 // Reset material map index
6767 last_material_map=0;
6768
6769 // Abort if momentum is too low
6770 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){
6771 //printf("Too low momentum? %f\n",1/S(state_q_over_p));
6772 break;
6773 }
6774
6775 // Scale cut for pruning hits according to the iteration number
6776 anneal_factor=(iter2<MIN_ITER3)?(ANNEAL_SCALE/pow(ANNEAL_POW_CONST,iter2)+1.):1.;
6777
6778 // Initialize path length variable and flight time
6779 len=0;
6780 ftime=0.;
6781 var_ftime=0.;
6782
6783 // Swim to create the reference trajectory
6784 jerror_t ref_track_error=SetCDCForwardReferenceTrajectory(S);
6785 if (ref_track_error!=NOERROR){
6786 if (iter2==0) return FIT_FAILED;
6787 break;
6788 }
6789
6790 // Reset the status of the cdc hits
6791 for (unsigned int j=0;j<num_cdchits;j++){
6792 if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
6793 }
6794
6795 // perform the filter
6796 C=C0;
6797 bool did_second_refit=false;
6798 error=KalmanForwardCDC(anneal_factor,S,C,chisq,my_ndf);
6799
6800 // Try to recover tracks that failed the first attempt at fitting by
6801 // cutting outer hits
6802 if (error!=FIT_SUCCEEDED && RECOVER_BROKEN_TRACKS
6803 && num_cdchits>=MIN_HITS_FOR_REFIT){
6804 DMatrix5x5 Ctemp=C;
6805 DMatrix5x1 Stemp=S;
6806 unsigned int temp_ndf=my_ndf;
6807 double temp_chi2=chisq;
6808 double x=x_,y=y_,z=z_;
6809
6810 if (error==MOMENTUM_OUT_OF_RANGE){
6811 //_DBG_ << "Momentum out of range" <<endl;
6812 unsigned int new_index=(3*max_cdc_index)/4;
6813 break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
6814 }
6815
6816 if (error==BROKEN_COVARIANCE_MATRIX){
6817 break_point_cdc_index=min_cdc_index_for_refit;
6818 //_DBG_ << "Bad Cov" <<endl;
6819 }
6820 if (error==POSITION_OUT_OF_RANGE){
6821 //_DBG_ << "Bad position" << endl;
6822 unsigned int new_index=(max_cdc_index)/2;
6823 break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
6824 }
6825 if (error==PRUNED_TOO_MANY_HITS){
6826 // _DBG_ << "Prune" << endl;
6827 unsigned int new_index=(3*max_cdc_index)/4;
6828 break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
6829 // anneal_factor*=10.;
6830 }
6831
6832 kalman_error_t refit_error=RecoverBrokenTracks(anneal_factor,S,C,C0,chisq,my_ndf);
6833 if (fit_type==kTimeBased && refit_error!=FIT_SUCCEEDED){
6834 anneal_factor=1000.;
6835 refit_error=RecoverBrokenTracks(anneal_factor,S,C,C0,chisq,my_ndf);
6836 //chisq=1e6;
6837 did_second_refit=true;
6838 }
6839
6840 if (refit_error!=FIT_SUCCEEDED){
6841 if (error==PRUNED_TOO_MANY_HITS || error==BREAK_POINT_FOUND){
6842 C=Ctemp;
6843 S=Stemp;
6844 my_ndf=temp_ndf;
6845 chisq=temp_chi2;
6846 x_=x,y_=y,z_=z;
6847
6848 // error=FIT_SUCCEEDED;
6849 }
6850 else error=FIT_FAILED;
6851 }
6852 else error=FIT_SUCCEEDED;
6853 }
6854 if ((error==POSITION_OUT_OF_RANGE || error==MOMENTUM_OUT_OF_RANGE)
6855 && iter2==0){
6856 return FIT_FAILED;
6857 }
6858 if (error==FIT_FAILED || error==INVALID_FIT || my_ndf==0){
6859 if (iter2==0) return error;
6860 break;
6861 }
6862
6863 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<6863<<" "
<< "--> Chisq " << chisq << " NDF "
6864 << my_ndf
6865 << " Prob: " << TMath::Prob(chisq,my_ndf)
6866 << endl;
6867
6868 if (iter2>MIN_ITER3 && did_second_refit==false){
6869 double new_reduced_chisq=chisq/my_ndf;
6870 double old_reduced_chisq=chisq_forward/last_ndf;
6871 double new_prob=TMath::Prob(chisq,my_ndf);
6872 double old_prob=TMath::Prob(chisq_forward,last_ndf);
6873 if (new_prob<old_prob
6874 || fabs(new_reduced_chisq-old_reduced_chisq)<CHISQ_DELTA0.01) break;
6875 }
6876
6877 chisq_forward=chisq;
6878 Slast=S;
6879 Clast=C;
6880 last_error=error;
6881 last_ndf=my_ndf;
6882 zlast=z_;
6883
6884 last_cdc_used_in_fit=cdc_used_in_fit;
6885 } //iteration
6886
6887 // Run the smoother
6888 IsSmoothed=false;
6889 if(fit_type==kTimeBased){
6890 cdc_pulls.clear();
6891 if (SmoothForwardCDC(cdc_pulls) == NOERROR){
6892 IsSmoothed = true;
6893 pulls.assign(cdc_pulls.begin(),cdc_pulls.end());
6894 }
6895 }
6896
6897 // total chisq and ndf
6898 chisq_=chisq_forward;
6899 ndf_=last_ndf;
6900
6901 // output lists of hits used in the fit and fill the pull vector
6902 cdchits_used_in_fit.clear();
6903 for (unsigned int m=0;m<last_cdc_used_in_fit.size();m++){
6904 if (last_cdc_used_in_fit[m]){
6905 cdchits_used_in_fit.push_back(my_cdchits[m]->hit);
6906 }
6907 }
6908 // output pulls vector
6909 //pulls.assign(last_cdc_pulls.begin(),last_cdc_pulls.end());
6910
6911 // Fill extrapolation vector
6912 ClearExtrapolations();
6913 if (forward_traj.size()>1){
6914 if (fit_type==kWireBased){
6915 ExtrapolateForwardToOtherDetectors();
6916 }
6917 else{
6918 ExtrapolateToInnerDetectors();
6919
6920 double reverse_chisq=1e16,reverse_chisq_old=1e16;
6921 unsigned int reverse_ndf=0,reverse_ndf_old=0;
6922
6923 // Run the Kalman filter in the reverse direction, to get the best guess
6924 // for the state vector at the last FDC point on the track
6925 DMatrix5x5 CReverse=C;
6926 DMatrix5x1 SReverse=S,SDownstream,SBest;
6927 kalman_error_t reverse_error=FIT_NOT_DONE;
6928 for (int iter=0;iter<20;iter++){
6929 reverse_chisq_old=reverse_chisq;
6930 reverse_ndf_old=reverse_ndf;
6931 SBest=SDownstream;
6932 reverse_error=KalmanReverse(0.,anneal_factor,SReverse,CReverse,
6933 SDownstream,reverse_chisq,reverse_ndf);
6934 if (reverse_error!=FIT_SUCCEEDED) break;
6935
6936 SReverse=SDownstream;
6937 for (unsigned int k=0;k<forward_traj.size()-1;k++){
6938 // Get dEdx for the upcoming step
6939 double dEdx=0.;
6940 if (CORRECT_FOR_ELOSS){
6941 dEdx=GetdEdx(SReverse(state_q_over_p),
6942 forward_traj[k].K_rho_Z_over_A,
6943 forward_traj[k].rho_Z_over_A,
6944 forward_traj[k].LnI,forward_traj[k].Z);
6945 }
6946 // Step through field
6947 DMatrix5x5 J;
6948 double z=forward_traj[k].z;
6949 double newz=forward_traj[k+1].z;
6950 StepJacobian(z,newz,SReverse,dEdx,J);
6951 Step(z,newz,dEdx,SReverse);
6952
6953 CReverse=forward_traj[k].Q.AddSym(J*CReverse*J.Transpose());
6954 }
6955
6956 double reduced_chisq=reverse_chisq/double(reverse_ndf);
6957 double reduced_chisq_old=reverse_chisq_old/double(reverse_ndf_old);
6958 if (reduced_chisq>reduced_chisq_old
6959 || fabs(reduced_chisq-reduced_chisq_old)<0.01) break;
6960 }
6961 if (reverse_error!=FIT_SUCCEEDED){
6962 ExtrapolateToOuterDetectors(forward_traj[0].S);
6963 }
6964 else{
6965 ExtrapolateToOuterDetectors(SBest);
6966 }
6967 }
6968 }
6969 if (extrapolations.at(SYS_BCAL).size()==1){
6970 // There needs to be some steps inside the the volume of the BCAL for
6971 // the extrapolation to be useful. If this is not the case, clear
6972 // the extrolation vector.
6973 extrapolations[SYS_BCAL].clear();
6974 }
6975
6976 // Extrapolate to the point of closest approach to the beam line
6977 z_=zlast;
6978 DVector2 beam_pos=beam_center+(z_-beam_z0)*beam_dir;
6979 double dx=Slast(state_x)-beam_pos.X();
6980 double dy=Slast(state_y)-beam_pos.Y();
6981 bool extrapolated=false;
6982 if (sqrt(dx*dx+dy*dy)>EPS21.e-4){
6983 if (ExtrapolateToVertex(Slast,Clast)!=NOERROR) return EXTRAPOLATION_FAILED;
6984 extrapolated=true;
6985 }
6986
6987 // Final momentum, positions and tangents
6988 x_=Slast(state_x), y_=Slast(state_y);
6989 tx_=Slast(state_tx),ty_=Slast(state_ty);
6990 q_over_p_=Slast(state_q_over_p);
6991
6992 // Convert from forward rep. to central rep.
6993 double tsquare=tx_*tx_+ty_*ty_;
6994 tanl_=1./sqrt(tsquare);
6995 double cosl=cos(atan(tanl_));
6996 q_over_pt_=q_over_p_/cosl;
6997 phi_=atan2(ty_,tx_);
6998 if (FORWARD_PARMS_COV==false){
6999 if (extrapolated){
7000 beam_pos=beam_center+(z_-beam_z0)*beam_dir;
7001 dx=x_-beam_pos.X();
7002 dy=y_-beam_pos.Y();
7003 }
7004 D_=sqrt(dx*dx+dy*dy)+EPS3.0e-8;
7005 x_ = dx; y_ = dy;
7006 double cosphi=cos(phi_);
7007 double sinphi=sin(phi_);
7008 if ((dx>0.0 && sinphi>0.0) || (dy<0.0 && cosphi>0.0)
7009 || (dy>0.0 && cosphi<0.0) || (dx<0.0 && sinphi<0.0)) D_*=-1.;
7010 TransformCovariance(Clast);
7011 }
7012 // Covariance matrix
7013 vector<double>dummy;
7014 // ... forward parameterization
7015 fcov.clear();
7016 for (unsigned int i=0;i<5;i++){
7017 dummy.clear();
7018 for(unsigned int j=0;j<5;j++){
7019 dummy.push_back(Clast(i,j));
7020 }
7021 fcov.push_back(dummy);
7022 }
7023
7024 return last_error;
7025}
7026
7027// Routine to fit hits in the CDC using the central parametrization
7028kalman_error_t DTrackFitterKalmanSIMD::CentralFit(const DVector2 &startpos,
7029 const DMatrix5x1 &S0,
7030 const DMatrix5x5 &C0){
7031 // Initial position in x and y
7032 DVector2 pos(startpos);
7033
7034 // Charge
7035 // double q=input_params.charge();
7036
7037 // Covariance matrix and state vector
7038 DMatrix5x5 Cc;
7039 DMatrix5x1 Sc=S0;
7040
7041 // Variables to store values from previous iterations
7042 DMatrix5x1 Sclast(Sc);
7043 DMatrix5x5 Cclast(C0);
7044 DVector2 last_pos=pos;
7045
7046 unsigned int num_cdchits=my_cdchits.size();
7047 unsigned int max_cdc_index=num_cdchits-1;
7048 unsigned int min_cdc_index_for_refit=MIN_HITS_FOR_REFIT-1;
7049
7050 // Vectors to keep track of updated state vectors and covariance matrices (after
7051 // adding the hit information)
7052 vector<pull_t>last_cdc_pulls;
7053 vector<pull_t>cdc_pulls;
7054 vector<bool>last_cdc_used_in_fit(num_cdchits);
7055
7056 double anneal_factor=ANNEAL_SCALE+1.; // variable for scaling cut for hit pruning
7057
7058 //Initialization of chisq, ndf, and error status
7059 double chisq_iter=-1.,chisq=-1.;
7060 unsigned int my_ndf=0;
7061 ndf_=0.;
7062 unsigned int last_ndf=1;
7063 kalman_error_t error=FIT_NOT_DONE,last_error=FIT_NOT_DONE;
7064
7065 // Iterate over reference trajectories
7066 int iter2=0;
7067 for (;iter2<(fit_type==kTimeBased?MAX_TB_PASSES20:MAX_WB_PASSES20);
7068 iter2++){
7069 if (DEBUG_LEVEL>1){
7070 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7070<<" "
<<"-------- iteration " << iter2+1 << " -----------" <<endl;
7071 }
7072
7073 // These variables provide the approximate location along the trajectory
7074 // where there is an indication of a kink in the track
7075 break_point_cdc_index=max_cdc_index;
7076 break_point_step_index=0;
7077
7078 // Reset material map index
7079 last_material_map=0;
7080
7081 // Break out of loop if p is too small
7082 double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl)));
7083 if (fabs(q_over_p)>Q_OVER_P_MAX) break;
7084
7085 // Initialize path length variable and flight time
7086 len=0.;
7087 ftime=0.;
7088 var_ftime=0.;
7089
7090 // Scale cut for pruning hits according to the iteration number
7091 anneal_factor=(iter2<MIN_ITER3)?(ANNEAL_SCALE/pow(ANNEAL_POW_CONST,iter2)+1.):1.;
7092
7093 // Initialize trajectory deque
7094 jerror_t ref_track_error=SetCDCReferenceTrajectory(last_pos,Sc);
7095 if (ref_track_error!=NOERROR){
7096 if (iter2==0) return FIT_FAILED;
7097 break;
7098 }
7099
7100 // Reset the status of the cdc hits
7101 for (unsigned int j=0;j<num_cdchits;j++){
7102 if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit;
7103 }
7104
7105 // perform the fit
7106 Cc=C0;
7107 bool did_second_refit=false;
7108 error=KalmanCentral(anneal_factor,Sc,Cc,pos,chisq,my_ndf);
7109
7110 // Try to recover tracks that failed the first attempt at fitting by
7111 // throwing away outer hits.
7112 if (error!=FIT_SUCCEEDED && RECOVER_BROKEN_TRACKS
7113 && num_cdchits>=MIN_HITS_FOR_REFIT){
7114 DVector2 temp_pos=pos;
7115 DMatrix5x1 Stemp=Sc;
7116 DMatrix5x5 Ctemp=Cc;
7117 unsigned int temp_ndf=my_ndf;
7118 double temp_chi2=chisq;
7119
7120 if (error==MOMENTUM_OUT_OF_RANGE){
7121 //_DBG_ << "Momentum out of range" <<endl;
7122 unsigned int new_index=(3*max_cdc_index)/4;
7123 break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
7124 }
7125
7126 if (error==BROKEN_COVARIANCE_MATRIX){
7127 break_point_cdc_index=min_cdc_index_for_refit;
7128 //_DBG_ << "Bad Cov" <<endl;
7129 }
7130 if (error==POSITION_OUT_OF_RANGE){
7131 //_DBG_ << "Bad position" << endl;
7132 unsigned int new_index=(max_cdc_index)/2;
7133 break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
7134 }
7135 if (error==PRUNED_TOO_MANY_HITS){
7136 unsigned int new_index=(3*max_cdc_index)/4;
7137 break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit;
7138 //anneal_factor*=10.;
7139 //_DBG_ << "Prune" << endl;
7140 }
7141
7142 kalman_error_t refit_error=RecoverBrokenTracks(anneal_factor,Sc,Cc,C0,pos,chisq,my_ndf);
7143 if (fit_type==kTimeBased && refit_error!=FIT_SUCCEEDED){
7144 anneal_factor=1000.;
7145 refit_error=RecoverBrokenTracks(anneal_factor,Sc,Cc,C0,pos,chisq,my_ndf);
7146 //chisq=1e6;
7147 did_second_refit=true;
7148 }
7149
7150 if (refit_error!=FIT_SUCCEEDED){
7151 //_DBG_ << error << endl;
7152 if (error==PRUNED_TOO_MANY_HITS || error==BREAK_POINT_FOUND){
7153 Cc=Ctemp;
7154 Sc=Stemp;
7155 my_ndf=temp_ndf;
7156 chisq=temp_chi2;
7157 pos=temp_pos;
7158 if (DEBUG_LEVEL > 1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7158<<" "
<< " Refit did not succeed, but restoring old values" << endl;
7159
7160 //error=FIT_SUCCEEDED;
7161 }
7162 }
7163 else error=FIT_SUCCEEDED;
7164 }
7165 if ((error==POSITION_OUT_OF_RANGE || error==MOMENTUM_OUT_OF_RANGE)
7166 && iter2==0){
7167 return FIT_FAILED;
7168 }
7169 if (error==FIT_FAILED || error==INVALID_FIT || my_ndf==0){
7170 if (iter2==0) return error;
7171 break;
7172 }
7173
7174 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7174<<" "
<< "--> Chisq " << chisq << " Ndof " << my_ndf
7175 << " Prob: " << TMath::Prob(chisq,my_ndf)
7176 << endl;
7177
7178 if (iter2>MIN_ITER3 && did_second_refit==false){
7179 double new_reduced_chisq=chisq/my_ndf;
7180 double old_reduced_chisq=chisq_iter/last_ndf;
7181 double new_prob=TMath::Prob(chisq,my_ndf);
7182 double old_prob=TMath::Prob(chisq_iter,last_ndf);
7183 if (new_prob<old_prob
7184 || fabs(new_reduced_chisq-old_reduced_chisq)<CHISQ_DELTA0.01) break;
7185 }
7186
7187 // Save the current state vector and covariance matrix
7188 Cclast=Cc;
7189 Sclast=Sc;
7190 last_pos=pos;
7191 chisq_iter=chisq;
7192 last_ndf=my_ndf;
7193 last_error=error;
7194
7195 last_cdc_used_in_fit=cdc_used_in_fit;
7196 }
7197
7198 // Run smoother and fill pulls vector
7199 IsSmoothed=false;
7200 if(fit_type==kTimeBased){
7201 cdc_pulls.clear();
7202 if (SmoothCentral(cdc_pulls) == NOERROR){
7203 IsSmoothed = true;
7204 pulls.assign(cdc_pulls.begin(),cdc_pulls.end());
7205 }
7206 }
7207
7208 // Fill extrapolations vector
7209 ClearExtrapolations();
7210 ExtrapolateCentralToOtherDetectors();
7211 if (extrapolations.at(SYS_BCAL).size()==1){
7212 // There needs to be some steps inside the the volume of the BCAL for
7213 // the extrapolation to be useful. If this is not the case, clear
7214 // the extrolation vector.
7215 extrapolations[SYS_BCAL].clear();
7216 }
7217
7218 // Extrapolate to the point of closest approach to the beam line
7219 DVector2 beam_pos=beam_center+(Sclast(state_z)-beam_z0)*beam_dir;
7220 bool extrapolated=false;
7221 if ((last_pos-beam_pos).Mod()>EPS21.e-4){ // in cm
7222 if (ExtrapolateToVertex(last_pos,Sclast,Cclast)!=NOERROR) return EXTRAPOLATION_FAILED;
7223 extrapolated=true;
7224 }
7225
7226 // output lists of hits used in the fit
7227 cdchits_used_in_fit.clear();
7228 for (unsigned int m=0;m<last_cdc_used_in_fit.size();m++){
7229 if (last_cdc_used_in_fit[m]){
7230 cdchits_used_in_fit.push_back(my_cdchits[m]->hit);
7231 }
7232 }
7233 // output the pull information
7234 //pulls.assign(last_cdc_pulls.begin(),last_cdc_pulls.end());
7235
7236 // Track Parameters at "vertex"
7237 phi_=Sclast(state_phi);
7238 q_over_pt_=Sclast(state_q_over_pt);
7239 tanl_=Sclast(state_tanl);
7240 x_=last_pos.X();
7241 y_=last_pos.Y();
7242 z_=Sclast(state_z);
7243 // Find the (signed) distance of closest approach to the beam line
7244 if (extrapolated){
7245 beam_pos=beam_center+(z_-beam_z0)*beam_dir;
7246 }
7247 double dx=x_-beam_pos.X();
7248 double dy=y_-beam_pos.Y();
7249 D_=sqrt(dx*dx+dy*dy)+EPS3.0e-8;
7250 x_ = dx; y_ = dy;
7251 double cosphi=cos(phi_);
7252 double sinphi=sin(phi_);
7253 if ((dx>0.0 && sinphi>0.0) || (dy <0.0 && cosphi>0.0)
7254 || (dy>0.0 && cosphi<0.0) || (dx<0.0 && sinphi<0.0)) D_*=-1.;
7255 // Rotate covariance matrix to coordinate system centered on x=0,y=0 in the
7256 // lab
7257 DMatrix5x5 Jc=I5x5;
7258 Jc(state_D,state_D)=(dy*cosphi-dx*sinphi)/D_;
7259 //Cclast=Cclast.SandwichMultiply(Jc);
7260 Cclast=Jc*Cclast*Jc.Transpose();
7261
7262 if (!isfinite(x_) || !isfinite(y_) || !isfinite(z_) || !isfinite(phi_)
7263 || !isfinite(q_over_pt_) || !isfinite(tanl_)){
7264 if (DEBUG_LEVEL>0){
7265 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7265<<" "
<< "At least one parameter is NaN or +-inf!!" <<endl;
7266 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7266<<" "
<< "x " << x_ << " y " << y_ << " z " << z_ << " phi " << phi_
7267 << " q/pt " << q_over_pt_ << " tanl " << tanl_ << endl;
7268 }
7269 return INVALID_FIT;
7270 }
7271
7272 // Covariance matrix at vertex
7273 fcov.clear();
7274 vector<double>dummy;
7275 for (unsigned int i=0;i<5;i++){
7276 dummy.clear();
7277 for(unsigned int j=0;j<5;j++){
7278 dummy.push_back(Cclast(i,j));
7279 }
7280 cov.push_back(dummy);
7281 }
7282
7283 // total chisq and ndf
7284 chisq_=chisq_iter;
7285 ndf_=last_ndf;
7286 //printf("NDof %d\n",ndf);
7287
7288 return last_error;
7289}
7290
7291// Smoothing algorithm for the forward trajectory. Updates the state vector
7292// at each step (going in the reverse direction to the filter) based on the
7293// information from all the steps and outputs the state vector at the
7294// outermost step.
7295jerror_t DTrackFitterKalmanSIMD::SmoothForward(vector<pull_t>&forward_pulls){
7296 if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE;
7297
7298 unsigned int max=forward_traj.size()-1;
7299 DMatrix5x1 S=(forward_traj[max].Skk);
7300 DMatrix5x5 C=(forward_traj[max].Ckk);
7301 DMatrix5x5 JT=forward_traj[max].J.Transpose();
7302 DMatrix5x1 Ss=S;
7303 DMatrix5x5 Cs=C;
7304 DMatrix5x5 A,dC;
7305
7306 if (DEBUG_LEVEL>19){
7307 jout << "---- Smoothed residuals ----" <<endl;
7308 jout << setprecision(4);
7309 }
7310
7311 for (unsigned int m=max-1;m>0;m--){
7312
7313 if (WRITE_ML_TRAINING_OUTPUT){
7314 mlfile << forward_traj[m].z;
7315 for (unsigned int k=0;k<5;k++){
7316 mlfile << " " << Ss(k);
7317 }
7318 for (unsigned int k=0;k<5;k++){
7319 mlfile << " " << Cs(k,k);
7320 for (unsigned int j=k+1;j<5;j++){
7321 mlfile <<" " << Cs(k,j);
7322 }
7323 }
7324 mlfile << endl;
7325 }
7326
7327 if (forward_traj[m].h_id>0){
7328 if (forward_traj[m].h_id<1000){
7329 unsigned int id=forward_traj[m].h_id-1;
7330 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7330<<" "
<< " Smoothing FDC ID " << id << endl;
7331 if (fdc_used_in_fit[id] && my_fdchits[id]->status==good_hit){
7332 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7332<<" "
<< " Used in fit " << endl;
7333 A=fdc_updates[id].C*JT*C.InvertSym();
7334 Ss=fdc_updates[id].S+A*(Ss-S);
7335
7336 if (!Ss.IsFinite()){
7337 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7337<<" "
<< "Invalid values for smoothed parameters..." << endl;
7338 return VALUE_OUT_OF_RANGE;
7339 }
7340 dC=A*(Cs-C)*A.Transpose();
7341 Cs=fdc_updates[id].C+dC;
7342 if (!Cs.IsPosDef()){
7343 if (DEBUG_LEVEL>1)
7344 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7344<<" "
<< "Covariance Matrix not PosDef..." << endl;
7345 return VALUE_OUT_OF_RANGE;
7346 }
7347
7348 // Position and direction from state vector with small angle
7349 // alignment correction
7350 double x=Ss(state_x) + my_fdchits[id]->phiZ*Ss(state_y);
7351 double y=Ss(state_y) - my_fdchits[id]->phiZ*Ss(state_x);
7352 double tx=Ss(state_tx)+ my_fdchits[id]->phiZ*Ss(state_ty)
7353 - my_fdchits[id]->phiY;
7354 double ty=Ss(state_ty) - my_fdchits[id]->phiZ*Ss(state_tx)
7355 + my_fdchits[id]->phiX;
7356
7357 double cosa=my_fdchits[id]->cosa;
7358 double sina=my_fdchits[id]->sina;
7359 double u=my_fdchits[id]->uwire;
7360 double v=my_fdchits[id]->vstrip;
7361
7362 // Projected position along the wire without doca-dependent corrections
7363 double vpred_uncorrected=x*sina+y*cosa;
7364
7365 // Projected position in the plane of the wires transverse to the wires
7366 double upred=x*cosa-y*sina;
7367
7368 // Direction tangent in the u-z plane
7369 double tu=tx*cosa-ty*sina;
7370 double one_plus_tu2=1.+tu*tu;
7371 double alpha=atan(tu);
7372 double cosalpha=cos(alpha);
7373 //double cosalpha2=cosalpha*cosalpha;
7374 double sinalpha=sin(alpha);
7375
7376 // (signed) distance of closest approach to wire
7377 double du=upred-u;
7378 double doca=du*cosalpha;
7379
7380 // Correction for lorentz effect
7381 double nz=my_fdchits[id]->nz;
7382 double nr=my_fdchits[id]->nr;
7383 double nz_sinalpha_plus_nr_cosalpha=nz*sinalpha+nr*cosalpha;
7384
7385 // Difference between measurement and projection
7386 double tv=tx*sina+ty*cosa;
7387 double resi=v-(vpred_uncorrected+doca*(nz_sinalpha_plus_nr_cosalpha
7388 -tv*sinalpha));
7389 double drift_time=my_fdchits[id]->t-mT0
7390 -forward_traj[m].t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
7391 double drift = 0.0;
7392 int left_right = -999;
7393 if (USE_FDC_DRIFT_TIMES) {
7394 drift = (du > 0.0 ? 1.0 : -1.0) * fdc_drift_distance(drift_time, forward_traj[m].B);
7395 left_right = (du > 0.0 ? +1 : -1);
7396 }
7397
7398 double resi_a = drift - doca;
7399
7400 // Variance from filter step
7401 // This V is really "R" in Fruhwirths notation, in the case that the track is used in the fit.
7402 DMatrix2x2 V=fdc_updates[id].V;
7403 // Compute projection matrix and find the variance for the residual
7404 DMatrix5x2 H_T;
7405 double temp2=nz_sinalpha_plus_nr_cosalpha-tv*sinalpha;
7406 H_T(state_x,1)=sina+cosa*cosalpha*temp2;
7407 H_T(state_y,1)=cosa-sina*cosalpha*temp2;
7408
7409 double cos2_minus_sin2=cosalpha*cosalpha-sinalpha*sinalpha;
7410 double fac=nz*cos2_minus_sin2-2.*nr*cosalpha*sinalpha;
7411 double doca_cosalpha=doca*cosalpha;
7412 double temp=doca_cosalpha*fac;
7413 H_T(state_tx,1)=cosa*temp
7414 -doca_cosalpha*(tu*sina+tv*cosa*cos2_minus_sin2)
7415 ;
7416 H_T(state_ty,1)=-sina*temp
7417 -doca_cosalpha*(tu*cosa-tv*sina*cos2_minus_sin2)
7418 ;
7419
7420 H_T(state_x,0)=cosa*cosalpha;
7421 H_T(state_y,0)=-sina*cosalpha;
7422 double factor=du*tu/sqrt(one_plus_tu2)/one_plus_tu2;
7423 H_T(state_ty,0)=sina*factor;
7424 H_T(state_tx,0)=-cosa*factor;
7425
7426 // Matrix transpose H_T -> H
7427 DMatrix2x5 H=Transpose(H_T);
7428
7429 if (my_fdchits[id]->hit!=NULL__null
7430 && my_fdchits[id]->hit->wire->layer==PLANE_TO_SKIP){
7431 //V+=Cs.SandwichMultiply(H_T);
7432 V=V+H*Cs*H_T;
7433 }
7434 else{
7435 //V-=dC.SandwichMultiply(H_T);
7436 V=V-H*dC*H_T;
7437 }
7438
7439
7440 vector<double> alignmentDerivatives;
7441 if (ALIGNMENT_FORWARD && my_fdchits[id]->hit!=NULL__null){
7442 alignmentDerivatives.resize(FDCTrackD::size);
7443 // Let's get the alignment derivatives
7444
7445 // Things are assumed to be linear near the wire, derivatives can be determined analytically.
7446 // First for the wires
7447
7448 //dDOCAW/ddeltax
7449 alignmentDerivatives[FDCTrackD::dDOCAW_dDeltaX] = -(1/sqrt(1 + pow(tx*cosa - ty*sina,2)));
7450
7451 //dDOCAW/ddeltaz
7452 alignmentDerivatives[FDCTrackD::dDOCAW_dDeltaZ] = (tx*cosa - ty*sina)/sqrt(1 + pow(tx*cosa - ty*sina,2));
7453
7454 //dDOCAW/ddeltaPhiX
7455 double cos2a = cos(2.*my_fdchits[id]->hit->wire->angle);
7456 double sin2a = sin(2.*my_fdchits[id]->hit->wire->angle);
7457 double cos3a = cos(3.*my_fdchits[id]->hit->wire->angle);
7458 double sin3a = sin(3.*my_fdchits[id]->hit->wire->angle);
7459 //double tx2 = tx*tx;
7460 //double ty2 = ty*ty;
7461 alignmentDerivatives[FDCTrackD::dDOCAW_dDeltaPhiX] = (sina*(-(tx*cosa) + ty*sina)*(u - x*cosa + y*sina))/
7462 pow(1 + pow(tx*cosa - ty*sina,2),1.5);
7463 alignmentDerivatives[FDCTrackD::dDOCAW_dDeltaPhiY] = -((cosa*(tx*cosa - ty*sina)*(u - x*cosa + y*sina))/
7464 pow(1 + pow(tx*cosa - ty*sina,2),1.5));
7465 alignmentDerivatives[FDCTrackD::dDOCAW_dDeltaPhiZ] = (tx*ty*u*cos2a + (x + pow(ty,2)*x - tx*ty*y)*sina +
7466 cosa*(-(tx*ty*x) + y + pow(tx,2)*y + (tx - ty)*(tx + ty)*u*sina))/
7467 pow(1 + pow(tx*cosa - ty*sina,2),1.5);
7468
7469 // dDOCAW/dt0
7470 double t0shift=4.;//ns
7471 double drift_shift = 0.0;
7472 if(USE_FDC_DRIFT_TIMES){
7473 if (drift_time < 0.) drift_shift = drift;
7474 else drift_shift = (du>0.0?1.:-1.)*fdc_drift_distance(drift_time+t0shift,forward_traj[m].B);
7475 }
7476 alignmentDerivatives[FDCTrackD::dW_dt0]= (drift_shift-drift)/t0shift;
7477
7478 // dDOCAW/dx
7479 alignmentDerivatives[FDCTrackD::dDOCAW_dx] = cosa/sqrt(1 + pow(tx*cosa - ty*sina,2));
7480
7481 // dDOCAW/dy
7482 alignmentDerivatives[FDCTrackD::dDOCAW_dy] = -(sina/sqrt(1 + pow(tx*cosa - ty*sina,2)));
7483
7484 // dDOCAW/dtx
7485 alignmentDerivatives[FDCTrackD::dDOCAW_dtx] = (cosa*(tx*cosa - ty*sina)*(u - x*cosa + y*sina))/pow(1 + pow(tx*cosa - ty*sina,2),1.5);
7486
7487 // dDOCAW/dty
7488 alignmentDerivatives[FDCTrackD::dDOCAW_dty] = (sina*(-(tx*cosa) + ty*sina)*(u - x*cosa + y*sina))/
7489 pow(1 + pow(tx*cosa - ty*sina,2),1.5);
7490
7491 // Then for the cathodes. The magnetic field correction now correlates the alignment constants for the wires and cathodes.
7492
7493 //dDOCAC/ddeltax
7494 alignmentDerivatives[FDCTrackD::dDOCAC_dDeltaX] =
7495 (-nr + (-nz + ty*cosa + tx*sina)*(tx*cosa - ty*sina))/(1 + pow(tx*cosa - ty*sina,2));
7496
7497 //dDOCAC/ddeltaz
7498 alignmentDerivatives[FDCTrackD::dDOCAC_dDeltaZ] =
7499 nz + (-nz + (nr*tx + ty)*cosa + (tx - nr*ty)*sina)/(1 + pow(tx*cosa - ty*sina,2));
7500
7501 //dDOCAC/ddeltaPhiX
7502 alignmentDerivatives[FDCTrackD::dDOCAC_dDeltaPhiX] =
7503 (-2*y*cosa*sina*(tx*cosa - ty*sina) - 2*x*pow(sina,2)*(tx*cosa - ty*sina) -
7504 (u - x*cosa + y*sina)*(-(nz*sina) + sina*(ty*cosa + tx*sina) -
7505 cosa*(tx*cosa - ty*sina)))/(1 + pow(tx*cosa - ty*sina,2)) +
7506 (2*sina*(tx*cosa - ty*sina)*(-((u - x*cosa + y*sina)*
7507 (nr + nz*(tx*cosa - ty*sina) - (ty*cosa + tx*sina)*(tx*cosa - ty*sina))) +
7508 y*cosa*(1 + pow(tx*cosa - ty*sina,2)) + x*sina*(1 + pow(tx*cosa - ty*sina,2))))/
7509 pow(1 + pow(tx*cosa - ty*sina,2),2);
7510
7511
7512 //dDOCAC/ddeltaPhiY
7513 alignmentDerivatives[FDCTrackD::dDOCAC_dDeltaPhiY] = (-2*y*pow(cosa,2)*(tx*cosa - ty*sina) - 2*x*cosa*sina*(tx*cosa - ty*sina) -
7514 (u - x*cosa + y*sina)*(-(nz*cosa) + cosa*(ty*cosa + tx*sina) +
7515 sina*(tx*cosa - ty*sina)))/(1 + pow(tx*cosa - ty*sina,2)) +
7516 (2*cosa*(tx*cosa - ty*sina)*(-((u - x*cosa + y*sina)*
7517 (nr + nz*(tx*cosa - ty*sina) - (ty*cosa + tx*sina)*(tx*cosa - ty*sina))) +
7518 y*cosa*(1 + pow(tx*cosa - ty*sina,2)) + x*sina*(1 + pow(tx*cosa - ty*sina,2))))/
7519 pow(1 + pow(tx*cosa - ty*sina,2),2);
7520
7521 //dDOCAC/ddeltaPhiZ
7522 alignmentDerivatives[FDCTrackD::dDOCAC_dDeltaPhiZ] = (-2*(ty*cosa + tx*sina)*(tx*cosa - ty*sina)*
7523 (-((u - x*cosa + y*sina)*(nr + nz*(tx*cosa - ty*sina) -
7524 (ty*cosa + tx*sina)*(tx*cosa - ty*sina))) +
7525 y*cosa*(1 + pow(tx*cosa - ty*sina,2)) + x*sina*(1 + pow(tx*cosa - ty*sina,2))))/
7526 pow(1 + pow(tx*cosa - ty*sina,2),2) +
7527 (2*y*cosa*(ty*cosa + tx*sina)*(tx*cosa - ty*sina) +
7528 2*x*sina*(ty*cosa + tx*sina)*(tx*cosa - ty*sina) -
7529 (-(y*cosa) - x*sina)*(nr + nz*(tx*cosa - ty*sina) -
7530 (ty*cosa + tx*sina)*(tx*cosa - ty*sina)) -
7531 x*cosa*(1 + pow(tx*cosa - ty*sina,2)) + y*sina*(1 + pow(tx*cosa - ty*sina,2)) -
7532 (u - x*cosa + y*sina)*(nz*(ty*cosa + tx*sina) - pow(ty*cosa + tx*sina,2) -
7533 (tx*cosa - ty*sina)*(-(tx*cosa) + ty*sina)))/(1 + pow(tx*cosa - ty*sina,2));
7534
7535 //dDOCAC/dx
7536 alignmentDerivatives[FDCTrackD::dDOCAC_dx] = (cosa*(nr - tx*ty + nz*tx*cosa) + sina + ty*(ty - nz*cosa)*sina)/
7537 (1 + pow(tx*cosa - ty*sina,2));
7538
7539 //dDOCAC/dy
7540 alignmentDerivatives[FDCTrackD::dDOCAC_dy] = ((1 + pow(tx,2))*cosa - (nr + tx*ty + nz*tx*cosa)*sina + nz*ty*pow(sina,2))/
7541 (1 + pow(tx*cosa - ty*sina,2));
7542
7543 //dDOCAC/dtx
7544 alignmentDerivatives[FDCTrackD::dDOCAC_dtx] = ((u - x*cosa + y*sina)*(4*nr*tx - 2*ty*(pow(tx,2) + pow(ty,2)) + nz*(-4 + 3*pow(tx,2) + pow(ty,2))*cosa +
7545 2*(2*nr*tx + ty*(2 - pow(tx,2) + pow(ty,2)))*cos2a + nz*(tx - ty)*(tx + ty)*cos3a - 2*nz*tx*ty*sina +
7546 4*(tx - nr*ty + tx*pow(ty,2))*sin2a - 2*nz*tx*ty*sin3a))/
7547 pow(2 + pow(tx,2) + pow(ty,2) + (tx - ty)*(tx + ty)*cos2a - 2*tx*ty*sin2a,2);
7548
7549 //dDOCAC/dty
7550 alignmentDerivatives[FDCTrackD::dDOCAC_dty] = -(((u - x*cosa + y*sina)*(-2*(pow(tx,3) + 2*nr*ty + tx*pow(ty,2)) - 2*nz*tx*ty*cosa -
7551 2*(2*tx + pow(tx,3) - 2*nr*ty - tx*pow(ty,2))*cos2a + 2*nz*tx*ty*cos3a +
7552 nz*(-4 + pow(tx,2) + 3*pow(ty,2))*sina + 4*(ty + tx*(nr + tx*ty))*sin2a + nz*(tx - ty)*(tx + ty)*sin3a))
7553 /pow(2 + pow(tx,2) + pow(ty,2) + (tx - ty)*(tx + ty)*cos2a - 2*tx*ty*sin2a,2));
7554
7555 }
7556
7557 if (DEBUG_LEVEL>19 && my_fdchits[id]->hit!=NULL__null){
7558 jout << "Layer " << my_fdchits[id]->hit->wire->layer
7559 <<": t " << drift_time << " x "<< x << " y " << y
7560 << " coordinate along wire " << v << " resi_c " <<resi
7561 << " coordinate transverse to wire " << drift
7562 <<" resi_a " << resi_a
7563 <<endl;
7564 }
7565
7566 double scale=1./sqrt(1.+tx*tx+ty*ty);
7567 double cosThetaRel=0.;
7568 if (my_fdchits[id]->hit!=NULL__null){
7569 my_fdchits[id]->hit->wire->udir.Dot(DVector3(scale*tx,scale*ty,scale));
7570 }
7571 DTrackFitter::pull_t thisPull = pull_t(resi_a,sqrt(V(0,0)),
7572 forward_traj[m].s,
7573 fdc_updates[id].tdrift,
7574 fdc_updates[id].doca,
7575 NULL__null,my_fdchits[id]->hit,
7576 0.,
7577 forward_traj[m].z,
7578 cosThetaRel,0.,
7579 resi,sqrt(V(1,1)));
7580 thisPull.left_right = left_right;
7581 thisPull.AddTrackDerivatives(alignmentDerivatives);
7582 forward_pulls.push_back(thisPull);
7583 }
7584 else{
7585 A=forward_traj[m].Ckk*JT*C.InvertSym();
7586 Ss=forward_traj[m].Skk+A*(Ss-S);
7587 Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose();
7588 }
7589
7590 }
7591 else{
7592 unsigned int id=forward_traj[m].h_id-1000;
7593 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7593<<" "
<< " Smoothing CDC ID " << id << endl;
7594 if (cdc_used_in_fit[id]&&my_cdchits[id]->status==good_hit){
7595 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7595<<" "
<< " Used in fit " << endl;
7596 A=cdc_updates[id].C*JT*C.InvertSym();
7597 Ss=cdc_updates[id].S+A*(Ss-S);
7598 Cs=cdc_updates[id].C+A*(Cs-C)*A.Transpose();
7599 if (!Cs.IsPosDef()){
7600 if (DEBUG_LEVEL>1)
7601 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7601<<" "
<< "Covariance Matrix not PosDef..." << endl;
7602 return VALUE_OUT_OF_RANGE;
7603 }
7604 if (!Ss.IsFinite()){
7605 if (DEBUG_LEVEL>5) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7605<<" "
<< "Invalid values for smoothed parameters..." << endl;
7606 return VALUE_OUT_OF_RANGE;
7607 }
7608
7609 // Fill in pulls information for cdc hits
7610 if(FillPullsVectorEntry(Ss,Cs,forward_traj[m],my_cdchits[id],
7611 cdc_updates[id],forward_pulls) != NOERROR) return VALUE_OUT_OF_RANGE;
7612 }
7613 else{
7614 A=forward_traj[m].Ckk*JT*C.InvertSym();
7615 Ss=forward_traj[m].Skk+A*(Ss-S);
7616 Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose();
7617 }
7618 }
7619 }
7620 else{
7621 A=forward_traj[m].Ckk*JT*C.InvertSym();
7622 Ss=forward_traj[m].Skk+A*(Ss-S);
7623 Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose();
7624 }
7625
7626 S=forward_traj[m].Skk;
7627 C=forward_traj[m].Ckk;
7628 JT=forward_traj[m].J.Transpose();
7629 }
7630
7631 return NOERROR;
7632}
7633
7634// at each step (going in the reverse direction to the filter) based on the
7635// information from all the steps.
7636jerror_t DTrackFitterKalmanSIMD::SmoothCentral(vector<pull_t>&cdc_pulls){
7637 if (central_traj.size()<2) return RESOURCE_UNAVAILABLE;
7638
7639 unsigned int max = central_traj.size()-1;
7640 DMatrix5x1 S=(central_traj[max].Skk);
7641 DMatrix5x5 C=(central_traj[max].Ckk);
7642 DMatrix5x5 JT=central_traj[max].J.Transpose();
7643 DMatrix5x1 Ss=S;
7644 DMatrix5x5 Cs=C;
7645 DMatrix5x5 A,dC;
7646
7647 if (DEBUG_LEVEL>1) {
7648 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7648<<" "
<< " S C JT at start of smoothing " << endl;
7649 S.Print(); C.Print(); JT.Print();
7650 }
7651
7652 for (unsigned int m=max-1;m>0;m--){
7653 if (central_traj[m].h_id>0){
7654 unsigned int id=central_traj[m].h_id-1;
7655 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7655<<" "
<< " Encountered Hit ID " << id << " At trajectory position " << m << "/" << max << endl;
7656 if (cdc_used_in_fit[id] && my_cdchits[id]->status == good_hit){
7657 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7657<<" "
<< " SmoothCentral CDC Hit ID " << id << " used in fit " << endl;
7658
7659 A=cdc_updates[id].C*JT*C.InvertSym();
7660 dC=Cs-C;
7661 Ss=cdc_updates[id].S+A*(Ss-S);
7662 Cs=cdc_updates[id].C+A*dC*A.Transpose();
7663
7664 if (!Ss.IsFinite()){
7665 if (DEBUG_LEVEL>5)
7666 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7666<<" "
<< "Invalid values for smoothed parameters..." << endl;
7667 return VALUE_OUT_OF_RANGE;
7668 }
7669 if (!Cs.IsPosDef()){
7670 if (DEBUG_LEVEL>5){
7671 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<7671<<" "
<< "Covariance Matrix not PosDef... Ckk dC A" << endl;
7672 cdc_updates[id].C.Print(); dC.Print(); A.Print();
7673 }
7674 return VALUE_OUT_OF_RANGE;
7675 }
7676
7677 // Get estimate for energy loss
7678 double q_over_p=Ss(state_q_over_pt)*cos(atan(Ss(state_tanl)));
7679 double dEdx=GetdEdx(q_over_p,central_traj[m].K_rho_Z_over_A,
7680 central_traj[m].rho_Z_over_A,
7681 central_traj[m].LnI,central_traj[m].Z);
7682
7683 // Use Brent's algorithm to find doca to the wire
7684 DVector2 xy(central_traj[m].xy.X()-Ss(state_D)*sin(Ss(state_phi)),
7685 central_traj[m].xy.Y()+Ss(state_D)*cos(Ss(state_phi)));
7686 DVector2 old_xy=xy;
7687 DMatrix5x1 myS=Ss;
7688 double myds;
7689 DVector2 origin=my_cdchits[id]->origin;
7690 DVector2 dir=my_cdchits[id]->dir;
7691 double z0wire=my_cdchits[id]->z0wire;
7692 //BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy,z0wire,origin,dir,myS,myds);
7693 if(BrentCentral(dEdx,xy,z0wire,origin,dir,myS,myds)!=NOERROR) return VALUE_OUT_OF_RANGE;
7694 if(DEBUG_HISTS) alignDerivHists[0]->Fill(myds);
7695 DVector2 wirepos=origin+(myS(state_z)-z0wire)*dir;
7696 double cosstereo=my_cdchits[id]->cosstereo;
7697 DVector2 diff=xy-wirepos;
7698 // here we add a small number to avoid division by zero errors
7699 double d=cosstereo*diff.Mod()+EPS3.0e-8;
7700
7701 // If we are doing the alignment, we need to numerically calculate the derivatives
7702 // wrt the wire origin, direction, and the track parameters.
7703 vector<double> alignmentDerivatives;
7704 if (ALIGNMENT_CENTRAL){
7705 double dscut_min=0., dscut_max=1.;
7706 DVector3 wireDir = my_cdchits[id]->hit->wire->udir;
7707 double cosstereo_shifted;
7708 DMatrix5x1 alignS=Ss; // We will mess with this one
7709 double alignds;
7710 alignmentDerivatives.resize(12);
7711 alignmentDerivatives[CDCTrackD::dDdt0]=cdc_updates[id].dDdt0;
7712 // Wire position shift
7713 double wposShift=0.025;
7714 double wdirShift=0.00005;
7715
7716 // Shift each track parameter value
7717 double shiftFraction=0.01;
7718 double shift_q_over_pt=shiftFraction*Ss(state_q_over_pt);
7719 double shift_phi=0.0001;
7720 double shift_tanl=shiftFraction*Ss(state_tanl);
7721 double shift_D=0.01;
7722 double shift_z=0.01;
7723
7724 // Some data containers we don't need multiples of
7725 double z0_shifted;
7726 DVector2 shift, origin_shifted, dir_shifted, wirepos_shifted, diff_shifted, xy_shifted;
7727
7728 // The DOCA for the shifted states == f(x+h)
7729 double d_dOriginX=0., d_dOriginY=0., d_dOriginZ=0.;
7730 double d_dDirX=0., d_dDirY=0., d_dDirZ=0.;
7731 double d_dS0=0., d_dS1=0., d_dS2=0., d_dS3=0., d_dS4=0.;
7732 // Let's do the wire shifts first
7733
7734 //dOriginX
7735 alignS=Ss;
7736 alignds=0.;
7737 shift.Set(wposShift, 0.);
7738 origin_shifted=origin+shift;
7739 dir_shifted=dir;
7740 z0_shifted=z0wire;
7741 xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
7742 central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
7743 if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted,
7744 dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE;
7745 if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
7746 //if (BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted,
7747 // dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE;
7748 wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted;
7749 diff_shifted=xy_shifted-wirepos_shifted;
7750 d_dOriginX=cosstereo*diff_shifted.Mod()+EPS3.0e-8;
7751 alignmentDerivatives[CDCTrackD::dDOCAdOriginX] = (d_dOriginX - d)/wposShift;
7752 if(DEBUG_HISTS){
7753 alignDerivHists[12]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginX]);
7754 alignDerivHists[1]->Fill(alignds);
7755 brentCheckHists[1]->Fill(alignds,d_dOriginX);
7756 }
7757
7758 //dOriginY
7759 alignS=Ss;
7760 alignds=0.;
7761 shift.Set(0.,wposShift);
7762 origin_shifted=origin+shift;
7763 dir_shifted=dir;
7764 z0_shifted=z0wire;
7765 xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
7766 central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
7767 if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted,
7768 dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE;
7769 if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
7770 //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted,
7771 // dir_shifted,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
7772 wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted;
7773 diff_shifted=xy_shifted-wirepos_shifted;
7774 d_dOriginY=cosstereo*diff_shifted.Mod()+EPS3.0e-8;
7775 alignmentDerivatives[CDCTrackD::dDOCAdOriginY] = (d_dOriginY - d)/wposShift;
7776 if(DEBUG_HISTS){
7777 alignDerivHists[13]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginY]);
7778 alignDerivHists[2]->Fill(alignds);
7779 brentCheckHists[1]->Fill(alignds,d_dOriginY);
7780 }
7781
7782 //dOriginZ
7783 alignS=Ss;
7784 alignds=0.;
7785 origin_shifted=origin;
7786 dir_shifted=dir;
7787 z0_shifted=z0wire+wposShift;
7788 xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
7789 central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
7790 if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted,
7791 dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE;
7792 if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
7793 //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted,
7794 // dir_shifted,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
7795 wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted;
7796 diff_shifted=xy_shifted-wirepos_shifted;
7797 d_dOriginZ=cosstereo*diff_shifted.Mod()+EPS3.0e-8;
7798 alignmentDerivatives[CDCTrackD::dDOCAdOriginZ] = (d_dOriginZ - d)/wposShift;
7799 if(DEBUG_HISTS){
7800 alignDerivHists[14]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginZ]);
7801 alignDerivHists[3]->Fill(alignds);
7802 brentCheckHists[1]->Fill(alignds,d_dOriginZ);
7803 }
7804
7805 //dDirX
7806 alignS=Ss;
7807 alignds=0.;
7808 shift.Set(wdirShift,0.);
7809 origin_shifted=origin;
7810 z0_shifted=z0wire;
7811 xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
7812 central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
7813 dir_shifted=dir+shift;
7814 cosstereo_shifted = cos((wireDir+DVector3(wdirShift,0.,0.)).Angle(DVector3(0.,0.,1.)));
7815 if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted,
7816 dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE;
7817 if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
7818 //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted,
7819 // dir_shifted,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
7820 wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted;
7821 diff_shifted=xy_shifted-wirepos_shifted;
7822 d_dDirX=cosstereo_shifted*diff_shifted.Mod()+EPS3.0e-8;
7823 alignmentDerivatives[CDCTrackD::dDOCAdDirX] = (d_dDirX - d)/wdirShift;
7824 if(DEBUG_HISTS){
7825 alignDerivHists[15]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirX]);
7826 alignDerivHists[4]->Fill(alignds);
7827 }
7828
7829 //dDirY
7830 alignS=Ss;
7831 alignds=0.;
7832 shift.Set(0.,wdirShift);
7833 origin_shifted=origin;
7834 z0_shifted=z0wire;
7835 xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
7836 central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
7837 dir_shifted=dir+shift;
7838 cosstereo_shifted = cos((wireDir+DVector3(0.,wdirShift,0.)).Angle(DVector3(0.,0.,1.)));
7839 if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted,
7840 dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE;
7841 if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
7842 //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted,
7843 // dir_shifted,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
7844 wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted;
7845 diff_shifted=xy_shifted-wirepos_shifted;
7846 d_dDirY=cosstereo_shifted*diff_shifted.Mod()+EPS3.0e-8;
7847 alignmentDerivatives[CDCTrackD::dDOCAdDirY] = (d_dDirY - d)/wdirShift;
7848 if(DEBUG_HISTS){
7849 alignDerivHists[16]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirY]);
7850 alignDerivHists[5]->Fill(alignds);
7851 }
7852
7853 //dDirZ
7854 alignS=Ss;
7855 alignds=0.;
7856 origin_shifted=origin;
7857 dir_shifted.Set(wireDir.X()/(wireDir.Z()+wdirShift), wireDir.Y()/(wireDir.Z()+wdirShift));
7858 z0_shifted=z0wire;
7859 xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
7860 central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
7861 cosstereo_shifted = cos((wireDir+DVector3(0.,0.,wdirShift)).Angle(DVector3(0.,0.,1.)));
7862 if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted,
7863 dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE;
7864 if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
7865 //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted,
7866 // dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE;
7867 wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted;
7868 diff_shifted=xy_shifted-wirepos_shifted;
7869 d_dDirZ=cosstereo_shifted*diff_shifted.Mod()+EPS3.0e-8;
7870 alignmentDerivatives[CDCTrackD::dDOCAdDirZ] = (d_dDirZ - d)/wdirShift;
7871 if(DEBUG_HISTS){
7872 alignDerivHists[17]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirZ]);
7873 alignDerivHists[6]->Fill(alignds);
7874 }
7875
7876 // And now the derivatives wrt the track parameters
7877 //DMatrix5x1 trackShift(shift_q_over_pt, shift_phi, shift_tanl, shift_D, shift_z);
7878
7879 DMatrix5x1 trackShiftS0(shift_q_over_pt, 0., 0., 0., 0.);
7880 DMatrix5x1 trackShiftS1(0., shift_phi, 0., 0., 0.);
7881 DMatrix5x1 trackShiftS2(0., 0., shift_tanl, 0., 0.);
7882 DMatrix5x1 trackShiftS3(0., 0., 0., shift_D, 0.);
7883 DMatrix5x1 trackShiftS4(0., 0., 0., 0., shift_z);
7884
7885 // dS0
7886 alignS=Ss+trackShiftS0;
7887 alignds=0.;
7888 xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
7889 central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
7890 if(BrentCentral(dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
7891 if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
7892 //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
7893 wirepos_shifted=origin+(alignS(state_z)-z0wire)*dir;
7894 diff_shifted=xy_shifted-wirepos_shifted;
7895 d_dS0=cosstereo*diff_shifted.Mod()+EPS3.0e-8;
7896 alignmentDerivatives[CDCTrackD::dDOCAdS0] = (d_dS0 - d)/shift_q_over_pt;
7897 if(DEBUG_HISTS){
7898 alignDerivHists[18]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS0]);
7899 alignDerivHists[7]->Fill(alignds);
7900 }
7901
7902 // dS1
7903 alignS=Ss+trackShiftS1;
7904 alignds=0.;
7905 xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
7906 central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
7907 if(BrentCentral(dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
7908 if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
7909 //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
7910 wirepos_shifted=origin+(alignS(state_z)-z0wire)*dir;
7911 diff_shifted=xy_shifted-wirepos_shifted;
7912 d_dS1=cosstereo*diff_shifted.Mod()+EPS3.0e-8;
7913 alignmentDerivatives[CDCTrackD::dDOCAdS1] = (d_dS1 - d)/shift_phi;
7914 if(DEBUG_HISTS){
7915 alignDerivHists[19]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS1]);
7916 alignDerivHists[8]->Fill(alignds);
7917 }
7918
7919 // dS2
7920 alignS=Ss+trackShiftS2;
7921 alignds=0.;
7922 xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
7923 central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
7924 if(BrentCentral(dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
7925 if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
7926 //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
7927 wirepos_shifted=origin+(alignS(state_z)-z0wire)*dir;
7928 diff_shifted=xy_shifted-wirepos_shifted;
7929 d_dS2=cosstereo*diff_shifted.Mod()+EPS3.0e-8;
7930 alignmentDerivatives[CDCTrackD::dDOCAdS2] = (d_dS2 - d)/shift_tanl;
7931 if(DEBUG_HISTS){
7932 alignDerivHists[20]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS2]);
7933 alignDerivHists[9]->Fill(alignds);
7934 }
7935
7936 // dS3
7937 alignS=Ss+trackShiftS3;
7938 alignds=0.;
7939 xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
7940 central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
7941 if(BrentCentral(dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
7942 if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
7943 //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
7944 wirepos_shifted=origin+(alignS(state_z)-z0wire)*dir;
7945 diff_shifted=xy_shifted-wirepos_shifted;
7946 d_dS3=cosstereo*diff_shifted.Mod()+EPS3.0e-8;
7947 alignmentDerivatives[CDCTrackD::dDOCAdS3] = (d_dS3 - d)/shift_D;
7948 if(DEBUG_HISTS){
7949 alignDerivHists[21]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS3]);
7950 alignDerivHists[10]->Fill(alignds);
7951 }
7952
7953 // dS4
7954 alignS=Ss+trackShiftS4;
7955 alignds=0.;
7956 xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)),
7957 central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi)));
7958 if(BrentCentral(dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
7959 if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE;
7960 //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE;
7961 wirepos_shifted=origin+(alignS(state_z)-z0wire)*dir;
7962 diff_shifted=xy_shifted-wirepos_shifted;
7963 d_dS4=cosstereo*diff_shifted.Mod()+EPS3.0e-8;
7964 alignmentDerivatives[CDCTrackD::dDOCAdS4] = (d_dS4 - d)/shift_z;
7965 if(DEBUG_HISTS){
7966 alignDerivHists[22]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS4]);
7967 alignDerivHists[11]->Fill(alignds);
7968 }
7969 }
7970
7971 // Compute the Jacobian matrix
7972 // Find the field and gradient at (old_x,old_y,old_z)
7973 bfield->GetFieldAndGradient(old_xy.X(),old_xy.Y(),Ss(state_z),
7974 Bx,By,Bz,
7975 dBxdx,dBxdy,dBxdz,dBydx,
7976 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
7977 DMatrix5x5 Jc;
7978 StepJacobian(old_xy,xy-old_xy,myds,Ss,dEdx,Jc);
7979
7980 // Projection matrix
7981 DMatrix5x1 H_T;
7982 double sinphi=sin(myS(state_phi));
7983 double cosphi=cos(myS(state_phi));
7984 double dx=diff.X();
7985 double dy=diff.Y();
7986 double cosstereo2_over_doca=cosstereo*cosstereo/d;
7987 H_T(state_D)=(dy*cosphi-dx*sinphi)*cosstereo2_over_doca;
7988 H_T(state_phi)
7989 =-myS(state_D)*cosstereo2_over_doca*(dx*cosphi+dy*sinphi);
7990 H_T(state_z)=-cosstereo2_over_doca*(dx*dir.X()+dy*dir.Y());
7991 DMatrix1x5 H;
7992 H(state_D)=H_T(state_D);
7993 H(state_phi)=H_T(state_phi);
7994 H(state_z)=H_T(state_z);
7995
7996 double Vhit=cdc_updates[id].variance;
7997 Cs=Jc*Cs*Jc.Transpose();
7998 //double Vtrack = Cs.SandwichMultiply(Jc*H_T);
7999 double Vtrack=H*Cs*H_T;
8000 double VRes;
8001
8002 bool skip_ring=(my_cdchits[id]->hit->wire->ring==RING_TO_SKIP);
8003 if (skip_ring) VRes = Vhit + Vtrack;
8004 else VRes = Vhit - Vtrack;
8005
8006 if (DEBUG_LEVEL>1 && (!isfinite(VRes) || VRes < 0.0) ) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<8006<<" "
<< " SmoothCentral Problem: VRes is " << VRes << " = " << Vhit << " - " << Vtrack << endl;
8007
8008 double lambda=atan(Ss(state_tanl));
8009 double sinl=sin(lambda);
8010 double cosl=cos(lambda);
8011 double cosThetaRel=my_cdchits[id]->hit->wire->udir.Dot(DVector3(cosphi*cosl,
8012 sinphi*cosl,
8013 sinl));
8014 pull_t thisPull(cdc_updates[id].doca-d,sqrt(VRes),
8015 central_traj[m].s,cdc_updates[id].tdrift,
8016 d,my_cdchits[id]->hit,NULL__null,
8017 diff.Phi(),myS(state_z),cosThetaRel,
8018 cdc_updates[id].tcorr);
8019
8020 thisPull.AddTrackDerivatives(alignmentDerivatives);
8021 cdc_pulls.push_back(thisPull);
8022 }
8023 else{
8024 A=central_traj[m].Ckk*JT*C.InvertSym();
8025 Ss=central_traj[m].Skk+A*(Ss-S);
8026 Cs=central_traj[m].Ckk+A*(Cs-C)*A.Transpose();
8027 }
8028 }
8029 else{
8030 A=central_traj[m].Ckk*JT*C.InvertSym();
8031 Ss=central_traj[m].Skk+A*(Ss-S);
8032 Cs=central_traj[m].Ckk+A*(Cs-C)*A.Transpose();
8033 }
8034 S=central_traj[m].Skk;
8035 C=central_traj[m].Ckk;
8036 JT=central_traj[m].J.Transpose();
8037 }
8038
8039 // ... last entries?
8040 // Don't really need since we should have already encountered all of the hits
8041
8042 return NOERROR;
8043
8044}
8045
8046// Smoothing algorithm for the forward_traj_cdc trajectory.
8047// Updates the state vector
8048// at each step (going in the reverse direction to the filter) based on the
8049// information from all the steps and outputs the state vector at the
8050// outermost step.
8051jerror_t DTrackFitterKalmanSIMD::SmoothForwardCDC(vector<pull_t>&cdc_pulls){
8052 if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE;
8053
8054 unsigned int max=forward_traj.size()-1;
8055 DMatrix5x1 S=(forward_traj[max].Skk);
8056 DMatrix5x5 C=(forward_traj[max].Ckk);
8057 DMatrix5x5 JT=forward_traj[max].J.Transpose();
8058 DMatrix5x1 Ss=S;
8059 DMatrix5x5 Cs=C;
8060 DMatrix5x5 A;
8061 for (unsigned int m=max-1;m>0;m--){
8062 if (forward_traj[m].h_id>999){
8063 unsigned int cdc_index=forward_traj[m].h_id-1000;
8064 if(cdc_used_in_fit[cdc_index] && my_cdchits[cdc_index]->status == good_hit){
8065 if (DEBUG_LEVEL > 5) {
8066 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<8066<<" "
<< " Smoothing CDC index " << cdc_index << " ring " << my_cdchits[cdc_index]->hit->wire->ring
8067 << " straw " << my_cdchits[cdc_index]->hit->wire->straw << endl;
8068 }
8069
8070 A=cdc_updates[cdc_index].C*JT*C.InvertSym();
8071 Ss=cdc_updates[cdc_index].S+A*(Ss-S);
8072 if (!Ss.IsFinite()){
8073 if (DEBUG_LEVEL>5)
8074 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<8074<<" "
<< "Invalid values for smoothed parameters..." << endl;
8075 return VALUE_OUT_OF_RANGE;
8076 }
8077
8078 Cs=cdc_updates[cdc_index].C+A*(Cs-C)*A.Transpose();
8079
8080 if (!Cs.IsPosDef()){
8081 if (DEBUG_LEVEL>5){
8082 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<8082<<" "
<< "Covariance Matrix not Pos Def..." << endl;
8083 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<8083<<" "
<< " cdc_updates[cdc_index].C A C_ Cs " << endl;
8084 cdc_updates[cdc_index].C.Print();
8085 A.Print();
8086 C.Print();
8087 Cs.Print();
8088 }
8089 return VALUE_OUT_OF_RANGE;
8090 }
8091 if(FillPullsVectorEntry(Ss,Cs,forward_traj[m],my_cdchits[cdc_index],
8092 cdc_updates[cdc_index],cdc_pulls) != NOERROR) return VALUE_OUT_OF_RANGE;
8093
8094 }
8095 else{
8096 A=forward_traj[m].Ckk*JT*C.InvertSym();
8097 Ss=forward_traj[m].Skk+A*(Ss-S);
8098 Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose();
8099 }
8100 }
8101 else{
8102 A=forward_traj[m].Ckk*JT*C.InvertSym();
8103 Ss=forward_traj[m].Skk+A*(Ss-S);
8104 Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose();
8105 }
8106
8107 S=forward_traj[m].Skk;
8108 C=forward_traj[m].Ckk;
8109 JT=forward_traj[m].J.Transpose();
8110 }
8111
8112 return NOERROR;
8113}
8114
8115// Fill the pulls vector with the best residual information using the smoothed
8116// filter results. Uses Brent's algorithm to find the distance of closest
8117// approach to the wire hit.
8118jerror_t DTrackFitterKalmanSIMD::FillPullsVectorEntry(const DMatrix5x1 &Ss,
8119 const DMatrix5x5 &Cs,
8120 const DKalmanForwardTrajectory_t &traj,const DKalmanSIMDCDCHit_t *hit,const DKalmanUpdate_t &update,
8121 vector<pull_t>&my_pulls){
8122
8123 // Get estimate for energy loss
8124 double dEdx=GetdEdx(Ss(state_q_over_p),traj.K_rho_Z_over_A,traj.rho_Z_over_A,
8125 traj.LnI,traj.Z);
8126
8127 // Use Brent's algorithm to find the doca to the wire
8128 DMatrix5x1 myS=Ss;
8129 DMatrix5x1 myS_temp=Ss;
8130 DMatrix5x5 myC=Cs;
8131 double mydz;
8132 double z=traj.z;
8133 DVector2 origin=hit->origin;
8134 DVector2 dir=hit->dir;
8135 double z0wire=hit->z0wire;
8136 if(BrentForward(z,dEdx,z0wire,origin,dir,myS,mydz) != NOERROR) return VALUE_OUT_OF_RANGE;
8137 if(DEBUG_HISTS)alignDerivHists[23]->Fill(mydz);
8138 double new_z=z+mydz;
8139 DVector2 wirepos=origin+(new_z-z0wire)*dir;
8140 double cosstereo=hit->cosstereo;
8141 DVector2 xy(myS(state_x),myS(state_y));
8142
8143 DVector2 diff=xy-wirepos;
8144 double d=cosstereo*diff.Mod();
8145
8146 // If we are doing the alignment, we need to numerically calculate the derivatives
8147 // wrt the wire origin, direction, and the track parameters.
8148 vector<double> alignmentDerivatives;
8149 if (ALIGNMENT_FORWARD && hit->hit!=NULL__null){
8150 double dzcut_min=0., dzcut_max=1.;
8151 DMatrix5x1 alignS=Ss; // We will mess with this one
8152 DVector3 wireDir = hit->hit->wire->udir;
8153 double cosstereo_shifted;
8154 double aligndz;
8155 alignmentDerivatives.resize(12);
8156
8157 // Set t0 derivative
8158 alignmentDerivatives[CDCTrackD::dDdt0]=update.dDdt0;
8159
8160 // Wire position shift
8161 double wposShift=0.025;
8162 double wdirShift=0.00005;
8163
8164 // Shift each track parameter
8165 double shiftFraction=0.01;
8166 double shift_x=0.01;
8167 double shift_y=0.01;
8168 double shift_tx=shiftFraction*Ss(state_tx);
8169 double shift_ty=shiftFraction*Ss(state_ty);;
8170 double shift_q_over_p=shiftFraction*Ss(state_q_over_p);
8171
8172 // Some data containers we don't need multiples of
8173 double z0_shifted, new_z_shifted;
8174 DVector2 shift, origin_shifted, dir_shifted, wirepos_shifted, diff_shifted, xy_shifted;
8175
8176 // The DOCA for the shifted states == f(x+h)
8177 double d_dOriginX=0., d_dOriginY=0., d_dOriginZ=0.;
8178 double d_dDirX=0., d_dDirY=0., d_dDirZ=0.;
8179 double d_dS0=0., d_dS1=0., d_dS2=0., d_dS3=0., d_dS4=0.;
8180 // Let's do the wire shifts first
8181
8182 //dOriginX
8183 alignS=Ss;
8184 aligndz=0.;
8185 shift.Set(wposShift, 0.);
8186 origin_shifted=origin+shift;
8187 dir_shifted=dir;
8188 z0_shifted=z0wire;
8189 if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8190 if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8191 //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8192 new_z_shifted=z+aligndz;
8193 wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted;
8194 xy_shifted.Set(alignS(state_x),alignS(state_y));
8195 diff_shifted=xy_shifted-wirepos_shifted;
8196 d_dOriginX=cosstereo*diff_shifted.Mod()+EPS3.0e-8;
8197 alignmentDerivatives[CDCTrackD::dDOCAdOriginX] = (d_dOriginX - d)/wposShift;
8198 if(DEBUG_HISTS){
8199 alignDerivHists[24]->Fill(aligndz);
8200 alignDerivHists[35]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginX]);
8201 brentCheckHists[0]->Fill(aligndz,d_dOriginX);
8202 }
8203
8204 //dOriginY
8205 alignS=Ss;
8206 aligndz=0.;
8207 shift.Set(0.,wposShift);
8208 origin_shifted=origin+shift;
8209 dir_shifted=dir;
8210 z0_shifted=z0wire;
8211 if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8212 if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8213 //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8214 new_z_shifted=z+aligndz;
8215 wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted;
8216 xy_shifted.Set(alignS(state_x),alignS(state_y));
8217 diff_shifted=xy_shifted-wirepos_shifted;
8218 d_dOriginY=cosstereo*diff_shifted.Mod()+EPS3.0e-8;
8219 alignmentDerivatives[CDCTrackD::dDOCAdOriginY] = (d_dOriginY - d)/wposShift;
8220 if(DEBUG_HISTS){
8221 alignDerivHists[25]->Fill(aligndz);
8222 alignDerivHists[36]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginY]);
8223 brentCheckHists[0]->Fill(aligndz,d_dOriginY);
8224 }
8225
8226 //dOriginZ
8227 alignS=Ss;
8228 aligndz=0.;
8229 origin_shifted=origin;
8230 dir_shifted=dir;
8231 z0_shifted=z0wire+wposShift;
8232 if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8233 if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8234 //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8235 new_z_shifted=z+aligndz;
8236 wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted;
8237 xy_shifted.Set(alignS(state_x),alignS(state_y));
8238 diff_shifted=xy_shifted-wirepos_shifted;
8239 d_dOriginZ=cosstereo*diff_shifted.Mod()+EPS3.0e-8;
8240 alignmentDerivatives[CDCTrackD::dDOCAdOriginZ] = (d_dOriginZ - d)/wposShift;
8241 if(DEBUG_HISTS){
8242 alignDerivHists[26]->Fill(aligndz);
8243 alignDerivHists[37]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginZ]);
8244 brentCheckHists[0]->Fill(aligndz,d_dOriginZ);
8245 }
8246
8247 //dDirX
8248 alignS=Ss;
8249 aligndz=0.;
8250 shift.Set(wdirShift,0.);
8251 origin_shifted=origin;
8252 z0_shifted=z0wire;
8253 dir_shifted=dir+shift;
8254 cosstereo_shifted = cos((wireDir+DVector3(wdirShift,0.,0.)).Angle(DVector3(0.,0.,1.)));
8255 if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8256 if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8257 //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8258 new_z_shifted=z+aligndz;
8259 wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted;
8260 xy_shifted.Set(alignS(state_x),alignS(state_y));
8261 diff_shifted=xy_shifted-wirepos_shifted;
8262 d_dDirX=cosstereo_shifted*diff_shifted.Mod()+EPS3.0e-8;
8263 alignmentDerivatives[CDCTrackD::dDOCAdDirX] = (d_dDirX - d)/wdirShift;
8264 if(DEBUG_HISTS){
8265 alignDerivHists[27]->Fill(aligndz);
8266 alignDerivHists[38]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirX]);
8267 }
8268
8269 //dDirY
8270 alignS=Ss;
8271 aligndz=0.;
8272 shift.Set(0.,wdirShift);
8273 origin_shifted=origin;
8274 z0_shifted=z0wire;
8275 dir_shifted=dir+shift;
8276 cosstereo_shifted = cos((wireDir+DVector3(0.,wdirShift,0.)).Angle(DVector3(0.,0.,1.)));
8277 if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8278 if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8279 //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8280 new_z_shifted=z+aligndz;
8281 wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted;
8282 xy_shifted.Set(alignS(state_x),alignS(state_y));
8283 diff_shifted=xy_shifted-wirepos_shifted;
8284 d_dDirY=cosstereo_shifted*diff_shifted.Mod()+EPS3.0e-8;
8285 alignmentDerivatives[CDCTrackD::dDOCAdDirY] = (d_dDirY - d)/wdirShift;
8286 if(DEBUG_HISTS){
8287 alignDerivHists[28]->Fill(aligndz);
8288 alignDerivHists[39]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirY]);
8289 }
8290
8291 //dDirZ - This is divided out in this code
8292 alignS=Ss;
8293 aligndz=0.;
8294 origin_shifted=origin;
8295 dir_shifted.Set(wireDir.X()/(wireDir.Z()+wdirShift), wireDir.Y()/(wireDir.Z()+wdirShift));
8296 z0_shifted=z0wire;
8297 cosstereo_shifted = cos((wireDir+DVector3(0.,0.,wdirShift)).Angle(DVector3(0.,0.,1.)));
8298 if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8299 if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8300 //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8301 new_z_shifted=z+aligndz;
8302 wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted;
8303 xy_shifted.Set(alignS(state_x),alignS(state_y));
8304 diff_shifted=xy_shifted-wirepos_shifted;
8305 d_dDirZ=cosstereo_shifted*diff_shifted.Mod()+EPS3.0e-8;
8306 alignmentDerivatives[CDCTrackD::dDOCAdDirZ] = (d_dDirZ - d)/wdirShift;
8307 if(DEBUG_HISTS){
8308 alignDerivHists[29]->Fill(aligndz);
8309 alignDerivHists[40]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirZ]);
8310 }
8311
8312 // And now the derivatives wrt the track parameters
8313
8314 DMatrix5x1 trackShiftS0(shift_x, 0., 0., 0., 0.);
8315 DMatrix5x1 trackShiftS1(0., shift_y, 0., 0., 0.);
8316 DMatrix5x1 trackShiftS2(0., 0., shift_tx, 0., 0.);
8317 DMatrix5x1 trackShiftS3(0., 0., 0., shift_ty, 0.);
8318 DMatrix5x1 trackShiftS4(0., 0., 0., 0., shift_q_over_p);
8319
8320 // dS0
8321 alignS=Ss+trackShiftS0;
8322 aligndz=0.;
8323 if(BrentForward(z,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8324 if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8325 //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8326 new_z_shifted=z+aligndz;
8327 wirepos_shifted=origin+(new_z_shifted-z0wire)*dir;
8328 xy_shifted.Set(alignS(state_x),alignS(state_y));
8329 diff_shifted=xy_shifted-wirepos_shifted;
8330 d_dS0=cosstereo*diff_shifted.Mod()+EPS3.0e-8;
8331 alignmentDerivatives[CDCTrackD::dDOCAdS0] = (d_dS0 - d)/shift_x;
8332 if(DEBUG_HISTS){
8333 alignDerivHists[30]->Fill(aligndz);
8334 alignDerivHists[41]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS0]);
8335 }
8336
8337 // dS1
8338 alignS=Ss+trackShiftS1;
8339 aligndz=0.;
8340 if(BrentForward(z,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8341 if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8342 //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8343 new_z_shifted=z+aligndz;
8344 wirepos_shifted=origin+(new_z_shifted-z0wire)*dir;
8345 xy_shifted.Set(alignS(state_x),alignS(state_y));
8346 diff_shifted=xy_shifted-wirepos_shifted;
8347 d_dS1=cosstereo*diff_shifted.Mod()+EPS3.0e-8;
8348 alignmentDerivatives[CDCTrackD::dDOCAdS1] = (d_dS1 - d)/shift_y;
8349 if(DEBUG_HISTS){
8350 alignDerivHists[31]->Fill(aligndz);
8351 alignDerivHists[42]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS1]);
8352 }
8353
8354 // dS2
8355 alignS=Ss+trackShiftS2;
8356 aligndz=0.;
8357 if(BrentForward(z,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8358 if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8359 //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8360 new_z_shifted=z+aligndz;
8361 wirepos_shifted=origin+(new_z_shifted-z0wire)*dir;
8362 xy_shifted.Set(alignS(state_x),alignS(state_y));
8363 diff_shifted=xy_shifted-wirepos_shifted;
8364 d_dS2=cosstereo*diff_shifted.Mod()+EPS3.0e-8;
8365 alignmentDerivatives[CDCTrackD::dDOCAdS2] = (d_dS2 - d)/shift_tx;
8366 if(DEBUG_HISTS){
8367 alignDerivHists[32]->Fill(aligndz);
8368 alignDerivHists[43]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS2]);
8369 }
8370
8371 // dS3
8372 alignS=Ss+trackShiftS3;
8373 aligndz=0.;
8374 if(BrentForward(z,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8375 if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8376 //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8377 new_z_shifted=z+aligndz;
8378 wirepos_shifted=origin+(new_z_shifted-z0wire)*dir;
8379 xy_shifted.Set(alignS(state_x),alignS(state_y));
8380 diff_shifted=xy_shifted-wirepos_shifted;
8381 d_dS3=cosstereo*diff_shifted.Mod()+EPS3.0e-8;
8382 alignmentDerivatives[CDCTrackD::dDOCAdS3] = (d_dS3 - d)/shift_ty;
8383 if(DEBUG_HISTS){
8384 alignDerivHists[33]->Fill(aligndz);
8385 alignDerivHists[44]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS3]);
8386 }
8387
8388 // dS4
8389 alignS=Ss+trackShiftS4;
8390 aligndz=0.;
8391 if(BrentForward(z,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8392 if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE;
8393 //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE;
8394 new_z_shifted=z+aligndz;
8395 wirepos_shifted=origin+(new_z_shifted-z0wire)*dir;
8396 xy_shifted.Set(alignS(state_x),alignS(state_y));
8397 diff_shifted=xy_shifted-wirepos_shifted;
8398 d_dS4=cosstereo*diff_shifted.Mod()+EPS3.0e-8;
8399 alignmentDerivatives[CDCTrackD::dDOCAdS4] = (d_dS4 - d)/shift_q_over_p;
8400 if(DEBUG_HISTS){
8401 alignDerivHists[34]->Fill(aligndz);
8402 alignDerivHists[45]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS4]);
8403 }
8404 }
8405
8406 // Find the field and gradient at (old_x,old_y,old_z) and compute the
8407 // Jacobian matrix for transforming from S to myS
8408 bfield->GetFieldAndGradient(Ss(state_x),Ss(state_y),z,
8409 Bx,By,Bz,dBxdx,dBxdy,dBxdz,dBydx,
8410 dBydy,dBydz,dBzdx,dBzdy,dBzdz);
8411 DMatrix5x5 Jc;
8412 StepJacobian(z,new_z,Ss,dEdx,Jc);
8413
8414 // Find the projection matrix
8415 DMatrix5x1 H_T;
8416 double cosstereo2_over_d=cosstereo*cosstereo/d;
8417 H_T(state_x)=diff.X()*cosstereo2_over_d;
8418 H_T(state_y)=diff.Y()*cosstereo2_over_d;
8419 DMatrix1x5 H;
8420 H(state_x)=H_T(state_x);
8421 H(state_y)=H_T(state_y);
8422
8423 // Find the variance for this hit
8424
8425 bool skip_ring=(hit->hit->wire->ring==RING_TO_SKIP);
8426
8427 double V=update.variance;
8428 myC=Jc*myC*Jc.Transpose();
8429 if (skip_ring) V+=H*myC*H_T;
8430 else V-=H*myC*H_T;
8431
8432 if (DEBUG_LEVEL>1 && (!isfinite(V) || V < 0.0) ) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<8432<<" "
<< " Problem: V is " << V << endl;
8433
8434 double tx=Ss(state_tx);
8435 double ty=Ss(state_ty);
8436 double scale=1./sqrt(1.+tx*tx+ty*ty);
8437 double cosThetaRel=hit->hit->wire->udir.Dot(DVector3(scale*tx,scale*ty,scale));
8438
8439 pull_t thisPull(update.doca-d,sqrt(V),traj.s,update.tdrift,d,hit->hit,
8440 NULL__null,diff.Phi(),new_z,cosThetaRel,update.tcorr);
8441 thisPull.AddTrackDerivatives(alignmentDerivatives);
8442 my_pulls.push_back(thisPull);
8443 return NOERROR;
8444}
8445
8446// Transform the 5x5 covariance matrix from the forward parametrization to the
8447// central parametrization.
8448void DTrackFitterKalmanSIMD::TransformCovariance(DMatrix5x5 &C){
8449 DMatrix5x5 J;
8450 double tsquare=tx_*tx_+ty_*ty_;
8451 double cosl=cos(atan(tanl_));
8452 double tanl2=tanl_*tanl_;
8453 double tanl3=tanl2*tanl_;
8454 double factor=1./sqrt(1.+tsquare);
8455 J(state_z,state_x)=tx_/tsquare;
8456 J(state_z,state_y)=ty_/tsquare;
8457 double diff=tx_*tx_-ty_*ty_;
8458 double frac=1./(tsquare*tsquare);
8459 J(state_z,state_tx)=-(x_*diff+2.*tx_*ty_*y_)*frac;
8460 J(state_z,state_ty)=-(2.*tx_*ty_*x_-y_*diff)*frac;
8461 J(state_tanl,state_tx)=-tx_*tanl3;
8462 J(state_tanl,state_ty)=-ty_*tanl3;
8463 J(state_q_over_pt,state_q_over_p)=1./cosl;
8464 J(state_q_over_pt,state_tx)=-q_over_p_*tx_*tanl3*factor;
8465 J(state_q_over_pt,state_ty)=-q_over_p_*ty_*tanl3*factor;
8466 J(state_phi,state_tx)=-ty_*tanl2;
8467 J(state_phi,state_ty)=tx_*tanl2;
8468 J(state_D,state_x)=x_/D_;
8469 J(state_D,state_y)=y_/D_;
8470
8471 C=J*C*J.Transpose();
8472
8473}
8474
8475jerror_t DTrackFitterKalmanSIMD::BrentForward(double z, double dedx, const double z0w,
8476 const DVector2 &origin, const DVector2 &dir, DMatrix5x1 &S, double &dz){
8477
8478 DVector2 wirepos=origin;
8479 wirepos+=(z-z0w)*dir;
8480 double dx=S(state_x)-wirepos.X();
8481 double dy=S(state_y)-wirepos.Y();
8482 double doca2 = dx*dx+dy*dy;
8483
8484 if (BrentsAlgorithm(z,-mStepSizeZ,dedx,z0w,origin,dir,S,dz)!=NOERROR){
8485 return VALUE_OUT_OF_RANGE;
8486 }
8487
8488 double newz = z+dz;
8489 unsigned int maxSteps=5;
8490 unsigned int stepCounter=0;
8491 if (fabs(dz)<EPS31.e-2){
8492 // doca
8493 double old_doca2=doca2;
8494
8495 double ztemp=newz;
8496 newz=ztemp-mStepSizeZ;
8497 Step(ztemp,newz,dedx,S);
8498 // new wire position
8499 wirepos=origin;
8500 wirepos+=(newz-z0w)*dir;
8501
8502 dx=S(state_x)-wirepos.X();
8503 dy=S(state_y)-wirepos.Y();
8504 doca2=dx*dx+dy*dy;
8505 ztemp=newz;
8506
8507 while(doca2<old_doca2 && stepCounter<maxSteps){
8508 newz=ztemp-mStepSizeZ;
8509 old_doca2=doca2;
8510
8511 // Step to the new z position
8512 Step(ztemp,newz,dedx,S);
8513 stepCounter++;
8514
8515 // find the new distance to the wire
8516 wirepos=origin;
8517 wirepos+=(newz-z0w)*dir;
8518
8519 dx=S(state_x)-wirepos.X();
8520 dy=S(state_y)-wirepos.Y();
8521 doca2=dx*dx+dy*dy;
8522
8523 ztemp=newz;
8524 }
8525
8526 // Find the true doca
8527 double dz2=0.;
8528 if (BrentsAlgorithm(newz,-mStepSizeZ,dedx,z0w,origin,dir,S,dz2)!=NOERROR){
8529 return VALUE_OUT_OF_RANGE;
8530 }
8531 newz=ztemp+dz2;
8532
8533 // Change in z relative to where we started for this wire
8534 dz=newz-z;
8535 }
8536 else if (fabs(dz)>2.*mStepSizeZ-EPS31.e-2){
8537 // whoops, looks like we didn't actually bracket the minimum
8538 // after all. Swim to make sure we pass the minimum doca.
8539
8540 double ztemp=newz;
8541 // new wire position
8542 wirepos=origin;
8543 wirepos+=(ztemp-z0w)*dir;
8544
8545 // doca
8546 double old_doca2=doca2;
8547
8548 dx=S(state_x)-wirepos.X();
8549 dy=S(state_y)-wirepos.Y();
8550 doca2=dx*dx+dy*dy;
8551
8552 while(doca2<old_doca2 && stepCounter<10*maxSteps){
8553 newz=ztemp+mStepSizeZ;
8554 old_doca2=doca2;
8555
8556 // Step to the new z position
8557 Step(ztemp,newz,dedx,S);
8558 stepCounter++;
8559
8560 // find the new distance to the wire
8561 wirepos=origin;
8562 wirepos+=(newz-z0w)*dir;
8563
8564 dx=S(state_x)-wirepos.X();
8565 dy=S(state_y)-wirepos.Y();
8566 doca2=dx*dx+dy*dy;
8567
8568 ztemp=newz;
8569 }
8570
8571 // Find the true doca
8572 double dz2=0.;
8573 if (BrentsAlgorithm(newz,mStepSizeZ,dedx,z0w,origin,dir,S,dz2)!=NOERROR){
8574 return VALUE_OUT_OF_RANGE;
8575 }
8576 newz=ztemp+dz2;
8577
8578 // Change in z relative to where we started for this wire
8579 dz=newz-z;
8580 }
8581 return NOERROR;
8582}
8583
8584jerror_t DTrackFitterKalmanSIMD::BrentCentral(double dedx, DVector2 &xy, const double z0w, const DVector2 &origin, const DVector2 &dir, DMatrix5x1 &Sc, double &ds){
8585
8586 DVector2 wirexy=origin;
8587 wirexy+=(Sc(state_z)-z0w)*dir;
8588
8589 // new doca
8590 double doca2=(xy-wirexy).Mod2();
8591 double old_doca2=doca2;
8592
8593 if (BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dedx,xy,z0w,
8594 origin,dir,Sc,ds)!=NOERROR){
8595 return VALUE_OUT_OF_RANGE;
8596 }
8597
8598 unsigned int maxSteps=3;
8599 unsigned int stepCounter=0;
8600
8601 if (fabs(ds)<EPS31.e-2){
8602 double my_ds=ds;
8603 old_doca2=doca2;
8604 Step(xy,-mStepSizeS,Sc,dedx);
8605 my_ds-=mStepSizeS;
8606 wirexy=origin;
8607 wirexy+=(Sc(state_z)-z0w)*dir;
8608 doca2=(xy-wirexy).Mod2();
8609 while(doca2<old_doca2 && stepCounter<maxSteps){
8610 old_doca2=doca2;
8611 // Bail if the transverse momentum has dropped below some minimum
8612 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
8613 return VALUE_OUT_OF_RANGE;
8614 }
8615
8616 // Step through the field
8617 Step(xy,-mStepSizeS,Sc,dedx);
8618 stepCounter++;
8619
8620 wirexy=origin;
8621 wirexy+=(Sc(state_z)-z0w)*dir;
8622 doca2=(xy-wirexy).Mod2();
8623
8624 my_ds-=mStepSizeS;
8625 }
8626 // Swim to the "true" doca
8627 double ds2=0.;
8628 if (BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dedx,xy,z0w,
8629 origin,dir,Sc,ds2)!=NOERROR){
8630 return VALUE_OUT_OF_RANGE;
8631 }
8632 ds=my_ds+ds2;
8633 }
8634 else if (fabs(ds)>2*mStepSizeS-EPS31.e-2){
8635 double my_ds=ds;
8636
8637 // new wire position
8638 wirexy=origin;
8639 wirexy+=(Sc(state_z)-z0w)*dir;
8640
8641 // doca
8642 old_doca2=doca2;
8643 doca2=(xy-wirexy).Mod2();
8644
8645 while(doca2<old_doca2 && stepCounter<maxSteps){
8646 old_doca2=doca2;
8647
8648 // Bail if the transverse momentum has dropped below some minimum
8649 if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){
8650 return VALUE_OUT_OF_RANGE;
8651 }
8652
8653 // Step through the field
8654 Step(xy,mStepSizeS,Sc,dedx);
8655 stepCounter++;
8656
8657 // Find the new distance to the wire
8658 wirexy=origin;
8659 wirexy+=(Sc(state_z)-z0w)*dir;
8660 doca2=(xy-wirexy).Mod2();
8661
8662 my_ds+=mStepSizeS;
8663 }
8664 // Swim to the "true" doca
8665 double ds2=0.;
8666 if (BrentsAlgorithm(mStepSizeS,mStepSizeS,dedx,xy,z0w,
8667 origin,dir,Sc,ds2)!=NOERROR){
8668 return VALUE_OUT_OF_RANGE;
8669 }
8670 ds=my_ds+ds2;
8671 }
8672 return NOERROR;
8673}
8674
8675// Find extrapolations to detectors outside of the tracking volume
8676jerror_t DTrackFitterKalmanSIMD::ExtrapolateToOuterDetectors(const DMatrix5x1 &S0){
8677 DMatrix5x1 S=S0;
8678 // Energy loss
8679 double dEdx=0.;
8680
8681 // material properties
8682 double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.;
8683
8684 // Position variables
8685 double z=forward_traj[0].z;
8686 double newz=z,dz=0.;
8687
8688 // Current time and path length
8689 double t=forward_traj[0].t;
8690 double s=forward_traj[0].s;
8691
8692 // Store the position and momentum at the exit to the tracking volume
8693 AddExtrapolation(SYS_NULL,z,S,t,s);
8694
8695 // Loop to propagate track to outer detectors
8696 const double z_outer_max=1000.;
8697 const double x_max=130.;
8698 const double y_max=130.;
8699 const double fcal_radius_sq=120.47*120.47;
8700 bool hit_tof=false;
8701 bool hit_dirc=false;
8702 bool hit_fcal=false;
8703 bool got_fmwpc=(dFMWPCz_vec.size()>0)?true:false;
8704 unsigned int fmwpc_index=0;
8705 unsigned int trd_index=0;
8706 while (z>Z_MIN-100. && z<z_outer_max && fabs(S(state_x))<x_max
8707 && fabs(S(state_y))<y_max){
8708 // Bail if the momentum has dropped below some minimum
8709 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){
8710 if (DEBUG_LEVEL>2)
8711 {
8712 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<8712<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p))
8713 << endl;
8714 }
8715 return VALUE_OUT_OF_RANGE;
8716 }
8717
8718 // Check if we have passed into the BCAL
8719 double r2=S(state_x)*S(state_x)+S(state_y)*S(state_y);
8720 if (r2>89.*89. && z<400.) return VALUE_OUT_OF_RANGE;
8721 if (r2>64.9*64.9 && r2<89.*89.){
8722 if (extrapolations.at(SYS_BCAL).size()>299){
8723 return VALUE_OUT_OF_RANGE;
8724 }
8725 if (z<406.){
8726 AddExtrapolation(SYS_BCAL,z,S,t,s);
8727 }
8728 else if (extrapolations.at(SYS_BCAL).size()<5){
8729 // There needs to be some steps inside the the volume of the BCAL for
8730 // the extrapolation to be useful. If this is not the case, clear
8731 // the extrapolation vector.
8732 extrapolations[SYS_BCAL].clear();
8733 }
8734 }
8735
8736 // Relationship between arc length and z
8737 double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)
8738 +S(state_ty)*S(state_ty));
8739
8740 // get material properties from the Root Geometry
8741 DVector3 pos(S(state_x),S(state_y),z);
8742 DVector3 dir(S(state_tx),S(state_ty),1.);
8743 double s_to_boundary=0.;
8744 if (geom->FindMatKalman(pos,dir,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
8745 last_material_map,&s_to_boundary)
8746 !=NOERROR){
8747 if (DEBUG_LEVEL>0)
8748 {
8749 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<8749<<" "
<< "Material error in ExtrapolateForwardToOuterDetectors!"<< endl;
8750 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<8750<<" "
<< " Position (x,y,z)=("<<pos.x()<<","<<pos.y()<<","<<pos.z()<<")"
8751 <<endl;
8752 }
8753 return VALUE_OUT_OF_RANGE;
8754 }
8755
8756 // Get dEdx for the upcoming step
8757 if (CORRECT_FOR_ELOSS){
8758 dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI,Z);
8759 }
8760
8761 // Adjust the step size
8762 double ds=mStepSizeS;
8763 if (fabs(dEdx)>EPS3.0e-8){
8764 ds=DE_PER_STEP0.001/fabs(dEdx);
8765 }
8766 if (ds>mStepSizeS) ds=mStepSizeS;
8767 if (s_to_boundary<ds) ds=s_to_boundary;
8768 if (ds<MIN_STEP_SIZE0.1) ds=MIN_STEP_SIZE0.1;
8769 if (ds<0.5 && z<406. && r2>65.*65.) ds=0.5;
8770 dz=ds*dz_ds;
8771 newz=z+dz;
8772 if (trd_index<dTRDz_vec.size() && newz>dTRDz_vec[trd_index]){
8773 newz=dTRDz_vec[trd_index]+EPS3.0e-8;
8774 ds=(newz-z)/dz_ds;
8775 }
8776 if (hit_tof==false && newz>dTOFz){
8777 newz=dTOFz+EPS3.0e-8;
8778 ds=(newz-z)/dz_ds;
8779 }
8780 if (hit_dirc==false && newz>dDIRCz){
8781 newz=dDIRCz+EPS3.0e-8;
8782 ds=(newz-z)/dz_ds;
8783 }
8784 if (hit_fcal==false && newz>dFCALz){
8785 newz=dFCALz+EPS3.0e-8;
8786 ds=(newz-z)/dz_ds;
8787 }
8788 if (fmwpc_index<dFMWPCz_vec.size()&&newz>dFMWPCz_vec[fmwpc_index]){
8789 newz=dFMWPCz_vec[fmwpc_index]+EPS3.0e-8;
8790 ds=(newz-z)/dz_ds;
8791 }
8792 if (got_fmwpc&&newz>dCTOFz){
8793 newz=dCTOFz+EPS3.0e-8;
8794 ds=(newz-z)/dz_ds;
8795 }
8796 s+=ds;
8797
8798 // Flight time
8799 double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
8800 double one_over_beta2=1.+mass2*q_over_p_sq;
8801 if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8;
8802 t+=ds*sqrt(one_over_beta2); // in units where c=1
8803
8804 // Step through field
8805 Step(z,newz,dEdx,S);
8806 z=newz;
8807
8808 if (trd_index<dTRDz_vec.size() && newz>dTRDz_vec[trd_index]){
8809 AddExtrapolation(SYS_TRD,z,S,t,s);
8810 trd_index++;
8811 }
8812 if (hit_dirc==false && newz>dDIRCz){
8813 hit_dirc=true;
8814 AddExtrapolation(SYS_DIRC,z,S,t,s);
8815 }
8816 if (hit_tof==false && newz>dTOFz){
8817 hit_tof=true;
8818 AddExtrapolation(SYS_TOF,z,S,t,s);
8819 }
8820 if (hit_fcal==false && newz>dFCALz){
8821 double r2=S(state_x)*S(state_x)+S(state_y)*S(state_y);
8822 if (r2>fcal_radius_sq) return NOERROR;
8823
8824 hit_fcal=true;
8825 AddExtrapolation(SYS_FCAL,z,S,t,s);
8826
8827 // Propagate the track to the back of the FCAL block
8828 int num=int(45./dz);
8829 int m=0;
8830 for (;m<num;m++){
8831 // propagate t and s to back of FCAL block
8832 double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
8833 double one_over_beta2=1.+mass2*q_over_p_sq;
8834 if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8;
8835 ds=dz*sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
8836 t+=ds*sqrt(one_over_beta2); // in units where c=1
8837 s+=ds;
8838
8839 newz=z+dz;
8840 // Step through field
8841 Step(z,newz,dEdx,S);
8842 z=newz;
8843
8844 r2=S(state_x)*S(state_x)+S(state_y)*S(state_y);
8845 if (r2>fcal_radius_sq){
8846 // Break out of the loop if the track exits out of the FCAL before
8847 // reaching the back end of the block
8848 break;
8849 }
8850 }
8851 if (m==num){
8852 newz=dFCALzBack;
8853
8854 // Propagate t and s to back of FCAL block
8855 double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
8856 double one_over_beta2=1.+mass2*q_over_p_sq;
8857 if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8;
8858 dz=newz-z;
8859 ds=dz*sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
8860 t+=ds*sqrt(one_over_beta2); // in units where c=1
8861 s+=ds;
8862
8863 // Step through field
8864 Step(z,newz,dEdx,S);
8865 z=newz;
8866 }
8867 // add another extrapolation point at downstream end of FCAL
8868 AddExtrapolation(SYS_FCAL,z,S,t,s);
8869 // .. and exit if the muon detector is not installed
8870 if (got_fmwpc==false) return NOERROR;
8871 }
8872 // Deal with muon detector
8873 if (hit_fcal==true
8874 && (fabs(S(state_x))>dFMWPCsize || (fabs(S(state_y))>dFMWPCsize))){
8875 return NOERROR;
8876 }
8877 if (fmwpc_index<dFMWPCz_vec.size() && newz>dFMWPCz_vec[fmwpc_index]){
8878 AddExtrapolation(SYS_FMWPC,z,S,t,s);
8879 fmwpc_index++;
8880 }
8881 if (got_fmwpc && newz>dCTOFz){
8882 AddExtrapolation(SYS_CTOF,z,S,t,s);
8883 return NOERROR;
8884 }
8885 }
8886
8887 return NOERROR;
8888}
8889
8890// Find extrapolations to detector layers within the tracking volume and
8891// inward (toward the target).
8892jerror_t DTrackFitterKalmanSIMD::ExtrapolateToInnerDetectors(){
8893 // First deal with start counter. Only do this if the track has a chance
8894 // to intersect with the start counter volume.
8895 unsigned int inner_index=forward_traj.size()-1;
8896 unsigned int index_beyond_start_counter=inner_index;
8897 DMatrix5x1 S=forward_traj[inner_index].S;
8898 bool intersected_start_counter=false;
8899 if (sc_norm.empty()==false
8900 && S(state_x)*S(state_x)+S(state_y)*S(state_y)<SC_BARREL_R2
8901 && forward_traj[inner_index].z<SC_END_NOSE_Z){
8902 double d_old=1000.,d=1000.,z=0.;
8903 unsigned int index=0;
8904 for (unsigned int m=0;m<12;m++){
8905 unsigned int k=inner_index;
8906 for (;k>1;k--){
8907 S=forward_traj[k].S;
8908 z=forward_traj[k].z;
8909
8910 double dphi=atan2(S(state_y),S(state_x))-SC_PHI_SECTOR1;
8911 if (dphi<0) dphi+=2.*M_PI3.14159265358979323846;
8912 index=int(floor(dphi/(2.*M_PI3.14159265358979323846/30.)));
8913 if (index>29) index=0;
8914 d=sc_norm[index][m].Dot(DVector3(S(state_x),S(state_y),z)
8915 -sc_pos[index][m]);
8916 if (d*d_old<0){ // break if we cross the current plane
8917 if (m==0) index_beyond_start_counter=k;
8918 break;
8919 }
8920 d_old=d;
8921 }
8922 // if the z position would be beyond the current segment along z of
8923 // the start counter, move to the next plane
8924 if (z>sc_pos[index][m+1].z()&&m<11){
8925 continue;
8926 }
8927 // allow for a little slop at the end of the nose
8928 else if (z<sc_pos[index][sc_pos[0].size()-1].z()+0.1){
8929 // Hone in on intersection with the appropriate segment of the start
8930 // counter
8931 int count=0;
8932 DMatrix5x1 bestS=S;
8933 double dmin=d;
8934 double bestz=z;
8935 double t=forward_traj[k].t;
8936 double s=forward_traj[k].s;
8937 double bestt=t,bests=s;
8938
8939 // Magnetic field
8940 bfield->GetField(S(state_x),S(state_y),z,Bx,By,Bz);
8941
8942 while (fabs(d)>0.001 && count<20){
8943 // track direction
8944 DVector3 phat(S(state_tx),S(state_ty),1);
8945 phat.SetMag(1.);
8946
8947 // Step to the start counter plane
8948 double ds=d/sc_norm[index][m].Dot(phat);
8949 FastStep(z,-ds,0.,S);
8950
8951 // Flight time
8952 double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
8953 double one_over_beta2=1.+mass2*q_over_p_sq;
8954 if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8;
8955 t-=ds*sqrt(one_over_beta2); // in units where c=1
8956 s-=ds;
8957
8958 // Find the index for the nearest start counter paddle
8959 double dphi=atan2(S(state_y),S(state_x))-SC_PHI_SECTOR1;
8960 if (dphi<0) dphi+=2.*M_PI3.14159265358979323846;
8961 index=int(floor(dphi/(2.*M_PI3.14159265358979323846/30.)));
8962
8963 // Find the new distance to the start counter (which could now be to
8964 // a plane in the one adjacent to the one before the step...)
8965 d=sc_norm[index][m].Dot(DVector3(S(state_x),S(state_y),z)
8966 -sc_pos[index][m]);
8967 if (fabs(d)<fabs(dmin)){
8968 bestS=S;
8969 dmin=d;
8970 bestz=z;
8971 bests=s;
8972 bestt=t;
8973 }
8974 count++;
8975 }
8976 AddExtrapolation(SYS_START,bestz,bestS,bestt,bests);
8977 intersected_start_counter=true;
8978 break;
8979 }
8980 }
8981 }
8982 // Accumulate multiple-scattering terms for use in matching routines
8983 double s_theta_ms_sum=0.;
8984 double theta2ms_sum=0.;
8985 if (intersected_start_counter){
8986 for (unsigned int k=inner_index;k>index_beyond_start_counter;k--){
8987 double ds_theta_ms_sq=3.*fabs(forward_traj[k].Q(state_x,state_x));
8988 s_theta_ms_sum+=sqrt(ds_theta_ms_sq);
8989 double ds=forward_traj[k].s-forward_traj[k-1].s;
8990 theta2ms_sum+=ds_theta_ms_sq/(ds*ds);
8991 }
8992 }
8993
8994 // Deal with points within fiducial volume of chambers
8995 unsigned int fdc_plane=0;
8996 mT0Detector=SYS_NULL;
8997 mT0MinimumDriftTime=1e6;
8998 for (int k=intersected_start_counter?index_beyond_start_counter:inner_index;k>=0;k--){
8999 double z=forward_traj[k].z;
9000 double t=forward_traj[k].t;
9001 double s=forward_traj[k].s;
9002 DMatrix5x1 S=forward_traj[k].S;
9003
9004 // Find estimate for t0 using earliest drift time
9005 if (forward_traj[k].h_id>999){
9006 unsigned int index=forward_traj[k].h_id-1000;
9007 double dt=my_cdchits[index]->tdrift-t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
9008 if (dt<mT0MinimumDriftTime){
9009 mT0MinimumDriftTime=dt;
9010 mT0Detector=SYS_CDC;
9011 }
9012 }
9013 else if (forward_traj[k].h_id>0){
9014 unsigned int index=forward_traj[k].h_id-1;
9015 double dt=my_fdchits[index]->t-t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
9016 if (dt<mT0MinimumDriftTime){
9017 mT0MinimumDriftTime=dt;
9018 mT0Detector=SYS_FDC;
9019 }
9020 }
9021
9022 //multiple scattering terms
9023 if (k>0){
9024 double ds_theta_ms_sq=3.*fabs(forward_traj[k].Q(state_x,state_x));
9025 s_theta_ms_sum+=sqrt(ds_theta_ms_sq);
9026 double ds=forward_traj[k].s-forward_traj[k-1].s;
9027 theta2ms_sum+=ds_theta_ms_sq/(ds*ds);
9028 }
9029 // Extrapolations in CDC region
9030 if (z<endplate_z_downstream){
9031 AddExtrapolation(SYS_CDC,z,S,t,s,s_theta_ms_sum,theta2ms_sum);
9032 }
9033 else{ // extrapolations in FDC region
9034 // output step near wire plane
9035 if (z>fdc_z_wires[fdc_plane]-0.25){
9036 double dz=z-fdc_z_wires[fdc_plane];
9037 //printf("extrp dz %f\n",dz);
9038 if (fabs(dz)>EPS21.e-4){
9039 Step(z,fdc_z_wires[fdc_plane],0.,S);
9040 }
9041 AddExtrapolation(SYS_FDC,fdc_z_wires[fdc_plane],S,t,s,s_theta_ms_sum,
9042 theta2ms_sum);
9043
9044 if (fdc_plane==23){
9045 return NOERROR;
9046 }
9047
9048 fdc_plane++;
9049 }
9050 }
9051 }
9052
9053
9054 //--------------------------------------------------------------------------
9055 // The following code continues the extrapolations to wire planes that were
9056 // not included in the forward trajectory
9057 //--------------------------------------------------------------------------
9058
9059 // Material properties
9060 double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.;
9061 double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.;
9062
9063 // Energy loss
9064 double dEdx=0.;
9065
9066 // multiple scattering matrix
9067 DMatrix5x5 Q;
9068
9069 // Position variables
9070 S=forward_traj[0].S;
9071 double z=forward_traj[0].z,newz=z,dz=0.;
Value stored to 'newz' during its initialization is never read
9072
9073 // Current time and path length
9074 double t=forward_traj[0].t;
9075 double s=forward_traj[0].s;
9076
9077 // Find intersection points to FDC planes beyond the exent of the forward
9078 // trajectory.
9079 while (z>Z_MIN-100. && z<fdc_z_wires[23]+1. && fdc_plane<24){
9080 // Bail if the momentum has dropped below some minimum
9081 if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){
9082 if (DEBUG_LEVEL>2)
9083 {
9084 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<9084<<" "
<< "Bailing: P = " << 1./fabs(S(state_q_over_p))
9085 << endl;
9086 }
9087 return VALUE_OUT_OF_RANGE;
9088 }
9089
9090 // Current position
9091 DVector3 pos(S(state_x),S(state_y),z);
9092 if (pos.Perp()>50.) break;
9093
9094 // get material properties from the Root Geometry
9095 DVector3 dir(S(state_tx),S(state_ty),1.);
9096 double s_to_boundary=0.;
9097 if (geom->FindMatKalman(pos,dir,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
9098 chi2c_factor,chi2a_factor,chi2a_corr,
9099 last_material_map,&s_to_boundary)
9100 !=NOERROR){
9101 if (DEBUG_LEVEL>0)
9102 {
9103 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<9103<<" "
<< "Material error in ExtrapolateForwardToOuterDetectors!"<< endl;
9104 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<9104<<" "
<< " Position (x,y,z)=("<<pos.x()<<","<<pos.y()<<","<<pos.z()<<")"
9105 <<endl;
9106 }
9107 return VALUE_OUT_OF_RANGE;
9108 }
9109
9110 // Get dEdx for the upcoming step
9111 if (CORRECT_FOR_ELOSS){
9112 dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI,Z);
9113 }
9114
9115 // Relationship between arc length and z
9116 double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
9117
9118 // Adjust the step size
9119 double ds=mStepSizeS;
9120 if (fabs(dEdx)>EPS3.0e-8){
9121 ds=DE_PER_STEP0.001/fabs(dEdx);
9122 }
9123 if (ds>mStepSizeS) ds=mStepSizeS;
9124 if (s_to_boundary<ds) ds=s_to_boundary;
9125 if (ds<MIN_STEP_SIZE0.1) ds=MIN_STEP_SIZE0.1;
9126 dz=ds*dz_ds;
9127 newz=z+dz;
9128
9129 bool got_fdc_hit=false;
9130 if (fdc_plane<24 && newz>fdc_z_wires[fdc_plane]){
9131 newz=fdc_z_wires[fdc_plane];
9132 ds=(newz-z)/dz_ds;
9133 got_fdc_hit=true;
9134 }
9135 s+=ds;
9136
9137 // Flight time
9138 double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p);
9139 double one_over_beta2=1.+mass2*q_over_p_sq;
9140 if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8;
9141 t+=ds*sqrt(one_over_beta2); // in units where c=1
9142
9143 // Get the contribution to the covariance matrix due to multiple
9144 // scattering
9145 GetProcessNoise(z,ds,chi2c_factor,chi2a_factor,chi2a_corr,S,Q);
9146 double ds_theta_ms_sq=3.*fabs(Q(state_x,state_x));
9147 s_theta_ms_sum+=sqrt(ds_theta_ms_sq);
9148 theta2ms_sum+=ds_theta_ms_sq/(ds*ds);
9149
9150 // Step through field
9151 Step(z,newz,dEdx,S);
9152 z=newz;
9153
9154 if (got_fdc_hit){
9155 AddExtrapolation(SYS_FDC,z,S,s,t,s_theta_ms_sum,theta2ms_sum);
9156 fdc_plane++;
9157 }
9158 }
9159
9160 return NOERROR;
9161}
9162
9163// Routine to find intersections with surfaces useful at a later stage for track
9164// matching
9165jerror_t DTrackFitterKalmanSIMD::ExtrapolateForwardToOtherDetectors(){
9166 if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE;
9167 //--------------------------------
9168 // First swim to Start counter and CDC/FDC layers
9169 //--------------------------------
9170 jerror_t error=ExtrapolateToInnerDetectors();
9171
9172 //--------------------------------
9173 // Next swim to outer detectors...
9174 //--------------------------------
9175 if (error==NOERROR){
9176 return ExtrapolateToOuterDetectors(forward_traj[0].S);
9177 }
9178
9179 return error;
9180}
9181
9182// Routine to find intersections with surfaces useful at a later stage for track
9183// matching
9184jerror_t DTrackFitterKalmanSIMD::ExtrapolateCentralToOtherDetectors(){
9185 if (central_traj.size()<2) return RESOURCE_UNAVAILABLE;
9186
9187 // First deal with start counter. Only do this if the track has a chance
9188 // to intersect with the start counter volume.
9189 unsigned int inner_index=central_traj.size()-1;
9190 unsigned int index_beyond_start_counter=inner_index;
9191 DVector2 xy=central_traj[inner_index].xy;
9192 DMatrix5x1 S=central_traj[inner_index].S;
9193 if (sc_norm.empty()==false
9194 &&xy.Mod2()<SC_BARREL_R2&& S(state_z)<SC_END_NOSE_Z){
9195 double d_old=1000.,d=1000.,z=0.;
9196 unsigned int index=0;
9197 for (unsigned int m=0;m<12;m++){
9198 unsigned int k=inner_index;
9199 for (;k>1;k--){
9200 S=central_traj[k].S;
9201 z=S(state_z);
9202 xy=central_traj[k].xy;
9203
9204 double dphi=xy.Phi()-SC_PHI_SECTOR1;
9205 if (dphi<0) dphi+=2.*M_PI3.14159265358979323846;
9206 index=int(floor(dphi/(2.*M_PI3.14159265358979323846/30.)));
9207 if (index>29) index=0;
9208 //cout << "dphi " << dphi << " " << index << endl;
9209
9210 d=sc_norm[index][m].Dot(DVector3(xy.X(),xy.Y(),z)
9211 -sc_pos[index][m]);
9212
9213 if (d*d_old<0){ // break if we cross the current plane
9214 if (m==0) index_beyond_start_counter=k;
9215 break;
9216 }
9217 d_old=d;
9218 }
9219 // if the z position would be beyond the current segment along z of
9220 // the start counter, move to the next plane
9221 if (z>sc_pos[index][m+1].z()&&m<11){
9222 continue;
9223 }
9224 // allow for a little slop at the end of the nose
9225 else if (z<sc_pos[index][sc_pos[0].size()-1].z()+0.1){
9226 // Propagate the state and covariance through the field
9227 // using a straight-line approximation for each step to zero in on the
9228 // start counter paddle
9229 int count=0;
9230 DMatrix5x1 bestS=S;
9231 double dmin=d;
9232 DVector2 bestXY=central_traj[k].xy;
9233 double t=central_traj[k].t;
9234 double s=central_traj[k].s;
9235 double bests=s,bestt=t;
9236 // Magnetic field
9237 bfield->GetField(xy.X(),xy.Y(),S(state_z),Bx,By,Bz);
9238
9239 while (fabs(d)>0.05 && count<20){
9240 // track direction
9241 DVector3 phat(cos(S(state_phi)),sin(S(state_phi)),S(state_tanl));
9242 phat.SetMag(1.);
9243
9244 // path length increment
9245 double ds=d/sc_norm[index][m].Dot(phat);
9246 s-=ds;
9247
9248 // Flight time
9249 double q_over_p=S(state_q_over_pt)*cos(atan(S(state_tanl)));
9250 double q_over_p_sq=q_over_p*q_over_p;
9251 double one_over_beta2=1.+mass2*q_over_p_sq;
9252 if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8;
9253 t-=ds*sqrt(one_over_beta2); // in units where c=1
9254
9255 // Step along the trajectory using d to estimate path length
9256 FastStep(xy,-ds,0.,S);
9257 // Find the index for the nearest start counter paddle
9258 double dphi=xy.Phi()-SC_PHI_SECTOR1;
9259 if (dphi<0) dphi+=2.*M_PI3.14159265358979323846;
9260 index=int(floor(dphi/(2.*M_PI3.14159265358979323846/30.)));
9261 if (index>29) index=0;
9262
9263 // Find the new distance to the start counter (which could now be to
9264 // a plane in the one adjacent to the one before the step...)
9265 d=sc_norm[index][m].Dot(DVector3(xy.X(),xy.Y(),S(state_z))
9266 -sc_pos[index][m]);
9267 if (fabs(d)<fabs(dmin)){
9268 bestS=S;
9269 dmin=d;
9270 bestXY=xy;
9271 bests=s;
9272 bestt=t;
9273 }
9274 count++;
9275 }
9276
9277 if (bestS(state_z)>sc_pos[0][0].z()-0.1){
9278 AddExtrapolation(SYS_START,bestS,bestXY,bestt,bests);
9279 }
9280 break;
9281 }
9282 }
9283 }
9284
9285 // Accumulate multiple-scattering terms for use in matching routines
9286 double s_theta_ms_sum=0.,theta2ms_sum=0.;
9287 for (unsigned int k=inner_index;k>index_beyond_start_counter;k--){
9288 double ds_theta_ms_sq=3.*fabs(central_traj[k].Q(state_D,state_D));
9289 s_theta_ms_sum+=sqrt(ds_theta_ms_sq);
9290 double ds=central_traj[k].s-central_traj[k-1].s;
9291 theta2ms_sum+=ds_theta_ms_sq/(ds*ds);
9292 }
9293
9294 // Deal with points within fiducial volume of chambers
9295 mT0Detector=SYS_NULL;
9296 mT0MinimumDriftTime=1e6;
9297 for (int k=index_beyond_start_counter;k>=0;k--){
9298 S=central_traj[k].S;
9299 xy=central_traj[k].xy;
9300 double t=central_traj[k].t;
9301 double s=central_traj[k].s;
9302
9303 // Find estimate for t0 using earliest drift time
9304 if (central_traj[k].h_id>0){
9305 unsigned int index=central_traj[k].h_id-1;
9306 double dt=my_cdchits[index]->tdrift-t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
9307 if (dt<mT0MinimumDriftTime){
9308 mT0MinimumDriftTime=dt;
9309 mT0Detector=SYS_CDC;
9310 }
9311 }
9312
9313 //multiple scattering terms
9314 if (k>0){
9315 double ds_theta_ms_sq=3.*fabs(central_traj[k].Q(state_D,state_D));
9316 s_theta_ms_sum+=sqrt(ds_theta_ms_sq);
9317 double ds=central_traj[k].s-central_traj[k-1].s;
9318 theta2ms_sum+=ds_theta_ms_sq/(ds*ds);
9319 }
9320 if (S(state_z)<endplate_z){
9321 AddExtrapolation(SYS_CDC,S,xy,t,s,s_theta_ms_sum,theta2ms_sum);
9322 }
9323 }
9324 // Save the extrapolation at the exit of the tracking volume
9325 S=central_traj[0].S;
9326 xy=central_traj[0].xy;
9327 double t=central_traj[0].t;
9328 double s=central_traj[0].s;
9329 AddExtrapolation(SYS_NULL,S,xy,t,s);
9330
9331 //------------------------------
9332 // Next swim to outer detectors
9333 //------------------------------
9334 // Position and step variables
9335 double r2=xy.Mod2();
9336 double ds=mStepSizeS; // step along path in cm
9337
9338 // Energy loss
9339 double dedx=0.;
9340
9341 // Track propagation loop
9342 //if (false)
9343 while (S(state_z)>0. && S(state_z)<Z_MAX370.0
9344 && r2<89.*89.){
9345 // Bail if the transverse momentum has dropped below some minimum
9346 if (fabs(S(state_q_over_pt))>Q_OVER_PT_MAX100.){
9347 if (DEBUG_LEVEL>2)
9348 {
9349 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<9349<<" "
<< "Bailing: PT = " << 1./fabs(S(state_q_over_pt))
9350 << endl;
9351 }
9352 return VALUE_OUT_OF_RANGE;
9353 }
9354
9355 // get material properties from the Root Geometry
9356 double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.;
9357 DVector3 pos3d(xy.X(),xy.Y(),S(state_z));
9358 double s_to_boundary=0.;
9359 DVector3 dir(cos(S(state_phi)),sin(S(state_phi)),S(state_tanl));
9360 if (geom->FindMatKalman(pos3d,dir,K_rho_Z_over_A,rho_Z_over_A,LnI,Z,
9361 last_material_map,&s_to_boundary)
9362 !=NOERROR){
9363 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<9363<<" "
<< "Material error in ExtrapolateToVertex! " << endl;
9364 _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<9364<<" "
<< " Position (x,y,z)=("<<pos3d.x()<<","<<pos3d.y()<<","
9365 << pos3d.z()<<")"
9366 <<endl;
9367 break;
9368 }
9369
9370 // Get dEdx for the upcoming step
9371 double q_over_p=S(state_q_over_pt)*cos(atan(S(state_tanl)));
9372 if (CORRECT_FOR_ELOSS){
9373 dedx=GetdEdx(q_over_p,K_rho_Z_over_A,rho_Z_over_A,LnI,Z);
9374 }
9375 // Adjust the step size
9376 if (fabs(dedx)>EPS3.0e-8){
9377 ds=DE_PER_STEP0.001/fabs(dedx);
9378 }
9379
9380 if (ds>mStepSizeS) ds=mStepSizeS;
9381 if (s_to_boundary<ds) ds=s_to_boundary;
9382 if (ds<MIN_STEP_SIZE0.1)ds=MIN_STEP_SIZE0.1;
9383 if (ds<0.5 && S(state_z)<400. && pos3d.Perp()>65.) ds=0.5;
9384 s+=ds;
9385
9386 // Flight time
9387 double q_over_p_sq=q_over_p*q_over_p;
9388 double one_over_beta2=1.+mass2*q_over_p_sq;
9389 if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8;
9390 t+=ds*sqrt(one_over_beta2); // in units where c=1
9391
9392 // Propagate the state through the field
9393 Step(xy,ds,S,dedx);
9394
9395 r2=xy.Mod2();
9396 // Check if we have passed into the BCAL
9397 if (r2>64.9*64.9){
9398 if (extrapolations.at(SYS_BCAL).size()>299){
9399 return VALUE_OUT_OF_RANGE;
9400 }
9401 if (S(state_z)<406.&&S(state_z)>17.0){
9402 AddExtrapolation(SYS_BCAL,S,xy,t,s);
9403 }
9404 else if (extrapolations.at(SYS_BCAL).size()<5){
9405 // There needs to be some steps inside the the volume of the BCAL for
9406 // the extrapolation to be useful. If this is not the case, clear
9407 // the extrolation vector.
9408 extrapolations[SYS_BCAL].clear();
9409 }
9410 }
9411 }
9412
9413 return NOERROR;
9414}
9415
9416/*---------------------------------------------------------------------------*/
9417
9418// Kalman engine for forward tracks, propagating from near the beam line to
9419// the outermost hits (opposite to regular direction).
9420kalman_error_t DTrackFitterKalmanSIMD::KalmanReverse(double fdc_anneal_factor,
9421 double cdc_anneal_factor,
9422 const DMatrix5x1 &Sstart,
9423 DMatrix5x5 &C,
9424 DMatrix5x1 &S,
9425 double &chisq,
9426 unsigned int &numdof){
9427 DMatrix2x1 Mdiff; // difference between measurement and prediction
9428 DMatrix2x5 H; // Track projection matrix
9429 DMatrix5x2 H_T; // Transpose of track projection matrix
9430 DMatrix1x5 Hc; // Track projection matrix for cdc hits
9431 DMatrix5x1 Hc_T; // Transpose of track projection matrix for cdc hits
9432 DMatrix5x5 J; // State vector Jacobian matrix
9433 //DMatrix5x5 J_T; // transpose of this matrix
9434 DMatrix5x5 Q; // Process noise covariance matrix
9435 DMatrix5x2 K; // Kalman gain matrix
9436 DMatrix5x1 Kc; // Kalman gain matrix for cdc hits
9437 DMatrix2x2 V(0.0833,0.,0.,FDC_CATHODE_VARIANCE0.000225); // Measurement covariance matrix
9438 DMatrix5x1 S0,S0_; //State vector
9439 DMatrix5x5 Ctest; // Covariance matrix
9440
9441 double Vc=0.0507;
9442
9443 unsigned int cdc_index=0;
9444 unsigned int num_cdc_hits=my_cdchits.size();
9445 bool more_cdc_measurements=(num_cdc_hits>0);
9446 double old_doca2=1e6;
9447
9448 // Initialize chi squared
9449 chisq=0;
9450
9451 // Initialize number of degrees of freedom
9452 numdof=0;
9453
9454 // Cuts for pruning hits
9455 double fdc_chi2cut=NUM_FDC_SIGMA_CUT*NUM_FDC_SIGMA_CUT;
9456 double cdc_chi2cut=NUM_CDC_SIGMA_CUT*NUM_CDC_SIGMA_CUT;
9457
9458 // Vectors for cdc wires
9459 DVector2 origin,dir,wirepos;
9460 double z0w=0.; // origin in z for wire
9461
9462 deque<DKalmanForwardTrajectory_t>::reverse_iterator rit = forward_traj.rbegin();
9463 S0_=(*rit).S;
9464 S=Sstart;
9465
9466 if (more_cdc_measurements){
9467 origin=my_cdchits[0]->origin;
9468 dir=my_cdchits[0]->dir;
9469 z0w=my_cdchits[0]->z0wire;
9470 wirepos=origin+((*rit).z-z0w)*dir;
9471 }
9472
9473 for (rit=forward_traj.rbegin()+1;rit!=forward_traj.rend();++rit){
9474 // Get the state vector, jacobian matrix, and multiple scattering matrix
9475 // from reference trajectory
9476 S0=(*rit).S;
9477 J=2.*I5x5-(*rit).J; // We only want to change the signs of the parts that depend on dz ...
9478 Q=(*rit).Q;
9479
9480 // Check that the position is within the tracking volume!
9481 if (S(state_x)*S(state_x)+S(state_y)*S(state_y)>65.*65.){
9482 return POSITION_OUT_OF_RANGE;
9483 }
9484 // Update the actual state vector and covariance matrix
9485 S=S0+J*(S-S0_);
9486 C=Q.AddSym(J*C*J.Transpose());
9487 //C.Print();
9488
9489 // Save the current state of the reference trajectory
9490 S0_=S0;
9491
9492 // Z position along the trajectory
9493 double z=(*rit).z;
9494
9495 if (more_cdc_measurements){
9496 // new wire position
9497 wirepos=origin;
9498 wirepos+=(z-z0w)*dir;
9499
9500 // doca variables
9501 double dx=S(state_x)-wirepos.X();
9502 double dy=S(state_y)-wirepos.Y();
9503 double doca2=dx*dx+dy*dy;
9504
9505 if (doca2>old_doca2){
9506 if(my_cdchits[cdc_index]->status==good_hit){
9507 find_doca_error_t swimmed_to_doca=DOCA_NO_BRENT;
9508 double newz=endplate_z;
9509 double dz=newz-z;
9510 // Sometimes the true doca would correspond to the case where the
9511 // wire would need to extend beyond the physical volume of the straw.
9512 // In this case, find the doca at the cdc endplate.
9513 if (z>endplate_z){
9514 swimmed_to_doca=DOCA_ENDPLATE;
9515 SwimToEndplate(z,*rit,S);
9516
9517 // wire position at the endplate
9518 wirepos=origin;
9519 wirepos+=(endplate_z-z0w)*dir;
9520
9521 dx=S(state_x)-wirepos.X();
9522 dy=S(state_y)-wirepos.Y();
9523 }
9524 else{
9525 // Find the true doca to the wire. If we had to use Brent's
9526 // algorithm, the routine returns USED_BRENT
9527 swimmed_to_doca=FindDoca(my_cdchits[cdc_index],*rit,mStepSizeZ,
9528 mStepSizeZ,S0,S,C,dx,dy,dz,true);
9529 if (swimmed_to_doca==BRENT_FAILED){
9530 //_DBG_ << "Brent's algorithm failed" <<endl;
9531 return MOMENTUM_OUT_OF_RANGE;
9532 }
9533
9534 newz=z+dz;
9535 }
9536 double cosstereo=my_cdchits[cdc_index]->cosstereo;
9537 double d=sqrt(dx*dx+dy*dy)*cosstereo+EPS3.0e-8;
9538
9539 // Track projection
9540 double cosstereo2_over_d=cosstereo*cosstereo/d;
9541 Hc_T(state_x)=dx*cosstereo2_over_d;
9542 Hc(state_x)=Hc_T(state_x);
9543 Hc_T(state_y)=dy*cosstereo2_over_d;
9544 Hc(state_y)=Hc_T(state_y);
9545 if (swimmed_to_doca==DOCA_NO_BRENT){
9546 Hc_T(state_ty)=Hc_T(state_y)*dz;
9547 Hc(state_ty)=Hc_T(state_ty);
9548 Hc_T(state_tx)=Hc_T(state_x)*dz;
9549 Hc(state_tx)=Hc_T(state_tx);
9550 }
9551 else{
9552 Hc_T(state_ty)=0.;
9553 Hc(state_ty)=0.;
9554 Hc_T(state_tx)=0.;
9555 Hc(state_tx)=0.;
9556 }
9557 // Find offset of wire with respect to the center of the
9558 // straw at this z position
9559 double delta=0.,dphi=0.;
9560 FindSag(dx,dy,newz-z0w,my_cdchits[cdc_index]->hit->wire,delta,dphi);
9561
9562 // Find drift time and distance
9563 double tdrift=my_cdchits[cdc_index]->tdrift-mT0
9564 -(*rit).t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
9565 double tcorr=0.,dmeas=0.;
9566 double B=(*rit).B;
9567 ComputeCDCDrift(dphi,delta,tdrift,B,dmeas,Vc,tcorr);
9568
9569 // Residual
9570 double res=dmeas-d;
9571
9572 // inverse variance including prediction
9573 double Vproj=Hc*C*Hc_T;
9574 double InvV1=1./(Vc+Vproj);
9575
9576 // Check if this hit is an outlier
9577 double chi2_hit=res*res*InvV1;
9578 if (chi2_hit<cdc_chi2cut){
9579 // Compute KalmanSIMD gain matrix
9580 Kc=InvV1*(C*Hc_T);
9581
9582 // Update state vector covariance matrix
9583 //C=C-K*(H*C);
9584 Ctest=C.SubSym(Kc*(Hc*C));
9585
9586 if (!Ctest.IsPosDef()){
9587 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc"
<<":"<<9587<<" "
<< "Broken covariance matrix!" <<endl;
9588 return BROKEN_COVARIANCE_MATRIX;
9589 }
9590
9591 if (tdrift >= CDC_T_DRIFT_MIN){
9592 C=Ctest;
9593 S+=res*Kc;
9594
9595 chisq+=(1.-Hc*Kc)*res*res/Vc;
9596 numdof++;
9597 }
9598 }
9599
9600 // If we had to use Brent's algorithm to find the true doca or the
9601 // doca to the line corresponding to the wire is downstream of the
9602 // cdc endplate, we need to swim the state vector and covariance
9603 // matrix back to the appropriate position along the reference
9604 // trajectory.
9605 if (swimmed_to_doca!=DOCA_NO_BRENT){
9606 double dedx=0.;
9607 if (CORRECT_FOR_ELOSS){
9608 dedx=GetdEdx(S(state_q_over_p),(*rit).K_rho_Z_over_A,
9609 (*rit).rho_Z_over_A,(*rit).LnI,(*rit).Z);
9610 }
9611 StepBack(dedx,newz,z,S0,S,C);
9612 }
9613 }
9614
9615 // new wire origin and direction
9616 if (cdc_index<num_cdc_hits-1){
9617 cdc_index++;
9618 origin=my_cdchits[cdc_index]->origin;
9619 z0w=my_cdchits[cdc_index]->z0wire;
9620 dir=my_cdchits[cdc_index]->dir;
9621 }
9622 else more_cdc_measurements=false;
9623
9624 // Update the wire position
9625 wirepos=origin+(z-z0w)*dir;
9626
9627 // new doca
9628 dx=S(state_x)-wirepos.X();
9629 dy=S(state_y)-wirepos.Y();
9630 doca2=dx*dx+dy*dy;
9631 }
9632 old_doca2=doca2;
9633 }
9634 if ((*rit).h_id>0&&(*rit).h_id<1000){
9635 unsigned int id=(*rit).h_id-1;
9636
9637 // Variance in coordinate transverse to wire
9638 V(0,0)=my_fdchits[id]->uvar;
9639
9640 // Variance in coordinate along wire
9641 V(1,1)=my_fdchits[id]->vvar;
9642
9643 double upred=0,vpred=0.,doca=0.,cosalpha=0.,lorentz_factor=0.;
9644 FindDocaAndProjectionMatrix(my_fdchits[id],S,upred,vpred,doca,cosalpha,
9645 lorentz_factor,H_T);
9646 // Matrix transpose H_T -> H
9647 H=Transpose(H_T);
9648
9649
9650 DMatrix2x2 Vtemp=V+H*C*H_T;
9651
9652 // Residual for coordinate along wire
9653 Mdiff(1)=my_fdchits[id]->vstrip-vpred-doca*lorentz_factor;
9654
9655 // Residual for coordinate transverse to wire
9656 double drift_time=my_fdchits[id]->t-mT0-(*rit).t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
9657 if (my_fdchits[id]->hit!=NULL__null){
9658 double drift=(doca>0.0?1.:-1.)*fdc_drift_distance(drift_time,(*rit).B);
9659 Mdiff(0)=drift-doca;
9660
9661 // Variance in drift distance
9662 V(0,0)=fdc_drift_variance(drift_time);
9663 }
9664 else if (USE_TRD_DRIFT_TIMES&&my_fdchits[id]->status==trd_hit){
9665 double drift =(doca>0.0?1.:-1.)*0.1*pow(drift_time/8./0.91,1./1.556);
9666 Mdiff(0)=drift-doca;
9667
9668 // Variance in drift distance
9669 V(0,0)=0.05*0.05;
9670 }
9671 if ((*rit).num_hits==1){
9672 // Add contribution of track covariance from state vector propagation
9673 // to measurement errors
9674 DMatrix2x2 Vtemp=V+H*C*H_T;
9675 double chi2_hit=Vtemp.Chi2(Mdiff);
9676 if (chi2_hit<fdc_chi2cut){
9677 // Compute Kalman gain matrix
9678 DMatrix2x2 InvV=Vtemp.Invert();
9679 DMatrix5x2 K=C*H_T*InvV;
9680
9681 // Update the state vector
9682 S+=K*Mdiff;
9683
9684 // Update state vector covariance matrix
9685 //C=C-K*(H*C);
9686 C=C.SubSym(K*(H*C));
9687
9688 if (DEBUG_LEVEL > 35) {
9689 jout << "S Update: " << endl; S.Print();
9690 jout << "C Update: " << endl; C.Print();
9691 }
9692
9693 // Filtered residual and covariance of filtered residual
9694 DMatrix2x1 R=Mdiff-H*K*Mdiff;
9695 DMatrix2x2 RC=V-H*(C*H_T);
9696
9697 // Update chi2 for this segment
9698 chisq+=RC.Chi2(R);
9699
9700 if (DEBUG_LEVEL>30)
9701 {
9702 printf("hit %d p %5.2f dm %5.4f %5.4f sig %5.4f %5.4f chi2 %5.2f\n",
9703 id,1./S(state_q_over_p),Mdiff(0),Mdiff(1),
9704 sqrt(V(0,0)),sqrt(V(1,1)),RC.Chi2(R));
9705 }
9706
9707 numdof+=2;
9708 }
9709 }
9710 // Handle the case where there are multiple adjacent hits in the plane
9711 else {
9712 UpdateSandCMultiHit(*rit,upred,vpred,doca,cosalpha,lorentz_factor,V,
9713 Mdiff,H,H_T,S,C,fdc_chi2cut,false,chisq,numdof);
9714 }
9715 }
9716
9717 //printf("chisq %f ndof %d prob %f\n",chisq,numdof,TMath::Prob(chisq,numdof));
9718 }
9719
9720 return FIT_SUCCEEDED;
9721}
9722
9723// Finds the distance of closest approach between a CDC wire and the trajectory
9724// of the track and updates the state vector and covariance matrix at this point.
9725find_doca_error_t
9726DTrackFitterKalmanSIMD::FindDoca(const DKalmanSIMDCDCHit_t *hit,
9727 const DKalmanForwardTrajectory_t &traj,
9728 double step1,double step2,
9729 DMatrix5x1 &S0,DMatrix5x1 &S,
9730 DMatrix5x5 &C,
9731 double &dx,double &dy,double &dz,
9732 bool do_reverse){
9733 double z=traj.z,newz=z;
9734 DMatrix5x5 J;
9735
9736 // wire position and direction
9737 DVector2 origin=hit->origin;
9738 double z0w=hit->z0wire;
9739 DVector2 dir=hit->dir;
9740
9741 // energy loss
9742 double dedx=0.;
9743
9744 // track direction variables
9745 double tx=S(state_tx);
9746 double ty=S(state_ty);
9747 double tanl=1./sqrt(tx*tx+ty*ty);
9748 double sinl=sin(atan(tanl));
9749
9750 // Wire direction variables
9751 double ux=dir.X();
9752 double uy=dir.Y();
9753 // Variables relating wire direction and track direction
9754 double my_ux=tx-ux;
9755 double my_uy=ty-uy;
9756 double denom=my_ux*my_ux+my_uy*my_uy;
9757
9758 // variables for dealing with propagation of S and C if we
9759 // need to use Brent's algorithm to find the doca to the wire
9760 int num_steps=0;
9761 double my_dz=0.;
9762
9763 // if the path length increment is small relative to the radius
9764 // of curvature, use a linear approximation to find dz
9765 bool do_brent=false;
9766 double sign=do_reverse?-1.:1.;
9767 double two_step=sign*(step1+step2);
9768 if (fabs(qBr2p0.003*S(state_q_over_p)
9769 *bfield->GetBz(S(state_x),S(state_y),z)
9770 *two_step/sinl)<0.05
9771 && denom>EPS3.0e-8){
9772 double dzw=z-z0w;
9773 dz=-((S(state_x)-origin.X()-ux*dzw)*my_ux
9774 +(S(state_y)-origin.Y()-uy*dzw)*my_uy)/denom;
9775 if (fabs(dz)>fabs(two_step) || sign*dz<0){
9776 do_brent=true;
9777 }
9778 else{
9779 newz=z+dz;
9780 // Check for exiting the straw
9781 if (newz>endplate_z){
9782 dz=endplate_z-z;
9783 }
9784 }
9785 }
9786 else do_brent=true;
9787 if (do_brent){
9788 if (CORRECT_FOR_ELOSS){
9789 dedx=GetdEdx(S(state_q_over_p),traj.K_rho_Z_over_A,traj.rho_Z_over_A,
9790 traj.LnI,traj.Z);
9791 }
9792
9793 // We have bracketed the minimum doca: use Brent's agorithm
9794 if (BrentForward(z,dedx,z0w,origin,dir,S,dz)!=NOERROR){
9795 return BRENT_FAILED;
9796 }
9797 // Step the state and covariance through the field
9798 if (fabs(dz)>mStepSizeZ){
9799 my_dz=(dz>0?1.0:-1.)*mStepSizeZ;
9800 num_steps=int(fabs(dz/my_dz));
9801 double dz3=dz-num_steps*my_dz;
9802
9803 double my_z=z;
9804 for (int m=0;m<num_steps;m++){
9805 newz=my_z+my_dz;
9806
9807 // propagate error matrix to z-position of hit
9808 StepJacobian(my_z,newz,S0,dedx,J);
9809 C=J*C*J.Transpose();
9810 //C=C.SandwichMultiply(J);
9811
9812 // Step reference trajectory by my_dz
9813 Step(my_z,newz,dedx,S0);
9814
9815 my_z=newz;
9816 }
9817
9818 newz=my_z+dz3;
9819 // propagate error matrix to z-position of hit
9820 StepJacobian(my_z,newz,S0,dedx,J);
9821 C=J*C*J.Transpose();
9822 //C=C.SandwichMultiply(J);
9823
9824 // Step reference trajectory by dz3
9825 Step(my_z,newz,dedx,S0);
9826 }
9827 else{
9828 newz = z + dz;
9829
9830 // propagate error matrix to z-position of hit
9831 StepJacobian(z,newz,S0,dedx,J);
9832 C=J*C*J.Transpose();
9833 //C=C.SandwichMultiply(J);
9834
9835 // Step reference trajectory by dz
9836 Step(z,newz,dedx,S0);
9837 }
9838 }
9839
9840 // Wire position at current z
9841 DVector2 wirepos=origin;
9842 wirepos+=(newz-z0w)*dir;
9843
9844 double xw=wirepos.X();
9845 double yw=wirepos.Y();
9846
9847 // predicted doca taking into account the orientation of the wire
9848 if (do_brent==false){
9849 // In this case we did not have to swim to find the doca and
9850 // the transformation from the state vector space to the
9851 // measurement space is straight-forward.
9852 dy=S(state_y)+S(state_ty)*dz-yw;
9853 dx=S(state_x)+S(state_tx)*dz-xw;
9854 }
9855 else{
9856 // In this case we swam the state vector to the position of the doca
9857 dy=S(state_y)-yw;
9858 dx=S(state_x)-xw;
9859 }
9860
9861 if (do_brent) return USED_BRENT;
9862 return DOCA_NO_BRENT;
9863}
9864
9865// Swim along a trajectory to the z-position z.
9866void DTrackFitterKalmanSIMD::StepBack(double dedx,double newz,double z,
9867 DMatrix5x1 &S0,DMatrix5x1 &S,
9868 DMatrix5x5 &C){
9869 double dz=newz-z;
9870 DMatrix5x5 J;
9871 int num_steps=int(fabs(dz/mStepSizeZ));
9872 if (num_steps==0){
9873 // Step C back to the z-position on the reference trajectory
9874 StepJacobian(newz,z,S0,dedx,J);
9875 C=J*C*J.Transpose();
9876 //C=C.SandwichMultiply(J);
9877
9878 // Step S to current position on the reference trajectory
9879 Step(newz,z,dedx,S);
9880
9881 // Step S0 to current position on the reference trajectory
9882 Step(newz,z,dedx,S0);
9883 }
9884 else{
9885 double my_z=newz;
9886 double my_dz=(dz>0.0?1.0:-1.)*mStepSizeZ;
9887 double dz3=dz-num_steps*my_dz;
9888 for (int m=0;m<num_steps;m++){
9889 z=my_z-my_dz;
9890
9891 // Step C along z
9892 StepJacobian(my_z,z,S0,dedx,J);
9893 C=J*C*J.Transpose();
9894 //C=C.SandwichMultiply(J);
9895
9896 // Step S along z
9897 Step(my_z,z,dedx,S);
9898
9899 // Step S0 along z
9900 Step(my_z,z,dedx,S0);
9901
9902 my_z=z;
9903 }
9904 z=my_z-dz3;
9905
9906 // Step C back to the z-position on the reference trajectory
9907 StepJacobian(my_z,z,S0,dedx,J);
9908 C=J*C*J.Transpose();
9909 //C=C.SandwichMultiply(J);
9910
9911 // Step S to current position on the reference trajectory
9912 Step(my_z,z,dedx,S);
9913
9914 // Step S0 to current position on the reference trajectory
9915 Step(my_z,z,dedx,S0);
9916 }
9917}
9918
9919// Swim a track to the CDC endplate given starting z position
9920void DTrackFitterKalmanSIMD::SwimToEndplate(double z,
9921 const DKalmanForwardTrajectory_t &traj,
9922 DMatrix5x1 &S){
9923 double dedx=0.;
9924 if (CORRECT_FOR_ELOSS){
9925 dedx=GetdEdx(S(state_q_over_p),traj.K_rho_Z_over_A,traj.rho_Z_over_A,
9926 traj.LnI,traj.Z);
9927 }
9928 double my_z=z;
9929 int num_steps=int(fabs((endplate_z-z)/mStepSizeZ));
9930 for (int m=0;m<num_steps;m++){
9931 my_z=z-mStepSizeZ;
9932 Step(z,my_z,dedx,S);
9933 z=my_z;
9934 }
9935 Step(z,endplate_z,dedx,S);
9936}
9937
9938// Find the sag parameters (delta,dphi) for the given straw at the local z
9939// position
9940void DTrackFitterKalmanSIMD::FindSag(double dx,double dy, double zlocal,
9941 const DCDCWire *mywire,double &delta,
9942 double &dphi) const{
9943 int ring_index=mywire->ring-1;
9944 int straw_index=mywire->straw-1;
9945 double phi_d=atan2(dy,dx);
9946 delta=max_sag[ring_index][straw_index]*(1.-zlocal*zlocal/5625.)
9947 *cos(phi_d + sag_phi_offset[ring_index][straw_index]);
9948
9949 dphi=phi_d-mywire->origin.Phi();
9950 while (dphi>M_PI3.14159265358979323846) dphi-=2*M_PI3.14159265358979323846;
9951 while (dphi<-M_PI3.14159265358979323846) dphi+=2*M_PI3.14159265358979323846;
9952 if (mywire->origin.Y()<0) dphi*=-1.;
9953}
9954
9955void DTrackFitterKalmanSIMD::FindDocaAndProjectionMatrix(const DKalmanSIMDFDCHit_t *hit,
9956 const DMatrix5x1 &S,
9957 double &upred,
9958 double &vpred,
9959 double &doca,
9960 double &cosalpha,
9961 double &lorentz_factor,
9962 DMatrix5x2 &H_T){
9963 // Make the small alignment rotations
9964 // Use small-angle form.
9965
9966 // Position and direction from state vector
9967 double x=S(state_x) + hit->phiZ*S(state_y);
9968 double y=S(state_y) - hit->phiZ*S(state_x);
9969 double tx =S(state_tx) + hit->phiZ*S(state_ty) - hit->phiY;
9970 double ty =S(state_ty) - hit->phiZ*S(state_tx) + hit->phiX;
9971
9972 // Plane orientation and measurements
9973 double cosa=hit->cosa;
9974 double sina=hit->sina;
9975 double u=hit->uwire;
9976
9977 // Projected coordinate along wire
9978 vpred=x*sina+y*cosa;
9979
9980 // Direction tangent in the u-z plane
9981 double tu=tx*cosa-ty*sina;
9982 double tv=tx*sina+ty*cosa;
9983 double alpha=atan(tu);
9984 cosalpha=cos(alpha);
9985 double cosalpha2=cosalpha*cosalpha;
9986 double sinalpha=sin(alpha);
9987
9988 // (signed) distance of closest approach to wire
9989 upred=x*cosa-y*sina;
9990 if (hit->status==gem_hit){
9991 doca=upred-u;
9992 }
9993 else{
9994 doca=(upred-u)*cosalpha;
9995 }
9996
9997 // Correction for lorentz effect
9998 double nz=hit->nz;
9999 double nr=hit->nr;
10000 double nz_sinalpha_plus_nr_cosalpha=nz*sinalpha+nr*cosalpha;
10001 lorentz_factor=nz_sinalpha_plus_nr_cosalpha-tv*sinalpha;
10002
10003 // To transform from (x,y) to (u,v), need to do a rotation:
10004 // u = x*cosa-y*sina
10005 // v = y*cosa+x*sina
10006 if (hit->status!=gem_hit){
10007 H_T(state_x,1)=sina+cosa*cosalpha*lorentz_factor;
10008 H_T(state_y,1)=cosa-sina*cosalpha*lorentz_factor;
10009
10010 double cos2_minus_sin2=cosalpha2-sinalpha*sinalpha;
10011 double fac=nz*cos2_minus_sin2-2.*nr*cosalpha*sinalpha;
10012 double doca_cosalpha=doca*cosalpha;
10013 double temp=doca_cosalpha*fac;
10014 H_T(state_tx,1)=cosa*temp-doca_cosalpha*(tu*sina+tv*cosa*cos2_minus_sin2);
10015 H_T(state_ty,1)=-sina*temp-doca_cosalpha*(tu*cosa-tv*sina*cos2_minus_sin2);
10016
10017 H_T(state_x,0)=cosa*cosalpha;
10018 H_T(state_y,0)=-sina*cosalpha;
10019
10020 double factor=doca*tu*cosalpha2;
10021 H_T(state_ty,0)=sina*factor;
10022 H_T(state_tx,0)=-cosa*factor;
10023 }
10024 else{
10025 H_T(state_x,1)=sina;
10026 H_T(state_y,1)=cosa;
10027 H_T(state_x,0)=cosa;
10028 H_T(state_y,0)=-sina;
10029 }
10030}
10031
10032// Update S and C using all the good adjacent hits in a particular FDC plane
10033void DTrackFitterKalmanSIMD::UpdateSandCMultiHit(const DKalmanForwardTrajectory_t &traj,
10034 double upred,double vpred,
10035 double doca,double cosalpha,
10036 double lorentz_factor,
10037 DMatrix2x2 &V,
10038 DMatrix2x1 &Mdiff,
10039 DMatrix2x5 &H,
10040 const DMatrix5x2 &H_T,
10041 DMatrix5x1 &S,DMatrix5x5 &C,
10042 double fdc_chi2cut,
10043 bool skip_plane,double &chisq,
10044 unsigned int &numdof,
10045 double fdc_anneal_factor){
10046 // If we do have multiple hits, then all of the hits within some
10047 // validation region are included with weights determined by how
10048 // close the hits are to the track projection of the state to the
10049 // "hit space".
10050 vector<DMatrix5x2> Klist;
10051 vector<DMatrix2x1> Mlist;
10052 vector<DMatrix2x5> Hlist;
10053 vector<DMatrix5x2> HTlist;
10054 vector<DMatrix2x2> Vlist;
10055 vector<double>probs;
10056 vector<unsigned int>used_ids;
10057
10058 // use a Gaussian model for the probability for the hit
10059 DMatrix2x2 Vtemp=V+H*C*H_T;
10060 double chi2_hit=Vtemp.Chi2(Mdiff);
10061 double prob_hit=0.;
10062
10063 // Add the first hit to the list, cutting out outliers
10064 unsigned int id=traj.h_id-1;
10065 if (chi2_hit<fdc_chi2cut && my_fdchits[id]->status==good_hit){
10066 DMatrix2x2 InvV=Vtemp.Invert();
10067
10068 prob_hit=exp(-0.5*chi2_hit)/(M_TWO_PI6.28318530717958647692*sqrt(Vtemp.Determinant()));
10069 probs.push_back(prob_hit);
10070 Vlist.push_back(V);
10071 Hlist.push_back(H);
10072 HTlist.push_back(H_T);
10073 Mlist.push_back(Mdiff);
10074 Klist.push_back(C*H_T*InvV); // Kalman gain
10075
10076 used_ids.push_back(id);
10077 fdc_used_in_fit[id]=true;
10078 }
10079 // loop over the remaining hits
10080 for (unsigned int m=1;m<traj.num_hits;m++){
10081 unsigned int my_id=id-m;
10082 if (my_fdchits[my_id]->status==good_hit){
10083 double u=my_fdchits[my_id]->uwire;
10084 double v=my_fdchits[my_id]->vstrip;
10085
10086 // Doca to this wire
10087 double mydoca=(upred-u)*cosalpha;
10088
10089 // variance for coordinate along the wire
10090 V(1,1)=my_fdchits[my_id]->vvar*fdc_anneal_factor;
10091
10092 // Difference between measurement and projection
10093 Mdiff(1)=v-(vpred+mydoca*lorentz_factor);
10094 Mdiff(0)=-mydoca;
10095 if (fit_type==kTimeBased && USE_FDC_DRIFT_TIMES){
10096 double drift_time=my_fdchits[my_id]->t-mT0-traj.t*TIME_UNIT_CONVERSION3.33564095198152014e-02;
10097 double sign=(doca>0.0)?1.:-1.;
10098 if (my_fdchits[my_id]->hit!=NULL__null){
10099 double drift=sign*fdc_drift_distance(drift_time,traj.B);
10100 Mdiff(0)+=drift;
10101
10102 // Variance in drift distance
10103 V(0,0)=fdc_drift_variance(drift_time)*fdc_anneal_factor;
10104 }
10105 else if (USE_TRD_DRIFT_TIMES&&my_fdchits[my_id]->status==trd_hit){
10106 double drift = sign*0.1*pow(drift_time/8./0.91,1./1.556);
10107 Mdiff(0)+=drift;
10108 V(0,0)=0.05*0.05;
10109 }
10110
10111 // H_T contains terms that are proportional to doca, so we only need
10112 // to scale the appropriate elements for the current hit.
10113 if (fabs(doca)<EPS3.0e-8){
10114 doca=(doca>0)?EPS3.0e-8:-EPS3.0e-8;
10115 }
10116 double doca_ratio=mydoca/doca;
10117 DMatrix5x2 H_T_temp=H_T;
10118 H_T_temp(state_tx,1)*=doca_ratio;
10119 H_T_temp(state_ty,1)*=doca_ratio;
10120 H_T_temp(state_tx,0)*=doca_ratio;
10121 H_T_temp(state_ty,0)*=doca_ratio;
10122 H=Transpose(H_T_temp);
10123
10124 // Update error matrix with state vector propagation covariance contrib.
10125 Vtemp=V+H*C*H_T_temp;
10126 // Cut out outliers and compute probability
10127 chi2_hit=Vtemp.Chi2(Mdiff);
10128 if (chi2_hit<fdc_chi2cut){
10129 DMatrix2x2 InvV=Vtemp.Invert();
10130
10131 prob_hit=exp(-0.5*chi2_hit)/(M_TWO_PI6.28318530717958647692*sqrt(Vtemp.Determinant()));
10132 probs.push_back(prob_hit);
10133 Mlist.push_back(Mdiff);
10134 Vlist.push_back(V);
10135 Hlist.push_back(H);
10136 HTlist.push_back(H_T_temp);
10137 Klist.push_back(C*H_T_temp*InvV);
10138
10139 used_ids.push_back(my_id);
10140 fdc_used_in_fit[my_id]=true;
10141
10142 // Add some hit info to the update vector for this plane
10143 fdc_updates[my_id].tdrift=drift_time;
10144 fdc_updates[my_id].tcorr=fdc_updates[my_id].tdrift;
10145 fdc_updates[my_id].doca=mydoca;
10146 }
10147 }
10148 } // check that the hit is "good"
10149 } // loop over remaining hits
10150 if (probs.size()==0) return;
10151
10152 double prob_tot=probs[0];
10153 for (unsigned int m=1;m<probs.size();m++){
10154 prob_tot+=probs[m];
10155 }
10156
10157 if (skip_plane==false){
10158 DMatrix5x5 sum=I5x5;
10159 DMatrix5x5 sum2;
10160 for (unsigned int m=0;m<Klist.size();m++){
10161 double my_prob=probs[m]/prob_tot;
10162 S+=my_prob*(Klist[m]*Mlist[m]);
10163 sum-=my_prob*(Klist[m]*Hlist[m]);
10164 sum2+=(my_prob*my_prob)*(Klist[m]*Vlist[m]*Transpose(Klist[m]));
10165
10166 // Update chi2
10167 DMatrix2x2 HK=Hlist[m]*Klist[m];
10168 DMatrix2x1 R=Mlist[m]-HK*Mlist[m];
10169 DMatrix2x2 RC=Vlist[m]-HK*Vlist[m];
10170 chisq+=my_prob*RC.Chi2(R);
10171
10172 unsigned int my_id=used_ids[m];
10173 fdc_updates[my_id].V=RC;
10174
10175 if (DEBUG_LEVEL > 25)
10176 {
10177 jout << " Adjusting state vector for FDC hit " << m << " with prob " << my_prob << " S:" << endl;
10178 S.Print();
10179 }
10180 }
10181 // Update the covariance matrix C
10182 C=sum2.AddSym(sum*C*sum.Transpose());
10183
10184 if (DEBUG_LEVEL > 25)
10185 { jout << " C: " << endl; C.Print();}
10186 }
10187
10188 // Save some information about the track at this plane in the update vector
10189 for (unsigned int m=0;m<Hlist.size();m++){
10190 unsigned int my_id=used_ids[m];
10191 fdc_updates[my_id].S=S;
10192 fdc_updates[my_id].C=C;
10193 if (skip_plane){
10194 fdc_updates[my_id].V=Vlist[m];
10195 }
10196 }
10197 // update number of degrees of freedom
10198 if (skip_plane==false){
10199 numdof+=2;
10200 }
10201}
10202
10203// Add extrapolation information for the given detector
10204void DTrackFitterKalmanSIMD::AddExtrapolation(DetectorSystem_t detector,
10205 double z,const DMatrix5x1 &S,
10206 double t,double s,
10207 double s_theta_ms_sum,
10208 double theta2ms_sum){
10209 double tsquare=S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty);
10210 double tanl=1./sqrt(tsquare);
10211 double cosl=cos(atan(tanl));
10212 double pt=cosl/fabs(S(state_q_over_p));
10213 double phi=atan2(S(state_ty),S(state_tx));
10214 DVector3 position(S(state_x),S(state_y),z);
10215 DVector3 momentum(pt*cos(phi),pt*sin(phi),pt*tanl);
10216 extrapolations[detector].push_back(Extrapolation_t(position,momentum,
10217 t*TIME_UNIT_CONVERSION3.33564095198152014e-02,s,
10218 s_theta_ms_sum,
10219 theta2ms_sum));
10220 if (DEBUG_LEVEL>0){
10221 cout << SystemName(detector) << ": s=" << s
10222 << " t=" << t*TIME_UNIT_CONVERSION3.33564095198152014e-02 << " (x,y,z)=("
10223 << position.x() <<","<<position.y()<<","<<position.z()<<") (px,py,pz)="
10224 << momentum.x() <<","<<momentum.y()<<","<<momentum.z()<<")"
10225 << endl;
10226 }
10227}
10228
10229// Add extrapolation information for the given detector
10230void DTrackFitterKalmanSIMD::AddExtrapolation(DetectorSystem_t detector,
10231 const DMatrix5x1 &S,
10232 const DVector2 &xy,
10233 double t,double s,
10234 double s_theta_ms_sum,
10235 double theta2ms_sum){
10236 double tanl=S(state_tanl);
10237 double pt=1/fabs(S(state_q_over_pt));
10238 double phi=S(state_phi);
10239 DVector3 position(xy.X(),xy.Y(),S(state_z));
10240 DVector3 momentum(pt*cos(phi),pt*sin(phi),pt*tanl);
10241 extrapolations[detector].push_back(Extrapolation_t(position,momentum,
10242 t*TIME_UNIT_CONVERSION3.33564095198152014e-02,s,
10243 s_theta_ms_sum,
10244 theta2ms_sum));
10245 if (DEBUG_LEVEL>0){
10246 cout << SystemName(detector) << ": s=" << s
10247 << " t=" << t*TIME_UNIT_CONVERSION3.33564095198152014e-02 << " (x,y,z)=("<< position.x()
10248 <<","<<position.y()<<","<<position.z()<<") (px,py,pz)="
10249 << momentum.x() <<","<<momentum.y()<<","<<momentum.z()<<")"
10250 << endl;
10251 }
10252}