Bug Summary

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