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