Bug Summary

File:libraries/TRACKING/DTrackFitterKalmanSIMD.cc
Location:line 8796, column 10
Description:Value stored to 'newz' during its initialization is never read

Annotated Source Code

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