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