File: | /volatile/halld/gluex/nightly/2024-03-08/Linux_CentOS7.7-x86_64-gcc4.8.5/halld_recon/src/libraries/TRACKING/DTrackFitterKalmanSIMD.cc |
Location: | line 8591, column 11 |
Description: | Value stored to 'old_doca2' during its initialization is never read |
1 | //************************************************************************ |
2 | // DTrackFitterKalmanSIMD.cc |
3 | //************************************************************************ |
4 | |
5 | #include "DTrackFitterKalmanSIMD.h" |
6 | #include "CDC/DCDCTrackHit.h" |
7 | #include "HDGEOMETRY/DLorentzDeflections.h" |
8 | #include "HDGEOMETRY/DMaterialMap.h" |
9 | #include "HDGEOMETRY/DRootGeom.h" |
10 | #include "DANA/DApplication.h" |
11 | #include <JANA/JCalibration.h> |
12 | #include "PID/DParticleID.h" |
13 | |
14 | #include <TH2F.h> |
15 | #include <TH1I.h> |
16 | #include <TROOT.h> |
17 | #include <TMath.h> |
18 | #include <DMatrix.h> |
19 | |
20 | #include <iomanip> |
21 | #include <math.h> |
22 | |
23 | #define MAX_TB_PASSES20 20 |
24 | #define MAX_WB_PASSES20 20 |
25 | |
26 | #define ALPHA1./137. 1./137. |
27 | #define CHISQ_DELTA0.01 0.01 |
28 | #define MIN_ITER3 3 |
29 | |
30 | // Only print messages for one thread whenever run number change |
31 | static pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } }; |
32 | static set<int> runs_announced; |
33 | |
34 | // Local boolean routines for sorting |
35 | //bool static DKalmanSIMDHit_cmp(DKalmanSIMDHit_t *a, DKalmanSIMDHit_t *b){ |
36 | // return a->z<b->z; |
37 | //} |
38 | |
39 | inline bool static DKalmanSIMDFDCHit_cmp(DKalmanSIMDFDCHit_t *a, DKalmanSIMDFDCHit_t *b){ |
40 | if (fabs(a->z-b->z)<EPS3.0e-8){ |
41 | if (a->hit!=NULL__null && b->hit!=NULL__null && fabs(a->t-b->t)<EPS3.0e-8){ |
42 | double tsum_1=a->hit->t_u+a->hit->t_v; |
43 | double tsum_2=b->hit->t_u+b->hit->t_v; |
44 | if (fabs(tsum_1-tsum_2)<EPS3.0e-8){ |
45 | return (a->dE>b->dE); |
46 | } |
47 | return (tsum_1<tsum_2); |
48 | } |
49 | return(a->t<b->t); |
50 | } |
51 | return a->z<b->z; |
52 | } |
53 | inline bool static DKalmanSIMDCDCHit_cmp(DKalmanSIMDCDCHit_t *a, DKalmanSIMDCDCHit_t *b){ |
54 | if (a==NULL__null || b==NULL__null){ |
55 | cout << "Null pointer in CDC hit list??" << endl; |
56 | return false; |
57 | } |
58 | const DCDCWire *wire_a= a->hit->wire; |
59 | const DCDCWire *wire_b= b->hit->wire; |
60 | if(wire_b->ring == wire_a->ring){ |
61 | return wire_b->straw < wire_a->straw; |
62 | } |
63 | |
64 | return (wire_b->ring>wire_a->ring); |
65 | } |
66 | |
67 | |
68 | // Locate a position in array xx given x |
69 | void DTrackFitterKalmanSIMD::locate(const double *xx,int n,double x,int *j){ |
70 | int jl=-1; |
71 | int ju=n; |
72 | int ascnd=(xx[n-1]>=xx[0]); |
73 | while(ju-jl>1){ |
74 | int jm=(ju+jl)>>1; |
75 | if ( (x>=xx[jm])==ascnd) |
76 | jl=jm; |
77 | else |
78 | ju=jm; |
79 | } |
80 | if (x==xx[0]) *j=0; |
81 | else if (x==xx[n-1]) *j=n-2; |
82 | else *j=jl; |
83 | } |
84 | |
85 | |
86 | |
87 | // Locate a position in vector xx given x |
88 | unsigned int DTrackFitterKalmanSIMD::locate(vector<double>&xx,double x){ |
89 | int n=xx.size(); |
90 | if (x==xx[0]) return 0; |
91 | else if (x==xx[n-1]) return n-2; |
92 | |
93 | int jl=-1; |
94 | int ju=n; |
95 | int ascnd=(xx[n-1]>=xx[0]); |
96 | while(ju-jl>1){ |
97 | int jm=(ju+jl)>>1; |
98 | if ( (x>=xx[jm])==ascnd) |
99 | jl=jm; |
100 | else |
101 | ju=jm; |
102 | } |
103 | return jl; |
104 | } |
105 | |
106 | // Crude approximation for the variance in drift distance due to smearing |
107 | double DTrackFitterKalmanSIMD::fdc_drift_variance(double t) const { |
108 | //return FDC_ANODE_VARIANCE; |
109 | double dt=0.; |
110 | double t_lo=DRIFT_RES_PARMS[3]; |
111 | double t_hi=DRIFT_RES_PARMS[4]; |
112 | if (t<t_lo) t=t_lo; |
113 | if (t>t_hi){ |
114 | t=t_hi; |
115 | dt=t-t_hi; |
116 | } |
117 | double sigma=DRIFT_RES_PARMS[0]/(t+1.)+DRIFT_RES_PARMS[1]+DRIFT_RES_PARMS[2]*t*t; |
118 | if (dt>0){ |
119 | sigma+=DRIFT_RES_PARMS[5]*dt; |
120 | } |
121 | |
122 | return sigma*sigma; |
123 | } |
124 | |
125 | // Convert time to distance for the cdc and compute variance |
126 | void DTrackFitterKalmanSIMD::ComputeCDCDrift(double dphi,double delta,double t, |
127 | double B, |
128 | double &d, double &V, double &tcorr){ |
129 | //d=0.39; // initialize at half-cell |
130 | //V=0.0507; // initialize with (cell size)/12. |
131 | tcorr = t; // Need this value even when t is negative for calibration |
132 | if (t>0){ |
133 | double dtc =(CDC_DRIFT_BSCALE_PAR1 + CDC_DRIFT_BSCALE_PAR2 * B)* t; |
134 | tcorr=t-dtc; |
135 | |
136 | // CDC_RES_PAR2=0.005; |
137 | double sigma=CDC_RES_PAR1/(tcorr+1.) + CDC_RES_PAR2 + CDC_RES_PAR3*tcorr; |
138 | |
139 | // Variables to store values for time-to-distance functions for delta=0 |
140 | // and delta!=0 |
141 | double f_0=0.; |
142 | double f_delta=0.; |
143 | // Derivative of d with respect to t, needed to add t0 variance |
144 | // dependence to sigma |
145 | double dd_dt=0; |
146 | // Scale factor to account for effect of B-field on maximum drift time |
147 | //double Bscale=long_drift_Bscale_par1+long_drift_Bscale_par2*B; |
148 | // tcorr=t*Bscale; |
149 | |
150 | // NSJ 26 May 2020 included long side a3, b3 and short side c1, c2, c3 |
151 | // Previously these parameters were not used (0 in ccdb) for production runs |
152 | // except intensity scan run 72312 by accident 5 May 2020, superseded 8 May. |
153 | // They were used in 2015 for runs 0-3050. |
154 | |
155 | // if (delta>0) |
156 | if (delta>-EPS21.e-4){ |
157 | double a1=long_drift_func[0][0]; |
158 | double a2=long_drift_func[0][1]; |
159 | double a3=long_drift_func[0][2]; |
160 | double b1=long_drift_func[1][0]; |
161 | double b2=long_drift_func[1][1]; |
162 | double b3=long_drift_func[1][2]; |
163 | double c1=long_drift_func[2][0]; |
164 | double c2=long_drift_func[2][1]; |
165 | double c3=long_drift_func[2][2]; |
166 | |
167 | // use "long side" functional form |
168 | double my_t=0.001*tcorr; |
169 | double sqrt_t=sqrt(my_t); |
170 | double t3=my_t*my_t*my_t; |
171 | double delta_mag=fabs(delta); |
172 | |
173 | double delta_sq=delta*delta; |
174 | double a=a1+a2*delta_mag+a3*delta_sq; |
175 | double b=b1+b2*delta_mag+b3*delta_sq; |
176 | double c=c1+c2*delta_mag+c3*delta_sq; |
177 | |
178 | f_delta=a*sqrt_t+b*my_t+c*t3; |
179 | f_0=a1*sqrt_t+b1*my_t+c1*t3; |
180 | |
181 | dd_dt=0.001*(0.5*a/sqrt_t+b+3.*c*my_t*my_t); |
182 | } |
183 | else{ |
184 | double my_t=0.001*tcorr; |
185 | double sqrt_t=sqrt(my_t); |
186 | double t3=my_t*my_t*my_t; |
187 | double delta_mag=fabs(delta); |
188 | |
189 | // use "short side" functional form |
190 | double a1=short_drift_func[0][0]; |
191 | double a2=short_drift_func[0][1]; |
192 | double a3=short_drift_func[0][2]; |
193 | double b1=short_drift_func[1][0]; |
194 | double b2=short_drift_func[1][1]; |
195 | double b3=short_drift_func[1][2]; |
196 | double c1=short_drift_func[2][0]; |
197 | double c2=short_drift_func[2][1]; |
198 | double c3=short_drift_func[2][2]; |
199 | |
200 | double delta_sq=delta*delta; |
201 | double a=a1+a2*delta_mag+a3*delta_sq; |
202 | double b=b1+b2*delta_mag+b3*delta_sq; |
203 | double c=c1+c2*delta_mag+c3*delta_sq; |
204 | |
205 | f_delta=a*sqrt_t+b*my_t+c*t3; |
206 | f_0=a1*sqrt_t+b1*my_t+c1*t3; |
207 | |
208 | dd_dt=0.001*(0.5*a/sqrt_t+b+3.*c*my_t*my_t); |
209 | |
210 | } |
211 | |
212 | unsigned int max_index=cdc_drift_table.size()-1; |
213 | if (tcorr>cdc_drift_table[max_index]){ |
214 | //_DBG_ << "t: " << tcorr <<" d " << f_delta <<endl; |
215 | d=f_delta; |
216 | V=sigma*sigma+mVarT0*dd_dt*dd_dt; |
217 | |
218 | return; |
219 | } |
220 | |
221 | // Drift time is within range of table -- interpolate... |
222 | unsigned int index=0; |
223 | index=locate(cdc_drift_table,tcorr); |
224 | double dt=cdc_drift_table[index+1]-cdc_drift_table[index]; |
225 | double frac=(tcorr-cdc_drift_table[index])/dt; |
226 | double d_0=0.01*(double(index)+frac); |
227 | |
228 | if (fabs(delta) < EPS21.e-4){ |
229 | d=d_0; |
230 | V=sigma*sigma+mVarT0*dd_dt*dd_dt; |
231 | } |
232 | else{ |
233 | double P=0.; |
234 | double tcut=250.0; // ns |
235 | if (tcorr<tcut) { |
236 | P=(tcut-tcorr)/tcut; |
237 | } |
238 | d=f_delta*(d_0/f_0*P+1.-P); |
239 | V=sigma*sigma+mVarT0*dd_dt*dd_dt; |
240 | } |
241 | } |
242 | else { // Time is negative, or exactly zero, choose position at wire, with error of t=0 hit |
243 | d=0.; |
244 | double sigma = CDC_RES_PAR1+CDC_RES_PAR2; |
245 | double dt=cdc_drift_table[1]-cdc_drift_table[0]; |
246 | V=sigma*sigma+mVarT0*0.0001/(dt*dt); |
247 | //V=0.0507; // straw radius^2 / 12 |
248 | } |
249 | |
250 | } |
251 | |
252 | #define FDC_T0_OFFSET17.6 17.6 |
253 | // Interpolate on a table to convert time to distance for the fdc |
254 | /* |
255 | double DTrackFitterKalmanSIMD::fdc_drift_distance(double t,double Bz) const { |
256 | double a=93.31,b=4.614,Bref=2.143; |
257 | t*=(a+b*Bref)/(a+b*Bz); |
258 | int id=int((t+FDC_T0_OFFSET)/2.); |
259 | if (id<0) id=0; |
260 | if (id>138) id=138; |
261 | double d=fdc_drift_table[id]; |
262 | if (id!=138){ |
263 | double frac=0.5*(t+FDC_T0_OFFSET-2.*double(id)); |
264 | double dd=fdc_drift_table[id+1]-fdc_drift_table[id]; |
265 | d+=frac*dd; |
266 | } |
267 | |
268 | return d; |
269 | } |
270 | */ |
271 | |
272 | // parametrization of time-to-distance for FDC |
273 | double DTrackFitterKalmanSIMD::fdc_drift_distance(double time,double Bz) const { |
274 | if (time<0.) return 0.; |
275 | double d=0.; |
276 | time/=1.+FDC_DRIFT_BSCALE_PAR1+FDC_DRIFT_BSCALE_PAR2*Bz*Bz; |
277 | double tsq=time*time; |
278 | double t_high=DRIFT_FUNC_PARMS[4]; |
279 | |
280 | if (time<t_high){ |
281 | d=DRIFT_FUNC_PARMS[0]*sqrt(time)+DRIFT_FUNC_PARMS[1]*time |
282 | +DRIFT_FUNC_PARMS[2]*tsq+DRIFT_FUNC_PARMS[3]*tsq*time; |
283 | } |
284 | else{ |
285 | double t_high_sq=t_high*t_high; |
286 | d=DRIFT_FUNC_PARMS[0]*sqrt(t_high)+DRIFT_FUNC_PARMS[1]*t_high |
287 | +DRIFT_FUNC_PARMS[2]*t_high_sq+DRIFT_FUNC_PARMS[3]*t_high_sq*t_high; |
288 | d+=DRIFT_FUNC_PARMS[5]*(time-t_high); |
289 | } |
290 | |
291 | return d; |
292 | } |
293 | |
294 | |
295 | DTrackFitterKalmanSIMD::DTrackFitterKalmanSIMD(JEventLoop *loop):DTrackFitter(loop){ |
296 | FactorForSenseOfRotation=(bfield->GetBz(0.,0.,65.)>0.)?-1.:1.; |
297 | |
298 | // keep track of which runs we print out messages for |
299 | int32_t runnumber = loop->GetJEvent().GetRunNumber(); |
300 | pthread_mutex_lock(&print_mutex); |
301 | bool print_messages = false; |
302 | if(runs_announced.find(runnumber) == runs_announced.end()){ |
303 | print_messages = true; |
304 | runs_announced.insert(runnumber); |
305 | } |
306 | pthread_mutex_unlock(&print_mutex); |
307 | |
308 | // Some useful values |
309 | two_m_e=2.*ELECTRON_MASS0.000511; |
310 | m_e_sq=ELECTRON_MASS0.000511*ELECTRON_MASS0.000511; |
311 | |
312 | // Get the position of the CDC downstream endplate from DGeometry |
313 | double endplate_rmin,endplate_rmax; |
314 | geom->GetCDCEndplate(endplate_z,endplate_dz,endplate_rmin,endplate_rmax); |
315 | endplate_z-=0.5*endplate_dz; |
316 | endplate_z_downstream=endplate_z+endplate_dz; |
317 | endplate_rmin+=0.1; // put just inside CDC |
318 | endplate_r2min=endplate_rmin*endplate_rmin; |
319 | endplate_r2max=endplate_rmax*endplate_rmax; |
320 | |
321 | // Beginning of the cdc |
322 | vector<double>cdc_center; |
323 | vector<double>cdc_upstream_endplate_pos; |
324 | vector<double>cdc_endplate_dim; |
325 | geom->Get("//posXYZ[@volume='CentralDC'/@X_Y_Z",cdc_origin); |
326 | geom->Get("//posXYZ[@volume='centralDC']/@X_Y_Z",cdc_center); |
327 | geom->Get("//posXYZ[@volume='CDPU']/@X_Y_Z",cdc_upstream_endplate_pos); |
328 | geom->Get("//tubs[@name='CDPU']/@Rio_Z",cdc_endplate_dim); |
329 | cdc_origin[2]+=cdc_center[2]+cdc_upstream_endplate_pos[2] |
330 | +0.5*cdc_endplate_dim[2]; |
331 | |
332 | // Outer detector geometry parameters |
333 | geom->GetFCALZ(dFCALz); |
334 | dFCALzBack=dFCALz+45.; |
335 | if (geom->GetDIRCZ(dDIRCz)==false) dDIRCz=1000.; |
336 | geom->GetFMWPCZ_vec(dFMWPCz_vec); |
337 | geom->GetFMWPCSize(dFMWPCsize); |
338 | geom->GetCTOFZ(dCTOFz); |
339 | |
340 | vector<double>tof_face; |
341 | geom->Get("//section/composition/posXYZ[@volume='ForwardTOF']/@X_Y_Z", |
342 | tof_face); |
343 | vector<double>tof_plane; |
344 | geom->Get("//composition[@name='ForwardTOF']/posXYZ[@volume='forwardTOF']/@X_Y_Z/plane[@value='0']", tof_plane); |
345 | dTOFz=tof_face[2]+tof_plane[2]; |
346 | geom->Get("//composition[@name='ForwardTOF']/posXYZ[@volume='forwardTOF']/@X_Y_Z/plane[@value='1']", tof_plane); |
347 | dTOFz+=tof_face[2]+tof_plane[2]; |
348 | dTOFz*=0.5; // mid plane between tof planes |
349 | geom->GetTRDZ(dTRDz_vec); // TRD planes |
350 | |
351 | // Get start counter geometry; |
352 | if (geom->GetStartCounterGeom(sc_pos, sc_norm)){ |
353 | // Create vector of direction vectors in scintillator planes |
354 | for (int i=0;i<30;i++){ |
355 | vector<DVector3>temp; |
356 | for (unsigned int j=0;j<sc_pos[i].size()-1;j++){ |
357 | double dx=sc_pos[i][j+1].x()-sc_pos[i][j].x(); |
358 | double dy=sc_pos[i][j+1].y()-sc_pos[i][j].y(); |
359 | double dz=sc_pos[i][j+1].z()-sc_pos[i][j].z(); |
360 | temp.push_back(DVector3(dx/dz,dy/dz,1.)); |
361 | } |
362 | sc_dir.push_back(temp); |
363 | } |
364 | SC_END_NOSE_Z=sc_pos[0][12].z(); |
365 | SC_BARREL_R2=sc_pos[0][0].Perp2(); |
366 | SC_PHI_SECTOR1=sc_pos[0][0].Phi(); |
367 | } |
368 | |
369 | // Get z positions of fdc wire planes |
370 | geom->GetFDCZ(fdc_z_wires); |
371 | |
372 | ADD_VERTEX_POINT=false; |
373 | gPARMS->SetDefaultParameter("KALMAN:ADD_VERTEX_POINT", ADD_VERTEX_POINT); |
374 | |
375 | THETA_CUT=60.0; |
376 | gPARMS->SetDefaultParameter("KALMAN:THETA_CUT", THETA_CUT); |
377 | |
378 | RING_TO_SKIP=0; |
379 | gPARMS->SetDefaultParameter("KALMAN:RING_TO_SKIP",RING_TO_SKIP); |
380 | |
381 | PLANE_TO_SKIP=0; |
382 | gPARMS->SetDefaultParameter("KALMAN:PLANE_TO_SKIP",PLANE_TO_SKIP); |
383 | |
384 | MINIMUM_HIT_FRACTION=0.7; |
385 | gPARMS->SetDefaultParameter("KALMAN:MINIMUM_HIT_FRACTION",MINIMUM_HIT_FRACTION); |
386 | MIN_HITS_FOR_REFIT=6; |
387 | gPARMS->SetDefaultParameter("KALMAN:MIN_HITS_FOR_REFIT", MIN_HITS_FOR_REFIT); |
388 | PHOTON_ENERGY_CUTOFF=0.125; |
389 | gPARMS->SetDefaultParameter("KALMAN:PHOTON_ENERGY_CUTOFF", |
390 | PHOTON_ENERGY_CUTOFF); |
391 | |
392 | USE_FDC_HITS=true; |
393 | gPARMS->SetDefaultParameter("TRKFIT:USE_FDC_HITS",USE_FDC_HITS); |
394 | USE_CDC_HITS=true; |
395 | gPARMS->SetDefaultParameter("TRKFIT:USE_CDC_HITS",USE_CDC_HITS); |
396 | USE_TRD_HITS=false; |
397 | gPARMS->SetDefaultParameter("TRKFIT:USE_TRD_HITS",USE_TRD_HITS); |
398 | USE_TRD_DRIFT_TIMES=true; |
399 | gPARMS->SetDefaultParameter("TRKFIT:USE_TRD_DRIFT_TIMES",USE_TRD_DRIFT_TIMES); |
400 | USE_GEM_HITS=false; |
401 | gPARMS->SetDefaultParameter("TRKFIT:USE_GEM_HITS",USE_GEM_HITS); |
402 | |
403 | |
404 | // Flag to enable calculation of alignment derivatives |
405 | ALIGNMENT=false; |
406 | gPARMS->SetDefaultParameter("TRKFIT:ALIGNMENT",ALIGNMENT); |
407 | |
408 | ALIGNMENT_FORWARD=false; |
409 | gPARMS->SetDefaultParameter("TRKFIT:ALIGNMENT_FORWARD",ALIGNMENT_FORWARD); |
410 | |
411 | ALIGNMENT_CENTRAL=false; |
412 | gPARMS->SetDefaultParameter("TRKFIT:ALIGNMENT_CENTRAL",ALIGNMENT_CENTRAL); |
413 | |
414 | if(ALIGNMENT){ALIGNMENT_FORWARD=true;ALIGNMENT_CENTRAL=true;} |
415 | |
416 | DEBUG_HISTS=false; |
417 | gPARMS->SetDefaultParameter("KALMAN:DEBUG_HISTS", DEBUG_HISTS); |
418 | |
419 | DEBUG_LEVEL=0; |
420 | gPARMS->SetDefaultParameter("KALMAN:DEBUG_LEVEL", DEBUG_LEVEL); |
421 | |
422 | USE_T0_FROM_WIRES=0; |
423 | gPARMS->SetDefaultParameter("KALMAN:USE_T0_FROM_WIRES", USE_T0_FROM_WIRES); |
424 | |
425 | ESTIMATE_T0_TB=false; |
426 | gPARMS->SetDefaultParameter("KALMAN:ESTIMATE_T0_TB",ESTIMATE_T0_TB); |
427 | |
428 | ENABLE_BOUNDARY_CHECK=true; |
429 | gPARMS->SetDefaultParameter("GEOM:ENABLE_BOUNDARY_CHECK", |
430 | ENABLE_BOUNDARY_CHECK); |
431 | |
432 | USE_MULS_COVARIANCE=true; |
433 | gPARMS->SetDefaultParameter("TRKFIT:USE_MULS_COVARIANCE", |
434 | USE_MULS_COVARIANCE); |
435 | |
436 | USE_PASS1_TIME_MODE=false; |
437 | gPARMS->SetDefaultParameter("KALMAN:USE_PASS1_TIME_MODE",USE_PASS1_TIME_MODE); |
438 | |
439 | USE_FDC_DRIFT_TIMES=true; |
440 | gPARMS->SetDefaultParameter("TRKFIT:USE_FDC_DRIFT_TIMES", |
441 | USE_FDC_DRIFT_TIMES); |
442 | |
443 | RECOVER_BROKEN_TRACKS=true; |
444 | gPARMS->SetDefaultParameter("KALMAN:RECOVER_BROKEN_TRACKS",RECOVER_BROKEN_TRACKS); |
445 | |
446 | NUM_CDC_SIGMA_CUT=5.0; |
447 | NUM_FDC_SIGMA_CUT=5.0; |
448 | gPARMS->SetDefaultParameter("KALMAN:NUM_CDC_SIGMA_CUT",NUM_CDC_SIGMA_CUT, |
449 | "maximum distance in number of sigmas away from projection to accept cdc hit"); |
450 | gPARMS->SetDefaultParameter("KALMAN:NUM_FDC_SIGMA_CUT",NUM_FDC_SIGMA_CUT, |
451 | "maximum distance in number of sigmas away from projection to accept fdc hit"); |
452 | |
453 | ANNEAL_SCALE=9.0; |
454 | ANNEAL_POW_CONST=1.5; |
455 | gPARMS->SetDefaultParameter("KALMAN:ANNEAL_SCALE",ANNEAL_SCALE, |
456 | "Scale factor for annealing"); |
457 | gPARMS->SetDefaultParameter("KALMAN:ANNEAL_POW_CONST",ANNEAL_POW_CONST, |
458 | "Annealing parameter"); |
459 | FORWARD_ANNEAL_SCALE=9.; |
460 | FORWARD_ANNEAL_POW_CONST=1.5; |
461 | gPARMS->SetDefaultParameter("KALMAN:FORWARD_ANNEAL_SCALE", |
462 | FORWARD_ANNEAL_SCALE, |
463 | "Scale factor for annealing"); |
464 | gPARMS->SetDefaultParameter("KALMAN:FORWARD_ANNEAL_POW_CONST", |
465 | FORWARD_ANNEAL_POW_CONST, |
466 | "Annealing parameter"); |
467 | |
468 | FORWARD_PARMS_COV=false; |
469 | gPARMS->SetDefaultParameter("KALMAN:FORWARD_PARMS_COV",FORWARD_PARMS_COV); |
470 | |
471 | CDC_VAR_SCALE_FACTOR=1.; |
472 | gPARMS->SetDefaultParameter("KALMAN:CDC_VAR_SCALE_FACTOR",CDC_VAR_SCALE_FACTOR); |
473 | CDC_T_DRIFT_MIN=-12.; // One f125 clock = 8 ns |
474 | gPARMS->SetDefaultParameter("KALMAN:CDC_T_DRIFT_MIN",CDC_T_DRIFT_MIN); |
475 | |
476 | MOLIERE_FRACTION=0.9; |
477 | gPARMS->SetDefaultParameter("KALMAN:MOLIERE_FRACTION",MOLIERE_FRACTION); |
478 | MS_SCALE_FACTOR=2.0; |
479 | gPARMS->SetDefaultParameter("KALMAN:MS_SCALE_FACTOR",MS_SCALE_FACTOR); |
480 | MOLIERE_RATIO1=0.5/(1.-MOLIERE_FRACTION); |
481 | MOLIERE_RATIO2=MS_SCALE_FACTOR*1.e-6/(1.+MOLIERE_FRACTION*MOLIERE_FRACTION); //scale_factor/(1+F*F) |
482 | |
483 | COVARIANCE_SCALE_FACTOR_CENTRAL=2.0; |
484 | gPARMS->SetDefaultParameter("KALMAN:COVARIANCE_SCALE_FACTOR_CENTRAL", |
485 | COVARIANCE_SCALE_FACTOR_CENTRAL); |
486 | |
487 | COVARIANCE_SCALE_FACTOR_FORWARD=2.0; |
488 | gPARMS->SetDefaultParameter("KALMAN:COVARIANCE_SCALE_FACTOR_FORWARD", |
489 | COVARIANCE_SCALE_FACTOR_FORWARD); |
490 | |
491 | WRITE_ML_TRAINING_OUTPUT=false; |
492 | gPARMS->SetDefaultParameter("KALMAN:WRITE_ML_TRAINING_OUTPUT", |
493 | WRITE_ML_TRAINING_OUTPUT); |
494 | |
495 | if (WRITE_ML_TRAINING_OUTPUT){ |
496 | mlfile.open("mltraining.dat"); |
497 | } |
498 | |
499 | |
500 | DApplication* dapp = dynamic_cast<DApplication*>(loop->GetJApplication()); |
501 | JCalibration *jcalib = dapp->GetJCalibration((loop->GetJEvent()).GetRunNumber()); |
502 | vector< map<string, double> > tvals; |
503 | cdc_drift_table.clear(); |
504 | if (jcalib->Get("CDC/cdc_drift_table", tvals)==false){ |
505 | for(unsigned int i=0; i<tvals.size(); i++){ |
506 | map<string, double> &row = tvals[i]; |
507 | cdc_drift_table.push_back(1000.*row["t"]); |
508 | } |
509 | } |
510 | else{ |
511 | jerr << " CDC time-to-distance table not available... bailing..." << endl; |
512 | exit(0); |
513 | } |
514 | |
515 | int straw_number[28]={42,42,54,54,66,66,80,80,93,93,106,106, |
516 | 123,123,135,135,146,146,158,158,170,170, |
517 | 182,182,197,197,209,209}; |
518 | max_sag.clear(); |
519 | sag_phi_offset.clear(); |
520 | int straw_count=0,ring_count=0; |
521 | if (jcalib->Get("CDC/sag_parameters", tvals)==false){ |
522 | vector<double>temp,temp2; |
523 | for(unsigned int i=0; i<tvals.size(); i++){ |
524 | map<string, double> &row = tvals[i]; |
525 | |
526 | temp.push_back(row["offset"]); |
527 | temp2.push_back(row["phi"]); |
528 | |
529 | straw_count++; |
530 | if (straw_count==straw_number[ring_count]){ |
531 | max_sag.push_back(temp); |
532 | sag_phi_offset.push_back(temp2); |
533 | temp.clear(); |
534 | temp2.clear(); |
535 | straw_count=0; |
536 | ring_count++; |
537 | } |
538 | } |
539 | } |
540 | |
541 | if (jcalib->Get("CDC/drift_parameters", tvals)==false){ |
542 | map<string, double> &row = tvals[0]; // long drift side |
543 | long_drift_func[0][0]=row["a1"]; |
544 | long_drift_func[0][1]=row["a2"]; |
545 | long_drift_func[0][2]=row["a3"]; |
546 | long_drift_func[1][0]=row["b1"]; |
547 | long_drift_func[1][1]=row["b2"]; |
548 | long_drift_func[1][2]=row["b3"]; |
549 | long_drift_func[2][0]=row["c1"]; |
550 | long_drift_func[2][1]=row["c2"]; |
551 | long_drift_func[2][2]=row["c3"]; |
552 | long_drift_Bscale_par1=row["B1"]; |
553 | long_drift_Bscale_par2=row["B2"]; |
554 | |
555 | row = tvals[1]; // short drift side |
556 | short_drift_func[0][0]=row["a1"]; |
557 | short_drift_func[0][1]=row["a2"]; |
558 | short_drift_func[0][2]=row["a3"]; |
559 | short_drift_func[1][0]=row["b1"]; |
560 | short_drift_func[1][1]=row["b2"]; |
561 | short_drift_func[1][2]=row["b3"]; |
562 | short_drift_func[2][0]=row["c1"]; |
563 | short_drift_func[2][1]=row["c2"]; |
564 | short_drift_func[2][2]=row["c3"]; |
565 | short_drift_Bscale_par1=row["B1"]; |
566 | short_drift_Bscale_par2=row["B2"]; |
567 | } |
568 | |
569 | map<string, double> cdc_drift_parms; |
570 | jcalib->Get("CDC/cdc_drift_parms", cdc_drift_parms); |
571 | CDC_DRIFT_BSCALE_PAR1 = cdc_drift_parms["bscale_par1"]; |
572 | CDC_DRIFT_BSCALE_PAR2 = cdc_drift_parms["bscale_par2"]; |
573 | |
574 | map<string, double> cdc_res_parms; |
575 | jcalib->Get("CDC/cdc_resolution_parms_v2", cdc_res_parms); |
576 | CDC_RES_PAR1 = cdc_res_parms["res_par1"]; |
577 | CDC_RES_PAR2 = cdc_res_parms["res_par2"]; |
578 | CDC_RES_PAR3 = cdc_res_parms["res_par3"]; |
579 | |
580 | // Parameters for correcting for deflection due to Lorentz force |
581 | map<string,double>lorentz_parms; |
582 | jcalib->Get("FDC/lorentz_deflection_parms",lorentz_parms); |
583 | LORENTZ_NR_PAR1=lorentz_parms["nr_par1"]; |
584 | LORENTZ_NR_PAR2=lorentz_parms["nr_par2"]; |
585 | LORENTZ_NZ_PAR1=lorentz_parms["nz_par1"]; |
586 | LORENTZ_NZ_PAR2=lorentz_parms["nz_par2"]; |
587 | |
588 | // Parameters for accounting for variation in drift distance from FDC |
589 | map<string,double>drift_res_parms; |
590 | jcalib->Get("FDC/drift_resolution_parms",drift_res_parms); |
591 | DRIFT_RES_PARMS[0]=drift_res_parms["p0"]; |
592 | DRIFT_RES_PARMS[1]=drift_res_parms["p1"]; |
593 | DRIFT_RES_PARMS[2]=drift_res_parms["p2"]; |
594 | map<string,double>drift_res_ext; |
595 | jcalib->Get("FDC/drift_resolution_ext",drift_res_ext); |
596 | DRIFT_RES_PARMS[3]=drift_res_ext["t_low"]; |
597 | DRIFT_RES_PARMS[4]=drift_res_ext["t_high"]; |
598 | DRIFT_RES_PARMS[5]=drift_res_ext["res_slope"]; |
599 | |
600 | // Time-to-distance function parameters for FDC |
601 | map<string,double>drift_func_parms; |
602 | jcalib->Get("FDC/drift_function_parms",drift_func_parms); |
603 | DRIFT_FUNC_PARMS[0]=drift_func_parms["p0"]; |
604 | DRIFT_FUNC_PARMS[1]=drift_func_parms["p1"]; |
605 | DRIFT_FUNC_PARMS[2]=drift_func_parms["p2"]; |
606 | DRIFT_FUNC_PARMS[3]=drift_func_parms["p3"]; |
607 | DRIFT_FUNC_PARMS[4]=1000.; |
608 | DRIFT_FUNC_PARMS[5]=0.; |
609 | map<string,double>drift_func_ext; |
610 | if (jcalib->Get("FDC/drift_function_ext",drift_func_ext)==false){ |
611 | DRIFT_FUNC_PARMS[4]=drift_func_ext["p4"]; |
612 | DRIFT_FUNC_PARMS[5]=drift_func_ext["p5"]; |
613 | } |
614 | // Factors for taking care of B-dependence of drift time for FDC |
615 | map<string, double> fdc_drift_parms; |
616 | jcalib->Get("FDC/fdc_drift_parms", fdc_drift_parms); |
617 | FDC_DRIFT_BSCALE_PAR1 = fdc_drift_parms["bscale_par1"]; |
618 | FDC_DRIFT_BSCALE_PAR2 = fdc_drift_parms["bscale_par2"]; |
619 | |
620 | |
621 | /* |
622 | if (jcalib->Get("FDC/fdc_drift2", tvals)==false){ |
623 | for(unsigned int i=0; i<tvals.size(); i++){ |
624 | map<string, float> &row = tvals[i]; |
625 | iter_float iter = row.begin(); |
626 | fdc_drift_table[i] = iter->second; |
627 | } |
628 | } |
629 | else{ |
630 | jerr << " FDC time-to-distance table not available... bailing..." << endl; |
631 | exit(0); |
632 | } |
633 | */ |
634 | |
635 | for (unsigned int i=0;i<5;i++)I5x5(i,i)=1.; |
636 | |
637 | |
638 | // center of the target |
639 | map<string, double> targetparms; |
640 | if (jcalib->Get("TARGET/target_parms",targetparms)==false){ |
641 | TARGET_Z = targetparms["TARGET_Z_POSITION"]; |
642 | } |
643 | else{ |
644 | geom->GetTargetZ(TARGET_Z); |
645 | } |
646 | if (ADD_VERTEX_POINT){ |
647 | gPARMS->SetDefaultParameter("KALMAN:VERTEX_POSITION",TARGET_Z); |
648 | } |
649 | |
650 | // Beam position and direction |
651 | map<string, double> beam_vals; |
652 | jcalib->Get("PHOTON_BEAM/beam_spot",beam_vals); |
653 | beam_center.Set(beam_vals["x"],beam_vals["y"]); |
654 | beam_dir.Set(beam_vals["dxdz"],beam_vals["dydz"]); |
655 | |
656 | if(print_messages) |
657 | jout << " Beam spot: x=" << beam_center.X() << " y=" << beam_center.Y() |
658 | << " z=" << beam_vals["z"] |
659 | << " dx/dz=" << beam_dir.X() << " dy/dz=" << beam_dir.Y() << endl; |
660 | beam_z0=beam_vals["z"]; |
661 | |
662 | // Inform user of some configuration settings |
663 | static bool config_printed = false; |
664 | if(!config_printed){ |
665 | config_printed = true; |
666 | stringstream ss; |
667 | ss << "vertex constraint: " ; |
668 | if(ADD_VERTEX_POINT){ |
669 | ss << "z = " << TARGET_Z << "cm" << endl; |
670 | }else{ |
671 | ss << "<none>" << endl; |
672 | } |
673 | jout << ss.str(); |
674 | } // config_printed |
675 | |
676 | if(DEBUG_HISTS){ |
677 | for (auto i=0; i < 46; i++){ |
678 | double min = -10., max=10.; |
679 | if(i%23<12) {min=-5; max=5;} |
680 | if(i<23)alignDerivHists[i]=new TH1I(Form("CentralDeriv%i",i),Form("CentralDeriv%i",i),200, min, max); |
681 | else alignDerivHists[i]=new TH1I(Form("ForwardDeriv%i",i%23),Form("ForwardDeriv%i",i%23),200, min, max); |
682 | } |
683 | brentCheckHists[0]=new TH2I("ForwardBrentCheck","DOCA vs ds", 100, -5., 5., 100, 0.0, 1.5); |
684 | brentCheckHists[1]=new TH2I("CentralBrentCheck","DOCA vs ds", 100, -5., 5., 100, 0.0, 1.5); |
685 | } |
686 | |
687 | dResourcePool_TMatrixFSym = std::make_shared<DResourcePool<TMatrixFSym>>(); |
688 | dResourcePool_TMatrixFSym->Set_ControlParams(20, 20, 50); |
689 | |
690 | my_fdchits.reserve(24); |
691 | my_cdchits.reserve(28); |
692 | fdc_updates.reserve(24); |
693 | cdc_updates.reserve(28); |
694 | cdc_used_in_fit.reserve(28); |
695 | fdc_used_in_fit.reserve(24); |
696 | } |
697 | |
698 | //----------------- |
699 | // ResetKalmanSIMD |
700 | //----------------- |
701 | void DTrackFitterKalmanSIMD::ResetKalmanSIMD(void) |
702 | { |
703 | last_material_map=0; |
704 | |
705 | for (unsigned int i=0;i<my_cdchits.size();i++){ |
706 | delete my_cdchits[i]; |
707 | } |
708 | for (unsigned int i=0;i<my_fdchits.size();i++){ |
709 | delete my_fdchits[i]; |
710 | } |
711 | central_traj.clear(); |
712 | forward_traj.clear(); |
713 | my_fdchits.clear(); |
714 | my_cdchits.clear(); |
715 | fdc_updates.clear(); |
716 | cdc_updates.clear(); |
717 | fdc_used_in_fit.clear(); |
718 | cdc_used_in_fit.clear(); |
719 | got_trd_gem_hits=false; |
720 | |
721 | cov.clear(); |
722 | fcov.clear(); |
723 | |
724 | len = 0.0; |
725 | ftime=0.0; |
726 | var_ftime=0.0; |
727 | x_=0.,y_=0.,tx_=0.,ty_=0.,q_over_p_ = 0.0; |
728 | z_=0.,phi_=0.,tanl_=0.,q_over_pt_ =0, D_= 0.0; |
729 | chisq_ = 0.0; |
730 | ndf_ = 0; |
731 | MASS=0.13957; |
732 | mass2=MASS*MASS; |
733 | Bx=By=0.; |
734 | Bz=2.; |
735 | dBxdx=0.,dBxdy=0.,dBxdz=0.,dBydx=0.,dBydy=0.,dBydy=0.,dBzdx=0.,dBzdy=0.,dBzdz=0.; |
736 | // Step sizes |
737 | mStepSizeS=2.0; |
738 | mStepSizeZ=2.0; |
739 | //mStepSizeZ=0.5; |
740 | |
741 | //if (fit_type==kTimeBased){ |
742 | // mStepSizeS=0.5; |
743 | // mStepSizeZ=0.5; |
744 | // } |
745 | |
746 | |
747 | mT0=0.,mT0MinimumDriftTime=1e6; |
748 | mVarT0=25.; |
749 | |
750 | mCDCInternalStepSize=0.5; |
751 | //mCDCInternalStepSize=1.0; |
752 | //mCentralStepSize=0.75; |
753 | mCentralStepSize=0.75; |
754 | |
755 | mT0Detector=SYS_CDC; |
756 | |
757 | IsHadron=true; |
758 | IsElectron=false; |
759 | IsPositron=false; |
760 | |
761 | PT_MIN=0.01; |
762 | Q_OVER_P_MAX=100.; |
763 | |
764 | // These variables provide the approximate location along the trajectory |
765 | // where there is an indication of a kink in the track |
766 | break_point_fdc_index=0; |
767 | break_point_cdc_index=0; |
768 | break_point_step_index=0; |
769 | |
770 | } |
771 | |
772 | //----------------- |
773 | // FitTrack |
774 | //----------------- |
775 | DTrackFitter::fit_status_t DTrackFitterKalmanSIMD::FitTrack(void) |
776 | { |
777 | // Reset member data and free an memory associated with the last fit, |
778 | // but some of which only for wire-based fits |
779 | ResetKalmanSIMD(); |
780 | |
781 | // Check that we have enough FDC and CDC hits to proceed |
782 | if (cdchits.size()==0 && fdchits.size()<4) return kFitNotDone; |
783 | if (cdchits.size()+fdchits.size() < 6) return kFitNotDone; |
784 | |
785 | // Copy hits from base class into structures specific to DTrackFitterKalmanSIMD |
786 | if (USE_CDC_HITS) |
787 | for(unsigned int i=0; i<cdchits.size(); i++)AddCDCHit(cdchits[i]); |
788 | if (USE_FDC_HITS) |
789 | for(unsigned int i=0; i<fdchits.size(); i++)AddFDCHit(fdchits[i]); |
790 | if (USE_TRD_HITS){ |
791 | for(unsigned int i=0; i<trdhits.size(); i++)AddTRDHit(trdhits[i]); |
792 | if (trdhits.size()>0){ |
793 | //_DBG_ << "Got TRD" <<endl; |
794 | got_trd_gem_hits=true; |
795 | } |
796 | } |
797 | if (USE_GEM_HITS){ |
798 | for(unsigned int i=0; i<gemhits.size(); i++)AddGEMHit(gemhits[i]); |
799 | if (gemhits.size()>0){ |
800 | //_DBG_ << " Got GEM" << endl; |
801 | got_trd_gem_hits=true; |
802 | } |
803 | } |
804 | |
805 | unsigned int num_good_cdchits=my_cdchits.size(); |
806 | unsigned int num_good_fdchits=my_fdchits.size(); |
807 | |
808 | // keep track of the range of detector elements that could be hit |
809 | // for calculating the number of expected hits later on |
810 | //int min_cdc_ring=-1, max_cdc_ring=-1; |
811 | |
812 | // Order the cdc hits by ring number |
813 | if (num_good_cdchits>0){ |
814 | stable_sort(my_cdchits.begin(),my_cdchits.end(),DKalmanSIMDCDCHit_cmp); |
815 | |
816 | //min_cdc_ring = my_cdchits[0]->hit->wire->ring; |
817 | //max_cdc_ring = my_cdchits[my_cdchits.size()-1]->hit->wire->ring; |
818 | |
819 | // Look for multiple hits on the same wire |
820 | for (unsigned int i=0;i<my_cdchits.size()-1;i++){ |
821 | if (my_cdchits[i]->hit->wire->ring==my_cdchits[i+1]->hit->wire->ring && |
822 | my_cdchits[i]->hit->wire->straw==my_cdchits[i+1]->hit->wire->straw){ |
823 | num_good_cdchits--; |
824 | if (my_cdchits[i]->tdrift<my_cdchits[i+1]->tdrift){ |
825 | my_cdchits[i+1]->status=late_hit; |
826 | } |
827 | else{ |
828 | my_cdchits[i]->status=late_hit; |
829 | } |
830 | } |
831 | } |
832 | |
833 | } |
834 | // Order the fdc hits by z |
835 | if (num_good_fdchits>0){ |
836 | stable_sort(my_fdchits.begin(),my_fdchits.end(),DKalmanSIMDFDCHit_cmp); |
837 | |
838 | // Look for multiple hits on the same wire |
839 | for (unsigned int i=0;i<my_fdchits.size()-1;i++){ |
840 | if (my_fdchits[i]->hit==NULL__null || my_fdchits[i+1]->hit==NULL__null) continue; |
841 | if (my_fdchits[i]->hit->wire->layer==my_fdchits[i+1]->hit->wire->layer && |
842 | my_fdchits[i]->hit->wire->wire==my_fdchits[i+1]->hit->wire->wire){ |
843 | num_good_fdchits--; |
844 | if (fabs(my_fdchits[i]->t-my_fdchits[i+1]->t)<EPS3.0e-8){ |
845 | double tsum_1=my_fdchits[i]->hit->t_u+my_fdchits[i]->hit->t_v; |
846 | double tsum_2=my_fdchits[i+1]->hit->t_u+my_fdchits[i+1]->hit->t_v; |
847 | if (tsum_1<tsum_2){ |
848 | my_fdchits[i+1]->status=late_hit; |
849 | } |
850 | else{ |
851 | my_fdchits[i]->status=late_hit; |
852 | } |
853 | } |
854 | else if (my_fdchits[i]->t<my_fdchits[i+1]->t){ |
855 | my_fdchits[i+1]->status=late_hit; |
856 | } |
857 | else{ |
858 | my_fdchits[i]->status=late_hit; |
859 | } |
860 | } |
861 | } |
862 | } |
863 | if (num_good_cdchits==0 && num_good_fdchits<4) return kFitNotDone; |
864 | if (num_good_cdchits+num_good_fdchits < 6) return kFitNotDone; |
865 | |
866 | // Create vectors of updates (from hits) to S and C |
867 | if (my_cdchits.size()>0){ |
868 | cdc_updates=vector<DKalmanUpdate_t>(my_cdchits.size()); |
869 | // Initialize vector to keep track of whether or not a hit is used in |
870 | // the fit |
871 | cdc_used_in_fit=vector<bool>(my_cdchits.size()); |
872 | } |
873 | if (my_fdchits.size()>0){ |
874 | fdc_updates=vector<DKalmanUpdate_t>(my_fdchits.size()); |
875 | // Initialize vector to keep track of whether or not a hit is used in |
876 | // the fit |
877 | fdc_used_in_fit=vector<bool>(my_fdchits.size()); |
878 | } |
879 | |
880 | // start time and variance |
881 | if (fit_type==kTimeBased){ |
882 | mT0=input_params.t0(); |
883 | switch(input_params.t0_detector()){ |
884 | case SYS_TOF: |
885 | mVarT0=0.01; |
886 | break; |
887 | case SYS_CDC: |
888 | mVarT0=7.5; |
889 | break; |
890 | case SYS_FDC: |
891 | mVarT0=7.5; |
892 | break; |
893 | case SYS_BCAL: |
894 | mVarT0=0.25; |
895 | break; |
896 | default: |
897 | mVarT0=0.09; |
898 | break; |
899 | } |
900 | } |
901 | |
902 | //_DBG_ << SystemName(input_params.t0_detector()) << " " << mT0 <<endl; |
903 | |
904 | //Set the mass |
905 | MASS=input_params.mass(); |
906 | mass2=MASS*MASS; |
907 | m_ratio=ELECTRON_MASS0.000511/MASS; |
908 | m_ratio_sq=m_ratio*m_ratio; |
909 | |
910 | // Is this particle an electron or positron? |
911 | if (MASS<0.001){ |
912 | IsHadron=false; |
913 | if (input_params.charge()<0.) IsElectron=true; |
914 | else IsPositron=true; |
915 | } |
916 | if (DEBUG_LEVEL>0) |
917 | { |
918 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<918<<" " << "------Starting " |
919 | <<(fit_type==kTimeBased?"Time-based":"Wire-based") |
920 | << " Fit with " << my_fdchits.size() << " FDC hits and " |
921 | << my_cdchits.size() << " CDC hits.-------" <<endl; |
922 | if (fit_type==kTimeBased){ |
923 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<923<<" " << " Using t0=" << mT0 << " from DET=" |
924 | << input_params.t0_detector() <<endl; |
925 | } |
926 | } |
927 | // Do the fit |
928 | jerror_t error = KalmanLoop(); |
929 | if (error!=NOERROR){ |
930 | if (DEBUG_LEVEL>0) |
931 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<931<<" " << "Fit failed with Error = " << error <<endl; |
932 | return kFitFailed; |
933 | } |
934 | |
935 | // Copy fit results into DTrackFitter base-class data members |
936 | DVector3 mom,pos; |
937 | GetPosition(pos); |
938 | GetMomentum(mom); |
939 | double charge = GetCharge(); |
940 | fit_params.setPosition(pos); |
941 | fit_params.setMomentum(mom); |
942 | fit_params.setTime(mT0MinimumDriftTime); |
943 | fit_params.setPID(IDTrack(charge, MASS)); |
944 | fit_params.setT0(mT0MinimumDriftTime,4.,mT0Detector); |
945 | |
946 | if (DEBUG_LEVEL>0){ |
947 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<947<<" " << "----- Pass: " |
948 | << (fit_type==kTimeBased?"Time-based ---":"Wire-based ---") |
949 | << " Mass: " << MASS |
950 | << " p=" << mom.Mag() |
951 | << " theta=" << 90.0-180./M_PI3.14159265358979323846*atan(tanl_) |
952 | << " vertex=(" << x_ << "," << y_ << "," << z_<<")" |
953 | << " chi2=" << chisq_ |
954 | <<endl; |
955 | if(DEBUG_LEVEL>3){ |
956 | //Dump pulls |
957 | for (unsigned int iPull = 0; iPull < pulls.size(); iPull++){ |
958 | if (pulls[iPull].cdc_hit != NULL__null){ |
959 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<959<<" " << " ring: " << pulls[iPull].cdc_hit->wire->ring |
960 | << " straw: " << pulls[iPull].cdc_hit->wire->straw |
961 | << " Residual: " << pulls[iPull].resi |
962 | << " Err: " << pulls[iPull].err |
963 | << " tdrift: " << pulls[iPull].tdrift |
964 | << " doca: " << pulls[iPull].d |
965 | << " docaphi: " << pulls[iPull].docaphi |
966 | << " z: " << pulls[iPull].z |
967 | << " cos(theta_rel): " << pulls[iPull].cosThetaRel |
968 | << " tcorr: " << pulls[iPull].tcorr |
969 | << endl; |
970 | } |
971 | } |
972 | } |
973 | } |
974 | |
975 | DMatrixDSym errMatrix(5); |
976 | // Fill the tracking error matrix and the one needed for kinematic fitting |
977 | if (fcov.size()!=0){ |
978 | // We MUST fill the entire matrix (not just upper right) even though |
979 | // this is a DMatrixDSym |
980 | for (unsigned int i=0;i<5;i++){ |
981 | for (unsigned int j=0;j<5;j++){ |
982 | errMatrix(i,j)=fcov[i][j]; |
983 | } |
984 | } |
985 | if (FORWARD_PARMS_COV){ |
986 | fit_params.setForwardParmFlag(true); |
987 | fit_params.setTrackingStateVector(x_,y_,tx_,ty_,q_over_p_); |
988 | |
989 | // Compute and fill the error matrix needed for kinematic fitting |
990 | fit_params.setErrorMatrix(Get7x7ErrorMatrixForward(errMatrix)); |
991 | } |
992 | else { |
993 | fit_params.setForwardParmFlag(false); |
994 | fit_params.setTrackingStateVector(q_over_pt_,phi_,tanl_,D_,z_); |
995 | |
996 | // Compute and fill the error matrix needed for kinematic fitting |
997 | fit_params.setErrorMatrix(Get7x7ErrorMatrix(errMatrix)); |
998 | } |
999 | } |
1000 | else if (cov.size()!=0){ |
1001 | fit_params.setForwardParmFlag(false); |
1002 | |
1003 | // We MUST fill the entire matrix (not just upper right) even though |
1004 | // this is a DMatrixDSym |
1005 | for (unsigned int i=0;i<5;i++){ |
1006 | for (unsigned int j=0;j<5;j++){ |
1007 | errMatrix(i,j)=cov[i][j]; |
1008 | } |
1009 | } |
1010 | fit_params.setTrackingStateVector(q_over_pt_,phi_,tanl_,D_,z_); |
1011 | |
1012 | // Compute and fill the error matrix needed for kinematic fitting |
1013 | fit_params.setErrorMatrix(Get7x7ErrorMatrix(errMatrix)); |
1014 | } |
1015 | auto locTrackingCovarianceMatrix = dResourcePool_TMatrixFSym->Get_SharedResource(); |
1016 | locTrackingCovarianceMatrix->ResizeTo(5, 5); |
1017 | for(unsigned int loc_i = 0; loc_i < 5; ++loc_i) |
1018 | { |
1019 | for(unsigned int loc_j = 0; loc_j < 5; ++loc_j) |
1020 | (*locTrackingCovarianceMatrix)(loc_i, loc_j) = errMatrix(loc_i, loc_j); |
1021 | |
1022 | } |
1023 | fit_params.setTrackingErrorMatrix(locTrackingCovarianceMatrix); |
1024 | this->chisq = GetChiSq(); |
1025 | this->Ndof = GetNDF(); |
1026 | fit_status = kFitSuccess; |
1027 | |
1028 | //_DBG_ << "========= done!" << endl; |
1029 | |
1030 | return fit_status; |
1031 | } |
1032 | |
1033 | //----------------- |
1034 | // ChiSq |
1035 | //----------------- |
1036 | double DTrackFitterKalmanSIMD::ChiSq(fit_type_t fit_type, DReferenceTrajectory *rt, double *chisq_ptr, int *dof_ptr, vector<pull_t> *pulls_ptr) |
1037 | { |
1038 | // This simply returns whatever was left in for the chisq/NDF from the last fit. |
1039 | // Using a DReferenceTrajectory is not really appropriate here so the base class' |
1040 | // requirement of it should be reviewed. |
1041 | double chisq = GetChiSq(); |
1042 | unsigned int ndf = GetNDF(); |
1043 | |
1044 | if(chisq_ptr)*chisq_ptr = chisq; |
1045 | if(dof_ptr)*dof_ptr = int(ndf); |
1046 | if(pulls_ptr)*pulls_ptr = pulls; |
1047 | |
1048 | return chisq/double(ndf); |
1049 | } |
1050 | |
1051 | // Return the momentum at the distance of closest approach to the origin. |
1052 | inline void DTrackFitterKalmanSIMD::GetMomentum(DVector3 &mom){ |
1053 | double pt=1./fabs(q_over_pt_); |
1054 | mom.SetXYZ(pt*cos(phi_),pt*sin(phi_),pt*tanl_); |
1055 | } |
1056 | |
1057 | // Return the "vertex" position (position at which track crosses beam line) |
1058 | inline void DTrackFitterKalmanSIMD::GetPosition(DVector3 &pos){ |
1059 | DVector2 beam_pos=beam_center+(z_-beam_z0)*beam_dir; |
1060 | pos.SetXYZ(x_+beam_pos.X(),y_+beam_pos.Y(),z_); |
1061 | } |
1062 | |
1063 | // Add GEM points |
1064 | void DTrackFitterKalmanSIMD::AddGEMHit(const DGEMPoint *gemhit){ |
1065 | DKalmanSIMDFDCHit_t *hit= new DKalmanSIMDFDCHit_t; |
1066 | |
1067 | hit->t=gemhit->time; |
1068 | hit->uwire=gemhit->x; |
1069 | hit->vstrip=gemhit->y; |
1070 | // From Justin (12/12/19): |
1071 | // DGEMPoint (GEM2 SRS, plane closest to the DIRC): |
1072 | // sigma_X = sigma_Y = 100 um |
1073 | hit->vvar=0.01*0.01; |
1074 | hit->uvar=hit->vvar; |
1075 | hit->z=gemhit->z; |
1076 | hit->cosa=1.; |
1077 | hit->sina=0.; |
1078 | hit->phiX=0.; |
1079 | hit->phiY=0.; |
1080 | hit->phiZ=0.; |
1081 | hit->nr=0.; |
1082 | hit->nz=0.; |
1083 | hit->status=gem_hit; |
1084 | hit->hit=NULL__null; |
1085 | |
1086 | my_fdchits.push_back(hit); |
1087 | } |
1088 | |
1089 | |
1090 | |
1091 | // Add TRD points |
1092 | void DTrackFitterKalmanSIMD::AddTRDHit(const DTRDPoint *trdhit){ |
1093 | DKalmanSIMDFDCHit_t *hit= new DKalmanSIMDFDCHit_t; |
1094 | |
1095 | hit->t=trdhit->time; |
1096 | hit->uwire=trdhit->x; |
1097 | hit->vstrip=trdhit->y; |
1098 | // From Justin (12/12/19): |
1099 | // sigma_X = 1 mm / sqrt(12) |
1100 | // sigma_Y = 300 um |
1101 | hit->vvar=0.03*0.03; |
1102 | hit->uvar=0.1*0.1/12.; |
1103 | hit->z=trdhit->z; |
1104 | hit->cosa=1.; |
1105 | hit->sina=0.; |
1106 | hit->phiX=0.; |
1107 | hit->phiY=0.; |
1108 | hit->phiZ=0.; |
1109 | hit->nr=0.; |
1110 | hit->nz=0.; |
1111 | hit->status=trd_hit; |
1112 | hit->hit=NULL__null; |
1113 | |
1114 | my_fdchits.push_back(hit); |
1115 | } |
1116 | |
1117 | // Add FDC hits |
1118 | void DTrackFitterKalmanSIMD::AddFDCHit(const DFDCPseudo *fdchit){ |
1119 | DKalmanSIMDFDCHit_t *hit= new DKalmanSIMDFDCHit_t; |
1120 | |
1121 | hit->t=fdchit->time; |
1122 | hit->uwire=fdchit->w; |
1123 | hit->vstrip=fdchit->s; |
1124 | hit->uvar=0.0833; |
1125 | hit->vvar=fdchit->ds*fdchit->ds; |
1126 | hit->z=fdchit->wire->origin.z(); |
1127 | hit->cosa=cos(fdchit->wire->angle); |
1128 | hit->sina=sin(fdchit->wire->angle); |
1129 | hit->phiX=fdchit->wire->angles.X(); |
1130 | hit->phiY=fdchit->wire->angles.Y(); |
1131 | hit->phiZ=fdchit->wire->angles.Z(); |
1132 | |
1133 | hit->nr=0.; |
1134 | hit->nz=0.; |
1135 | hit->dE=1e6*fdchit->dE; |
1136 | hit->hit=fdchit; |
1137 | hit->status=good_hit; |
1138 | |
1139 | my_fdchits.push_back(hit); |
1140 | } |
1141 | |
1142 | // Add CDC hits |
1143 | void DTrackFitterKalmanSIMD::AddCDCHit (const DCDCTrackHit *cdchit){ |
1144 | DKalmanSIMDCDCHit_t *hit= new DKalmanSIMDCDCHit_t; |
1145 | |
1146 | hit->hit=cdchit; |
1147 | hit->status=good_hit; |
1148 | hit->origin.Set(cdchit->wire->origin.x(),cdchit->wire->origin.y()); |
1149 | double one_over_uz=1./cdchit->wire->udir.z(); |
1150 | hit->dir.Set(one_over_uz*cdchit->wire->udir.x(), |
1151 | one_over_uz*cdchit->wire->udir.y()); |
1152 | hit->z0wire=cdchit->wire->origin.z(); |
1153 | hit->cosstereo=cos(cdchit->wire->stereo); |
1154 | hit->tdrift=cdchit->tdrift; |
1155 | my_cdchits.push_back(hit); |
1156 | } |
1157 | |
1158 | // Calculate the derivative of the state vector with respect to z |
1159 | jerror_t DTrackFitterKalmanSIMD::CalcDeriv(double z, |
1160 | const DMatrix5x1 &S, |
1161 | double dEdx, |
1162 | DMatrix5x1 &D){ |
1163 | double tx=S(state_tx),ty=S(state_ty); |
1164 | double q_over_p=S(state_q_over_p); |
1165 | |
1166 | // Turn off dEdx if the magnitude of the momentum drops below some cutoff |
1167 | if (fabs(q_over_p)>Q_OVER_P_MAX){ |
1168 | dEdx=0.; |
1169 | } |
1170 | // Try to keep the direction tangents from heading towards 90 degrees |
1171 | if (fabs(tx)>TAN_MAX10.) tx=TAN_MAX10.*(tx>0.0?1.:-1.); |
1172 | if (fabs(ty)>TAN_MAX10.) ty=TAN_MAX10.*(ty>0.0?1.:-1.); |
1173 | |
1174 | // useful combinations of terms |
1175 | double kq_over_p=qBr2p0.003*q_over_p; |
1176 | double tx2=tx*tx; |
1177 | double ty2=ty*ty; |
1178 | double txty=tx*ty; |
1179 | double one_plus_tx2=1.+tx2; |
1180 | double dsdz=sqrt(one_plus_tx2+ty2); |
1181 | double dtx_Bfac=ty*Bz+txty*Bx-one_plus_tx2*By; |
1182 | double dty_Bfac=Bx*(1.+ty2)-txty*By-tx*Bz; |
1183 | double kq_over_p_dsdz=kq_over_p*dsdz; |
1184 | |
1185 | // Derivative of S with respect to z |
1186 | D(state_x)=tx; |
1187 | D(state_y)=ty; |
1188 | D(state_tx)=kq_over_p_dsdz*dtx_Bfac; |
1189 | D(state_ty)=kq_over_p_dsdz*dty_Bfac; |
1190 | |
1191 | D(state_q_over_p)=0.; |
1192 | if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS3.0e-8){ |
1193 | double q_over_p_sq=q_over_p*q_over_p; |
1194 | double E=sqrt(1./q_over_p_sq+mass2); |
1195 | D(state_q_over_p)=-q_over_p_sq*q_over_p*E*dEdx*dsdz; |
1196 | } |
1197 | return NOERROR; |
1198 | } |
1199 | |
1200 | // Reference trajectory for forward tracks in CDC region |
1201 | // At each point we store the state vector and the Jacobian needed to get to |
1202 | //this state along z from the previous state. |
1203 | jerror_t DTrackFitterKalmanSIMD::SetCDCForwardReferenceTrajectory(DMatrix5x1 &S){ |
1204 | int i=0,forward_traj_length=forward_traj.size(); |
1205 | double z=z_; |
1206 | double r2=0.; |
1207 | bool stepped_to_boundary=false; |
1208 | |
1209 | // Magnetic field and gradient at beginning of trajectory |
1210 | //bfield->GetField(x_,y_,z_,Bx,By,Bz); |
1211 | bfield->GetFieldAndGradient(x_,y_,z_,Bx,By,Bz, |
1212 | dBxdx,dBxdy,dBxdz,dBydx, |
1213 | dBydy,dBydz,dBzdx,dBzdy,dBzdz); |
1214 | |
1215 | // Reset cdc status flags |
1216 | for (unsigned int i=0;i<my_cdchits.size();i++){ |
1217 | if (my_cdchits[i]->status!=late_hit) my_cdchits[i]->status=good_hit; |
1218 | } |
1219 | |
1220 | // Continue adding to the trajectory until we have reached the endplate |
1221 | // or the maximum radius |
1222 | while(z<endplate_z_downstream && z>cdc_origin[2] && |
1223 | r2<endplate_r2max && fabs(S(state_q_over_p))<Q_OVER_P_MAX |
1224 | && fabs(S(state_tx))<TAN_MAX10. |
1225 | && fabs(S(state_ty))<TAN_MAX10. |
1226 | ){ |
1227 | if (PropagateForwardCDC(forward_traj_length,i,z,r2,S,stepped_to_boundary) |
1228 | !=NOERROR) return UNRECOVERABLE_ERROR; |
1229 | } |
1230 | |
1231 | // Only use hits that would fall within the range of the reference trajectory |
1232 | /* |
1233 | for (unsigned int i=0;i<my_cdchits.size();i++){ |
1234 | DKalmanSIMDCDCHit_t *hit=my_cdchits[i]; |
1235 | double my_r2=(hit->origin+(z-hit->z0wire)*hit->dir).Mod2(); |
1236 | if (my_r2>r2) hit->status=bad_hit; |
1237 | } |
1238 | */ |
1239 | |
1240 | // If the current length of the trajectory deque is less than the previous |
1241 | // trajectory deque, remove the extra elements and shrink the deque |
1242 | if (i<(int)forward_traj.size()){ |
1243 | forward_traj_length=forward_traj.size(); |
1244 | for (int j=0;j<forward_traj_length-i;j++){ |
1245 | forward_traj.pop_front(); |
1246 | } |
1247 | } |
1248 | |
1249 | // return an error if there are not enough entries in the trajectory |
1250 | if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE; |
1251 | |
1252 | if (DEBUG_LEVEL>20) |
1253 | { |
1254 | cout << "--- Forward cdc trajectory ---" <<endl; |
1255 | for (unsigned int m=0;m<forward_traj.size();m++){ |
1256 | // DMatrix5x1 S=*(forward_traj[m].S); |
1257 | DMatrix5x1 S=(forward_traj[m].S); |
1258 | double tx=S(state_tx),ty=S(state_ty); |
1259 | double phi=atan2(ty,tx); |
1260 | double cosphi=cos(phi); |
1261 | double sinphi=sin(phi); |
1262 | double p=fabs(1./S(state_q_over_p)); |
1263 | double tanl=1./sqrt(tx*tx+ty*ty); |
1264 | double sinl=sin(atan(tanl)); |
1265 | double cosl=cos(atan(tanl)); |
1266 | cout |
1267 | << setiosflags(ios::fixed)<< "pos: " << setprecision(4) |
1268 | << forward_traj[m].S(state_x) << ", " |
1269 | << forward_traj[m].S(state_y) << ", " |
1270 | << forward_traj[m].z << " mom: " |
1271 | << p*cosphi*cosl<< ", " << p*sinphi*cosl << ", " |
1272 | << p*sinl << " -> " << p |
1273 | <<" s: " << setprecision(3) |
1274 | << forward_traj[m].s |
1275 | <<" t: " << setprecision(3) |
1276 | << forward_traj[m].t/SPEED_OF_LIGHT29.9792458 |
1277 | <<" B: " << forward_traj[m].B |
1278 | << endl; |
1279 | } |
1280 | } |
1281 | |
1282 | // Current state vector |
1283 | S=forward_traj[0].S; |
1284 | |
1285 | // position at the end of the swim |
1286 | x_=forward_traj[0].S(state_x); |
1287 | y_=forward_traj[0].S(state_y); |
1288 | z_=forward_traj[0].z; |
1289 | |
1290 | return NOERROR; |
1291 | } |
1292 | |
1293 | // Routine that extracts the state vector propagation part out of the reference |
1294 | // trajectory loop |
1295 | jerror_t DTrackFitterKalmanSIMD::PropagateForwardCDC(int length,int &index, |
1296 | double &z,double &r2, |
1297 | DMatrix5x1 &S, |
1298 | bool &stepped_to_boundary){ |
1299 | DMatrix5x5 J,Q; |
1300 | DKalmanForwardTrajectory_t temp; |
1301 | int my_i=0; |
1302 | temp.h_id=0; |
1303 | temp.num_hits=0; |
1304 | double dEdx=0.; |
1305 | double s_to_boundary=1e6; |
1306 | double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty)); |
1307 | |
1308 | // current position |
1309 | DVector3 pos(S(state_x),S(state_y),z); |
1310 | temp.z=z; |
1311 | // squared radius |
1312 | r2=pos.Perp2(); |
1313 | |
1314 | temp.s=len; |
1315 | temp.t=ftime; |
1316 | temp.S=S; |
1317 | |
1318 | // Kinematic variables |
1319 | double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p); |
1320 | double one_over_beta2=1.+mass2*q_over_p_sq; |
1321 | if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8; |
1322 | |
1323 | // get material properties from the Root Geometry |
1324 | if (ENABLE_BOUNDARY_CHECK && fit_type==kTimeBased){ |
1325 | DVector3 mom(S(state_tx),S(state_ty),1.); |
1326 | if(geom->FindMatKalman(pos,mom,temp.K_rho_Z_over_A, |
1327 | temp.rho_Z_over_A,temp.LnI,temp.Z, |
1328 | temp.chi2c_factor,temp.chi2a_factor, |
1329 | temp.chi2a_corr, |
1330 | last_material_map, |
1331 | &s_to_boundary)!=NOERROR){ |
1332 | return UNRECOVERABLE_ERROR; |
1333 | } |
1334 | } |
1335 | else |
1336 | { |
1337 | if(geom->FindMatKalman(pos,temp.K_rho_Z_over_A, |
1338 | temp.rho_Z_over_A,temp.LnI,temp.Z, |
1339 | temp.chi2c_factor,temp.chi2a_factor, |
1340 | temp.chi2a_corr, |
1341 | last_material_map)!=NOERROR){ |
1342 | return UNRECOVERABLE_ERROR; |
1343 | } |
1344 | } |
1345 | |
1346 | // Get dEdx for the upcoming step |
1347 | if (CORRECT_FOR_ELOSS){ |
1348 | dEdx=GetdEdx(S(state_q_over_p),temp.K_rho_Z_over_A,temp.rho_Z_over_A, |
1349 | temp.LnI,temp.Z); |
1350 | } |
1351 | |
1352 | index++; |
1353 | if (index<=length){ |
1354 | my_i=length-index; |
1355 | forward_traj[my_i].s=temp.s; |
1356 | forward_traj[my_i].t=temp.t; |
1357 | forward_traj[my_i].h_id=temp.h_id; |
1358 | forward_traj[my_i].num_hits=0; |
1359 | forward_traj[my_i].z=temp.z; |
1360 | forward_traj[my_i].rho_Z_over_A=temp.rho_Z_over_A; |
1361 | forward_traj[my_i].K_rho_Z_over_A=temp.K_rho_Z_over_A; |
1362 | forward_traj[my_i].LnI=temp.LnI; |
1363 | forward_traj[my_i].Z=temp.Z; |
1364 | forward_traj[my_i].S=S; |
1365 | } |
1366 | |
1367 | // Determine the step size based on energy loss |
1368 | //double step=mStepSizeS*dz_ds; |
1369 | double max_step_size |
1370 | =(z<endplate_z&& r2>endplate_r2min)?mCDCInternalStepSize:mStepSizeS; |
1371 | double ds=mStepSizeS; |
1372 | if (z<endplate_z && r2<endplate_r2max && z>cdc_origin[2]){ |
1373 | if (!stepped_to_boundary){ |
1374 | stepped_to_boundary=false; |
1375 | if (fabs(dEdx)>EPS3.0e-8){ |
1376 | ds=DE_PER_STEP0.001/fabs(dEdx); |
1377 | } |
1378 | if (ds>max_step_size) ds=max_step_size; |
1379 | if (s_to_boundary<ds){ |
1380 | ds=s_to_boundary+EPS31.e-2; |
1381 | stepped_to_boundary=true; |
1382 | } |
1383 | if(ds<MIN_STEP_SIZE0.1)ds=MIN_STEP_SIZE0.1; |
1384 | } |
1385 | else{ |
1386 | ds=MIN_STEP_SIZE0.1; |
1387 | stepped_to_boundary=false; |
1388 | } |
1389 | } |
1390 | double newz=z+ds*dz_ds; // new z position |
1391 | |
1392 | // Store magnetic field |
1393 | temp.B=sqrt(Bx*Bx+By*By+Bz*Bz); |
1394 | |
1395 | // Step through field |
1396 | ds=FasterStep(z,newz,dEdx,S); |
1397 | |
1398 | // update path length |
1399 | len+=fabs(ds); |
1400 | |
1401 | // Update flight time |
1402 | ftime+=ds*sqrt(one_over_beta2);// in units where c=1 |
1403 | |
1404 | // Get the contribution to the covariance matrix due to multiple |
1405 | // scattering |
1406 | GetProcessNoise(z,ds,temp.chi2c_factor,temp.chi2a_factor,temp.chi2a_corr, |
1407 | temp.S,Q); |
1408 | |
1409 | // Energy loss straggling |
1410 | if (CORRECT_FOR_ELOSS){ |
1411 | double varE=GetEnergyVariance(ds,one_over_beta2,temp.K_rho_Z_over_A); |
1412 | Q(state_q_over_p,state_q_over_p)=varE*q_over_p_sq*q_over_p_sq*one_over_beta2; |
1413 | } |
1414 | |
1415 | // Compute the Jacobian matrix and its transpose |
1416 | StepJacobian(newz,z,S,dEdx,J); |
1417 | |
1418 | // update the trajectory |
1419 | if (index<=length){ |
1420 | forward_traj[my_i].B=temp.B; |
1421 | forward_traj[my_i].Q=Q; |
1422 | forward_traj[my_i].J=J; |
1423 | } |
1424 | else{ |
1425 | temp.Q=Q; |
1426 | temp.J=J; |
1427 | temp.Ckk=Zero5x5; |
1428 | temp.Skk=Zero5x1; |
1429 | forward_traj.push_front(temp); |
1430 | } |
1431 | |
1432 | //update z |
1433 | z=newz; |
1434 | |
1435 | return NOERROR; |
1436 | } |
1437 | |
1438 | // Routine that extracts the state vector propagation part out of the reference |
1439 | // trajectory loop |
1440 | jerror_t DTrackFitterKalmanSIMD::PropagateCentral(int length, int &index, |
1441 | DVector2 &my_xy, |
1442 | double &var_t_factor, |
1443 | DMatrix5x1 &Sc, |
1444 | bool &stepped_to_boundary){ |
1445 | DKalmanCentralTrajectory_t temp; |
1446 | DMatrix5x5 J; // State vector Jacobian matrix |
1447 | DMatrix5x5 Q; // Process noise covariance matrix |
1448 | |
1449 | //Initialize some variables needed later |
1450 | double dEdx=0.; |
1451 | double s_to_boundary=1e6; |
1452 | int my_i=0; |
1453 | // Kinematic variables |
1454 | double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl))); |
1455 | double q_over_p_sq=q_over_p*q_over_p; |
1456 | double one_over_beta2=1.+mass2*q_over_p_sq; |
1457 | if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8; |
1458 | |
1459 | // Reset D to zero |
1460 | Sc(state_D)=0.; |
1461 | |
1462 | temp.xy=my_xy; |
1463 | temp.s=len; |
1464 | temp.t=ftime; |
1465 | temp.h_id=0; |
1466 | temp.S=Sc; |
1467 | |
1468 | // Store magnitude of magnetic field |
1469 | temp.B=sqrt(Bx*Bx+By*By+Bz*Bz); |
1470 | |
1471 | // get material properties from the Root Geometry |
1472 | DVector3 pos3d(my_xy.X(),my_xy.Y(),Sc(state_z)); |
1473 | if (ENABLE_BOUNDARY_CHECK && fit_type==kTimeBased){ |
1474 | DVector3 mom(cos(Sc(state_phi)),sin(Sc(state_phi)),Sc(state_tanl)); |
1475 | if(geom->FindMatKalman(pos3d,mom,temp.K_rho_Z_over_A, |
1476 | temp.rho_Z_over_A,temp.LnI,temp.Z, |
1477 | temp.chi2c_factor,temp.chi2a_factor, |
1478 | temp.chi2a_corr, |
1479 | last_material_map, |
1480 | &s_to_boundary) |
1481 | !=NOERROR){ |
1482 | return UNRECOVERABLE_ERROR; |
1483 | } |
1484 | } |
1485 | else if(geom->FindMatKalman(pos3d,temp.K_rho_Z_over_A, |
1486 | temp.rho_Z_over_A,temp.LnI,temp.Z, |
1487 | temp.chi2c_factor,temp.chi2a_factor, |
1488 | temp.chi2a_corr, |
1489 | last_material_map)!=NOERROR){ |
1490 | return UNRECOVERABLE_ERROR; |
1491 | } |
1492 | |
1493 | if (CORRECT_FOR_ELOSS){ |
1494 | dEdx=GetdEdx(q_over_p,temp.K_rho_Z_over_A,temp.rho_Z_over_A,temp.LnI, |
1495 | temp.Z); |
1496 | } |
1497 | |
1498 | // If the deque already exists, update it |
1499 | index++; |
1500 | if (index<=length){ |
1501 | my_i=length-index; |
1502 | central_traj[my_i].B=temp.B; |
1503 | central_traj[my_i].s=temp.s; |
1504 | central_traj[my_i].t=temp.t; |
1505 | central_traj[my_i].h_id=0; |
1506 | central_traj[my_i].xy=temp.xy; |
1507 | central_traj[my_i].rho_Z_over_A=temp.rho_Z_over_A; |
1508 | central_traj[my_i].K_rho_Z_over_A=temp.K_rho_Z_over_A; |
1509 | central_traj[my_i].LnI=temp.LnI; |
1510 | central_traj[my_i].Z=temp.Z; |
1511 | central_traj[my_i].S=Sc; |
1512 | } |
1513 | |
1514 | // Adjust the step size |
1515 | double step_size=mStepSizeS; |
1516 | if (stepped_to_boundary){ |
1517 | step_size=MIN_STEP_SIZE0.1; |
1518 | stepped_to_boundary=false; |
1519 | } |
1520 | else{ |
1521 | if (fabs(dEdx)>EPS3.0e-8){ |
1522 | step_size=DE_PER_STEP0.001/fabs(dEdx); |
1523 | } |
1524 | if(step_size>mStepSizeS) step_size=mStepSizeS; |
1525 | if (s_to_boundary<step_size){ |
1526 | step_size=s_to_boundary+EPS31.e-2; |
1527 | stepped_to_boundary=true; |
1528 | } |
1529 | if(step_size<MIN_STEP_SIZE0.1)step_size=MIN_STEP_SIZE0.1; |
1530 | } |
1531 | double r2=my_xy.Mod2(); |
1532 | if (r2>endplate_r2min |
1533 | && step_size>mCDCInternalStepSize) step_size=mCDCInternalStepSize; |
1534 | // Propagate the state through the field |
1535 | FasterStep(my_xy,step_size,Sc,dEdx); |
1536 | |
1537 | // update path length |
1538 | len+=step_size; |
1539 | |
1540 | // Update flight time |
1541 | double dt=step_size*sqrt(one_over_beta2); // in units of c=1 |
1542 | double one_minus_beta2=1.-1./one_over_beta2; |
1543 | ftime+=dt; |
1544 | var_ftime+=dt*dt*one_minus_beta2*one_minus_beta2*0.0004; |
1545 | var_t_factor=dt*dt*one_minus_beta2*one_minus_beta2; |
1546 | |
1547 | //printf("t %f sigt %f\n",TIME_UNIT_CONVERSION*ftime,TIME_UNIT_CONVERSION*sqrt(var_ftime)); |
1548 | |
1549 | // Multiple scattering |
1550 | GetProcessNoiseCentral(step_size,temp.chi2c_factor,temp.chi2a_factor, |
1551 | temp.chi2a_corr,temp.S,Q); |
1552 | |
1553 | // Energy loss straggling in the approximation of thick absorbers |
1554 | if (CORRECT_FOR_ELOSS){ |
1555 | double varE |
1556 | =GetEnergyVariance(step_size,one_over_beta2,temp.K_rho_Z_over_A); |
1557 | Q(state_q_over_pt,state_q_over_pt) |
1558 | +=varE*temp.S(state_q_over_pt)*temp.S(state_q_over_pt)*one_over_beta2 |
1559 | *q_over_p_sq; |
1560 | } |
1561 | |
1562 | // B-field and gradient at current (x,y,z) |
1563 | bfield->GetFieldAndGradient(my_xy.X(),my_xy.Y(),Sc(state_z),Bx,By,Bz, |
1564 | dBxdx,dBxdy,dBxdz,dBydx, |
1565 | dBydy,dBydz,dBzdx,dBzdy,dBzdz); |
1566 | |
1567 | // Compute the Jacobian matrix and its transpose |
1568 | StepJacobian(my_xy,temp.xy-my_xy,-step_size,Sc,dEdx,J); |
1569 | |
1570 | // Update the trajectory info |
1571 | if (index<=length){ |
1572 | central_traj[my_i].Q=Q; |
1573 | central_traj[my_i].J=J; |
1574 | } |
1575 | else{ |
1576 | temp.Q=Q; |
1577 | temp.J=J; |
1578 | temp.Ckk=Zero5x5; |
1579 | temp.Skk=Zero5x1; |
1580 | central_traj.push_front(temp); |
1581 | } |
1582 | |
1583 | return NOERROR; |
1584 | } |
1585 | |
1586 | |
1587 | |
1588 | // Reference trajectory for central tracks |
1589 | // At each point we store the state vector and the Jacobian needed to get to this state |
1590 | // along s from the previous state. |
1591 | // The tricky part is that we swim out from the target to find Sc and pos along the trajectory |
1592 | // but we need the Jacobians for the opposite direction, because the filter proceeds from |
1593 | // the outer hits toward the target. |
1594 | jerror_t DTrackFitterKalmanSIMD::SetCDCReferenceTrajectory(const DVector2 &xy, |
1595 | DMatrix5x1 &Sc){ |
1596 | bool stepped_to_boundary=false; |
1597 | int i=0,central_traj_length=central_traj.size(); |
1598 | // factor for scaling momentum resolution to propagate variance in flight |
1599 | // time |
1600 | double var_t_factor=0; |
1601 | |
1602 | // Magnetic field and gradient at beginning of trajectory |
1603 | //bfield->GetField(x_,y_,z_,Bx,By,Bz); |
1604 | bfield->GetFieldAndGradient(x_,y_,z_,Bx,By,Bz, |
1605 | dBxdx,dBxdy,dBxdz,dBydx, |
1606 | dBydy,dBydz,dBzdx,dBzdy,dBzdz); |
1607 | |
1608 | // Copy of initial position in xy |
1609 | DVector2 my_xy=xy; |
1610 | double r2=xy.Mod2(),z=z_; |
1611 | |
1612 | // Reset cdc status flags |
1613 | for (unsigned int j=0;j<my_cdchits.size();j++){ |
1614 | if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit; |
1615 | } |
1616 | |
1617 | // Continue adding to the trajectory until we have reached the endplate |
1618 | // or the maximum radius |
1619 | while(z<endplate_z && z>=Z_MIN-100. && r2<endplate_r2max |
1620 | && fabs(Sc(state_q_over_pt))<Q_OVER_PT_MAX100. |
1621 | ){ |
1622 | if (PropagateCentral(central_traj_length,i,my_xy,var_t_factor,Sc,stepped_to_boundary) |
1623 | !=NOERROR) return UNRECOVERABLE_ERROR; |
1624 | z=Sc(state_z); |
1625 | r2=my_xy.Mod2(); |
1626 | } |
1627 | |
1628 | // If the current length of the trajectory deque is less than the previous |
1629 | // trajectory deque, remove the extra elements and shrink the deque |
1630 | if (i<(int)central_traj.size()){ |
1631 | int central_traj_length=central_traj.size(); |
1632 | for (int j=0;j<central_traj_length-i;j++){ |
1633 | central_traj.pop_front(); |
1634 | } |
1635 | } |
1636 | |
1637 | // Only use hits that would fall within the range of the reference trajectory |
1638 | /*for (unsigned int j=0;j<my_cdchits.size();j++){ |
1639 | DKalmanSIMDCDCHit_t *hit=my_cdchits[j]; |
1640 | double my_r2=(hit->origin+(z-hit->z0wire)*hit->dir).Mod2(); |
1641 | if (my_r2>r2) hit->status=bad_hit; |
1642 | } |
1643 | */ |
1644 | |
1645 | // return an error if there are not enough entries in the trajectory |
1646 | if (central_traj.size()<2) return RESOURCE_UNAVAILABLE; |
1647 | |
1648 | if (DEBUG_LEVEL>20) |
1649 | { |
1650 | cout << "---------" << central_traj.size() <<" entries------" <<endl; |
1651 | for (unsigned int m=0;m<central_traj.size();m++){ |
1652 | DMatrix5x1 S=central_traj[m].S; |
1653 | double cosphi=cos(S(state_phi)); |
1654 | double sinphi=sin(S(state_phi)); |
1655 | double pt=fabs(1./S(state_q_over_pt)); |
1656 | double tanl=S(state_tanl); |
1657 | |
1658 | cout |
1659 | << m << "::" |
1660 | << setiosflags(ios::fixed)<< "pos: " << setprecision(4) |
1661 | << central_traj[m].xy.X() << ", " |
1662 | << central_traj[m].xy.Y() << ", " |
1663 | << central_traj[m].S(state_z) << " mom: " |
1664 | << pt*cosphi << ", " << pt*sinphi << ", " |
1665 | << pt*tanl << " -> " << pt/cos(atan(tanl)) |
1666 | <<" s: " << setprecision(3) |
1667 | << central_traj[m].s |
1668 | <<" t: " << setprecision(3) |
1669 | << central_traj[m].t/SPEED_OF_LIGHT29.9792458 |
1670 | <<" B: " << central_traj[m].B |
1671 | << endl; |
1672 | } |
1673 | } |
1674 | |
1675 | // State at end of swim |
1676 | Sc=central_traj[0].S; |
1677 | |
1678 | return NOERROR; |
1679 | } |
1680 | |
1681 | // Routine that extracts the state vector propagation part out of the reference |
1682 | // trajectory loop |
1683 | jerror_t DTrackFitterKalmanSIMD::PropagateForward(int length,int &i, |
1684 | double &z,double zhit, |
1685 | DMatrix5x1 &S, bool &done, |
1686 | bool &stepped_to_boundary, |
1687 | bool &stepped_to_endplate){ |
1688 | DMatrix5x5 J,Q; |
1689 | DKalmanForwardTrajectory_t temp; |
1690 | |
1691 | // Initialize some variables |
1692 | temp.h_id=0; |
1693 | temp.num_hits=0; |
1694 | int my_i=0; |
1695 | double s_to_boundary=1e6; |
1696 | double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty)); |
1697 | |
1698 | // current position |
1699 | DVector3 pos(S(state_x),S(state_y),z); |
1700 | double r2=pos.Perp2(); |
1701 | |
1702 | temp.s=len; |
1703 | temp.t=ftime; |
1704 | temp.z=z; |
1705 | temp.S=S; |
1706 | |
1707 | // Kinematic variables |
1708 | double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p); |
1709 | double one_over_beta2=1.+mass2*q_over_p_sq; |
1710 | if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8; |
1711 | |
1712 | // get material properties from the Root Geometry |
1713 | if (ENABLE_BOUNDARY_CHECK && fit_type==kTimeBased){ |
1714 | DVector3 mom(S(state_tx),S(state_ty),1.); |
1715 | if (geom->FindMatKalman(pos,mom,temp.K_rho_Z_over_A, |
1716 | temp.rho_Z_over_A,temp.LnI,temp.Z, |
1717 | temp.chi2c_factor,temp.chi2a_factor, |
1718 | temp.chi2a_corr, |
1719 | last_material_map, |
1720 | &s_to_boundary) |
1721 | !=NOERROR){ |
1722 | return UNRECOVERABLE_ERROR; |
1723 | } |
1724 | } |
1725 | else |
1726 | { |
1727 | if (geom->FindMatKalman(pos,temp.K_rho_Z_over_A, |
1728 | temp.rho_Z_over_A,temp.LnI,temp.Z, |
1729 | temp.chi2c_factor,temp.chi2a_factor, |
1730 | temp.chi2a_corr, |
1731 | last_material_map)!=NOERROR){ |
1732 | return UNRECOVERABLE_ERROR; |
1733 | } |
1734 | } |
1735 | |
1736 | // Get dEdx for the upcoming step |
1737 | double dEdx=0.; |
1738 | if (CORRECT_FOR_ELOSS){ |
1739 | dEdx=GetdEdx(S(state_q_over_p),temp.K_rho_Z_over_A, |
1740 | temp.rho_Z_over_A,temp.LnI,temp.Z); |
1741 | } |
1742 | i++; |
1743 | my_i=length-i; |
1744 | if (i<=length){ |
1745 | forward_traj[my_i].s=temp.s; |
1746 | forward_traj[my_i].t=temp.t; |
1747 | forward_traj[my_i].h_id=temp.h_id; |
1748 | forward_traj[my_i].num_hits=temp.num_hits; |
1749 | forward_traj[my_i].z=temp.z; |
1750 | forward_traj[my_i].rho_Z_over_A=temp.rho_Z_over_A; |
1751 | forward_traj[my_i].K_rho_Z_over_A=temp.K_rho_Z_over_A; |
1752 | forward_traj[my_i].LnI=temp.LnI; |
1753 | forward_traj[my_i].Z=temp.Z; |
1754 | forward_traj[my_i].S=S; |
1755 | } |
1756 | else{ |
1757 | temp.S=S; |
1758 | } |
1759 | |
1760 | // Determine the step size based on energy loss |
1761 | // step=mStepSizeS*dz_ds; |
1762 | double max_step_size |
1763 | =(z<endplate_z&& r2>endplate_r2min)?mCentralStepSize:mStepSizeS; |
1764 | double ds=mStepSizeS; |
1765 | if (z>cdc_origin[2]){ |
1766 | if (!stepped_to_boundary){ |
1767 | stepped_to_boundary=false; |
1768 | if (fabs(dEdx)>EPS3.0e-8){ |
1769 | ds=DE_PER_STEP0.001/fabs(dEdx); |
1770 | } |
1771 | if (ds>max_step_size) ds=max_step_size; |
1772 | if (s_to_boundary<ds){ |
1773 | ds=s_to_boundary+EPS31.e-2; |
1774 | stepped_to_boundary=true; |
1775 | } |
1776 | if(ds<MIN_STEP_SIZE0.1)ds=MIN_STEP_SIZE0.1; |
1777 | |
1778 | } |
1779 | else{ |
1780 | ds=MIN_STEP_SIZE0.1; |
1781 | stepped_to_boundary=false; |
1782 | } |
1783 | } |
1784 | |
1785 | double dz=stepped_to_endplate ? endplate_dz : ds*dz_ds; |
1786 | double newz=z+dz; // new z position |
1787 | // Check if we are stepping through the CDC endplate |
1788 | if (newz>endplate_z && z<endplate_z){ |
1789 | // _DBG_ << endl; |
1790 | newz=endplate_z+EPS31.e-2; |
1791 | stepped_to_endplate=true; |
1792 | } |
1793 | |
1794 | // Check if we are about to step to one of the wire planes |
1795 | done=false; |
1796 | if (newz>zhit){ |
1797 | newz=zhit; |
1798 | done=true; |
1799 | } |
1800 | |
1801 | // Store magnitude of magnetic field |
1802 | temp.B=sqrt(Bx*Bx+By*By+Bz*Bz); |
1803 | |
1804 | // Step through field |
1805 | ds=FasterStep(z,newz,dEdx,S); |
1806 | |
1807 | // update path length |
1808 | len+=ds; |
1809 | |
1810 | // update flight time |
1811 | ftime+=ds*sqrt(one_over_beta2); // in units where c=1 |
1812 | |
1813 | // Get the contribution to the covariance matrix due to multiple |
1814 | // scattering |
1815 | GetProcessNoise(z,ds,temp.chi2c_factor,temp.chi2a_factor,temp.chi2a_corr, |
1816 | temp.S,Q); |
1817 | |
1818 | // Energy loss straggling |
1819 | if (CORRECT_FOR_ELOSS){ |
1820 | double varE=GetEnergyVariance(ds,one_over_beta2,temp.K_rho_Z_over_A); |
1821 | Q(state_q_over_p,state_q_over_p)=varE*q_over_p_sq*q_over_p_sq*one_over_beta2; |
1822 | } |
1823 | |
1824 | // Compute the Jacobian matrix and its transpose |
1825 | StepJacobian(newz,z,S,dEdx,J); |
1826 | |
1827 | // update the trajectory data |
1828 | if (i<=length){ |
1829 | forward_traj[my_i].B=temp.B; |
1830 | forward_traj[my_i].Q=Q; |
1831 | forward_traj[my_i].J=J; |
1832 | } |
1833 | else{ |
1834 | temp.Q=Q; |
1835 | temp.J=J; |
1836 | temp.Ckk=Zero5x5; |
1837 | temp.Skk=Zero5x1; |
1838 | forward_traj.push_front(temp); |
1839 | } |
1840 | |
1841 | // update z |
1842 | z=newz; |
1843 | |
1844 | return NOERROR; |
1845 | } |
1846 | |
1847 | // Reference trajectory for trajectories with hits in the forward direction |
1848 | // At each point we store the state vector and the Jacobian needed to get to this state |
1849 | // along z from the previous state. |
1850 | jerror_t DTrackFitterKalmanSIMD::SetReferenceTrajectory(DMatrix5x1 &S){ |
1851 | |
1852 | // Magnetic field and gradient at beginning of trajectory |
1853 | //bfield->GetField(x_,y_,z_,Bx,By,Bz); |
1854 | bfield->GetFieldAndGradient(x_,y_,z_,Bx,By,Bz, |
1855 | dBxdx,dBxdy,dBxdz,dBydx, |
1856 | dBydy,dBydz,dBzdx,dBzdy,dBzdz); |
1857 | |
1858 | // progress in z from hit to hit |
1859 | double z=z_; |
1860 | int i=0; |
1861 | |
1862 | int forward_traj_length=forward_traj.size(); |
1863 | // loop over the fdc hits |
1864 | double zhit=0.,old_zhit=0.; |
1865 | bool stepped_to_boundary=false; |
1866 | bool stepped_to_endplate=false; |
1867 | unsigned int m=0; |
1868 | double z_max=400.; |
1869 | double r2max=50.*50.; |
1870 | if (got_trd_gem_hits){ |
1871 | z_max=600.; |
1872 | r2max=100.*100.; |
1873 | } |
1874 | for (m=0;m<my_fdchits.size();m++){ |
1875 | if (fabs(S(state_q_over_p))>Q_OVER_P_MAX |
1876 | || fabs(S(state_tx))>TAN_MAX10. |
1877 | || fabs(S(state_ty))>TAN_MAX10. |
1878 | || S(state_x)*S(state_x)+S(state_y)*S(state_y)>r2max |
1879 | || z>z_max || z<Z_MIN-100. |
1880 | ){ |
1881 | break; |
1882 | } |
1883 | |
1884 | zhit=my_fdchits[m]->z; |
1885 | if (fabs(old_zhit-zhit)>EPS3.0e-8){ |
1886 | bool done=false; |
1887 | while (!done){ |
1888 | if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX |
1889 | || fabs(S(state_tx))>TAN_MAX10. |
1890 | || fabs(S(state_ty))>TAN_MAX10. |
1891 | || S(state_x)*S(state_x)+S(state_y)*S(state_y)>r2max |
1892 | || z>z_max || z< Z_MIN-100. |
1893 | ){ |
1894 | break; |
1895 | } |
1896 | |
1897 | if (PropagateForward(forward_traj_length,i,z,zhit,S,done, |
1898 | stepped_to_boundary,stepped_to_endplate) |
1899 | !=NOERROR) |
1900 | return UNRECOVERABLE_ERROR; |
1901 | } |
1902 | } |
1903 | old_zhit=zhit; |
1904 | } |
1905 | |
1906 | // If m<2 then no useable FDC hits survived the check on the magnitude on the |
1907 | // momentum |
1908 | if (m<2) return UNRECOVERABLE_ERROR; |
1909 | |
1910 | // Make sure the reference trajectory goes one step beyond the most |
1911 | // downstream hit plane |
1912 | if (m==my_fdchits.size()){ |
1913 | bool done=false; |
1914 | if (PropagateForward(forward_traj_length,i,z,z_max,S,done, |
1915 | stepped_to_boundary,stepped_to_endplate) |
1916 | !=NOERROR) |
1917 | return UNRECOVERABLE_ERROR; |
1918 | if (PropagateForward(forward_traj_length,i,z,z_max,S,done, |
1919 | stepped_to_boundary,stepped_to_endplate) |
1920 | !=NOERROR) |
1921 | return UNRECOVERABLE_ERROR; |
1922 | } |
1923 | |
1924 | // Shrink the deque if the new trajectory has less points in it than the |
1925 | // old trajectory |
1926 | if (i<(int)forward_traj.size()){ |
1927 | int mylen=forward_traj.size(); |
1928 | //_DBG_ << "Shrinking: " << mylen << " to " << i << endl; |
1929 | for (int j=0;j<mylen-i;j++){ |
1930 | forward_traj.pop_front(); |
1931 | } |
1932 | // _DBG_ << " Now " << forward_traj.size() << endl; |
1933 | } |
1934 | |
1935 | // If we lopped off some hits on the downstream end, truncate the trajectory to |
1936 | // the point in z just beyond the last valid hit |
1937 | unsigned int my_id=my_fdchits.size(); |
1938 | if (m<my_id){ |
1939 | if (zhit<z) my_id=m; |
1940 | else my_id=m-1; |
1941 | zhit=my_fdchits[my_id-1]->z; |
1942 | //_DBG_ << "Shrinking: " << forward_traj.size()<< endl; |
1943 | for (;;){ |
1944 | z=forward_traj[0].z; |
1945 | if (z<zhit+EPS21.e-4) break; |
1946 | forward_traj.pop_front(); |
1947 | } |
1948 | //_DBG_ << " Now " << forward_traj.size() << endl; |
1949 | |
1950 | // Temporory structure keeping state and trajectory information |
1951 | DKalmanForwardTrajectory_t temp; |
1952 | temp.h_id=0; |
1953 | temp.num_hits=0; |
1954 | temp.B=0.; |
1955 | temp.K_rho_Z_over_A=temp.rho_Z_over_A=temp.LnI=0.; |
1956 | temp.Z=0.; |
1957 | temp.Q=Zero5x5; |
1958 | |
1959 | // last S vector |
1960 | S=forward_traj[0].S; |
1961 | |
1962 | // Step just beyond the last hit |
1963 | double newz=z+0.01; |
1964 | double ds=Step(z,newz,0.,S); // ignore energy loss for this small step |
1965 | temp.s=forward_traj[0].s+ds; |
1966 | temp.z=newz; |
1967 | temp.S=S; |
1968 | |
1969 | // Flight time |
1970 | double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p); |
1971 | double one_over_beta2=1.+mass2*q_over_p_sq; |
1972 | if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8; |
1973 | temp.t=forward_traj[0].t+ds*sqrt(one_over_beta2); // in units where c=1 |
1974 | |
1975 | // Covariance and state vector needed for smoothing code |
1976 | temp.Ckk=Zero5x5; |
1977 | temp.Skk=Zero5x1; |
1978 | |
1979 | // Jacobian matrices |
1980 | temp.J=I5x5; |
1981 | |
1982 | forward_traj.push_front(temp); |
1983 | } |
1984 | |
1985 | // return an error if there are not enough entries in the trajectory |
1986 | if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE; |
1987 | |
1988 | // Fill in Lorentz deflection parameters |
1989 | for (unsigned int m=0;m<forward_traj.size();m++){ |
1990 | if (my_id>0){ |
1991 | unsigned int hit_id=my_id-1; |
1992 | double z=forward_traj[m].z; |
1993 | if (fabs(z-my_fdchits[hit_id]->z)<EPS21.e-4){ |
1994 | forward_traj[m].h_id=my_id; |
1995 | |
1996 | if (my_fdchits[hit_id]->hit!=NULL__null){ |
1997 | // Get the magnetic field at this position along the trajectory |
1998 | bfield->GetField(forward_traj[m].S(state_x),forward_traj[m].S(state_y), |
1999 | z,Bx,By,Bz); |
2000 | double Br=sqrt(Bx*Bx+By*By); |
2001 | |
2002 | // Angle between B and wire |
2003 | double my_phi=0.; |
2004 | if (Br>0.) my_phi=acos((Bx*my_fdchits[hit_id]->sina |
2005 | +By*my_fdchits[hit_id]->cosa)/Br); |
2006 | /* |
2007 | lorentz_def->GetLorentzCorrectionParameters(forward_traj[m].pos.x(), |
2008 | forward_traj[m].pos.y(), |
2009 | forward_traj[m].pos.z(), |
2010 | tanz,tanr); |
2011 | my_fdchits[hit_id]->nr=tanr; |
2012 | my_fdchits[hit_id]->nz=tanz; |
2013 | */ |
2014 | |
2015 | my_fdchits[hit_id]->nr=LORENTZ_NR_PAR1*Bz*(1.+LORENTZ_NR_PAR2*Br); |
2016 | my_fdchits[hit_id]->nz=(LORENTZ_NZ_PAR1+LORENTZ_NZ_PAR2*Bz)*(Br*cos(my_phi)); |
2017 | } |
2018 | |
2019 | my_id--; |
2020 | |
2021 | unsigned int num=1; |
2022 | while (hit_id>0 |
2023 | && fabs(my_fdchits[hit_id]->z-my_fdchits[hit_id-1]->z)<EPS3.0e-8){ |
2024 | hit_id=my_id-1; |
2025 | num++; |
2026 | my_id--; |
2027 | } |
2028 | forward_traj[m].num_hits=num; |
2029 | } |
2030 | |
2031 | } |
2032 | } |
2033 | |
2034 | if (DEBUG_LEVEL>20) |
2035 | { |
2036 | cout << "--- Forward fdc trajectory ---" <<endl; |
2037 | for (unsigned int m=0;m<forward_traj.size();m++){ |
2038 | DMatrix5x1 S=(forward_traj[m].S); |
2039 | double tx=S(state_tx),ty=S(state_ty); |
2040 | double phi=atan2(ty,tx); |
2041 | double cosphi=cos(phi); |
2042 | double sinphi=sin(phi); |
2043 | double p=fabs(1./S(state_q_over_p)); |
2044 | double tanl=1./sqrt(tx*tx+ty*ty); |
2045 | double sinl=sin(atan(tanl)); |
2046 | double cosl=cos(atan(tanl)); |
2047 | cout |
2048 | << setiosflags(ios::fixed)<< "pos: " << setprecision(4) |
2049 | << forward_traj[m].S(state_x) << ", " |
2050 | << forward_traj[m].S(state_y) << ", " |
2051 | << forward_traj[m].z << " mom: " |
2052 | << p*cosphi*cosl<< ", " << p*sinphi*cosl << ", " |
2053 | << p*sinl << " -> " << p |
2054 | <<" s: " << setprecision(3) |
2055 | << forward_traj[m].s |
2056 | <<" t: " << setprecision(3) |
2057 | << forward_traj[m].t/SPEED_OF_LIGHT29.9792458 |
2058 | <<" id: " << forward_traj[m].h_id |
2059 | << endl; |
2060 | } |
2061 | } |
2062 | |
2063 | |
2064 | // position at the end of the swim |
2065 | z_=z; |
2066 | x_=S(state_x); |
2067 | y_=S(state_y); |
2068 | |
2069 | return NOERROR; |
2070 | } |
2071 | |
2072 | // Step the state vector through the field from oldz to newz. |
2073 | // Uses the 4th-order Runga-Kutte algorithm. |
2074 | double DTrackFitterKalmanSIMD::Step(double oldz,double newz, double dEdx, |
2075 | DMatrix5x1 &S){ |
2076 | double delta_z=newz-oldz; |
2077 | if (fabs(delta_z)<EPS3.0e-8) return 0.; // skip if the step is too small |
2078 | |
2079 | // Direction tangents |
2080 | double tx=S(state_tx); |
2081 | double ty=S(state_ty); |
2082 | double ds=sqrt(1.+tx*tx+ty*ty)*delta_z; |
2083 | |
2084 | double delta_z_over_2=0.5*delta_z; |
2085 | double midz=oldz+delta_z_over_2; |
2086 | DMatrix5x1 D1,D2,D3,D4; |
2087 | |
2088 | //B-field and gradient at at (x,y,z) |
2089 | bfield->GetFieldAndGradient(S(state_x),S(state_y),oldz,Bx,By,Bz, |
2090 | dBxdx,dBxdy,dBxdz,dBydx, |
2091 | dBydy,dBydz,dBzdx,dBzdy,dBzdz); |
2092 | double Bx0=Bx,By0=By,Bz0=Bz; |
2093 | |
2094 | // Calculate the derivative and propagate the state to the next point |
2095 | CalcDeriv(oldz,S,dEdx,D1); |
2096 | DMatrix5x1 S1=S+delta_z_over_2*D1; |
2097 | |
2098 | // Calculate the field at the first intermediate point |
2099 | double dx=S1(state_x)-S(state_x); |
2100 | double dy=S1(state_y)-S(state_y); |
2101 | Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z_over_2; |
2102 | By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z_over_2; |
2103 | Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z_over_2; |
2104 | |
2105 | // Calculate the derivative and propagate the state to the next point |
2106 | CalcDeriv(midz,S1,dEdx,D2); |
2107 | S1=S+delta_z_over_2*D2; |
2108 | |
2109 | // Calculate the field at the second intermediate point |
2110 | dx=S1(state_x)-S(state_x); |
2111 | dy=S1(state_y)-S(state_y); |
2112 | Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z_over_2; |
2113 | By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z_over_2; |
2114 | Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z_over_2; |
2115 | |
2116 | // Calculate the derivative and propagate the state to the next point |
2117 | CalcDeriv(midz,S1,dEdx,D3); |
2118 | S1=S+delta_z*D3; |
2119 | |
2120 | // Calculate the field at the final point |
2121 | dx=S1(state_x)-S(state_x); |
2122 | dy=S1(state_y)-S(state_y); |
2123 | Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z; |
2124 | By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z; |
2125 | Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z; |
2126 | |
2127 | // Final derivative |
2128 | CalcDeriv(newz,S1,dEdx,D4); |
2129 | |
2130 | // S+=delta_z*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4); |
2131 | double dz_over_6=delta_z*ONE_SIXTH0.16666666666666667; |
2132 | double dz_over_3=delta_z*ONE_THIRD0.33333333333333333; |
2133 | S+=dz_over_6*D1; |
2134 | S+=dz_over_3*D2; |
2135 | S+=dz_over_3*D3; |
2136 | S+=dz_over_6*D4; |
2137 | |
2138 | // Don't let the magnitude of the momentum drop below some cutoff |
2139 | //if (fabs(S(state_q_over_p))>Q_OVER_P_MAX) |
2140 | // S(state_q_over_p)=Q_OVER_P_MAX*(S(state_q_over_p)>0.0?1.:-1.); |
2141 | // Try to keep the direction tangents from heading towards 90 degrees |
2142 | //if (fabs(S(state_tx))>TAN_MAX) |
2143 | // S(state_tx)=TAN_MAX*(S(state_tx)>0.0?1.:-1.); |
2144 | //if (fabs(S(state_ty))>TAN_MAX) |
2145 | // S(state_ty)=TAN_MAX*(S(state_ty)>0.0?1.:-1.); |
2146 | |
2147 | return ds; |
2148 | } |
2149 | // Step the state vector through the field from oldz to newz. |
2150 | // Uses the 4th-order Runga-Kutte algorithm. |
2151 | // Uses the gradient to compute the field at the intermediate and last |
2152 | // points. |
2153 | double DTrackFitterKalmanSIMD::FasterStep(double oldz,double newz, double dEdx, |
2154 | DMatrix5x1 &S){ |
2155 | double delta_z=newz-oldz; |
2156 | if (fabs(delta_z)<EPS3.0e-8) return 0.; // skip if the step is too small |
2157 | |
2158 | // Direction tangents |
2159 | double tx=S(state_tx); |
2160 | double ty=S(state_ty); |
2161 | double ds=sqrt(1.+tx*tx+ty*ty)*delta_z; |
2162 | |
2163 | double delta_z_over_2=0.5*delta_z; |
2164 | double midz=oldz+delta_z_over_2; |
2165 | DMatrix5x1 D1,D2,D3,D4; |
2166 | double Bx0=Bx,By0=By,Bz0=Bz; |
2167 | |
2168 | // The magnetic field at the beginning of the step is assumed to be |
2169 | // obtained at the end of the previous step through StepJacobian |
2170 | |
2171 | // Calculate the derivative and propagate the state to the next point |
2172 | CalcDeriv(oldz,S,dEdx,D1); |
2173 | DMatrix5x1 S1=S+delta_z_over_2*D1; |
2174 | |
2175 | // Calculate the field at the first intermediate point |
2176 | double dx=S1(state_x)-S(state_x); |
2177 | double dy=S1(state_y)-S(state_y); |
2178 | Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z_over_2; |
2179 | By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z_over_2; |
2180 | Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z_over_2; |
2181 | |
2182 | // Calculate the derivative and propagate the state to the next point |
2183 | CalcDeriv(midz,S1,dEdx,D2); |
2184 | S1=S+delta_z_over_2*D2; |
2185 | |
2186 | // Calculate the field at the second intermediate point |
2187 | dx=S1(state_x)-S(state_x); |
2188 | dy=S1(state_y)-S(state_y); |
2189 | Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z_over_2; |
2190 | By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z_over_2; |
2191 | Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z_over_2; |
2192 | |
2193 | // Calculate the derivative and propagate the state to the next point |
2194 | CalcDeriv(midz,S1,dEdx,D3); |
2195 | S1=S+delta_z*D3; |
2196 | |
2197 | // Calculate the field at the final point |
2198 | dx=S1(state_x)-S(state_x); |
2199 | dy=S1(state_y)-S(state_y); |
2200 | Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*delta_z; |
2201 | By=By0+dBydx*dx+dBydy*dy+dBydz*delta_z; |
2202 | Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*delta_z; |
2203 | |
2204 | // Final derivative |
2205 | CalcDeriv(newz,S1,dEdx,D4); |
2206 | |
2207 | // S+=delta_z*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4); |
2208 | double dz_over_6=delta_z*ONE_SIXTH0.16666666666666667; |
2209 | double dz_over_3=delta_z*ONE_THIRD0.33333333333333333; |
2210 | S+=dz_over_6*D1; |
2211 | S+=dz_over_3*D2; |
2212 | S+=dz_over_3*D3; |
2213 | S+=dz_over_6*D4; |
2214 | |
2215 | // Don't let the magnitude of the momentum drop below some cutoff |
2216 | //if (fabs(S(state_q_over_p))>Q_OVER_P_MAX) |
2217 | // S(state_q_over_p)=Q_OVER_P_MAX*(S(state_q_over_p)>0.0?1.:-1.); |
2218 | // Try to keep the direction tangents from heading towards 90 degrees |
2219 | //if (fabs(S(state_tx))>TAN_MAX) |
2220 | // S(state_tx)=TAN_MAX*(S(state_tx)>0.0?1.:-1.); |
2221 | //if (fabs(S(state_ty))>TAN_MAX) |
2222 | // S(state_ty)=TAN_MAX*(S(state_ty)>0.0?1.:-1.); |
2223 | |
2224 | return ds; |
2225 | } |
2226 | |
2227 | |
2228 | |
2229 | // Compute the Jacobian matrix for the forward parametrization. |
2230 | jerror_t DTrackFitterKalmanSIMD::StepJacobian(double oldz,double newz, |
2231 | const DMatrix5x1 &S, |
2232 | double dEdx,DMatrix5x5 &J){ |
2233 | // Initialize the Jacobian matrix |
2234 | //J.Zero(); |
2235 | //for (int i=0;i<5;i++) J(i,i)=1.; |
2236 | J=I5x5; |
2237 | |
2238 | // Step in z |
2239 | double delta_z=newz-oldz; |
2240 | if (fabs(delta_z)<EPS3.0e-8) return NOERROR; //skip if the step is too small |
2241 | |
2242 | // Current values of state vector variables |
2243 | double x=S(state_x), y=S(state_y),tx=S(state_tx),ty=S(state_ty); |
2244 | double q_over_p=S(state_q_over_p); |
2245 | |
2246 | //B-field and field gradient at (x,y,z) |
2247 | //if (get_field) |
2248 | bfield->GetFieldAndGradient(x,y,oldz,Bx,By,Bz,dBxdx,dBxdy, |
2249 | dBxdz,dBydx,dBydy, |
2250 | dBydz,dBzdx,dBzdy,dBzdz); |
2251 | |
2252 | // Don't let the magnitude of the momentum drop below some cutoff |
2253 | if (fabs(q_over_p)>Q_OVER_P_MAX){ |
2254 | q_over_p=Q_OVER_P_MAX*(q_over_p>0.0?1.:-1.); |
2255 | dEdx=0.; |
2256 | } |
2257 | // Try to keep the direction tangents from heading towards 90 degrees |
2258 | if (fabs(tx)>TAN_MAX10.) tx=TAN_MAX10.*(tx>0.0?1.:-1.); |
2259 | if (fabs(ty)>TAN_MAX10.) ty=TAN_MAX10.*(ty>0.0?1.:-1.); |
2260 | // useful combinations of terms |
2261 | double kq_over_p=qBr2p0.003*q_over_p; |
2262 | double tx2=tx*tx; |
2263 | double twotx2=2.*tx2; |
2264 | double ty2=ty*ty; |
2265 | double twoty2=2.*ty2; |
2266 | double txty=tx*ty; |
2267 | double one_plus_tx2=1.+tx2; |
2268 | double one_plus_ty2=1.+ty2; |
2269 | double one_plus_twotx2_plus_ty2=one_plus_ty2+twotx2; |
2270 | double one_plus_twoty2_plus_tx2=one_plus_tx2+twoty2; |
2271 | double dsdz=sqrt(1.+tx2+ty2); |
2272 | double ds=dsdz*delta_z; |
2273 | double kds=qBr2p0.003*ds; |
2274 | double kqdz_over_p_over_dsdz=kq_over_p*delta_z/dsdz; |
2275 | double kq_over_p_ds=kq_over_p*ds; |
2276 | double dtx_Bdep=ty*Bz+txty*Bx-one_plus_tx2*By; |
2277 | double dty_Bdep=Bx*one_plus_ty2-txty*By-tx*Bz; |
2278 | double Bxty=Bx*ty; |
2279 | double Bytx=By*tx; |
2280 | double Bztxty=Bz*txty; |
2281 | double Byty=By*ty; |
2282 | double Bxtx=Bx*tx; |
2283 | |
2284 | // Jacobian |
2285 | J(state_x,state_tx)=J(state_y,state_ty)=delta_z; |
2286 | J(state_tx,state_q_over_p)=kds*dtx_Bdep; |
2287 | J(state_ty,state_q_over_p)=kds*dty_Bdep; |
2288 | J(state_tx,state_tx)+=kqdz_over_p_over_dsdz*(Bxty*(one_plus_twotx2_plus_ty2) |
2289 | -Bytx*(3.*one_plus_tx2+twoty2) |
2290 | +Bztxty); |
2291 | J(state_tx,state_x)=kq_over_p_ds*(ty*dBzdx+txty*dBxdx-one_plus_tx2*dBydx); |
2292 | J(state_ty,state_ty)+=kqdz_over_p_over_dsdz*(Bxty*(3.*one_plus_ty2+twotx2) |
2293 | -Bytx*(one_plus_twoty2_plus_tx2) |
2294 | -Bztxty); |
2295 | J(state_ty,state_y)= kq_over_p_ds*(one_plus_ty2*dBxdy-txty*dBydy-tx*dBzdy); |
2296 | J(state_tx,state_ty)=kqdz_over_p_over_dsdz |
2297 | *((Bxtx+Bz)*(one_plus_twoty2_plus_tx2)-Byty*one_plus_tx2); |
2298 | J(state_tx,state_y)= kq_over_p_ds*(tx*dBzdy+txty*dBxdy-one_plus_tx2*dBydy); |
2299 | J(state_ty,state_tx)=-kqdz_over_p_over_dsdz*((Byty+Bz)*(one_plus_twotx2_plus_ty2) |
2300 | -Bxtx*one_plus_ty2); |
2301 | J(state_ty,state_x)=kq_over_p_ds*(one_plus_ty2*dBxdx-txty*dBydx-tx*dBzdx); |
2302 | if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS3.0e-8){ |
2303 | double one_over_p_sq=q_over_p*q_over_p; |
2304 | double E=sqrt(1./one_over_p_sq+mass2); |
2305 | J(state_q_over_p,state_q_over_p)-=dEdx*ds/E*(2.+3.*mass2*one_over_p_sq); |
2306 | double temp=-(q_over_p*one_over_p_sq/dsdz)*E*dEdx*delta_z; |
2307 | J(state_q_over_p,state_tx)=tx*temp; |
2308 | J(state_q_over_p,state_ty)=ty*temp; |
2309 | } |
2310 | |
2311 | return NOERROR; |
2312 | } |
2313 | |
2314 | // Calculate the derivative for the alternate set of parameters {q/pT, phi, |
2315 | // tan(lambda),D,z} |
2316 | jerror_t DTrackFitterKalmanSIMD::CalcDeriv(DVector2 &dpos,const DMatrix5x1 &S, |
2317 | double dEdx,DMatrix5x1 &D1){ |
2318 | //Direction at current point |
2319 | double tanl=S(state_tanl); |
2320 | // Don't let tanl exceed some maximum |
2321 | if (fabs(tanl)>TAN_MAX10.) tanl=TAN_MAX10.*(tanl>0.0?1.:-1.); |
2322 | |
2323 | double phi=S(state_phi); |
2324 | double cosphi=cos(phi); |
2325 | double sinphi=sin(phi); |
2326 | double lambda=atan(tanl); |
2327 | double sinl=sin(lambda); |
2328 | double cosl=cos(lambda); |
2329 | // Other parameters |
2330 | double q_over_pt=S(state_q_over_pt); |
2331 | double pt=fabs(1./q_over_pt); |
2332 | |
2333 | // Turn off dEdx if the pt drops below some minimum |
2334 | if (pt<PT_MIN) { |
2335 | dEdx=0.; |
2336 | } |
2337 | double kq_over_pt=qBr2p0.003*q_over_pt; |
2338 | |
2339 | // Derivative of S with respect to s |
2340 | double By_cosphi_minus_Bx_sinphi=By*cosphi-Bx*sinphi; |
2341 | D1(state_q_over_pt) |
2342 | =kq_over_pt*q_over_pt*sinl*By_cosphi_minus_Bx_sinphi; |
2343 | double one_over_cosl=1./cosl; |
2344 | if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS3.0e-8){ |
2345 | double p=pt*one_over_cosl; |
2346 | double p_sq=p*p; |
2347 | double E=sqrt(p_sq+mass2); |
2348 | D1(state_q_over_pt)-=q_over_pt*E*dEdx/p_sq; |
2349 | } |
2350 | // D1(state_phi) |
2351 | // =kq_over_pt*(Bx*cosphi*sinl+By*sinphi*sinl-Bz*cosl); |
2352 | D1(state_phi)=kq_over_pt*((Bx*cosphi+By*sinphi)*sinl-Bz*cosl); |
2353 | D1(state_tanl)=kq_over_pt*By_cosphi_minus_Bx_sinphi*one_over_cosl; |
2354 | D1(state_z)=sinl; |
2355 | |
2356 | // New direction |
2357 | dpos.Set(cosl*cosphi,cosl*sinphi); |
2358 | |
2359 | return NOERROR; |
2360 | } |
2361 | |
2362 | // Calculate the derivative and Jacobian matrices for the alternate set of |
2363 | // parameters {q/pT, phi, tan(lambda),D,z} |
2364 | jerror_t DTrackFitterKalmanSIMD::CalcDerivAndJacobian(const DVector2 &xy, |
2365 | DVector2 &dxy, |
2366 | const DMatrix5x1 &S, |
2367 | double dEdx, |
2368 | DMatrix5x5 &J1, |
2369 | DMatrix5x1 &D1){ |
2370 | //Direction at current point |
2371 | double tanl=S(state_tanl); |
2372 | // Don't let tanl exceed some maximum |
2373 | if (fabs(tanl)>TAN_MAX10.) tanl=TAN_MAX10.*(tanl>0.0?1.:-1.); |
2374 | |
2375 | double phi=S(state_phi); |
2376 | double cosphi=cos(phi); |
2377 | double sinphi=sin(phi); |
2378 | double lambda=atan(tanl); |
2379 | double sinl=sin(lambda); |
2380 | double cosl=cos(lambda); |
2381 | double cosl2=cosl*cosl; |
2382 | double cosl3=cosl*cosl2; |
2383 | double one_over_cosl=1./cosl; |
2384 | // Other parameters |
2385 | double q_over_pt=S(state_q_over_pt); |
2386 | double pt=fabs(1./q_over_pt); |
2387 | double q=pt*q_over_pt; |
2388 | |
2389 | // Turn off dEdx if pt drops below some minimum |
2390 | if (pt<PT_MIN) { |
2391 | dEdx=0.; |
2392 | } |
2393 | double kq_over_pt=qBr2p0.003*q_over_pt; |
2394 | |
2395 | // B-field and gradient at (x,y,z) |
2396 | bfield->GetFieldAndGradient(xy.X(),xy.Y(),S(state_z),Bx,By,Bz, |
2397 | dBxdx,dBxdy,dBxdz,dBydx, |
2398 | dBydy,dBydz,dBzdx,dBzdy,dBzdz); |
2399 | |
2400 | // Derivative of S with respect to s |
2401 | double By_cosphi_minus_Bx_sinphi=By*cosphi-Bx*sinphi; |
2402 | double By_sinphi_plus_Bx_cosphi=By*sinphi+Bx*cosphi; |
2403 | D1(state_q_over_pt)=kq_over_pt*q_over_pt*sinl*By_cosphi_minus_Bx_sinphi; |
2404 | D1(state_phi)=kq_over_pt*(By_sinphi_plus_Bx_cosphi*sinl-Bz*cosl); |
2405 | D1(state_tanl)=kq_over_pt*By_cosphi_minus_Bx_sinphi*one_over_cosl; |
2406 | D1(state_z)=sinl; |
2407 | |
2408 | // New direction |
2409 | dxy.Set(cosl*cosphi,cosl*sinphi); |
2410 | |
2411 | // Jacobian matrix elements |
2412 | J1(state_phi,state_phi)=kq_over_pt*sinl*By_cosphi_minus_Bx_sinphi; |
2413 | J1(state_phi,state_q_over_pt) |
2414 | =qBr2p0.003*(By_sinphi_plus_Bx_cosphi*sinl-Bz*cosl); |
2415 | J1(state_phi,state_tanl)=kq_over_pt*(By_sinphi_plus_Bx_cosphi*cosl |
2416 | +Bz*sinl)*cosl2; |
2417 | J1(state_phi,state_z) |
2418 | =kq_over_pt*(dBxdz*cosphi*sinl+dBydz*sinphi*sinl-dBzdz*cosl); |
2419 | |
2420 | J1(state_tanl,state_phi)=-kq_over_pt*By_sinphi_plus_Bx_cosphi*one_over_cosl; |
2421 | J1(state_tanl,state_q_over_pt)=qBr2p0.003*By_cosphi_minus_Bx_sinphi*one_over_cosl; |
2422 | J1(state_tanl,state_tanl)=kq_over_pt*sinl*By_cosphi_minus_Bx_sinphi; |
2423 | J1(state_tanl,state_z)=kq_over_pt*(dBydz*cosphi-dBxdz*sinphi)*one_over_cosl; |
2424 | J1(state_q_over_pt,state_phi) |
2425 | =-kq_over_pt*q_over_pt*sinl*By_sinphi_plus_Bx_cosphi; |
2426 | J1(state_q_over_pt,state_q_over_pt) |
2427 | =2.*kq_over_pt*sinl*By_cosphi_minus_Bx_sinphi; |
2428 | J1(state_q_over_pt,state_tanl) |
2429 | =kq_over_pt*q_over_pt*cosl3*By_cosphi_minus_Bx_sinphi; |
2430 | if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS3.0e-8){ |
2431 | double p=pt*one_over_cosl; |
2432 | double p_sq=p*p; |
2433 | double m2_over_p2=mass2/p_sq; |
2434 | double E=sqrt(p_sq+mass2); |
2435 | |
2436 | D1(state_q_over_pt)-=q_over_pt*E/p_sq*dEdx; |
2437 | J1(state_q_over_pt,state_q_over_pt)-=dEdx*(2.+3.*m2_over_p2)/E; |
2438 | J1(state_q_over_pt,state_tanl)+=q*dEdx*sinl*(1.+2.*m2_over_p2)/(p*E); |
2439 | } |
2440 | J1(state_q_over_pt,state_z) |
2441 | =kq_over_pt*q_over_pt*sinl*(dBydz*cosphi-dBxdz*sinphi); |
2442 | J1(state_z,state_tanl)=cosl3; |
2443 | |
2444 | return NOERROR; |
2445 | } |
2446 | |
2447 | // Step the state and the covariance matrix through the field |
2448 | jerror_t DTrackFitterKalmanSIMD::StepStateAndCovariance(DVector2 &xy, |
2449 | double ds, |
2450 | double dEdx, |
2451 | DMatrix5x1 &S, |
2452 | DMatrix5x5 &J, |
2453 | DMatrix5x5 &C){ |
2454 | //Initialize the Jacobian matrix |
2455 | J=I5x5; |
2456 | if (fabs(ds)<EPS3.0e-8) return NOERROR; // break out if ds is too small |
2457 | |
2458 | // B-field and gradient at current (x,y,z) |
2459 | bfield->GetFieldAndGradient(xy.X(),xy.Y(),S(state_z),Bx,By,Bz, |
2460 | dBxdx,dBxdy,dBxdz,dBydx, |
2461 | dBydy,dBydz,dBzdx,dBzdy,dBzdz); |
2462 | double Bx0=Bx,By0=By,Bz0=Bz; |
2463 | |
2464 | // Matrices for intermediate steps |
2465 | DMatrix5x1 D1,D2,D3,D4; |
2466 | DMatrix5x1 S1; |
2467 | DMatrix5x5 J1; |
2468 | DVector2 dxy1,dxy2,dxy3,dxy4; |
2469 | double ds_2=0.5*ds; |
2470 | |
2471 | // Find the derivative at the first point, propagate the state to the |
2472 | // first intermediate point and start filling the Jacobian matrix |
2473 | CalcDerivAndJacobian(xy,dxy1,S,dEdx,J1,D1); |
2474 | S1=S+ds_2*D1; |
2475 | |
2476 | // Calculate the field at the first intermediate point |
2477 | double dz=S1(state_z)-S(state_z); |
2478 | double dx=ds_2*dxy1.X(); |
2479 | double dy=ds_2*dxy1.Y(); |
2480 | Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz; |
2481 | By=By0+dBydx*dx+dBydy*dy+dBydz*dz; |
2482 | Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz; |
2483 | |
2484 | // Calculate the derivative and propagate the state to the next point |
2485 | CalcDeriv(dxy2,S1,dEdx,D2); |
2486 | S1=S+ds_2*D2; |
2487 | |
2488 | // Calculate the field at the second intermediate point |
2489 | dz=S1(state_z)-S(state_z); |
2490 | dx=ds_2*dxy2.X(); |
2491 | dy=ds_2*dxy2.Y(); |
2492 | Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz; |
2493 | By=By0+dBydx*dx+dBydy*dy+dBydz*dz; |
2494 | Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz; |
2495 | |
2496 | // Calculate the derivative and propagate the state to the next point |
2497 | CalcDeriv(dxy3,S1,dEdx,D3); |
2498 | S1=S+ds*D3; |
2499 | |
2500 | // Calculate the field at the final point |
2501 | dz=S1(state_z)-S(state_z); |
2502 | dx=ds*dxy3.X(); |
2503 | dy=ds*dxy3.Y(); |
2504 | Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz; |
2505 | By=By0+dBydx*dx+dBydy*dy+dBydz*dz; |
2506 | Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz; |
2507 | |
2508 | // Final derivative |
2509 | CalcDeriv(dxy4,S1,dEdx,D4); |
2510 | |
2511 | // Position vector increment |
2512 | //DVector3 dpos |
2513 | // =ds*(ONE_SIXTH*dpos1+ONE_THIRD*dpos2+ONE_THIRD*dpos3+ONE_SIXTH*dpos4); |
2514 | double ds_over_6=ds*ONE_SIXTH0.16666666666666667; |
2515 | double ds_over_3=ds*ONE_THIRD0.33333333333333333; |
2516 | DVector2 dxy=ds_over_6*dxy1; |
2517 | dxy+=ds_over_3*dxy2; |
2518 | dxy+=ds_over_3*dxy3; |
2519 | dxy+=ds_over_6*dxy4; |
2520 | |
2521 | // New Jacobian matrix |
2522 | J+=ds*J1; |
2523 | |
2524 | // Deal with changes in D |
2525 | double B=sqrt(Bx0*Bx0+By0*By0+Bz0*Bz0); |
2526 | //double qrc_old=qpt/(qBr2p*Bz_); |
2527 | double qpt=1./S(state_q_over_pt); |
2528 | double q=(qpt>0.)?1.:-1.; |
2529 | double qrc_old=qpt/(qBr2p0.003*B); |
2530 | double sinphi=sin(S(state_phi)); |
2531 | double cosphi=cos(S(state_phi)); |
2532 | double qrc_plus_D=S(state_D)+qrc_old; |
2533 | dx=dxy.X(); |
2534 | dy=dxy.Y(); |
2535 | double dx_sinphi_minus_dy_cosphi=dx*sinphi-dy*cosphi; |
2536 | double rc=sqrt(dxy.Mod2() |
2537 | +2.*qrc_plus_D*(dx_sinphi_minus_dy_cosphi) |
2538 | +qrc_plus_D*qrc_plus_D); |
2539 | double q_over_rc=q/rc; |
2540 | |
2541 | J(state_D,state_D)=q_over_rc*(dx_sinphi_minus_dy_cosphi+qrc_plus_D); |
2542 | J(state_D,state_q_over_pt)=qpt*qrc_old*(J(state_D,state_D)-1.); |
2543 | J(state_D,state_phi)=q_over_rc*qrc_plus_D*(dx*cosphi+dy*sinphi); |
2544 | |
2545 | // New xy vector |
2546 | xy+=dxy; |
2547 | |
2548 | // New state vector |
2549 | //S+=ds*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4); |
2550 | S+=ds_over_6*D1; |
2551 | S+=ds_over_3*D2; |
2552 | S+=ds_over_3*D3; |
2553 | S+=ds_over_6*D4; |
2554 | |
2555 | // Don't let the pt drop below some minimum |
2556 | //if (fabs(1./S(state_q_over_pt))<PT_MIN) { |
2557 | // S(state_q_over_pt)=(1./PT_MIN)*(S(state_q_over_pt)>0.0?1.:-1.); |
2558 | // } |
2559 | // Don't let tanl exceed some maximum |
2560 | if (fabs(S(state_tanl))>TAN_MAX10.){ |
2561 | S(state_tanl)=TAN_MAX10.*(S(state_tanl)>0.0?1.:-1.); |
2562 | } |
2563 | |
2564 | // New covariance matrix |
2565 | // C=J C J^T |
2566 | //C=C.SandwichMultiply(J); |
2567 | C=J*C*J.Transpose(); |
2568 | |
2569 | return NOERROR; |
2570 | } |
2571 | |
2572 | // Runga-Kutte for alternate parameter set {q/pT,phi,tanl(lambda),D,z} |
2573 | // Uses the gradient to compute the field at the intermediate and last |
2574 | // points. |
2575 | jerror_t DTrackFitterKalmanSIMD::FasterStep(DVector2 &xy,double ds, |
2576 | DMatrix5x1 &S, |
2577 | double dEdx){ |
2578 | if (fabs(ds)<EPS3.0e-8) return NOERROR; // break out if ds is too small |
2579 | |
2580 | // Matrices for intermediate steps |
2581 | DMatrix5x1 D1,D2,D3,D4; |
2582 | DMatrix5x1 S1; |
2583 | DVector2 dxy1,dxy2,dxy3,dxy4; |
2584 | double ds_2=0.5*ds; |
2585 | double Bx0=Bx,By0=By,Bz0=Bz; |
2586 | |
2587 | // The magnetic field at the beginning of the step is assumed to be |
2588 | // obtained at the end of the previous step through StepJacobian |
2589 | |
2590 | // Calculate the derivative and propagate the state to the next point |
2591 | CalcDeriv(dxy1,S,dEdx,D1); |
2592 | S1=S+ds_2*D1; |
2593 | |
2594 | // Calculate the field at the first intermediate point |
2595 | double dz=S1(state_z)-S(state_z); |
2596 | double dx=ds_2*dxy1.X(); |
2597 | double dy=ds_2*dxy1.Y(); |
2598 | Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz; |
2599 | By=By0+dBydx*dx+dBydy*dy+dBydz*dz; |
2600 | Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz; |
2601 | |
2602 | // Calculate the derivative and propagate the state to the next point |
2603 | CalcDeriv(dxy2,S1,dEdx,D2); |
2604 | S1=S+ds_2*D2; |
2605 | |
2606 | // Calculate the field at the second intermediate point |
2607 | dz=S1(state_z)-S(state_z); |
2608 | dx=ds_2*dxy2.X(); |
2609 | dy=ds_2*dxy2.Y(); |
2610 | Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz; |
2611 | By=By0+dBydx*dx+dBydy*dy+dBydz*dz; |
2612 | Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz; |
2613 | |
2614 | // Calculate the derivative and propagate the state to the next point |
2615 | CalcDeriv(dxy3,S1,dEdx,D3); |
2616 | S1=S+ds*D3; |
2617 | |
2618 | // Calculate the field at the final point |
2619 | dz=S1(state_z)-S(state_z); |
2620 | dx=ds*dxy3.X(); |
2621 | dy=ds*dxy3.Y(); |
2622 | Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz; |
2623 | By=By0+dBydx*dx+dBydy*dy+dBydz*dz; |
2624 | Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz; |
2625 | |
2626 | // Final derivative |
2627 | CalcDeriv(dxy4,S1,dEdx,D4); |
2628 | |
2629 | // New state vector |
2630 | // S+=ds*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4); |
2631 | double ds_over_6=ds*ONE_SIXTH0.16666666666666667; |
2632 | double ds_over_3=ds*ONE_THIRD0.33333333333333333; |
2633 | S+=ds_over_6*D1; |
2634 | S+=ds_over_3*D2; |
2635 | S+=ds_over_3*D3; |
2636 | S+=ds_over_6*D4; |
2637 | |
2638 | // New position |
2639 | //pos+=ds*(ONE_SIXTH*dpos1+ONE_THIRD*dpos2+ONE_THIRD*dpos3+ONE_SIXTH*dpos4); |
2640 | xy+=ds_over_6*dxy1; |
2641 | xy+=ds_over_3*dxy2; |
2642 | xy+=ds_over_3*dxy3; |
2643 | xy+=ds_over_6*dxy4; |
2644 | |
2645 | // Don't let the pt drop below some minimum |
2646 | //if (fabs(1./S(state_q_over_pt))<PT_MIN) { |
2647 | // S(state_q_over_pt)=(1./PT_MIN)*(S(state_q_over_pt)>0.0?1.:-1.); |
2648 | //} |
2649 | // Don't let tanl exceed some maximum |
2650 | if (fabs(S(state_tanl))>TAN_MAX10.){ |
2651 | S(state_tanl)=TAN_MAX10.*(S(state_tanl)>0.0?1.:-1.); |
2652 | } |
2653 | |
2654 | return NOERROR; |
2655 | } |
2656 | |
2657 | // Runga-Kutte for alternate parameter set {q/pT,phi,tanl(lambda),D,z} |
2658 | jerror_t DTrackFitterKalmanSIMD::Step(DVector2 &xy,double ds, |
2659 | DMatrix5x1 &S, |
2660 | double dEdx){ |
2661 | if (fabs(ds)<EPS3.0e-8) return NOERROR; // break out if ds is too small |
2662 | |
2663 | // B-field and gradient at current (x,y,z) |
2664 | bfield->GetFieldAndGradient(xy.X(),xy.Y(),S(state_z),Bx,By,Bz, |
2665 | dBxdx,dBxdy,dBxdz,dBydx, |
2666 | dBydy,dBydz,dBzdx,dBzdy,dBzdz); |
2667 | double Bx0=Bx,By0=By,Bz0=Bz; |
2668 | |
2669 | // Matrices for intermediate steps |
2670 | DMatrix5x1 D1,D2,D3,D4; |
2671 | DMatrix5x1 S1; |
2672 | DVector2 dxy1,dxy2,dxy3,dxy4; |
2673 | double ds_2=0.5*ds; |
2674 | |
2675 | // Find the derivative at the first point, propagate the state to the |
2676 | // first intermediate point |
2677 | CalcDeriv(dxy1,S,dEdx,D1); |
2678 | S1=S+ds_2*D1; |
2679 | |
2680 | // Calculate the field at the first intermediate point |
2681 | double dz=S1(state_z)-S(state_z); |
2682 | double dx=ds_2*dxy1.X(); |
2683 | double dy=ds_2*dxy1.Y(); |
2684 | Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz; |
2685 | By=By0+dBydx*dx+dBydy*dy+dBydz*dz; |
2686 | Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz; |
2687 | |
2688 | // Calculate the derivative and propagate the state to the next point |
2689 | CalcDeriv(dxy2,S1,dEdx,D2); |
2690 | S1=S+ds_2*D2; |
2691 | |
2692 | // Calculate the field at the second intermediate point |
2693 | dz=S1(state_z)-S(state_z); |
2694 | dx=ds_2*dxy2.X(); |
2695 | dy=ds_2*dxy2.Y(); |
2696 | Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz; |
2697 | By=By0+dBydx*dx+dBydy*dy+dBydz*dz; |
2698 | Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz; |
2699 | |
2700 | // Calculate the derivative and propagate the state to the next point |
2701 | CalcDeriv(dxy3,S1,dEdx,D3); |
2702 | S1=S+ds*D3; |
2703 | |
2704 | // Calculate the field at the final point |
2705 | dz=S1(state_z)-S(state_z); |
2706 | dx=ds*dxy3.X(); |
2707 | dy=ds*dxy3.Y(); |
2708 | Bx=Bx0+dBxdx*dx+dBxdy*dy+dBxdz*dz; |
2709 | By=By0+dBydx*dx+dBydy*dy+dBydz*dz; |
2710 | Bz=Bz0+dBzdx*dx+dBzdy*dy+dBzdz*dz; |
2711 | |
2712 | // Final derivative |
2713 | CalcDeriv(dxy4,S1,dEdx,D4); |
2714 | |
2715 | // New state vector |
2716 | // S+=ds*(ONE_SIXTH*D1+ONE_THIRD*D2+ONE_THIRD*D3+ONE_SIXTH*D4); |
2717 | double ds_over_6=ds*ONE_SIXTH0.16666666666666667; |
2718 | double ds_over_3=ds*ONE_THIRD0.33333333333333333; |
2719 | S+=ds_over_6*D1; |
2720 | S+=ds_over_3*D2; |
2721 | S+=ds_over_3*D3; |
2722 | S+=ds_over_6*D4; |
2723 | |
2724 | // New position |
2725 | //pos+=ds*(ONE_SIXTH*dpos1+ONE_THIRD*dpos2+ONE_THIRD*dpos3+ONE_SIXTH*dpos4); |
2726 | xy+=ds_over_6*dxy1; |
2727 | xy+=ds_over_3*dxy2; |
2728 | xy+=ds_over_3*dxy3; |
2729 | xy+=ds_over_6*dxy4; |
2730 | |
2731 | // Don't let the pt drop below some minimum |
2732 | //if (fabs(1./S(state_q_over_pt))<PT_MIN) { |
2733 | // S(state_q_over_pt)=(1./PT_MIN)*(S(state_q_over_pt)>0.0?1.:-1.); |
2734 | //} |
2735 | // Don't let tanl exceed some maximum |
2736 | if (fabs(S(state_tanl))>TAN_MAX10.){ |
2737 | S(state_tanl)=TAN_MAX10.*(S(state_tanl)>0.0?1.:-1.); |
2738 | } |
2739 | |
2740 | return NOERROR; |
2741 | } |
2742 | |
2743 | // Assuming that the magnetic field is constant over the step, use a helical |
2744 | // model to step directly to the next point along the trajectory. |
2745 | void DTrackFitterKalmanSIMD::FastStep(double &z,double ds, double dEdx, |
2746 | DMatrix5x1 &S){ |
2747 | |
2748 | // Compute convenience terms involving Bx, By, Bz |
2749 | double one_over_p=fabs(S(state_q_over_p)); |
2750 | double p=1./one_over_p; |
2751 | double tx=S(state_tx),ty=S(state_ty); |
2752 | double denom=sqrt(1.+tx*tx+ty*ty); |
2753 | double px=p*tx/denom; |
2754 | double py=p*ty/denom; |
2755 | double pz=p/denom; |
2756 | double q=S(state_q_over_p)>0?1.:-1.; |
2757 | double k_q=qBr2p0.003*q; |
2758 | double ds_over_p=ds*one_over_p; |
2759 | double factor=k_q*(0.25*ds_over_p); |
2760 | double Ax=factor*Bx,Ay=factor*By,Az=factor*Bz; |
2761 | double Ax2=Ax*Ax,Ay2=Ay*Ay,Az2=Az*Az; |
2762 | double AxAy=Ax*Ay,AxAz=Ax*Az,AyAz=Ay*Az; |
2763 | double one_plus_Ax2=1.+Ax2; |
2764 | double scale=ds_over_p/(one_plus_Ax2+Ay2+Az2); |
2765 | |
2766 | // Compute new position |
2767 | double dx=scale*(px*one_plus_Ax2+py*(AxAy+Az)+pz*(AxAz-Ay)); |
2768 | double dy=scale*(px*(AxAy-Az)+py*(1.+Ay2)+pz*(AyAz+Ax)); |
2769 | double dz=scale*(px*(AxAz+Ay)+py*(AyAz-Ax)+pz*(1.+Az2)); |
2770 | S(state_x)+=dx; |
2771 | S(state_y)+=dy; |
2772 | z+=dz; |
2773 | |
2774 | // Compute new momentum |
2775 | px+=k_q*(Bz*dy-By*dz); |
2776 | py+=k_q*(Bx*dz-Bz*dx); |
2777 | pz+=k_q*(By*dx-Bx*dy); |
2778 | S(state_tx)=px/pz; |
2779 | S(state_ty)=py/pz; |
2780 | if (fabs(dEdx)>EPS3.0e-8){ |
2781 | double one_over_p_sq=one_over_p*one_over_p; |
2782 | double E=sqrt(1./one_over_p_sq+mass2); |
2783 | S(state_q_over_p)-=S(state_q_over_p)*one_over_p_sq*E*dEdx*ds; |
2784 | } |
2785 | } |
2786 | // Assuming that the magnetic field is constant over the step, use a helical |
2787 | // model to step directly to the next point along the trajectory. |
2788 | void DTrackFitterKalmanSIMD::FastStep(DVector2 &xy,double ds, double dEdx, |
2789 | DMatrix5x1 &S){ |
2790 | |
2791 | // Compute convenience terms involving Bx, By, Bz |
2792 | double pt=fabs(1./S(state_q_over_pt)); |
2793 | double one_over_p=cos(atan(S(state_tanl)))/pt; |
2794 | double px=pt*cos(S(state_phi)); |
2795 | double py=pt*sin(S(state_phi)); |
2796 | double pz=pt*S(state_tanl); |
2797 | double q=S(state_q_over_pt)>0?1.:-1.; |
2798 | double k_q=qBr2p0.003*q; |
2799 | double ds_over_p=ds*one_over_p; |
2800 | double factor=k_q*(0.25*ds_over_p); |
2801 | double Ax=factor*Bx,Ay=factor*By,Az=factor*Bz; |
2802 | double Ax2=Ax*Ax,Ay2=Ay*Ay,Az2=Az*Az; |
2803 | double AxAy=Ax*Ay,AxAz=Ax*Az,AyAz=Ay*Az; |
2804 | double one_plus_Ax2=1.+Ax2; |
2805 | double scale=ds_over_p/(one_plus_Ax2+Ay2+Az2); |
2806 | |
2807 | // Compute new position |
2808 | double dx=scale*(px*one_plus_Ax2+py*(AxAy+Az)+pz*(AxAz-Ay)); |
2809 | double dy=scale*(px*(AxAy-Az)+py*(1.+Ay2)+pz*(AyAz+Ax)); |
2810 | double dz=scale*(px*(AxAz+Ay)+py*(AyAz-Ax)+pz*(1.+Az2)); |
2811 | xy.Set(xy.X()+dx,xy.Y()+dy); |
2812 | S(state_z)+=dz; |
2813 | |
2814 | // Compute new momentum |
2815 | px+=k_q*(Bz*dy-By*dz); |
2816 | py+=k_q*(Bx*dz-Bz*dx); |
2817 | pz+=k_q*(By*dx-Bx*dy); |
2818 | pt=sqrt(px*px+py*py); |
2819 | S(state_q_over_pt)=q/pt; |
2820 | S(state_phi)=atan2(py,px); |
2821 | S(state_tanl)=pz/pt; |
2822 | if (fabs(dEdx)>EPS3.0e-8){ |
2823 | double one_over_p_sq=one_over_p*one_over_p; |
2824 | double E=sqrt(1./one_over_p_sq+mass2); |
2825 | S(state_q_over_p)-=S(state_q_over_pt)*one_over_p_sq*E*dEdx*ds; |
2826 | } |
2827 | } |
2828 | |
2829 | // Calculate the jacobian matrix for the alternate parameter set |
2830 | // {q/pT,phi,tanl(lambda),D,z} |
2831 | jerror_t DTrackFitterKalmanSIMD::StepJacobian(const DVector2 &xy, |
2832 | const DVector2 &dxy, |
2833 | double ds,const DMatrix5x1 &S, |
2834 | double dEdx,DMatrix5x5 &J){ |
2835 | // Initialize the Jacobian matrix |
2836 | //J.Zero(); |
2837 | //for (int i=0;i<5;i++) J(i,i)=1.; |
2838 | J=I5x5; |
2839 | |
2840 | if (fabs(ds)<EPS3.0e-8) return NOERROR; // break out if ds is too small |
2841 | // B-field and gradient at current (x,y,z) |
2842 | //bfield->GetFieldAndGradient(xy.X(),xy.Y(),S(state_z),Bx,By,Bz, |
2843 | //dBxdx,dBxdy,dBxdz,dBydx, |
2844 | //dBydy,dBydz,dBzdx,dBzdy,dBzdz); |
2845 | |
2846 | // Charge |
2847 | double q=(S(state_q_over_pt)>0.0)?1.:-1.; |
2848 | |
2849 | //kinematic quantities |
2850 | double q_over_pt=S(state_q_over_pt); |
2851 | double sinphi=sin(S(state_phi)); |
2852 | double cosphi=cos(S(state_phi)); |
2853 | double D=S(state_D); |
2854 | double lambda=atan(S(state_tanl)); |
2855 | double sinl=sin(lambda); |
2856 | double cosl=cos(lambda); |
2857 | double cosl2=cosl*cosl; |
2858 | double cosl3=cosl*cosl2; |
2859 | double one_over_cosl=1./cosl; |
2860 | double pt=fabs(1./q_over_pt); |
2861 | |
2862 | // Turn off dEdx if pt drops below some minimum |
2863 | if (pt<PT_MIN) { |
2864 | dEdx=0.; |
2865 | } |
2866 | double kds=qBr2p0.003*ds; |
2867 | double kq_ds_over_pt=kds*q_over_pt; |
2868 | double By_cosphi_minus_Bx_sinphi=By*cosphi-Bx*sinphi; |
2869 | double By_sinphi_plus_Bx_cosphi=By*sinphi+Bx*cosphi; |
2870 | |
2871 | // Jacobian matrix elements |
2872 | J(state_phi,state_phi)+=kq_ds_over_pt*sinl*By_cosphi_minus_Bx_sinphi; |
2873 | J(state_phi,state_q_over_pt)=kds*(By_sinphi_plus_Bx_cosphi*sinl-Bz*cosl); |
2874 | J(state_phi,state_tanl)=kq_ds_over_pt*(By_sinphi_plus_Bx_cosphi*cosl |
2875 | +Bz*sinl)*cosl2; |
2876 | J(state_phi,state_z) |
2877 | =kq_ds_over_pt*(dBxdz*cosphi*sinl+dBydz*sinphi*sinl-dBzdz*cosl); |
2878 | |
2879 | J(state_tanl,state_phi)=-kq_ds_over_pt*By_sinphi_plus_Bx_cosphi*one_over_cosl; |
2880 | J(state_tanl,state_q_over_pt)=kds*By_cosphi_minus_Bx_sinphi*one_over_cosl; |
2881 | J(state_tanl,state_tanl)+=kq_ds_over_pt*sinl*By_cosphi_minus_Bx_sinphi; |
2882 | J(state_tanl,state_z)=kq_ds_over_pt*(dBydz*cosphi-dBxdz*sinphi)*one_over_cosl; |
2883 | J(state_q_over_pt,state_phi) |
2884 | =-kq_ds_over_pt*q_over_pt*sinl*By_sinphi_plus_Bx_cosphi; |
2885 | J(state_q_over_pt,state_q_over_pt) |
2886 | +=2.*kq_ds_over_pt*sinl*By_cosphi_minus_Bx_sinphi; |
2887 | J(state_q_over_pt,state_tanl) |
2888 | =kq_ds_over_pt*q_over_pt*cosl3*By_cosphi_minus_Bx_sinphi; |
2889 | if (CORRECT_FOR_ELOSS && fabs(dEdx)>EPS3.0e-8){ |
2890 | double p=pt*one_over_cosl; |
2891 | double p_sq=p*p; |
2892 | double m2_over_p2=mass2/p_sq; |
2893 | double E=sqrt(p_sq+mass2); |
2894 | double dE_over_E=dEdx*ds/E; |
2895 | |
2896 | J(state_q_over_pt,state_q_over_pt)-=dE_over_E*(2.+3.*m2_over_p2); |
2897 | J(state_q_over_pt,state_tanl)+=q*dE_over_E*sinl*(1.+2.*m2_over_p2)/p; |
2898 | } |
2899 | J(state_q_over_pt,state_z) |
2900 | =kq_ds_over_pt*q_over_pt*sinl*(dBydz*cosphi-dBxdz*sinphi); |
2901 | J(state_z,state_tanl)=cosl3*ds; |
2902 | |
2903 | // Deal with changes in D |
2904 | double B=sqrt(Bx*Bx+By*By+Bz*Bz); |
2905 | //double qrc_old=qpt/(qBr2p*fabs(Bz)); |
2906 | double qpt=FactorForSenseOfRotation/q_over_pt; |
2907 | double qrc_old=qpt/(qBr2p0.003*B); |
2908 | double qrc_plus_D=D+qrc_old; |
2909 | double dx=dxy.X(); |
2910 | double dy=dxy.Y(); |
2911 | double dx_sinphi_minus_dy_cosphi=dx*sinphi-dy*cosphi; |
2912 | double rc=sqrt(dxy.Mod2() |
2913 | +2.*qrc_plus_D*(dx_sinphi_minus_dy_cosphi) |
2914 | +qrc_plus_D*qrc_plus_D); |
2915 | double q_over_rc=FactorForSenseOfRotation*q/rc; |
2916 | |
2917 | J(state_D,state_D)=q_over_rc*(dx_sinphi_minus_dy_cosphi+qrc_plus_D); |
2918 | J(state_D,state_q_over_pt)=qpt*qrc_old*(J(state_D,state_D)-1.); |
2919 | J(state_D,state_phi)=q_over_rc*qrc_plus_D*(dx*cosphi+dy*sinphi); |
2920 | |
2921 | return NOERROR; |
2922 | } |
2923 | |
2924 | |
2925 | |
2926 | |
2927 | // Runga-Kutte for alternate parameter set {q/pT,phi,tanl(lambda),D,z} |
2928 | jerror_t DTrackFitterKalmanSIMD::StepJacobian(const DVector2 &xy, |
2929 | double ds,const DMatrix5x1 &S, |
2930 | double dEdx,DMatrix5x5 &J){ |
2931 | // Initialize the Jacobian matrix |
2932 | //J.Zero(); |
2933 | //for (int i=0;i<5;i++) J(i,i)=1.; |
2934 | J=I5x5; |
2935 | |
2936 | if (fabs(ds)<EPS3.0e-8) return NOERROR; // break out if ds is too small |
2937 | |
2938 | // Matrices for intermediate steps |
2939 | DMatrix5x5 J1; |
2940 | DMatrix5x1 D1; |
2941 | DVector2 dxy1; |
2942 | |
2943 | // charge |
2944 | double q=(S(state_q_over_pt)>0.0)?1.:-1.; |
2945 | q*=FactorForSenseOfRotation; |
2946 | |
2947 | //kinematic quantities |
2948 | double qpt=1./S(state_q_over_pt) * FactorForSenseOfRotation; |
2949 | double sinphi=sin(S(state_phi)); |
2950 | double cosphi=cos(S(state_phi)); |
2951 | double D=S(state_D); |
2952 | |
2953 | CalcDerivAndJacobian(xy,dxy1,S,dEdx,J1,D1); |
2954 | // double Bz_=fabs(Bz); // needed for computing D |
2955 | |
2956 | // New Jacobian matrix |
2957 | J+=ds*J1; |
2958 | |
2959 | // change in position |
2960 | DVector2 dxy =ds*dxy1; |
2961 | |
2962 | // Deal with changes in D |
2963 | double B=sqrt(Bx*Bx+By*By+Bz*Bz); |
2964 | //double qrc_old=qpt/(qBr2p*Bz_); |
2965 | double qrc_old=qpt/(qBr2p0.003*B); |
2966 | double qrc_plus_D=D+qrc_old; |
2967 | double dx=dxy.X(); |
2968 | double dy=dxy.Y(); |
2969 | double dx_sinphi_minus_dy_cosphi=dx*sinphi-dy*cosphi; |
2970 | double rc=sqrt(dxy.Mod2() |
2971 | +2.*qrc_plus_D*(dx_sinphi_minus_dy_cosphi) |
2972 | +qrc_plus_D*qrc_plus_D); |
2973 | double q_over_rc=q/rc; |
2974 | |
2975 | J(state_D,state_D)=q_over_rc*(dx_sinphi_minus_dy_cosphi+qrc_plus_D); |
2976 | J(state_D,state_q_over_pt)=qpt*qrc_old*(J(state_D,state_D)-1.); |
2977 | J(state_D,state_phi)=q_over_rc*qrc_plus_D*(dx*cosphi+dy*sinphi); |
2978 | |
2979 | return NOERROR; |
2980 | } |
2981 | |
2982 | // Compute contributions to the covariance matrix due to multiple scattering |
2983 | // using the Lynch/Dahl empirical formulas |
2984 | jerror_t DTrackFitterKalmanSIMD::GetProcessNoiseCentral(double ds, |
2985 | double chi2c_factor, |
2986 | double chi2a_factor, |
2987 | double chi2a_corr, |
2988 | const DMatrix5x1 &Sc, |
2989 | DMatrix5x5 &Q){ |
2990 | Q.Zero(); |
2991 | //return NOERROR; |
2992 | if (USE_MULS_COVARIANCE && chi2c_factor>0. && fabs(ds)>EPS3.0e-8){ |
2993 | double tanl=Sc(state_tanl); |
2994 | double tanl2=tanl*tanl; |
2995 | double one_plus_tanl2=1.+tanl2; |
2996 | double one_over_pt=fabs(Sc(state_q_over_pt)); |
2997 | double my_ds=fabs(ds); |
2998 | double my_ds_2=0.5*my_ds; |
2999 | |
3000 | Q(state_phi,state_phi)=one_plus_tanl2; |
3001 | Q(state_tanl,state_tanl)=one_plus_tanl2*one_plus_tanl2; |
3002 | Q(state_q_over_pt,state_q_over_pt)=one_over_pt*one_over_pt*tanl2; |
3003 | Q(state_q_over_pt,state_tanl)=Q(state_tanl,state_q_over_pt) |
3004 | =Sc(state_q_over_pt)*tanl*one_plus_tanl2; |
3005 | Q(state_D,state_D)=ONE_THIRD0.33333333333333333*ds*ds; |
3006 | |
3007 | // I am not sure the following is correct... |
3008 | double sign_D=(Sc(state_D)>0.0)?1.:-1.; |
3009 | Q(state_D,state_phi)=Q(state_phi,state_D)=sign_D*my_ds_2*sqrt(one_plus_tanl2); |
3010 | Q(state_D,state_tanl)=Q(state_tanl,state_D)=sign_D*my_ds_2*one_plus_tanl2; |
3011 | Q(state_D,state_q_over_pt)=Q(state_q_over_pt,state_D)=sign_D*my_ds_2*tanl*Sc(state_q_over_pt); |
3012 | |
3013 | double one_over_p_sq=one_over_pt*one_over_pt/one_plus_tanl2; |
3014 | double one_over_beta2=1.+mass2*one_over_p_sq; |
3015 | double chi2c_p_sq=chi2c_factor*my_ds*one_over_beta2; |
3016 | double chi2a_p_sq=chi2a_factor*(1.+chi2a_corr*one_over_beta2); |
3017 | // F=Fraction of Moliere distribution to be taken into account |
3018 | // nu=0.5*chi2c/(chi2a*(1.-F)); |
3019 | double nu=MOLIERE_RATIO1*chi2c_p_sq/chi2a_p_sq; |
3020 | double one_plus_nu=1.+nu; |
3021 | // sig2_ms=chi2c*1e-6/(1.+F*F)*((one_plus_nu)/nu*log(one_plus_nu)-1.); |
3022 | double sig2_ms=chi2c_p_sq*one_over_p_sq*MOLIERE_RATIO2 |
3023 | *(one_plus_nu/nu*log(one_plus_nu)-1.); |
3024 | |
3025 | Q*=sig2_ms; |
3026 | } |
3027 | |
3028 | return NOERROR; |
3029 | } |
3030 | |
3031 | // Compute contributions to the covariance matrix due to multiple scattering |
3032 | // using the Lynch/Dahl empirical formulas |
3033 | jerror_t DTrackFitterKalmanSIMD::GetProcessNoise(double z, double ds, |
3034 | double chi2c_factor, |
3035 | double chi2a_factor, |
3036 | double chi2a_corr, |
3037 | const DMatrix5x1 &S, |
3038 | DMatrix5x5 &Q){ |
3039 | |
3040 | Q.Zero(); |
3041 | //return NOERROR; |
3042 | if (USE_MULS_COVARIANCE && chi2c_factor>0. && fabs(ds)>EPS3.0e-8){ |
3043 | double tx=S(state_tx),ty=S(state_ty); |
3044 | double one_over_p_sq=S(state_q_over_p)*S(state_q_over_p); |
3045 | double my_ds=fabs(ds); |
3046 | double my_ds_2=0.5*my_ds; |
3047 | double tx2=tx*tx; |
3048 | double ty2=ty*ty; |
3049 | double one_plus_tx2=1.+tx2; |
3050 | double one_plus_ty2=1.+ty2; |
3051 | double tsquare=tx2+ty2; |
3052 | double one_plus_tsquare=1.+tsquare; |
3053 | |
3054 | Q(state_tx,state_tx)=one_plus_tx2*one_plus_tsquare; |
3055 | Q(state_ty,state_ty)=one_plus_ty2*one_plus_tsquare; |
3056 | Q(state_tx,state_ty)=Q(state_ty,state_tx)=tx*ty*one_plus_tsquare; |
3057 | |
3058 | Q(state_x,state_x)=ONE_THIRD0.33333333333333333*ds*ds; |
3059 | Q(state_y,state_y)=Q(state_x,state_x); |
3060 | Q(state_y,state_ty)=Q(state_ty,state_y) |
3061 | = my_ds_2*sqrt(one_plus_tsquare*one_plus_ty2); |
3062 | Q(state_x,state_tx)=Q(state_tx,state_x) |
3063 | = my_ds_2*sqrt(one_plus_tsquare*one_plus_tx2); |
3064 | |
3065 | double one_over_beta2=1.+one_over_p_sq*mass2; |
3066 | double chi2c_p_sq=chi2c_factor*my_ds*one_over_beta2; |
3067 | double chi2a_p_sq=chi2a_factor*(1.+chi2a_corr*one_over_beta2); |
3068 | // F=MOLIERE_FRACTION =Fraction of Moliere distribution to be taken into account |
3069 | // nu=0.5*chi2c/(chi2a*(1.-F)); |
3070 | double nu=MOLIERE_RATIO1*chi2c_p_sq/chi2a_p_sq; |
3071 | double one_plus_nu=1.+nu; |
3072 | double sig2_ms=chi2c_p_sq*one_over_p_sq*MOLIERE_RATIO2 |
3073 | *(one_plus_nu/nu*log(one_plus_nu)-1.); |
3074 | |
3075 | // printf("fac %f %f %f\n",chi2c_factor,chi2a_factor,chi2a_corr); |
3076 | //printf("omega %f\n",chi2c/chi2a); |
3077 | |
3078 | |
3079 | Q*=sig2_ms; |
3080 | } |
3081 | |
3082 | return NOERROR; |
3083 | } |
3084 | |
3085 | // Calculate the energy loss per unit length given properties of the material |
3086 | // through which a particle of momentum p is passing |
3087 | double DTrackFitterKalmanSIMD::GetdEdx(double q_over_p,double K_rho_Z_over_A, |
3088 | double rho_Z_over_A,double LnI,double Z){ |
3089 | if (rho_Z_over_A<=0.) return 0.; |
3090 | //return 0.; |
3091 | |
3092 | double p=fabs(1./q_over_p); |
3093 | double betagamma=p/MASS; |
3094 | double betagamma2=betagamma*betagamma; |
3095 | double gamma2=1.+betagamma2; |
3096 | double beta2=betagamma2/gamma2; |
3097 | if (beta2<EPS3.0e-8) beta2=EPS3.0e-8; |
3098 | |
3099 | // density effect |
3100 | double delta=CalcDensityEffect(betagamma,rho_Z_over_A,LnI); |
3101 | |
3102 | double dEdx=0.; |
3103 | // For particles heavier than electrons: |
3104 | if (IsHadron){ |
3105 | double two_Me_betagamma_sq=two_m_e*betagamma2; |
3106 | double Tmax |
3107 | =two_Me_betagamma_sq/(1.+2.*sqrt(gamma2)*m_ratio+m_ratio_sq); |
3108 | |
3109 | dEdx=K_rho_Z_over_A/beta2*(-log(two_Me_betagamma_sq*Tmax) |
3110 | +2.*(LnI + beta2)+delta); |
3111 | } |
3112 | else{ |
3113 | // relativistic kinetic energy in units of M_e c^2 |
3114 | double tau=sqrt(gamma2)-1.; |
3115 | double tau_sq=tau*tau; |
3116 | double tau_plus_1=tau+1.; |
3117 | double tau_plus_2=tau+2.; |
3118 | double tau_plus_2_sq=tau_plus_2*tau_plus_2; |
3119 | double f=0.; // function that depends on tau; see Leo (2nd ed.), p. 38. |
3120 | if (IsElectron){ |
3121 | f=1.-beta2+(0.125*tau_sq-(2.*tau+1.)*log(2.))/(tau_plus_1*tau_plus_1); |
3122 | } |
3123 | else{ |
3124 | f=2.*log(2.)-(beta2/12.)*(23.+14./tau_plus_2+10./tau_plus_2_sq |
3125 | +4./(tau_plus_2*tau_plus_2_sq)); |
3126 | } |
3127 | |
3128 | // collision loss (Leo eq. 2.66) |
3129 | double dEdx_coll |
3130 | =-K_rho_Z_over_A/beta2*(log(0.5*tau_sq*tau_plus_2*m_e_sq)-LnI+f-delta); |
3131 | |
3132 | // radiation loss (Leo eqs. 2.74, 2.76 with Z^2 -> Z(Z+1) |
3133 | double a=Z*ALPHA1./137.; |
3134 | double a2=a*a; |
3135 | double a4=a2*a2; |
3136 | double epsilon=1.-PHOTON_ENERGY_CUTOFF; |
3137 | double epsilon2=epsilon*epsilon; |
3138 | double f_Z=a2*(1./(1.+a2)+0.20206-0.0369*a2+0.0083*a4-0.002*a2*a4); |
3139 | // The expression below is the integral of the photon energy weighted |
3140 | // by the bremsstrahlung cross section up to a maximum photon energy |
3141 | // expressed as a fraction of the incident electron energy. |
3142 | double dEdx_rad=-K_rho_Z_over_A*tau_plus_1*(2.*ALPHA1./137./M_PI3.14159265358979323846)*(Z+1.) |
3143 | *((log(183.*pow(Z,-1./3.))-f_Z) |
3144 | *(1.-epsilon-(1./3.)*(epsilon2-epsilon*epsilon2)) |
3145 | +1./18.*(1.-epsilon2)); |
3146 | |
3147 | |
3148 | // dEdx_rad=0.; |
3149 | |
3150 | dEdx=dEdx_coll+dEdx_rad; |
3151 | } |
3152 | |
3153 | return dEdx; |
3154 | } |
3155 | |
3156 | // Calculate the variance in the energy loss in a Gaussian approximation. |
3157 | // The standard deviation of the energy loss distribution is |
3158 | // var=0.1535*density*(Z/A)*x*(1-0.5*beta^2)*Tmax [MeV] |
3159 | // where Tmax is the maximum energy transfer. |
3160 | // (derived from Leo (2nd ed.), eq. 2.100. Note that I think there is a typo |
3161 | // in this formula in the text...) |
3162 | double DTrackFitterKalmanSIMD::GetEnergyVariance(double ds, |
3163 | double one_over_beta2, |
3164 | double K_rho_Z_over_A){ |
3165 | if (K_rho_Z_over_A<=0.) return 0.; |
3166 | |
3167 | double betagamma2=1./(one_over_beta2-1.); |
3168 | double gamma2=betagamma2*one_over_beta2; |
3169 | double two_Me_betagamma_sq=two_m_e*betagamma2; |
3170 | double Tmax=two_Me_betagamma_sq/(1.+2.*sqrt(gamma2)*m_ratio+m_ratio_sq); |
3171 | double var=K_rho_Z_over_A*one_over_beta2*fabs(ds)*Tmax*(1.-0.5/one_over_beta2); |
3172 | return var; |
3173 | } |
3174 | |
3175 | // Interface routine for Kalman filter |
3176 | jerror_t DTrackFitterKalmanSIMD::KalmanLoop(void){ |
3177 | if (z_<Z_MIN-100.) return VALUE_OUT_OF_RANGE; |
3178 | |
3179 | // Vector to store the list of hits used in the fit for the forward parametrization |
3180 | vector<const DCDCTrackHit*>forward_cdc_used_in_fit; |
3181 | |
3182 | // State vector and initial guess for covariance matrix |
3183 | DMatrix5x1 S0; |
3184 | DMatrix5x5 C0; |
3185 | |
3186 | chisq_=-1.; |
3187 | |
3188 | // Angle with respect to beam line |
3189 | double theta_deg=(180/M_PI3.14159265358979323846)*input_params.momentum().Theta(); |
3190 | //double theta_deg_sq=theta_deg*theta_deg; |
3191 | double tanl0=tanl_=tan(M_PI_21.57079632679489661923-input_params.momentum().Theta()); |
3192 | |
3193 | // Azimuthal angle |
3194 | double phi0=phi_=input_params.momentum().Phi(); |
3195 | |
3196 | // Guess for momentum error |
3197 | double dpt_over_pt=0.1; |
3198 | /* |
3199 | if (theta_deg<15){ |
3200 | dpt_over_pt=0.107-0.0178*theta_deg+0.000966*theta_deg_sq; |
3201 | } |
3202 | else { |
3203 | dpt_over_pt=0.0288+0.00579*theta_deg-2.77e-5*theta_deg_sq; |
3204 | } |
3205 | */ |
3206 | /* |
3207 | if (theta_deg<28.){ |
3208 | theta_deg=28.; |
3209 | theta_deg_sq=theta_deg*theta_deg; |
3210 | } |
3211 | else if (theta_deg>125.){ |
3212 | theta_deg=125.; |
3213 | theta_deg_sq=theta_deg*theta_deg; |
3214 | } |
3215 | */ |
3216 | double sig_lambda=0.02; |
3217 | double dp_over_p_sq |
3218 | =dpt_over_pt*dpt_over_pt+tanl_*tanl_*sig_lambda*sig_lambda; |
3219 | |
3220 | // Input charge |
3221 | double q=input_params.charge(); |
3222 | |
3223 | // Input momentum |
3224 | DVector3 pvec=input_params.momentum(); |
3225 | double p_mag=pvec.Mag(); |
3226 | double px=pvec.x(); |
3227 | double py=pvec.y(); |
3228 | double pz=pvec.z(); |
3229 | double q_over_p0=q_over_p_=q/p_mag; |
3230 | double q_over_pt0=q_over_pt_=q/pvec.Perp(); |
3231 | |
3232 | // Initial position |
3233 | double x0=x_=input_params.position().x(); |
3234 | double y0=y_=input_params.position().y(); |
3235 | double z0=z_=input_params.position().z(); |
3236 | |
3237 | if (fit_type==kWireBased && theta_deg>10.){ |
3238 | double Bz=fabs(bfield->GetBz(x0,y0,z0)); |
3239 | double sperp=25.; // empirical guess |
3240 | if (my_fdchits.size()>0 && my_fdchits[0]->hit!=NULL__null){ |
3241 | double my_z=my_fdchits[0]->z; |
3242 | double my_x=my_fdchits[0]->hit->xy.X(); |
3243 | double my_y=my_fdchits[0]->hit->xy.Y(); |
3244 | Bz+=fabs(bfield->GetBz(my_x,my_y,my_z)); |
3245 | Bz*=0.5; // crude average |
3246 | sperp=(my_z-z0)/tanl_; |
3247 | } |
3248 | double twokappa=qBr2p0.003*Bz*q_over_pt0*FactorForSenseOfRotation; |
3249 | double one_over_2k=1./twokappa; |
3250 | if (my_fdchits.size()==0){ |
3251 | for (unsigned int i=my_cdchits.size()-1;i>1;i--){ |
3252 | // Use outermost axial straw to estimate a resonable arc length |
3253 | if (my_cdchits[i]->hit->is_stereo==false){ |
3254 | double tworc=2.*fabs(one_over_2k); |
3255 | double ratio=(my_cdchits[i]->hit->wire->origin |
3256 | -input_params.position()).Perp()/tworc; |
3257 | sperp=(ratio<1.)?tworc*asin(ratio):tworc*M_PI_21.57079632679489661923; |
3258 | if (sperp<25.) sperp=25.; |
3259 | break; |
3260 | } |
3261 | } |
3262 | } |
3263 | double twoks=twokappa*sperp; |
3264 | double cosphi=cos(phi0); |
3265 | double sinphi=sin(phi0); |
3266 | double sin2ks=sin(twoks); |
3267 | double cos2ks=cos(twoks); |
3268 | double one_minus_cos2ks=1.-cos2ks; |
3269 | double myx=x0+one_over_2k*(cosphi*sin2ks-sinphi*one_minus_cos2ks); |
3270 | double myy=y0+one_over_2k*(sinphi*sin2ks+cosphi*one_minus_cos2ks); |
3271 | double mypx=px*cos2ks-py*sin2ks; |
3272 | double mypy=py*cos2ks+px*sin2ks; |
3273 | double myphi=atan2(mypy,mypx); |
3274 | phi0=phi_=myphi; |
3275 | px=mypx; |
3276 | py=mypy; |
3277 | x0=x_=myx; |
3278 | y0=y_=myy; |
3279 | z0+=tanl_*sperp; |
3280 | z_=z0; |
3281 | } |
3282 | |
3283 | // Check integrity of input parameters |
3284 | if (!isfinite(x0) || !isfinite(y0) || !isfinite(q_over_p0)){ |
3285 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<3285<<" " << "Invalid input parameters!" <<endl; |
3286 | return UNRECOVERABLE_ERROR; |
3287 | } |
3288 | |
3289 | // Initial direction tangents |
3290 | double tx0=tx_=px/pz; |
3291 | double ty0=ty_=py/pz; |
3292 | double one_plus_tsquare=1.+tx_*tx_+ty_*ty_; |
3293 | |
3294 | // deal with hits in FDC |
3295 | double fdc_prob=0.,fdc_chisq=-1.; |
3296 | unsigned int fdc_ndf=0; |
3297 | if (my_fdchits.size()>0 |
3298 | && // Make sure that these parameters are valid for forward-going tracks |
3299 | (isfinite(tx0) && isfinite(ty0)) |
3300 | ){ |
3301 | if (DEBUG_LEVEL>0){ |
3302 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<3302<<" " << "Using forward parameterization." <<endl; |
3303 | } |
3304 | |
3305 | // Initial guess for the state vector |
3306 | S0(state_x)=x_; |
3307 | S0(state_y)=y_; |
3308 | S0(state_tx)=tx_; |
3309 | S0(state_ty)=ty_; |
3310 | S0(state_q_over_p)=q_over_p_; |
3311 | |
3312 | // Initial guess for forward representation covariance matrix |
3313 | C0(state_x,state_x)=2.0; |
3314 | C0(state_y,state_y)=2.0; |
3315 | double temp=sig_lambda*one_plus_tsquare; |
3316 | C0(state_tx,state_tx)=C0(state_ty,state_ty)=temp*temp; |
3317 | C0(state_q_over_p,state_q_over_p)=dp_over_p_sq*q_over_p_*q_over_p_; |
3318 | C0*=COVARIANCE_SCALE_FACTOR_FORWARD; |
3319 | |
3320 | if (my_cdchits.size()>0){ |
3321 | mCDCInternalStepSize=0.25; |
3322 | } |
3323 | |
3324 | // The position from the track candidate is reported just outside the |
3325 | // start counter for tracks containing cdc hits. Propagate to the distance |
3326 | // of closest approach to the beam line |
3327 | if (fit_type==kWireBased) ExtrapolateToVertex(S0); |
3328 | |
3329 | kalman_error_t error=ForwardFit(S0,C0); |
3330 | if (error==FIT_SUCCEEDED) return NOERROR; |
3331 | if ((error==FIT_FAILED || ndf_==0) && my_cdchits.size()<6){ |
3332 | return UNRECOVERABLE_ERROR; |
3333 | } |
3334 | |
3335 | fdc_prob=TMath::Prob(chisq_,ndf_); |
3336 | fdc_ndf=ndf_; |
3337 | fdc_chisq=chisq_; |
3338 | } |
3339 | |
3340 | // Deal with hits in the CDC |
3341 | if (my_cdchits.size()>5){ |
3342 | kalman_error_t error=FIT_NOT_DONE; |
3343 | kalman_error_t cdc_error=FIT_NOT_DONE; |
3344 | |
3345 | // Save the current state of the extrapolation vector if it exists |
3346 | map<DetectorSystem_t,vector<Extrapolation_t> >saved_extrapolations; |
3347 | if (!extrapolations.empty()){ |
3348 | saved_extrapolations=extrapolations; |
3349 | ClearExtrapolations(); |
3350 | } |
3351 | bool save_IsSmoothed=IsSmoothed; |
3352 | |
3353 | // Chi-squared, degrees of freedom, and probability |
3354 | double forward_prob=0.; |
3355 | double chisq_forward=-1.; |
3356 | unsigned int ndof_forward=0; |
3357 | |
3358 | // Parameters at "vertex" |
3359 | double phi=phi_,q_over_pt=q_over_pt_,tanl=tanl_,x=x_,y=y_,z=z_; |
3360 | vector< vector <double> > fcov_save; |
3361 | vector<pull_t>pulls_save; |
3362 | pulls_save.assign(pulls.begin(),pulls.end()); |
3363 | if (!fcov.empty()){ |
3364 | fcov_save.assign(fcov.begin(),fcov.end()); |
3365 | } |
3366 | if (my_fdchits.size()>0){ |
3367 | if (error==INVALID_FIT) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<3367<<" "<< "Invalid fit " << fcov.size() << " " << fdc_ndf <<endl; |
3368 | } |
3369 | |
3370 | // Use forward parameters for CDC-only tracks with theta<THETA_CUT degrees |
3371 | if (theta_deg<THETA_CUT){ |
3372 | if (DEBUG_LEVEL>0){ |
3373 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<3373<<" " << "Using forward parameterization." <<endl; |
3374 | } |
3375 | |
3376 | // Step size |
3377 | mStepSizeS=mCentralStepSize; |
3378 | |
3379 | // Initialize the state vector |
3380 | S0(state_x)=x_=x0; |
3381 | S0(state_y)=y_=y0; |
3382 | S0(state_tx)=tx_=tx0; |
3383 | S0(state_ty)=ty_=ty0; |
3384 | S0(state_q_over_p)=q_over_p_=q_over_p0; |
3385 | z_=z0; |
3386 | |
3387 | // Initial guess for forward representation covariance matrix |
3388 | double temp=sig_lambda*one_plus_tsquare; |
3389 | C0(state_x,state_x)=2.0; |
3390 | C0(state_y,state_y)=2.0; |
3391 | C0(state_tx,state_tx)=C0(state_ty,state_ty)=temp*temp; |
3392 | C0(state_q_over_p,state_q_over_p)=dp_over_p_sq*q_over_p_*q_over_p_; |
3393 | C0*=COVARIANCE_SCALE_FACTOR_FORWARD; |
3394 | |
3395 | //C0*=1.+1./tsquare; |
3396 | |
3397 | // The position from the track candidate is reported just outside the |
3398 | // start counter for tracks containing cdc hits. Propagate to the |
3399 | // distance of closest approach to the beam line |
3400 | if (fit_type==kWireBased) ExtrapolateToVertex(S0); |
3401 | |
3402 | error=ForwardCDCFit(S0,C0); |
3403 | if (error==FIT_SUCCEEDED) return NOERROR; |
3404 | |
3405 | // Find the CL of the fit |
3406 | forward_prob=TMath::Prob(chisq_,ndf_); |
3407 | if (my_fdchits.size()>0){ |
3408 | if (fdc_ndf==0 || forward_prob>fdc_prob){ |
3409 | // We did not end up using the fdc hits after all... |
3410 | fdchits_used_in_fit.clear(); |
3411 | } |
3412 | else{ |
3413 | chisq_=fdc_chisq; |
3414 | ndf_=fdc_ndf; |
3415 | x_=x; |
3416 | y_=y; |
3417 | z_=z; |
3418 | phi_=phi; |
3419 | tanl_=tanl; |
3420 | q_over_pt_=q_over_pt; |
3421 | if (!fcov_save.empty()){ |
3422 | fcov.assign(fcov_save.begin(),fcov_save.end()); |
3423 | } |
3424 | if (!saved_extrapolations.empty()){ |
3425 | extrapolations=saved_extrapolations; |
3426 | } |
3427 | IsSmoothed=save_IsSmoothed; |
3428 | pulls.assign(pulls_save.begin(),pulls_save.end()); |
3429 | |
3430 | // _DBG_ << endl; |
3431 | return NOERROR; |
3432 | } |
3433 | |
3434 | // Save the best values for the parameters and chi2 for now |
3435 | chisq_forward=chisq_; |
3436 | ndof_forward=ndf_; |
3437 | x=x_; |
3438 | y=y_; |
3439 | z=z_; |
3440 | phi=phi_; |
3441 | tanl=tanl_; |
3442 | q_over_pt=q_over_pt_; |
3443 | fcov_save.assign(fcov.begin(),fcov.end()); |
3444 | pulls_save.assign(pulls.begin(),pulls.end()); |
3445 | save_IsSmoothed=IsSmoothed; |
3446 | if (!extrapolations.empty()){ |
3447 | saved_extrapolations=extrapolations; |
3448 | ClearExtrapolations(); |
3449 | } |
3450 | |
3451 | // Save the list of hits used in the fit |
3452 | forward_cdc_used_in_fit.assign(cdchits_used_in_fit.begin(),cdchits_used_in_fit.end()); |
3453 | |
3454 | } |
3455 | } |
3456 | |
3457 | // Attempt to fit the track using the central parametrization. |
3458 | if (DEBUG_LEVEL>0){ |
3459 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<3459<<" " << "Using central parameterization." <<endl; |
3460 | } |
3461 | |
3462 | // Step size |
3463 | mStepSizeS=mCentralStepSize; |
3464 | |
3465 | // Initialize the state vector |
3466 | S0(state_q_over_pt)=q_over_pt_=q_over_pt0; |
3467 | S0(state_phi)=phi_=phi0; |
3468 | S0(state_tanl)=tanl_=tanl0; |
3469 | S0(state_z)=z_=z0; |
3470 | S0(state_D)=0.; |
3471 | |
3472 | // Initialize the covariance matrix |
3473 | double dz=1.0; |
3474 | C0(state_z,state_z)=dz*dz; |
3475 | C0(state_q_over_pt,state_q_over_pt) |
3476 | =q_over_pt_*q_over_pt_*dpt_over_pt*dpt_over_pt; |
3477 | double dphi=0.02; |
3478 | C0(state_phi,state_phi)=dphi*dphi; |
3479 | C0(state_D,state_D)=1.0; |
3480 | double tanl2=tanl_*tanl_; |
3481 | double one_plus_tanl2=1.+tanl2; |
3482 | C0(state_tanl,state_tanl)=(one_plus_tanl2)*(one_plus_tanl2) |
3483 | *sig_lambda*sig_lambda; |
3484 | C0*=COVARIANCE_SCALE_FACTOR_CENTRAL; |
3485 | |
3486 | //if (theta_deg>90.) C0*=1.+5.*tanl2; |
3487 | //else C0*=1.+5.*tanl2*tanl2; |
3488 | |
3489 | mCentralStepSize=0.4; |
3490 | mCDCInternalStepSize=0.2; |
3491 | |
3492 | // The position from the track candidate is reported just outside the |
3493 | // start counter for tracks containing cdc hits. Propagate to the |
3494 | // distance of closest approach to the beam line |
3495 | DVector2 xy(x0,y0); |
3496 | if (fit_type==kWireBased){ |
3497 | ExtrapolateToVertex(xy,S0); |
3498 | } |
3499 | |
3500 | cdc_error=CentralFit(xy,S0,C0); |
3501 | if (cdc_error==FIT_SUCCEEDED){ |
3502 | // if the result of the fit using the forward parameterization succeeded |
3503 | // but the chi2 was too high, it still may provide the best estimate |
3504 | // for the track parameters... |
3505 | double central_prob=TMath::Prob(chisq_,ndf_); |
3506 | |
3507 | if (central_prob<forward_prob){ |
3508 | phi_=phi; |
3509 | q_over_pt_=q_over_pt; |
3510 | tanl_=tanl; |
3511 | x_=x; |
3512 | y_=y; |
3513 | z_=z; |
3514 | chisq_=chisq_forward; |
3515 | ndf_= ndof_forward; |
3516 | fcov.assign(fcov_save.begin(),fcov_save.end()); |
3517 | pulls.assign(pulls_save.begin(),pulls_save.end()); |
3518 | IsSmoothed=save_IsSmoothed; |
3519 | if (!saved_extrapolations.empty()){ |
3520 | extrapolations=saved_extrapolations; |
3521 | } |
3522 | |
3523 | cdchits_used_in_fit.assign(forward_cdc_used_in_fit.begin(),forward_cdc_used_in_fit.end()); |
3524 | |
3525 | // We did not end up using any fdc hits... |
3526 | fdchits_used_in_fit.clear(); |
3527 | |
3528 | } |
3529 | return NOERROR; |
3530 | |
3531 | } |
3532 | // otherwise if the fit using the forward parametrization worked, return that |
3533 | else if (error!=FIT_FAILED){ |
3534 | phi_=phi; |
3535 | q_over_pt_=q_over_pt; |
3536 | tanl_=tanl; |
3537 | x_=x; |
3538 | y_=y; |
3539 | z_=z; |
3540 | chisq_=chisq_forward; |
3541 | ndf_= ndof_forward; |
3542 | |
3543 | if (!saved_extrapolations.empty()){ |
3544 | extrapolations=saved_extrapolations; |
3545 | } |
3546 | IsSmoothed=save_IsSmoothed; |
3547 | fcov.assign(fcov_save.begin(),fcov_save.end()); |
3548 | pulls.assign(pulls_save.begin(),pulls_save.end()); |
3549 | cdchits_used_in_fit.assign(forward_cdc_used_in_fit.begin(),forward_cdc_used_in_fit.end()); |
3550 | |
3551 | // We did not end up using any fdc hits... |
3552 | fdchits_used_in_fit.clear(); |
3553 | |
3554 | return NOERROR; |
3555 | } |
3556 | else return UNRECOVERABLE_ERROR; |
3557 | } |
3558 | |
3559 | if (ndf_==0) return UNRECOVERABLE_ERROR; |
3560 | |
3561 | return NOERROR; |
3562 | } |
3563 | |
3564 | #define ITMAX20 20 |
3565 | #define CGOLD0.3819660 0.3819660 |
3566 | #define ZEPS1.0e-10 1.0e-10 |
3567 | #define SHFT(a,b,c,d)(a)=(b);(b)=(c);(c)=(d); (a)=(b);(b)=(c);(c)=(d); |
3568 | #define SIGN(a,b)((b)>=0.0?fabs(a):-fabs(a)) ((b)>=0.0?fabs(a):-fabs(a)) |
3569 | // Routine for finding the minimum of a function bracketed between two values |
3570 | // (see Numerical Recipes in C, pp. 404-405). |
3571 | jerror_t DTrackFitterKalmanSIMD::BrentsAlgorithm(double ds1,double ds2, |
3572 | double dedx,DVector2 &pos, |
3573 | const double z0wire, |
3574 | const DVector2 &origin, |
3575 | const DVector2 &dir, |
3576 | DMatrix5x1 &Sc, |
3577 | double &ds_out){ |
3578 | double d=0.; |
3579 | double e=0.0; // will be distance moved on step before last |
3580 | double ax=0.; |
3581 | double bx=-ds1; |
3582 | double cx=-ds1-ds2; |
3583 | |
3584 | double a=(ax<cx?ax:cx); |
3585 | double b=(ax>cx?ax:cx); |
3586 | double x=bx,w=bx,v=bx; |
3587 | |
3588 | // printf("ds1 %f ds2 %f\n",ds1,ds2); |
3589 | // Initialize return step size |
3590 | ds_out=0.; |
3591 | |
3592 | // Save the starting position |
3593 | // DVector3 pos0=pos; |
3594 | // DMatrix S0(Sc); |
3595 | |
3596 | // Step to intermediate point |
3597 | Step(pos,x,Sc,dedx); |
3598 | // Bail if the transverse momentum has dropped below some minimum |
3599 | if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){ |
3600 | if (DEBUG_LEVEL>2) |
3601 | { |
3602 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<3602<<" " << "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt)) |
3603 | << endl; |
3604 | } |
3605 | return VALUE_OUT_OF_RANGE; |
3606 | } |
3607 | |
3608 | DVector2 wirepos=origin+(Sc(state_z)-z0wire)*dir; |
3609 | double u_old=x; |
3610 | double u=0.; |
3611 | |
3612 | // initialization |
3613 | double fw=(pos-wirepos).Mod2(); |
3614 | double fv=fw,fx=fw; |
3615 | |
3616 | // main loop |
3617 | for (unsigned int iter=1;iter<=ITMAX20;iter++){ |
3618 | double xm=0.5*(a+b); |
3619 | double tol1=EPS21.e-4*fabs(x)+ZEPS1.0e-10; |
3620 | double tol2=2.0*tol1; |
3621 | |
3622 | if (fabs(x-xm)<=(tol2-0.5*(b-a))){ |
3623 | if (Sc(state_z)<=cdc_origin[2]){ |
3624 | unsigned int iter2=0; |
3625 | double ds_temp=0.; |
3626 | while (fabs(Sc(state_z)-cdc_origin[2])>EPS21.e-4 && iter2<20){ |
3627 | u=x-(cdc_origin[2]-Sc(state_z))*sin(atan(Sc(state_tanl))); |
3628 | x=u; |
3629 | ds_temp+=u_old-u; |
3630 | // Bail if the transverse momentum has dropped below some minimum |
3631 | if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){ |
3632 | if (DEBUG_LEVEL>2) |
3633 | { |
3634 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<3634<<" " << "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt)) |
3635 | << endl; |
3636 | } |
3637 | return VALUE_OUT_OF_RANGE; |
3638 | } |
3639 | |
3640 | // Function evaluation |
3641 | Step(pos,u_old-u,Sc,dedx); |
3642 | u_old=u; |
3643 | iter2++; |
3644 | } |
3645 | //printf("new z %f ds %f \n",pos.z(),x); |
3646 | ds_out=ds_temp; |
3647 | return NOERROR; |
3648 | } |
3649 | else if (Sc(state_z)>=endplate_z){ |
3650 | unsigned int iter2=0; |
3651 | double ds_temp=0.; |
3652 | while (fabs(Sc(state_z)-endplate_z)>EPS21.e-4 && iter2<20){ |
3653 | u=x-(endplate_z-Sc(state_z))*sin(atan(Sc(state_tanl))); |
3654 | x=u; |
3655 | ds_temp+=u_old-u; |
3656 | |
3657 | // Bail if the transverse momentum has dropped below some minimum |
3658 | if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){ |
3659 | if (DEBUG_LEVEL>2) |
3660 | { |
3661 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<3661<<" " << "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt)) |
3662 | << endl; |
3663 | } |
3664 | return VALUE_OUT_OF_RANGE; |
3665 | } |
3666 | |
3667 | // Function evaluation |
3668 | Step(pos,u_old-u,Sc,dedx); |
3669 | u_old=u; |
3670 | iter2++; |
3671 | } |
3672 | //printf("new z %f ds %f \n",pos.z(),x); |
3673 | ds_out=ds_temp; |
3674 | return NOERROR; |
3675 | } |
3676 | ds_out=cx-x; |
3677 | return NOERROR; |
3678 | } |
3679 | // trial parabolic fit |
3680 | if (fabs(e)>tol1){ |
3681 | double x_minus_w=x-w; |
3682 | double x_minus_v=x-v; |
3683 | double r=x_minus_w*(fx-fv); |
3684 | double q=x_minus_v*(fx-fw); |
3685 | double p=x_minus_v*q-x_minus_w*r; |
3686 | q=2.0*(q-r); |
3687 | if (q>0.0) p=-p; |
3688 | q=fabs(q); |
3689 | double etemp=e; |
3690 | e=d; |
3691 | if (fabs(p)>=fabs(0.5*q*etemp) || p<=q*(a-x) || p>=q*(b-x)) |
3692 | // fall back on the Golden Section technique |
3693 | d=CGOLD0.3819660*(e=(x>=xm?a-x:b-x)); |
3694 | else{ |
3695 | // parabolic step |
3696 | d=p/q; |
3697 | u=x+d; |
3698 | if (u-a<tol2 || b-u <tol2) |
3699 | d=SIGN(tol1,xm-x)((xm-x)>=0.0?fabs(tol1):-fabs(tol1)); |
3700 | } |
3701 | } else{ |
3702 | d=CGOLD0.3819660*(e=(x>=xm?a-x:b-x)); |
3703 | } |
3704 | u=(fabs(d)>=tol1 ? x+d: x+SIGN(tol1,d)((d)>=0.0?fabs(tol1):-fabs(tol1))); |
3705 | |
3706 | // Bail if the transverse momentum has dropped below some minimum |
3707 | if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){ |
3708 | if (DEBUG_LEVEL>2) |
3709 | { |
3710 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<3710<<" " << "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt)) |
3711 | << endl; |
3712 | } |
3713 | return VALUE_OUT_OF_RANGE; |
3714 | } |
3715 | |
3716 | // Function evaluation |
3717 | Step(pos,u_old-u,Sc,dedx); |
3718 | u_old=u; |
3719 | |
3720 | wirepos=origin; |
3721 | wirepos+=(Sc(state_z)-z0wire)*dir; |
3722 | double fu=(pos-wirepos).Mod2(); |
3723 | |
3724 | //cout << "Brent: z="<<Sc(state_z) << " d="<<sqrt(fu) << endl; |
3725 | |
3726 | if (fu<=fx){ |
3727 | if (u>=x) a=x; else b=x; |
3728 | SHFT(v,w,x,u)(v)=(w);(w)=(x);(x)=(u);; |
3729 | SHFT(fv,fw,fx,fu)(fv)=(fw);(fw)=(fx);(fx)=(fu);; |
3730 | } |
3731 | else { |
3732 | if (u<x) a=u; else b=u; |
3733 | if (fu<=fw || w==x){ |
3734 | v=w; |
3735 | w=u; |
3736 | fv=fw; |
3737 | fw=fu; |
3738 | } |
3739 | else if (fu<=fv || v==x || v==w){ |
3740 | v=u; |
3741 | fv=fu; |
3742 | } |
3743 | } |
3744 | } |
3745 | ds_out=cx-x; |
3746 | |
3747 | return NOERROR; |
3748 | } |
3749 | |
3750 | // Routine for finding the minimum of a function bracketed between two values |
3751 | // (see Numerical Recipes in C, pp. 404-405). |
3752 | jerror_t DTrackFitterKalmanSIMD::BrentsAlgorithm(double z,double dz, |
3753 | double dedx, |
3754 | const double z0wire, |
3755 | const DVector2 &origin, |
3756 | const DVector2 &dir, |
3757 | DMatrix5x1 &S, |
3758 | double &dz_out){ |
3759 | double d=0.,u=0.; |
3760 | double e=0.0; // will be distance moved on step before last |
3761 | double ax=0.; |
3762 | double bx=-dz; |
3763 | double cx=-2.*dz; |
3764 | |
3765 | double a=(ax<cx?ax:cx); |
3766 | double b=(ax>cx?ax:cx); |
3767 | double x=bx,w=bx,v=bx; |
3768 | |
3769 | // Initialize dz_out |
3770 | dz_out=0.; |
3771 | |
3772 | // Step to intermediate point |
3773 | double z_new=z+x; |
3774 | Step(z,z_new,dedx,S); |
3775 | // Bail if the momentum has dropped below some minimum |
3776 | if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){ |
3777 | if (DEBUG_LEVEL>2) |
3778 | { |
3779 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<3779<<" " << "Bailing: P = " << 1./fabs(S(state_q_over_p)) |
3780 | << endl; |
3781 | } |
3782 | return VALUE_OUT_OF_RANGE; |
3783 | } |
3784 | |
3785 | double dz0wire=z-z0wire; |
3786 | DVector2 wirepos=origin+(dz0wire+x)*dir; |
3787 | DVector2 pos(S(state_x),S(state_y)); |
3788 | double z_old=z_new; |
3789 | |
3790 | // initialization |
3791 | double fw=(pos-wirepos).Mod2(); |
3792 | double fv=fw; |
3793 | double fx=fw; |
3794 | |
3795 | // main loop |
3796 | for (unsigned int iter=1;iter<=ITMAX20;iter++){ |
3797 | double xm=0.5*(a+b); |
3798 | double tol1=EPS21.e-4*fabs(x)+ZEPS1.0e-10; |
3799 | double tol2=2.0*tol1; |
3800 | if (fabs(x-xm)<=(tol2-0.5*(b-a))){ |
3801 | if (z_new>=endplate_z){ |
3802 | x=endplate_z-z_new; |
3803 | |
3804 | // Bail if the momentum has dropped below some minimum |
3805 | if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){ |
3806 | if (DEBUG_LEVEL>2) |
3807 | { |
3808 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<3808<<" " << "Bailing: P = " << 1./fabs(S(state_q_over_p)) |
3809 | << endl; |
3810 | } |
3811 | return VALUE_OUT_OF_RANGE; |
3812 | } |
3813 | if (!isfinite(S(state_x)) || !isfinite(S(state_y))){ |
3814 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<3814<<" " <<endl; |
3815 | return VALUE_OUT_OF_RANGE; |
3816 | } |
3817 | Step(z_new,endplate_z,dedx,S); |
3818 | } |
3819 | dz_out=x; |
3820 | return NOERROR; |
3821 | } |
3822 | // trial parabolic fit |
3823 | if (fabs(e)>tol1){ |
3824 | double x_minus_w=x-w; |
3825 | double x_minus_v=x-v; |
3826 | double r=x_minus_w*(fx-fv); |
3827 | double q=x_minus_v*(fx-fw); |
3828 | double p=x_minus_v*q-x_minus_w*r; |
3829 | q=2.0*(q-r); |
3830 | if (q>0.0) p=-p; |
3831 | q=fabs(q); |
3832 | double etemp=e; |
3833 | e=d; |
3834 | if (fabs(p)>=fabs(0.5*q*etemp) || p<=q*(a-x) || p>=q*(b-x)) |
3835 | // fall back on the Golden Section technique |
3836 | d=CGOLD0.3819660*(e=(x>=xm?a-x:b-x)); |
3837 | else{ |
3838 | // parabolic step |
3839 | d=p/q; |
3840 | u=x+d; |
3841 | if (u-a<tol2 || b-u <tol2) |
3842 | d=SIGN(tol1,xm-x)((xm-x)>=0.0?fabs(tol1):-fabs(tol1)); |
3843 | } |
3844 | } else{ |
3845 | d=CGOLD0.3819660*(e=(x>=xm?a-x:b-x)); |
3846 | } |
3847 | u=(fabs(d)>=tol1 ? x+d: x+SIGN(tol1,d)((d)>=0.0?fabs(tol1):-fabs(tol1))); |
3848 | |
3849 | // Function evaluation |
3850 | //S=S0; |
3851 | z_new=z+u; |
3852 | // Bail if the momentum has dropped below some minimum |
3853 | if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){ |
3854 | if (DEBUG_LEVEL>2) |
3855 | { |
3856 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<3856<<" " << "Bailing: P = " << 1./fabs(S(state_q_over_p)) |
3857 | << endl; |
3858 | } |
3859 | return VALUE_OUT_OF_RANGE; |
3860 | } |
3861 | |
3862 | Step(z_old,z_new,dedx,S); |
3863 | z_old=z_new; |
3864 | |
3865 | wirepos=origin; |
3866 | wirepos+=(dz0wire+u)*dir; |
3867 | pos.Set(S(state_x),S(state_y)); |
3868 | double fu=(pos-wirepos).Mod2(); |
3869 | |
3870 | // _DBG_ << "Brent: z="<< z+u << " d^2="<<fu << endl; |
3871 | |
3872 | if (fu<=fx){ |
3873 | if (u>=x) a=x; else b=x; |
3874 | SHFT(v,w,x,u)(v)=(w);(w)=(x);(x)=(u);; |
3875 | SHFT(fv,fw,fx,fu)(fv)=(fw);(fw)=(fx);(fx)=(fu);; |
3876 | } |
3877 | else { |
3878 | if (u<x) a=u; else b=u; |
3879 | if (fu<=fw || w==x){ |
3880 | v=w; |
3881 | w=u; |
3882 | fv=fw; |
3883 | fw=fu; |
3884 | } |
3885 | else if (fu<=fv || v==x || v==w){ |
3886 | v=u; |
3887 | fv=fu; |
3888 | } |
3889 | } |
3890 | } |
3891 | dz_out=x; |
3892 | return NOERROR; |
3893 | } |
3894 | |
3895 | // Kalman engine for Central tracks; updates the position on the trajectory |
3896 | // after the last hit (closest to the target) is added |
3897 | kalman_error_t DTrackFitterKalmanSIMD::KalmanCentral(double anneal_factor, |
3898 | DMatrix5x1 &Sc, |
3899 | DMatrix5x5 &Cc, |
3900 | DVector2 &xy,double &chisq, |
3901 | unsigned int &my_ndf |
3902 | ){ |
3903 | DMatrix1x5 H; // Track projection matrix |
3904 | DMatrix5x1 H_T; // Transpose of track projection matrix |
3905 | DMatrix5x5 J; // State vector Jacobian matrix |
3906 | DMatrix5x5 Q; // Process noise covariance matrix |
3907 | DMatrix5x1 K; // KalmanSIMD gain matrix |
3908 | DMatrix5x5 Ctest; // covariance matrix |
3909 | // double V=0.2028; //1.56*1.56/12.; // Measurement variance |
3910 | double V=0.0507; |
3911 | double InvV; // inverse of variance |
3912 | //DMatrix5x1 dS; // perturbation in state vector |
3913 | DMatrix5x1 S0,S0_; // state vector |
3914 | |
3915 | // set the used_in_fit flags to false for cdc hits |
3916 | unsigned int num_cdc=cdc_used_in_fit.size(); |
3917 | for (unsigned int i=0;i<num_cdc;i++) cdc_used_in_fit[i]=false; |
3918 | for (unsigned int i=0;i<central_traj.size();i++){ |
3919 | central_traj[i].h_id=0; |
3920 | } |
3921 | |
3922 | // Initialize the chi2 for this part of the track |
3923 | chisq=0.; |
3924 | my_ndf=0; |
3925 | |
3926 | double chi2cut=NUM_CDC_SIGMA_CUT*NUM_CDC_SIGMA_CUT; |
3927 | |
3928 | // path length increment |
3929 | double ds2=0.; |
3930 | |
3931 | //printf(">>>>>>>>>>>>>>>>\n"); |
3932 | |
3933 | // beginning position |
3934 | double phi=Sc(state_phi); |
3935 | xy.Set(central_traj[break_point_step_index].xy.X()-Sc(state_D)*sin(phi), |
3936 | central_traj[break_point_step_index].xy.Y()+Sc(state_D)*cos(phi)); |
3937 | |
3938 | // Wire origin and direction |
3939 | // unsigned int cdc_index=my_cdchits.size()-1; |
3940 | unsigned int cdc_index=break_point_cdc_index; |
3941 | if (break_point_cdc_index<num_cdc-1){ |
3942 | num_cdc=break_point_cdc_index+1; |
3943 | } |
3944 | |
3945 | if (num_cdc<MIN_HITS_FOR_REFIT) chi2cut=BIG1.0e8; |
3946 | |
3947 | // Wire origin and direction |
3948 | DVector2 origin=my_cdchits[cdc_index]->origin; |
3949 | double z0w=my_cdchits[cdc_index]->z0wire; |
3950 | DVector2 dir=my_cdchits[cdc_index]->dir; |
3951 | DVector2 wirexy=origin+(Sc(state_z)-z0w)*dir; |
3952 | |
3953 | // Save the starting values for C and S in the deque |
3954 | central_traj[break_point_step_index].Skk=Sc; |
3955 | central_traj[break_point_step_index].Ckk=Cc; |
3956 | |
3957 | // doca variables |
3958 | double doca2,old_doca2=(xy-wirexy).Mod2(); |
3959 | |
3960 | // energy loss |
3961 | double dedx=0.; |
3962 | |
3963 | // Boolean for flagging when we are done with measurements |
3964 | bool more_measurements=true; |
3965 | |
3966 | // Initialize S0_ and perform the loop over the trajectory |
3967 | S0_=central_traj[break_point_step_index].S; |
3968 | |
3969 | for (unsigned int k=break_point_step_index+1;k<central_traj.size();k++){ |
3970 | unsigned int k_minus_1=k-1; |
3971 | |
3972 | // Get the state vector, jacobian matrix, and multiple scattering matrix |
3973 | // from reference trajectory |
3974 | S0=central_traj[k].S; |
3975 | J=central_traj[k].J; |
3976 | Q=central_traj[k].Q; |
3977 | |
3978 | //Q.Print(); |
3979 | //J.Print(); |
3980 | |
3981 | // State S is perturbation about a seed S0 |
3982 | //dS=Sc-S0_; |
3983 | //dS.Zero(); |
3984 | |
3985 | // Update the actual state vector and covariance matrix |
3986 | Sc=S0+J*(Sc-S0_); |
3987 | // Cc=J*(Cc*JT)+Q; |
3988 | // Cc=Q.AddSym(Cc.SandwichMultiply(J)); |
3989 | Cc=Q.AddSym(J*Cc*J.Transpose()); |
3990 | |
3991 | // Save the current state and covariance matrix in the deque |
3992 | if (fit_type==kTimeBased){ |
3993 | central_traj[k].Skk=Sc; |
3994 | central_traj[k].Ckk=Cc; |
3995 | } |
3996 | |
3997 | // update position based on new doca to reference trajectory |
3998 | xy.Set(central_traj[k].xy.X()-Sc(state_D)*sin(Sc(state_phi)), |
3999 | central_traj[k].xy.Y()+Sc(state_D)*cos(Sc(state_phi))); |
4000 | |
4001 | // Bail if the position is grossly outside of the tracking volume |
4002 | if (xy.Mod2()>R2_MAX4225.0 || Sc(state_z)<Z_MIN-100. || Sc(state_z)>Z_MAX370.0){ |
4003 | if (DEBUG_LEVEL>2) |
4004 | { |
4005 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<4005<<" "<< "Went outside of tracking volume at z="<<Sc(state_z) |
4006 | << " r="<<xy.Mod()<<endl; |
4007 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<4007<<" " << " Break indexes: " << break_point_cdc_index <<"," |
4008 | << break_point_step_index << endl; |
4009 | } |
4010 | return POSITION_OUT_OF_RANGE; |
4011 | } |
4012 | // Bail if the transverse momentum has dropped below some minimum |
4013 | if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){ |
4014 | if (DEBUG_LEVEL>2) |
4015 | { |
4016 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<4016<<" " << "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt)) |
4017 | << " at step " << k |
4018 | << endl; |
4019 | } |
4020 | return MOMENTUM_OUT_OF_RANGE; |
4021 | } |
4022 | |
4023 | |
4024 | // Save the current state of the reference trajectory |
4025 | S0_=S0; |
4026 | |
4027 | // new wire position |
4028 | wirexy=origin; |
4029 | wirexy+=(Sc(state_z)-z0w)*dir; |
4030 | |
4031 | // new doca |
4032 | doca2=(xy-wirexy).Mod2(); |
4033 | |
4034 | // Check if the doca is no longer decreasing |
4035 | if (more_measurements && (doca2>old_doca2 && Sc(state_z)>cdc_origin[2])){ |
4036 | if (my_cdchits[cdc_index]->status==good_hit){ |
4037 | if (DEBUG_LEVEL>9) { |
4038 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<4038<<" " << " Good Hit Ring " << my_cdchits[cdc_index]->hit->wire->ring << " Straw " << my_cdchits[cdc_index]->hit->wire->straw << endl; |
4039 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<4039<<" " << " doca " << sqrt(doca2) << endl; |
4040 | } |
4041 | |
4042 | // Save values at end of current step |
4043 | DVector2 xy0=central_traj[k].xy; |
4044 | |
4045 | // Variables for the computation of D at the doca to the wire |
4046 | double D=Sc(state_D); |
4047 | double q=(Sc(state_q_over_pt)>0.0)?1.:-1.; |
4048 | |
4049 | q*=FactorForSenseOfRotation; |
4050 | |
4051 | double qpt=1./Sc(state_q_over_pt) * FactorForSenseOfRotation; |
4052 | double sinphi=sin(Sc(state_phi)); |
4053 | double cosphi=cos(Sc(state_phi)); |
4054 | //double qrc_old=qpt/fabs(qBr2p*bfield->GetBz(pos.x(),pos.y(),pos.z())); |
4055 | double qrc_old=qpt/fabs(qBr2p0.003*central_traj[k].B); |
4056 | double qrc_plus_D=D+qrc_old; |
4057 | |
4058 | // wire direction variable |
4059 | double ux=dir.X(); |
4060 | double uy=dir.Y(); |
4061 | double cosstereo=my_cdchits[cdc_index]->cosstereo; |
4062 | // Variables relating wire direction and track direction |
4063 | //double my_ux=ux*sinl-cosl*cosphi; |
4064 | //double my_uy=uy*sinl-cosl*sinphi; |
4065 | //double denom=my_ux*my_ux+my_uy*my_uy; |
4066 | // distance variables |
4067 | DVector2 diff,dxy1; |
4068 | |
4069 | // use Brent's algorithm to find the poca to the wire |
4070 | // See Numerical Recipes in C, pp 404-405 |
4071 | |
4072 | // dEdx for current position along trajectory |
4073 | double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl))); |
4074 | if (CORRECT_FOR_ELOSS){ |
4075 | dedx=GetdEdx(q_over_p, central_traj[k].K_rho_Z_over_A, |
4076 | central_traj[k].rho_Z_over_A, |
4077 | central_traj[k].LnI,central_traj[k].Z); |
4078 | } |
4079 | |
4080 | if (BrentCentral(dedx,xy,z0w,origin,dir,Sc,ds2)!=NOERROR) return MOMENTUM_OUT_OF_RANGE; |
4081 | |
4082 | //Step along the reference trajectory and compute the new covariance matrix |
4083 | StepStateAndCovariance(xy0,ds2,dedx,S0,J,Cc); |
4084 | |
4085 | // Compute the value of D (signed distance to the reference trajectory) |
4086 | // at the doca to the wire |
4087 | dxy1=xy0-central_traj[k].xy; |
4088 | double rc=sqrt(dxy1.Mod2() |
4089 | +2.*qrc_plus_D*(dxy1.X()*sinphi-dxy1.Y()*cosphi) |
4090 | +qrc_plus_D*qrc_plus_D); |
4091 | Sc(state_D)=q*rc-qrc_old; |
4092 | |
4093 | // wire position |
4094 | wirexy=origin; |
4095 | wirexy+=(Sc(state_z)-z0w)*dir; |
4096 | diff=xy-wirexy; |
4097 | |
4098 | // prediction for measurement |
4099 | double doca=diff.Mod()+EPS3.0e-8; |
4100 | double prediction=doca*cosstereo; |
4101 | |
4102 | // Measurement |
4103 | double measurement=0.39,tdrift=0.,tcorr=0.,dDdt0=0.; |
4104 | if (fit_type==kTimeBased || USE_PASS1_TIME_MODE){ |
4105 | // Find offset of wire with respect to the center of the |
4106 | // straw at this z position |
4107 | const DCDCWire *mywire=my_cdchits[cdc_index]->hit->wire; |
4108 | int ring_index=mywire->ring-1; |
4109 | int straw_index=mywire->straw-1; |
4110 | double dz=Sc(state_z)-z0w; |
4111 | double phi_d=diff.Phi(); |
4112 | double delta |
4113 | =max_sag[ring_index][straw_index]*(1.-dz*dz/5625.) |
4114 | *cos(phi_d + sag_phi_offset[ring_index][straw_index]); |
4115 | double dphi=phi_d-mywire->origin.Phi(); |
4116 | while (dphi>M_PI3.14159265358979323846) dphi-=2*M_PI3.14159265358979323846; |
4117 | while (dphi<-M_PI3.14159265358979323846) dphi+=2*M_PI3.14159265358979323846; |
4118 | if (mywire->origin.Y()<0) dphi*=-1.; |
4119 | |
4120 | tdrift=my_cdchits[cdc_index]->tdrift-mT0 |
4121 | -central_traj[k_minus_1].t*TIME_UNIT_CONVERSION3.33564095198152014e-02; |
4122 | double B=central_traj[k_minus_1].B; |
4123 | ComputeCDCDrift(dphi,delta,tdrift,B,measurement,V,tcorr); |
4124 | V*=anneal_factor; |
4125 | if (ALIGNMENT_CENTRAL){ |
4126 | double myV=0.; |
4127 | double mytcorr=0.; |
4128 | double d_shifted; |
4129 | double dt=2.0; |
4130 | ComputeCDCDrift(dphi,delta,tdrift+dt,B,d_shifted,myV,mytcorr); |
4131 | dDdt0=(d_shifted-measurement)/dt; |
4132 | } |
4133 | |
4134 | //_DBG_ << tcorr << " " << dphi << " " << dm << endl; |
4135 | |
4136 | } |
4137 | |
4138 | // Projection matrix |
4139 | sinphi=sin(Sc(state_phi)); |
4140 | cosphi=cos(Sc(state_phi)); |
4141 | double dx=diff.X(); |
4142 | double dy=diff.Y(); |
4143 | double cosstereo_over_doca=cosstereo/doca; |
4144 | H_T(state_D)=(dy*cosphi-dx*sinphi)*cosstereo_over_doca; |
4145 | H_T(state_phi) |
4146 | =-Sc(state_D)*cosstereo_over_doca*(dx*cosphi+dy*sinphi); |
4147 | H_T(state_z)=-cosstereo_over_doca*(dx*ux+dy*uy); |
4148 | H(state_tanl)=0.; |
4149 | H_T(state_tanl)=0.; |
4150 | H(state_D)=H_T(state_D); |
4151 | H(state_z)=H_T(state_z); |
4152 | H(state_phi)=H_T(state_phi); |
4153 | |
4154 | // Difference and inverse of variance |
4155 | //InvV=1./(V+H*(Cc*H_T)); |
4156 | //double Vproj=Cc.SandwichMultiply(H_T); |
4157 | double Vproj=H*Cc*H_T; |
4158 | InvV=1./(V+Vproj); |
4159 | double dm=measurement-prediction; |
4160 | |
4161 | if (InvV<0.){ |
4162 | if (DEBUG_LEVEL>1) |
4163 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<4163<<" " << k <<" "<< central_traj.size()-1<<" Negative variance??? " << V << " " << H*(Cc*H_T) <<endl; |
4164 | |
4165 | break_point_cdc_index=(3*num_cdc)/4; |
4166 | return NEGATIVE_VARIANCE; |
4167 | } |
4168 | /* |
4169 | if (fabs(cosstereo)<1.){ |
4170 | printf("t %f delta %f sigma %f V %f chi2 %f\n",my_cdchits[cdc_index]->hit->tdrift-mT0,dm,sqrt(V),1./InvV,dm*dm*InvV); |
4171 | } |
4172 | */ |
4173 | |
4174 | // Check how far this hit is from the expected position |
4175 | double chi2check=dm*dm*InvV; |
4176 | if (DEBUG_LEVEL>9) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<4176<<" " << " Prediction " << prediction << " Measurement " << measurement << " Chi2 " << chi2check << endl; |
4177 | if (chi2check<chi2cut) |
4178 | { |
4179 | if (DEBUG_LEVEL>9) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<4179<<" " << " Passed Chi^2 check Ring " << my_cdchits[cdc_index]->hit->wire->ring << " Straw " << my_cdchits[cdc_index]->hit->wire->straw << endl; |
4180 | |
4181 | // Compute Kalman gain matrix |
4182 | K=InvV*(Cc*H_T); |
4183 | |
4184 | // Update state vector covariance matrix |
4185 | //Cc=Cc-(K*(H*Cc)); |
4186 | Ctest=Cc.SubSym(K*(H*Cc)); |
4187 | // Joseph form |
4188 | // C = (I-KH)C(I-KH)^T + KVK^T |
4189 | //Ctest=Cc.SandwichMultiply(I5x5-K*H)+V*MultiplyTranspose(K); |
4190 | // Check that Ctest is positive definite |
4191 | if (!Ctest.IsPosDef()){ |
4192 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<4192<<" " << "Broken covariance matrix!" <<endl; |
4193 | return BROKEN_COVARIANCE_MATRIX; |
4194 | } |
4195 | bool skip_ring |
4196 | =(my_cdchits[cdc_index]->hit->wire->ring==RING_TO_SKIP); |
4197 | //Update covariance matrix and state vector |
4198 | if (skip_ring==false && tdrift >= CDC_T_DRIFT_MIN){ |
4199 | Cc=Ctest; |
4200 | Sc+=dm*K; |
4201 | } |
4202 | |
4203 | // Mark point on ref trajectory with a hit id for the straw |
4204 | central_traj[k].h_id=cdc_index+1; |
4205 | if (DEBUG_LEVEL>9) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<4205<<" " << " Marked Trajectory central_traj[k].h_id=cdc_index+1 (k cdc_index)" << k << " " << cdc_index << endl; |
4206 | |
4207 | // Save some updated information for this hit |
4208 | double scale=(skip_ring)?1.:(1.-H*K); |
4209 | cdc_updates[cdc_index].tcorr=tcorr; |
4210 | cdc_updates[cdc_index].tdrift=tdrift; |
4211 | cdc_updates[cdc_index].doca=measurement; |
4212 | cdc_updates[cdc_index].variance=V; |
4213 | cdc_updates[cdc_index].dDdt0=dDdt0; |
4214 | cdc_used_in_fit[cdc_index]=true; |
4215 | if (tdrift < CDC_T_DRIFT_MIN) cdc_used_in_fit[cdc_index]=false; |
4216 | |
4217 | // Update chi2 for this hit |
4218 | if (skip_ring==false && tdrift >= CDC_T_DRIFT_MIN){ |
4219 | chisq+=scale*dm*dm/V; |
4220 | my_ndf++; |
4221 | } |
4222 | if (DEBUG_LEVEL>10) |
4223 | cout |
4224 | << "ring " << my_cdchits[cdc_index]->hit->wire->ring |
4225 | << " t " << my_cdchits[cdc_index]->hit->tdrift |
4226 | << " Dm-Dpred " << dm |
4227 | << " chi2 " << (1.-H*K)*dm*dm/V |
4228 | << endl; |
4229 | |
4230 | break_point_cdc_index=cdc_index; |
4231 | break_point_step_index=k_minus_1; |
4232 | |
4233 | //else printf("Negative variance!!!\n"); |
4234 | |
4235 | |
4236 | } |
4237 | |
4238 | // Move back to the right step along the reference trajectory. |
4239 | StepStateAndCovariance(xy,-ds2,dedx,Sc,J,Cc); |
4240 | |
4241 | // Save state and covariance matrix to update vector |
4242 | cdc_updates[cdc_index].S=Sc; |
4243 | cdc_updates[cdc_index].C=Cc; |
4244 | |
4245 | //Sc.Print(); |
4246 | //Cc.Print(); |
4247 | |
4248 | // update position on current trajectory based on corrected doca to |
4249 | // reference trajectory |
4250 | xy.Set(central_traj[k].xy.X()-Sc(state_D)*sin(Sc(state_phi)), |
4251 | central_traj[k].xy.Y()+Sc(state_D)*cos(Sc(state_phi))); |
4252 | |
4253 | } |
4254 | |
4255 | // new wire origin and direction |
4256 | if (cdc_index>0){ |
4257 | cdc_index--; |
4258 | origin=my_cdchits[cdc_index]->origin; |
4259 | z0w=my_cdchits[cdc_index]->z0wire; |
4260 | dir=my_cdchits[cdc_index]->dir; |
4261 | } |
4262 | else{ |
4263 | more_measurements=false; |
4264 | } |
4265 | |
4266 | // Update the wire position |
4267 | wirexy=origin+(Sc(state_z)-z0w)*dir; |
4268 | |
4269 | //s+=ds2; |
4270 | // new doca |
4271 | doca2=(xy-wirexy).Mod2(); |
4272 | } |
4273 | |
4274 | old_doca2=doca2; |
4275 | |
4276 | } |
4277 | |
4278 | // If there are not enough degrees of freedom, something went wrong... |
4279 | if (my_ndf<6){ |
4280 | chisq=-1.; |
4281 | my_ndf=0; |
4282 | return PRUNED_TOO_MANY_HITS; |
4283 | } |
4284 | else my_ndf-=5; |
4285 | |
4286 | // Check if we have a kink in the track or threw away too many cdc hits |
4287 | if (num_cdc>=MIN_HITS_FOR_REFIT){ |
4288 | if (break_point_cdc_index>1){ |
4289 | if (break_point_cdc_index<num_cdc/2){ |
4290 | break_point_cdc_index=(3*num_cdc)/4; |
4291 | } |
4292 | return BREAK_POINT_FOUND; |
4293 | } |
4294 | |
4295 | unsigned int num_good=0; |
4296 | for (unsigned int j=0;j<num_cdc;j++){ |
4297 | if (cdc_used_in_fit[j]) num_good++; |
4298 | } |
4299 | if (double(num_good)/double(num_cdc)<MINIMUM_HIT_FRACTION){ |
4300 | return PRUNED_TOO_MANY_HITS; |
4301 | } |
4302 | } |
4303 | |
4304 | return FIT_SUCCEEDED; |
4305 | } |
4306 | |
4307 | // Kalman engine for forward tracks |
4308 | kalman_error_t DTrackFitterKalmanSIMD::KalmanForward(double fdc_anneal_factor, |
4309 | double cdc_anneal_factor, |
4310 | DMatrix5x1 &S, |
4311 | DMatrix5x5 &C, |
4312 | double &chisq, |
4313 | unsigned int &numdof){ |
4314 | DMatrix2x1 Mdiff; // difference between measurement and prediction |
4315 | DMatrix2x5 H; // Track projection matrix |
4316 | DMatrix5x2 H_T; // Transpose of track projection matrix |
4317 | DMatrix1x5 Hc; // Track projection matrix for cdc hits |
4318 | DMatrix5x1 Hc_T; // Transpose of track projection matrix for cdc hits |
4319 | DMatrix5x5 J; // State vector Jacobian matrix |
4320 | //DMatrix5x5 J_T; // transpose of this matrix |
4321 | DMatrix5x5 Q; // Process noise covariance matrix |
4322 | DMatrix5x2 K; // Kalman gain matrix |
4323 | DMatrix5x1 Kc; // Kalman gain matrix for cdc hits |
4324 | DMatrix2x2 V(0.0833,0.,0.,FDC_CATHODE_VARIANCE0.000225); // Measurement covariance matrix |
4325 | DMatrix2x1 R; // Filtered residual |
4326 | DMatrix2x2 RC; // Covariance of filtered residual |
4327 | DMatrix5x1 S0,S0_; //State vector |
4328 | DMatrix5x5 Ctest; // Covariance matrix |
4329 | DMatrix2x2 InvV; // Inverse of error matrix |
4330 | |
4331 | double Vc=0.0507; |
4332 | |
4333 | // Vectors for cdc wires |
4334 | DVector2 origin,dir,wirepos; |
4335 | double z0w=0.; // origin in z for wire |
4336 | |
4337 | // Set used_in_fit flags to false for fdc and cdc hits |
4338 | unsigned int num_cdc=cdc_used_in_fit.size(); |
4339 | unsigned int num_fdc=fdc_used_in_fit.size(); |
4340 | for (unsigned int i=0;i<num_cdc;i++) cdc_used_in_fit[i]=false; |
4341 | for (unsigned int i=0;i<num_fdc;i++) fdc_used_in_fit[i]=false; |
4342 | for (unsigned int i=0;i<forward_traj.size();i++){ |
4343 | if (forward_traj[i].h_id>999) |
4344 | forward_traj[i].h_id=0; |
4345 | } |
4346 | |
4347 | // Save the starting values for C and S in the deque |
4348 | forward_traj[break_point_step_index].Skk=S; |
4349 | forward_traj[break_point_step_index].Ckk=C; |
4350 | |
4351 | // Initialize chi squared |
4352 | chisq=0; |
4353 | |
4354 | // Initialize number of degrees of freedom |
4355 | numdof=0; |
4356 | |
4357 | double fdc_chi2cut=NUM_FDC_SIGMA_CUT*NUM_FDC_SIGMA_CUT; |
4358 | double cdc_chi2cut=NUM_CDC_SIGMA_CUT*NUM_CDC_SIGMA_CUT; |
4359 | |
4360 | unsigned int num_fdc_hits=break_point_fdc_index+1; |
4361 | unsigned int max_num_fdc_used_in_fit=num_fdc_hits; |
4362 | unsigned int num_cdc_hits=my_cdchits.size(); |
4363 | unsigned int cdc_index=0; |
4364 | if (num_cdc_hits>0) cdc_index=num_cdc_hits-1; |
4365 | bool more_cdc_measurements=(num_cdc_hits>0); |
4366 | double old_doca2=1e6; |
4367 | |
4368 | if (num_fdc_hits+num_cdc_hits<MIN_HITS_FOR_REFIT){ |
4369 | cdc_chi2cut=BIG1.0e8; |
4370 | fdc_chi2cut=BIG1.0e8; |
4371 | } |
4372 | |
4373 | if (more_cdc_measurements){ |
4374 | origin=my_cdchits[cdc_index]->origin; |
4375 | dir=my_cdchits[cdc_index]->dir; |
4376 | z0w=my_cdchits[cdc_index]->z0wire; |
4377 | wirepos=origin+(forward_traj[break_point_step_index].z-z0w)*dir; |
4378 | } |
4379 | |
4380 | S0_=(forward_traj[break_point_step_index].S); |
4381 | |
4382 | if (DEBUG_LEVEL > 25){ |
4383 | jout << "Entering DTrackFitterKalmanSIMD::KalmanForward ================================" << endl; |
4384 | jout << " We have the following starting parameters for our fit. S = State vector, C = Covariance matrix" << endl; |
4385 | S.Print(); |
4386 | C.Print(); |
4387 | jout << setprecision(6); |
4388 | jout << " There are " << num_cdc << " CDC Updates and " << num_fdc << " FDC Updates on this track" << endl; |
4389 | jout << " There are " << num_cdc_hits << " CDC Hits and " << num_fdc_hits << " FDC Hits on this track" << endl; |
4390 | jout << " With NUM_FDC_SIGMA_CUT = " << NUM_FDC_SIGMA_CUT << " and NUM_CDC_SIGMA_CUT = " << NUM_CDC_SIGMA_CUT << endl; |
4391 | jout << " fdc_anneal_factor = " << fdc_anneal_factor << " cdc_anneal_factor = " << cdc_anneal_factor << endl; |
4392 | jout << " yields fdc_chi2cut = " << fdc_chi2cut << " cdc_chi2cut = " << cdc_chi2cut << endl; |
4393 | jout << " Starting from break_point_step_index " << break_point_step_index << endl; |
4394 | jout << " S0_ which is the state vector of the reference trajectory at the break point step:" << endl; |
4395 | S0_.Print(); |
4396 | jout << " ===== Beginning pass over reference trajectory ======== " << endl; |
4397 | } |
4398 | |
4399 | for (unsigned int k=break_point_step_index+1;k<forward_traj.size();k++){ |
4400 | unsigned int k_minus_1=k-1; |
4401 | |
4402 | // Get the state vector, jacobian matrix, and multiple scattering matrix |
4403 | // from reference trajectory |
4404 | S0=(forward_traj[k].S); |
4405 | J=(forward_traj[k].J); |
4406 | Q=(forward_traj[k].Q); |
4407 | |
4408 | // State S is perturbation about a seed S0 |
4409 | //dS=S-S0_; |
4410 | |
4411 | // Update the actual state vector and covariance matrix |
4412 | S=S0+J*(S-S0_); |
4413 | |
4414 | // Bail if the momentum has dropped below some minimum |
4415 | if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX){ |
4416 | if (DEBUG_LEVEL>2) |
4417 | { |
4418 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<4418<<" " << "Bailing: P = " << 1./fabs(S(state_q_over_p)) << endl; |
4419 | } |
4420 | break_point_fdc_index=(3*num_fdc)/4; |
4421 | return MOMENTUM_OUT_OF_RANGE; |
4422 | } |
4423 | |
4424 | |
4425 | //C=J*(C*J_T)+Q; |
4426 | //C=Q.AddSym(C.SandwichMultiply(J)); |
4427 | C=Q.AddSym(J*C*J.Transpose()); |
4428 | |
4429 | // Save the current state and covariance matrix in the deque |
4430 | forward_traj[k].Skk=S; |
4431 | forward_traj[k].Ckk=C; |
4432 | |
4433 | // Save the current state of the reference trajectory |
4434 | S0_=S0; |
4435 | |
4436 | // Z position along the trajectory |
4437 | double z=forward_traj[k].z; |
4438 | |
4439 | if (DEBUG_LEVEL > 25){ |
4440 | jout << " At reference trajectory index " << k << " at z=" << z << endl; |
4441 | jout << " The State vector from the reference trajectory" << endl; |
4442 | S0.Print(); |
4443 | jout << " The Jacobian matrix " << endl; |
4444 | J.Print(); |
4445 | jout << " The Q matrix "<< endl; |
4446 | Q.Print(); |
4447 | jout << " The updated State vector S=S0+J*(S-S0_)" << endl; |
4448 | S.Print(); |
4449 | jout << " The updated Covariance matrix C=J*(C*J_T)+Q;" << endl; |
4450 | C.Print(); |
4451 | } |
4452 | |
4453 | // Add the hit |
4454 | if (num_fdc_hits>0){ |
4455 | if (forward_traj[k].h_id>0 && forward_traj[k].h_id<1000){ |
4456 | unsigned int id=forward_traj[k].h_id-1; |
4457 | // Check if this is a plane we want to skip in the fit (we still want |
4458 | // to store track and hit info at this plane, however). |
4459 | bool skip_plane=(my_fdchits[id]->hit!=NULL__null |
4460 | &&my_fdchits[id]->hit->wire->layer==PLANE_TO_SKIP); |
4461 | double upred=0,vpred=0.,doca=0.,cosalpha=0.,lorentz_factor=0.; |
4462 | FindDocaAndProjectionMatrix(my_fdchits[id],S,upred,vpred,doca,cosalpha, |
4463 | lorentz_factor,H_T); |
4464 | // Matrix transpose H_T -> H |
4465 | H=Transpose(H_T); |
4466 | |
4467 | // Variance in coordinate transverse to wire |
4468 | V(0,0)=my_fdchits[id]->uvar; |
4469 | if (my_fdchits[id]->hit==NULL__null&&my_fdchits[id]->status!=trd_hit){ |
4470 | V(0,0)*=fdc_anneal_factor; |
4471 | } |
4472 | |
4473 | // Variance in coordinate along wire |
4474 | V(1,1)=my_fdchits[id]->vvar*fdc_anneal_factor; |
4475 | |
4476 | // Residual for coordinate along wire |
4477 | Mdiff(1)=my_fdchits[id]->vstrip-vpred-doca*lorentz_factor; |
4478 | |
4479 | // Residual for coordinate transverse to wire |
4480 | Mdiff(0)=-doca; |
4481 | double drift_time=my_fdchits[id]->t-mT0-forward_traj[k].t*TIME_UNIT_CONVERSION3.33564095198152014e-02; |
4482 | if (fit_type==kTimeBased && USE_FDC_DRIFT_TIMES){ |
4483 | if (my_fdchits[id]->hit!=NULL__null){ |
4484 | double drift=(doca>0.0?1.:-1.) |
4485 | *fdc_drift_distance(drift_time,forward_traj[k].B); |
4486 | Mdiff(0)+=drift; |
4487 | |
4488 | // Variance in drift distance |
4489 | V(0,0)=fdc_drift_variance(drift_time)*fdc_anneal_factor; |
4490 | } |
4491 | else if (USE_TRD_DRIFT_TIMES&&my_fdchits[id]->status==trd_hit){ |
4492 | double drift =(doca>0.0?1.:-1.)*0.1*pow(drift_time/8./0.91,1./1.556); |
4493 | Mdiff(0)+=drift; |
4494 | |
4495 | // Variance in drift distance |
4496 | V(0,0)=0.05*0.05*fdc_anneal_factor; |
4497 | } |
4498 | } |
4499 | // Check to see if we have multiple hits in the same plane |
4500 | if (!ALIGNMENT_FORWARD && forward_traj[k].num_hits>1){ |
4501 | UpdateSandCMultiHit(forward_traj[k],upred,vpred,doca,cosalpha, |
4502 | lorentz_factor,V,Mdiff,H,H_T,S,C, |
4503 | fdc_chi2cut,skip_plane,chisq,numdof, |
4504 | fdc_anneal_factor); |
4505 | } |
4506 | else{ |
4507 | if (DEBUG_LEVEL > 25) jout << " == There is a single FDC hit on this plane" << endl; |
4508 | |
4509 | // Variance for this hit |
4510 | DMatrix2x2 Vtemp=V+H*C*H_T; |
4511 | InvV=Vtemp.Invert(); |
4512 | |
4513 | // Check if this hit is an outlier |
4514 | double chi2_hit=Vtemp.Chi2(Mdiff); |
4515 | if (chi2_hit<fdc_chi2cut){ |
4516 | // Compute Kalman gain matrix |
4517 | K=C*H_T*InvV; |
4518 | |
4519 | if (skip_plane==false){ |
4520 | // Update the state vector |
4521 | S+=K*Mdiff; |
4522 | |
4523 | // Update state vector covariance matrix |
4524 | //C=C-K*(H*C); |
4525 | C=C.SubSym(K*(H*C)); |
4526 | |
4527 | if (DEBUG_LEVEL > 25) { |
4528 | jout << "S Update: " << endl; S.Print(); |
4529 | jout << "C Uodate: " << endl; C.Print(); |
4530 | } |
4531 | } |
4532 | |
4533 | // Store the "improved" values for the state vector and covariance |
4534 | fdc_updates[id].S=S; |
4535 | fdc_updates[id].C=C; |
4536 | fdc_updates[id].tdrift=drift_time; |
4537 | fdc_updates[id].tcorr=fdc_updates[id].tdrift; // temporary! |
4538 | fdc_updates[id].doca=doca; |
4539 | fdc_used_in_fit[id]=true; |
4540 | |
4541 | if (skip_plane==false){ |
4542 | // Filtered residual and covariance of filtered residual |
4543 | R=Mdiff-H*K*Mdiff; |
4544 | RC=V-H*(C*H_T); |
4545 | |
4546 | fdc_updates[id].V=RC; |
4547 | |
4548 | // Update chi2 for this segment |
4549 | chisq+=RC.Chi2(R); |
4550 | |
4551 | // update number of degrees of freedom |
4552 | numdof+=2; |
4553 | |
4554 | if (DEBUG_LEVEL>20) |
4555 | { |
4556 | printf("hit %d p %5.2f t %f dm %5.2f sig %f chi2 %5.2f z %5.2f\n", |
4557 | id,1./S(state_q_over_p),fdc_updates[id].tdrift,Mdiff(1), |
4558 | sqrt(V(1,1)),RC.Chi2(R), |
4559 | forward_traj[k].z); |
4560 | |
4561 | } |
4562 | } |
4563 | else{ |
4564 | fdc_updates[id].V=V; |
4565 | } |
4566 | |
4567 | break_point_fdc_index=id; |
4568 | break_point_step_index=k; |
4569 | } |
4570 | } |
4571 | if (num_fdc_hits>=forward_traj[k].num_hits) |
4572 | num_fdc_hits-=forward_traj[k].num_hits; |
4573 | } |
4574 | } |
4575 | else if (more_cdc_measurements /* && z<endplate_z*/){ |
4576 | // new wire position |
4577 | wirepos=origin; |
4578 | wirepos+=(z-z0w)*dir; |
4579 | |
4580 | // doca variables |
4581 | double dx=S(state_x)-wirepos.X(); |
4582 | double dy=S(state_y)-wirepos.Y(); |
4583 | double doca2=dx*dx+dy*dy; |
4584 | |
4585 | // Check if the doca is no longer decreasing |
4586 | if (doca2>old_doca2){ |
4587 | if(my_cdchits[cdc_index]->status==good_hit){ |
4588 | find_doca_error_t swimmed_to_doca=DOCA_NO_BRENT; |
4589 | double newz=endplate_z; |
4590 | double dz=newz-z; |
4591 | // Sometimes the true doca would correspond to the case where the |
4592 | // wire would need to extend beyond the physical volume of the straw. |
4593 | // In this case, find the doca at the cdc endplate. |
4594 | if (z>endplate_z){ |
4595 | swimmed_to_doca=DOCA_ENDPLATE; |
4596 | SwimToEndplate(z,forward_traj[k],S); |
4597 | |
4598 | // wire position at the endplate |
4599 | wirepos=origin; |
4600 | wirepos+=(endplate_z-z0w)*dir; |
4601 | |
4602 | dx=S(state_x)-wirepos.X(); |
4603 | dy=S(state_y)-wirepos.Y(); |
4604 | } |
4605 | else{ |
4606 | // Find the true doca to the wire. If we had to use Brent's |
4607 | // algorithm, the routine returns true. |
4608 | double step1=mStepSizeZ; |
4609 | double step2=mStepSizeZ; |
4610 | if (k>=2){ |
4611 | step1=-forward_traj[k].z+forward_traj[k_minus_1].z; |
4612 | step2=-forward_traj[k_minus_1].z+forward_traj[k-2].z; |
4613 | } |
4614 | swimmed_to_doca=FindDoca(my_cdchits[cdc_index],forward_traj[k], |
4615 | step1,step2,S0,S,C,dx,dy,dz); |
4616 | if (swimmed_to_doca==BRENT_FAILED){ |
4617 | //break_point_fdc_index=(3*num_fdc)/4; |
4618 | return MOMENTUM_OUT_OF_RANGE; |
4619 | } |
4620 | |
4621 | newz=forward_traj[k].z+dz; |
4622 | } |
4623 | double cosstereo=my_cdchits[cdc_index]->cosstereo; |
4624 | double d=sqrt(dx*dx+dy*dy)*cosstereo+EPS3.0e-8; |
4625 | |
4626 | // Track projection |
4627 | double cosstereo2_over_d=cosstereo*cosstereo/d; |
4628 | Hc_T(state_x)=dx*cosstereo2_over_d; |
4629 | Hc(state_x)=Hc_T(state_x); |
4630 | Hc_T(state_y)=dy*cosstereo2_over_d; |
4631 | Hc(state_y)=Hc_T(state_y); |
4632 | if (swimmed_to_doca==DOCA_NO_BRENT){ |
4633 | Hc_T(state_ty)=Hc_T(state_y)*dz; |
4634 | Hc(state_ty)=Hc_T(state_ty); |
4635 | Hc_T(state_tx)=Hc_T(state_x)*dz; |
4636 | Hc(state_tx)=Hc_T(state_tx); |
4637 | } |
4638 | else{ |
4639 | Hc_T(state_ty)=0.; |
4640 | Hc(state_ty)=0.; |
4641 | Hc_T(state_tx)=0.; |
4642 | Hc(state_tx)=0.; |
4643 | } |
4644 | |
4645 | //H.Print(); |
4646 | |
4647 | // The next measurement |
4648 | double dm=0.39,tdrift=0.,tcorr=0.,dDdt0=0.; |
4649 | if (fit_type==kTimeBased){ |
4650 | // Find offset of wire with respect to the center of the |
4651 | // straw at this z position |
4652 | double delta=0,dphi=0.; |
4653 | FindSag(dx,dy,newz-z0w,my_cdchits[cdc_index]->hit->wire,delta,dphi); |
4654 | |
4655 | // Find drift time and distance |
4656 | tdrift=my_cdchits[cdc_index]->tdrift-mT0 |
4657 | -forward_traj[k_minus_1].t*TIME_UNIT_CONVERSION3.33564095198152014e-02; |
4658 | double B=forward_traj[k_minus_1].B; |
4659 | ComputeCDCDrift(dphi,delta,tdrift,B,dm,Vc,tcorr); |
4660 | Vc*=cdc_anneal_factor; |
4661 | if (ALIGNMENT_FORWARD){ |
4662 | double myV=0.; |
4663 | double mytcorr=0.; |
4664 | double d_shifted; |
4665 | double dt=5.0; |
4666 | // Dont compute this for negative drift times |
4667 | if (tdrift < 0.) d_shifted = dm; |
4668 | else ComputeCDCDrift(dphi,delta,tdrift+dt,B,d_shifted,myV,mytcorr); |
4669 | dDdt0=(d_shifted-dm)/dt; |
4670 | } |
4671 | |
4672 | if (max_num_fdc_used_in_fit>4) |
4673 | { |
4674 | Vc*=CDC_VAR_SCALE_FACTOR; //de-weight CDC hits |
4675 | } |
4676 | //_DBG_ << "t " << tdrift << " d " << d << " delta " << delta << " dphi " << atan2(dy,dx)-mywire->origin.Phi() << endl; |
4677 | |
4678 | //_DBG_ << tcorr << " " << dphi << " " << dm << endl; |
4679 | } |
4680 | |
4681 | // Residual |
4682 | double res=dm-d; |
4683 | |
4684 | // inverse variance including prediction |
4685 | //double InvV1=1./(Vc+H*(C*H_T)); |
4686 | //double Vproj=C.SandwichMultiply(Hc_T); |
4687 | double Vproj=Hc*C*Hc_T; |
4688 | double InvV1=1./(Vc+Vproj); |
4689 | if (InvV1<0.){ |
4690 | if (DEBUG_LEVEL>0) |
4691 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<4691<<" " << "Negative variance???" << endl; |
4692 | return NEGATIVE_VARIANCE; |
4693 | } |
4694 | |
4695 | // Check if this hit is an outlier |
4696 | double chi2_hit=res*res*InvV1; |
4697 | if (chi2_hit<cdc_chi2cut){ |
4698 | // Compute KalmanSIMD gain matrix |
4699 | Kc=InvV1*(C*Hc_T); |
4700 | |
4701 | // Update state vector covariance matrix |
4702 | //C=C-K*(H*C); |
4703 | Ctest=C.SubSym(Kc*(Hc*C)); |
4704 | //Ctest=C.SandwichMultiply(I5x5-K*H)+Vc*MultiplyTranspose(K); |
4705 | // Check that Ctest is positive definite |
4706 | if (!Ctest.IsPosDef()){ |
4707 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<4707<<" " << "Broken covariance matrix!" <<endl; |
4708 | return BROKEN_COVARIANCE_MATRIX; |
4709 | } |
4710 | bool skip_ring |
4711 | =(my_cdchits[cdc_index]->hit->wire->ring==RING_TO_SKIP); |
4712 | // update covariance matrix and state vector |
4713 | if (my_cdchits[cdc_index]->hit->wire->ring!=RING_TO_SKIP && tdrift >= CDC_T_DRIFT_MIN){ |
4714 | C=Ctest; |
4715 | S+=res*Kc; |
4716 | |
4717 | if (DEBUG_LEVEL > 25) { |
4718 | jout << " == Adding CDC Hit in Ring " << my_cdchits[cdc_index]->hit->wire->ring << endl; |
4719 | jout << " New S: " << endl; S.Print(); |
4720 | jout << " New C: " << endl; C.Print(); |
4721 | } |
4722 | } |
4723 | |
4724 | // Flag the place along the reference trajectory with hit id |
4725 | forward_traj[k].h_id=1000+cdc_index; |
4726 | |
4727 | // Store updated info related to this hit |
4728 | double scale=(skip_ring)?1.:(1.-Hc*Kc); |
4729 | cdc_updates[cdc_index].tdrift=tdrift; |
4730 | cdc_updates[cdc_index].tcorr=tcorr; |
4731 | cdc_updates[cdc_index].variance=Vc; |
4732 | cdc_updates[cdc_index].doca=dm; |
4733 | cdc_updates[cdc_index].dDdt0=dDdt0; |
4734 | cdc_used_in_fit[cdc_index]=true; |
4735 | if(tdrift < CDC_T_DRIFT_MIN){ |
4736 | //_DBG_ << tdrift << endl; |
4737 | cdc_used_in_fit[cdc_index]=false; |
4738 | } |
4739 | |
4740 | // Update chi2 and number of degrees of freedom for this hit |
4741 | if (skip_ring==false && tdrift >= CDC_T_DRIFT_MIN){ |
4742 | chisq+=scale*res*res/Vc; |
4743 | numdof++; |
4744 | } |
4745 | |
4746 | if (DEBUG_LEVEL>10) |
4747 | jout << "Ring " << my_cdchits[cdc_index]->hit->wire->ring |
4748 | << " Straw " << my_cdchits[cdc_index]->hit->wire->straw |
4749 | << " Pred " << d << " Meas " << dm |
4750 | << " Sigma meas " << sqrt(Vc) |
4751 | << " t " << tcorr |
4752 | << " Chi2 " << (1.-Hc*Kc)*res*res/Vc << endl; |
4753 | |
4754 | break_point_cdc_index=cdc_index; |
4755 | break_point_step_index=k_minus_1; |
4756 | |
4757 | } |
4758 | |
4759 | // If we had to use Brent's algorithm to find the true doca or the |
4760 | // doca to the line corresponding to the wire is downstream of the |
4761 | // cdc endplate, we need to swim the state vector and covariance |
4762 | // matrix back to the appropriate position along the reference |
4763 | // trajectory. |
4764 | if (swimmed_to_doca!=DOCA_NO_BRENT){ |
4765 | double dedx=0.; |
4766 | if (CORRECT_FOR_ELOSS){ |
4767 | dedx=GetdEdx(S(state_q_over_p), |
4768 | forward_traj[k].K_rho_Z_over_A, |
4769 | forward_traj[k].rho_Z_over_A, |
4770 | forward_traj[k].LnI,forward_traj[k].Z); |
4771 | } |
4772 | StepBack(dedx,newz,forward_traj[k].z,S0,S,C); |
4773 | } |
4774 | |
4775 | cdc_updates[cdc_index].S=S; |
4776 | cdc_updates[cdc_index].C=C; |
4777 | } |
4778 | |
4779 | // new wire origin and direction |
4780 | if (cdc_index>0){ |
4781 | cdc_index--; |
4782 | origin=my_cdchits[cdc_index]->origin; |
4783 | z0w=my_cdchits[cdc_index]->z0wire; |
4784 | dir=my_cdchits[cdc_index]->dir; |
4785 | } |
4786 | else more_cdc_measurements=false; |
4787 | |
4788 | // Update the wire position |
4789 | wirepos=origin+(z-z0w)*dir; |
4790 | |
4791 | // new doca |
4792 | dx=S(state_x)-wirepos.X(); |
4793 | dy=S(state_y)-wirepos.Y(); |
4794 | doca2=dx*dx+dy*dy; |
4795 | } |
4796 | old_doca2=doca2; |
4797 | } |
4798 | } |
4799 | // Save final z position |
4800 | z_=forward_traj[forward_traj.size()-1].z; |
4801 | |
4802 | // The following code segment addes a fake point at a well-defined z position |
4803 | // that would correspond to a thin foil target. It should not be turned on |
4804 | // for an extended target. |
4805 | if (ADD_VERTEX_POINT){ |
4806 | double dz_to_target=TARGET_Z-z_; |
4807 | double my_dz=mStepSizeZ*(dz_to_target>0?1.:-1.); |
4808 | int num_steps=int(fabs(dz_to_target/my_dz)); |
4809 | |
4810 | for (int k=0;k<num_steps;k++){ |
4811 | double newz=z_+my_dz; |
4812 | // Step C along z |
4813 | StepJacobian(z_,newz,S,0.,J); |
4814 | C=J*C*J.Transpose(); |
4815 | //C=C.SandwichMultiply(J); |
4816 | |
4817 | // Step S along z |
4818 | Step(z_,newz,0.,S); |
4819 | |
4820 | z_=newz; |
4821 | } |
4822 | |
4823 | // Step C along z |
4824 | StepJacobian(z_,TARGET_Z,S,0.,J); |
4825 | C=J*C*J.Transpose(); |
4826 | //C=C.SandwichMultiply(J); |
4827 | |
4828 | // Step S along z |
4829 | Step(z_,TARGET_Z,0.,S); |
4830 | |
4831 | z_=TARGET_Z; |
4832 | |
4833 | // predicted doca taking into account the orientation of the wire |
4834 | double dy=S(state_y); |
4835 | double dx=S(state_x); |
4836 | double d=sqrt(dx*dx+dy*dy); |
4837 | |
4838 | // Track projection |
4839 | double one_over_d=1./d; |
4840 | Hc_T(state_x)=dx*one_over_d; |
4841 | Hc(state_x)=Hc_T(state_x); |
4842 | Hc_T(state_y)=dy*one_over_d; |
4843 | Hc(state_y)=Hc_T(state_y); |
4844 | |
4845 | // Variance of target point |
4846 | // Variance is for average beam spot size assuming triangular distribution |
4847 | // out to 2.2 mm from the beam line. |
4848 | // sigma_r = 2.2 mm/ sqrt(18) |
4849 | Vc=0.002689; |
4850 | |
4851 | // inverse variance including prediction |
4852 | double InvV1=1./(Vc+Hc*(C*Hc_T)); |
4853 | //double InvV1=1./(Vc+C.SandwichMultiply(H_T)); |
4854 | if (InvV1<0.){ |
4855 | if (DEBUG_LEVEL>0) |
4856 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<4856<<" " << "Negative variance???" << endl; |
4857 | return NEGATIVE_VARIANCE; |
4858 | } |
4859 | // Compute KalmanSIMD gain matrix |
4860 | Kc=InvV1*(C*Hc_T); |
4861 | |
4862 | // Update the state vector with the target point |
4863 | // "Measurement" is average of expected beam spot size |
4864 | double res=0.1466666667-d; |
4865 | S+=res*Kc; |
4866 | // Update state vector covariance matrix |
4867 | //C=C-K*(H*C); |
4868 | C=C.SubSym(Kc*(Hc*C)); |
4869 | |
4870 | // Update chi2 for this segment |
4871 | chisq+=(1.-Hc*Kc)*res*res/Vc; |
4872 | numdof++; |
4873 | } |
4874 | |
4875 | // Check that there were enough hits to make this a valid fit |
4876 | if (numdof<6){ |
4877 | chisq=-1.; |
4878 | numdof=0; |
4879 | |
4880 | if (num_cdc==0){ |
4881 | unsigned int new_index=(3*num_fdc)/4; |
4882 | break_point_fdc_index=(new_index>=MIN_HITS_FOR_REFIT)?new_index:(MIN_HITS_FOR_REFIT-1); |
4883 | } |
4884 | else{ |
4885 | unsigned int new_index=(3*num_fdc)/4; |
4886 | if (new_index+num_cdc>=MIN_HITS_FOR_REFIT){ |
4887 | break_point_fdc_index=new_index; |
4888 | } |
4889 | else{ |
4890 | break_point_fdc_index=MIN_HITS_FOR_REFIT-num_cdc; |
4891 | } |
4892 | } |
4893 | return PRUNED_TOO_MANY_HITS; |
4894 | } |
4895 | |
4896 | // chisq*=anneal_factor; |
4897 | numdof-=5; |
4898 | |
4899 | // Final positions in x and y for this leg |
4900 | x_=S(state_x); |
4901 | y_=S(state_y); |
4902 | |
4903 | if (DEBUG_LEVEL>1){ |
4904 | cout << "Position after forward filter: " << x_ << ", " << y_ << ", " << z_ <<endl; |
4905 | cout << "Momentum " << 1./S(state_q_over_p) <<endl; |
4906 | } |
4907 | |
4908 | if (!S.IsFinite()) return FIT_FAILED; |
4909 | |
4910 | // Check if we have a kink in the track or threw away too many hits |
4911 | if (num_cdc>0 && break_point_fdc_index>0 && break_point_cdc_index>2){ |
4912 | if (break_point_fdc_index+num_cdc<MIN_HITS_FOR_REFIT){ |
4913 | //_DBG_ << endl; |
4914 | unsigned int new_index=(3*num_fdc)/4; |
4915 | if (new_index+num_cdc>=MIN_HITS_FOR_REFIT){ |
4916 | break_point_fdc_index=new_index; |
4917 | } |
4918 | else{ |
4919 | break_point_fdc_index=MIN_HITS_FOR_REFIT-num_cdc; |
4920 | } |
4921 | } |
4922 | return BREAK_POINT_FOUND; |
4923 | } |
4924 | if (num_cdc==0 && break_point_fdc_index>2){ |
4925 | //_DBG_ << endl; |
4926 | if (break_point_fdc_index<num_fdc/2){ |
4927 | break_point_fdc_index=(3*num_fdc)/4; |
4928 | } |
4929 | if (break_point_fdc_index<MIN_HITS_FOR_REFIT-1){ |
4930 | break_point_fdc_index=MIN_HITS_FOR_REFIT-1; |
4931 | } |
4932 | return BREAK_POINT_FOUND; |
4933 | } |
4934 | if (num_cdc>5 && break_point_cdc_index>2){ |
4935 | //_DBG_ << endl; |
4936 | unsigned int new_index=3*(num_fdc)/4; |
4937 | if (new_index+num_cdc>=MIN_HITS_FOR_REFIT){ |
4938 | break_point_fdc_index=new_index; |
4939 | } |
4940 | else{ |
4941 | break_point_fdc_index=MIN_HITS_FOR_REFIT-num_cdc; |
4942 | } |
4943 | return BREAK_POINT_FOUND; |
4944 | } |
4945 | unsigned int num_good=0; |
4946 | unsigned int num_hits=num_cdc+max_num_fdc_used_in_fit; |
4947 | for (unsigned int j=0;j<num_cdc;j++){ |
4948 | if (cdc_used_in_fit[j]) num_good++; |
4949 | } |
4950 | for (unsigned int j=0;j<num_fdc;j++){ |
4951 | if (fdc_used_in_fit[j]) num_good++; |
4952 | } |
4953 | if (double(num_good)/double(num_hits)<MINIMUM_HIT_FRACTION){ |
4954 | //_DBG_ <<endl; |
4955 | if (num_cdc==0){ |
4956 | unsigned int new_index=(3*num_fdc)/4; |
4957 | break_point_fdc_index=(new_index>=MIN_HITS_FOR_REFIT)?new_index:(MIN_HITS_FOR_REFIT-1); |
4958 | } |
4959 | else{ |
4960 | unsigned int new_index=(3*num_fdc)/4; |
4961 | if (new_index+num_cdc>=MIN_HITS_FOR_REFIT){ |
4962 | break_point_fdc_index=new_index; |
4963 | } |
4964 | else{ |
4965 | break_point_fdc_index=MIN_HITS_FOR_REFIT-num_cdc; |
4966 | } |
4967 | } |
4968 | return PRUNED_TOO_MANY_HITS; |
4969 | } |
4970 | |
4971 | return FIT_SUCCEEDED; |
4972 | } |
4973 | |
4974 | |
4975 | |
4976 | // Kalman engine for forward tracks -- this routine adds CDC hits |
4977 | kalman_error_t DTrackFitterKalmanSIMD::KalmanForwardCDC(double anneal, |
4978 | DMatrix5x1 &S, |
4979 | DMatrix5x5 &C, |
4980 | double &chisq, |
4981 | unsigned int &numdof){ |
4982 | DMatrix1x5 H; // Track projection matrix |
4983 | DMatrix5x1 H_T; // Transpose of track projection matrix |
4984 | DMatrix5x5 J; // State vector Jacobian matrix |
4985 | //DMatrix5x5 J_T; // transpose of this matrix |
4986 | DMatrix5x5 Q; // Process noise covariance matrix |
4987 | DMatrix5x1 K; // KalmanSIMD gain matrix |
4988 | DMatrix5x1 S0,S0_,Stest; //State vector |
4989 | DMatrix5x5 Ctest; // covariance matrix |
4990 | //DMatrix5x1 dS; // perturbation in state vector |
4991 | double V=0.0507; |
4992 | |
4993 | // set used_in_fit flags to false for cdc hits |
4994 | unsigned int num_cdc=cdc_used_in_fit.size(); |
4995 | for (unsigned int i=0;i<num_cdc;i++) cdc_used_in_fit[i]=false; |
4996 | for (unsigned int i=0;i<forward_traj.size();i++){ |
4997 | forward_traj[i].h_id=0; |
4998 | } |
4999 | |
5000 | // initialize chi2 info |
5001 | chisq=0.; |
5002 | numdof=0; |
5003 | |
5004 | double chi2cut=NUM_CDC_SIGMA_CUT*NUM_CDC_SIGMA_CUT; |
5005 | |
5006 | // Save the starting values for C and S in the deque |
5007 | forward_traj[break_point_step_index].Skk=S; |
5008 | forward_traj[break_point_step_index].Ckk=C; |
5009 | |
5010 | // z-position |
5011 | double z=forward_traj[break_point_step_index].z; |
5012 | |
5013 | // wire information |
5014 | unsigned int cdc_index=break_point_cdc_index; |
5015 | if (cdc_index<num_cdc-1){ |
5016 | num_cdc=cdc_index+1; |
5017 | } |
5018 | |
5019 | if (num_cdc<MIN_HITS_FOR_REFIT) chi2cut=BIG1.0e8; |
5020 | |
5021 | DVector2 origin=my_cdchits[cdc_index]->origin; |
5022 | double z0w=my_cdchits[cdc_index]->z0wire; |
5023 | DVector2 dir=my_cdchits[cdc_index]->dir; |
5024 | DVector2 wirepos=origin+(z-z0w)*dir; |
5025 | bool more_measurements=true; |
5026 | |
5027 | // doca variables |
5028 | double dx=S(state_x)-wirepos.X(); |
5029 | double dy=S(state_y)-wirepos.Y(); |
5030 | double doca2=0.,old_doca2=dx*dx+dy*dy; |
5031 | |
5032 | // loop over entries in the trajectory |
5033 | S0_=(forward_traj[break_point_step_index].S); |
5034 | for (unsigned int k=break_point_step_index+1;k<forward_traj.size()/*-1*/;k++){ |
5035 | unsigned int k_minus_1=k-1; |
5036 | |
5037 | z=forward_traj[k].z; |
5038 | |
5039 | // Get the state vector, jacobian matrix, and multiple scattering matrix |
5040 | // from reference trajectory |
5041 | S0=(forward_traj[k].S); |
5042 | J=(forward_traj[k].J); |
5043 | Q=(forward_traj[k].Q); |
5044 | |
5045 | // Update the actual state vector and covariance matrix |
5046 | S=S0+J*(S-S0_); |
5047 | |
5048 | // Bail if the position is grossly outside of the tracking volume |
5049 | if (S(state_x)*S(state_x)+S(state_y)*S(state_y)>R2_MAX4225.0){ |
5050 | if (DEBUG_LEVEL>2) |
5051 | { |
5052 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5052<<" "<< "Went outside of tracking volume at x=" << S(state_x) |
5053 | << " y=" << S(state_y) <<" z="<<z<<endl; |
5054 | } |
5055 | return POSITION_OUT_OF_RANGE; |
5056 | } |
5057 | // Bail if the momentum has dropped below some minimum |
5058 | if (fabs(S(state_q_over_p))>=Q_OVER_P_MAX){ |
5059 | if (DEBUG_LEVEL>2) |
5060 | { |
5061 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5061<<" " << "Bailing: P = " << 1./fabs(S(state_q_over_p)) << endl; |
5062 | } |
5063 | return MOMENTUM_OUT_OF_RANGE; |
5064 | } |
5065 | |
5066 | //C=J*(C*J_T)+Q; |
5067 | C=Q.AddSym(J*C*J.Transpose()); |
5068 | //C=Q.AddSym(C.SandwichMultiply(J)); |
5069 | |
5070 | // Save the current state of the reference trajectory |
5071 | S0_=S0; |
5072 | |
5073 | // new wire position |
5074 | wirepos=origin; |
5075 | wirepos+=(z-z0w)*dir; |
5076 | |
5077 | // new doca |
5078 | dx=S(state_x)-wirepos.X(); |
5079 | dy=S(state_y)-wirepos.Y(); |
5080 | doca2=dx*dx+dy*dy; |
5081 | |
5082 | // Save the current state and covariance matrix in the deque |
5083 | if (fit_type==kTimeBased){ |
5084 | forward_traj[k].Skk=S; |
5085 | forward_traj[k].Ckk=C; |
5086 | } |
5087 | |
5088 | // Check if the doca is no longer decreasing |
5089 | if (more_measurements && doca2>old_doca2/* && z<endplate_z_downstream*/){ |
5090 | if (my_cdchits[cdc_index]->status==good_hit){ |
5091 | find_doca_error_t swimmed_to_doca=DOCA_NO_BRENT; |
5092 | double newz=endplate_z; |
5093 | double dz=newz-z; |
5094 | // Sometimes the true doca would correspond to the case where the |
5095 | // wire would need to extend beyond the physical volume of the straw. |
5096 | // In this case, find the doca at the cdc endplate. |
5097 | if (z>endplate_z){ |
5098 | swimmed_to_doca=DOCA_ENDPLATE; |
5099 | SwimToEndplate(z,forward_traj[k],S); |
5100 | |
5101 | // wire position at the endplate |
5102 | wirepos=origin; |
5103 | wirepos+=(endplate_z-z0w)*dir; |
5104 | |
5105 | dx=S(state_x)-wirepos.X(); |
5106 | dy=S(state_y)-wirepos.Y(); |
5107 | } |
5108 | else{ |
5109 | // Find the true doca to the wire. If we had to use Brent's |
5110 | // algorithm, the routine returns USED_BRENT |
5111 | double step1=mStepSizeZ; |
5112 | double step2=mStepSizeZ; |
5113 | if (k>=2){ |
5114 | step1=-forward_traj[k].z+forward_traj[k_minus_1].z; |
5115 | step2=-forward_traj[k_minus_1].z+forward_traj[k-2].z; |
5116 | } |
5117 | swimmed_to_doca=FindDoca(my_cdchits[cdc_index],forward_traj[k], |
5118 | step1,step2,S0,S,C,dx,dy,dz); |
5119 | if (swimmed_to_doca==BRENT_FAILED){ |
5120 | break_point_cdc_index=(3*num_cdc)/4; |
5121 | return MOMENTUM_OUT_OF_RANGE; |
5122 | } |
5123 | newz=forward_traj[k].z+dz; |
5124 | } |
5125 | double cosstereo=my_cdchits[cdc_index]->cosstereo; |
5126 | double d=sqrt(dx*dx+dy*dy)*cosstereo+EPS3.0e-8; |
5127 | |
5128 | // Track projection |
5129 | double cosstereo2_over_d=cosstereo*cosstereo/d; |
5130 | H_T(state_x)=dx*cosstereo2_over_d; |
5131 | H(state_x)=H_T(state_x); |
5132 | H_T(state_y)=dy*cosstereo2_over_d; |
5133 | H(state_y)=H_T(state_y); |
5134 | if (swimmed_to_doca==DOCA_NO_BRENT){ |
5135 | H_T(state_ty)=H_T(state_y)*dz; |
5136 | H(state_ty)=H_T(state_ty); |
5137 | H_T(state_tx)=H_T(state_x)*dz; |
5138 | H(state_tx)=H_T(state_tx); |
5139 | } |
5140 | else{ |
5141 | H_T(state_ty)=0.; |
5142 | H(state_ty)=0.; |
5143 | H_T(state_tx)=0.; |
5144 | H(state_tx)=0.; |
5145 | } |
5146 | |
5147 | // The next measurement |
5148 | double dm=0.39,tdrift=0.,tcorr=0.,dDdt0=0.; |
5149 | if (fit_type==kTimeBased || USE_PASS1_TIME_MODE){ |
5150 | // Find offset of wire with respect to the center of the |
5151 | // straw at this z position |
5152 | double delta=0,dphi=0.; |
5153 | FindSag(dx,dy,newz-z0w,my_cdchits[cdc_index]->hit->wire,delta,dphi); |
5154 | // Find drift time and distance |
5155 | tdrift=my_cdchits[cdc_index]->tdrift-mT0 |
5156 | -forward_traj[k_minus_1].t*TIME_UNIT_CONVERSION3.33564095198152014e-02; |
5157 | double B=forward_traj[k_minus_1].B; |
5158 | ComputeCDCDrift(dphi,delta,tdrift,B,dm,V,tcorr); |
5159 | V*=anneal; |
5160 | if (ALIGNMENT_FORWARD){ |
5161 | double myV=0.; |
5162 | double mytcorr=0.; |
5163 | double d_shifted; |
5164 | double dt=2.0; |
5165 | if (tdrift < 0.) d_shifted = dm; |
5166 | else ComputeCDCDrift(dphi,delta,tdrift+dt,B,d_shifted,myV,mytcorr); |
5167 | dDdt0=(d_shifted-dm)/dt; |
5168 | } |
5169 | //_DBG_ << tcorr << " " << dphi << " " << dm << endl; |
5170 | |
5171 | } |
5172 | // residual |
5173 | double res=dm-d; |
5174 | |
5175 | // inverse of variance including prediction |
5176 | double Vproj=H*C*H_T; |
5177 | double InvV=1./(V+Vproj); |
5178 | if (InvV<0.){ |
5179 | if (DEBUG_LEVEL>0) |
5180 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5180<<" " << "Negative variance???" << endl; |
5181 | break_point_cdc_index=(3*num_cdc)/4; |
5182 | return NEGATIVE_VARIANCE; |
5183 | } |
5184 | |
5185 | // Check how far this hit is from the expected position |
5186 | double chi2check=res*res*InvV; |
5187 | if (chi2check<chi2cut){ |
5188 | // Compute KalmanSIMD gain matrix |
5189 | K=InvV*(C*H_T); |
5190 | |
5191 | // Update state vector covariance matrix |
5192 | Ctest=C.SubSym(K*(H*C)); |
5193 | // Joseph form |
5194 | // C = (I-KH)C(I-KH)^T + KVK^T |
5195 | //Ctest=C.SandwichMultiply(I5x5-K*H)+V*MultiplyTranspose(K); |
5196 | // Check that Ctest is positive definite |
5197 | if (!Ctest.IsPosDef()){ |
5198 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5198<<" " << "Broken covariance matrix!" <<endl; |
5199 | return BROKEN_COVARIANCE_MATRIX; |
5200 | } |
5201 | |
5202 | bool skip_ring |
5203 | =(my_cdchits[cdc_index]->hit->wire->ring==RING_TO_SKIP); |
5204 | // update covariance matrix and state vector |
5205 | if (skip_ring==false && tdrift >= CDC_T_DRIFT_MIN){ |
5206 | C=Ctest; |
5207 | S+=res*K; |
5208 | } |
5209 | // Mark point on ref trajectory with a hit id for the straw |
5210 | forward_traj[k].h_id=cdc_index+1000; |
5211 | |
5212 | // Store some updated values related to the hit |
5213 | double scale=(skip_ring)?1.:(1.-H*K); |
5214 | cdc_updates[cdc_index].tcorr=tcorr; |
5215 | cdc_updates[cdc_index].tdrift=tdrift; |
5216 | cdc_updates[cdc_index].doca=dm; |
5217 | cdc_updates[cdc_index].variance=V; |
5218 | cdc_updates[cdc_index].dDdt0=dDdt0; |
5219 | cdc_used_in_fit[cdc_index]=true; |
5220 | if(tdrift < CDC_T_DRIFT_MIN) cdc_used_in_fit[cdc_index]=false; |
5221 | |
5222 | // Update chi2 for this segment |
5223 | if (skip_ring==false && tdrift >= CDC_T_DRIFT_MIN){ |
5224 | chisq+=scale*res*res/V; |
5225 | numdof++; |
5226 | } |
5227 | break_point_cdc_index=cdc_index; |
5228 | break_point_step_index=k_minus_1; |
5229 | |
5230 | if (DEBUG_LEVEL>9) |
5231 | printf("Ring %d straw %d pred %f meas %f chi2 %f useBrent %i \n", |
5232 | my_cdchits[cdc_index]->hit->wire->ring, |
5233 | my_cdchits[cdc_index]->hit->wire->straw, |
5234 | d,dm,(1.-H*K)*res*res/V,swimmed_to_doca); |
5235 | |
5236 | } |
5237 | |
5238 | // If we had to use Brent's algorithm to find the true doca or the |
5239 | // doca to the line corresponding to the wire is downstream of the |
5240 | // cdc endplate, we need to swim the state vector and covariance |
5241 | // matrix back to the appropriate position along the reference |
5242 | // trajectory. |
5243 | if (swimmed_to_doca!=DOCA_NO_BRENT){ |
5244 | double dedx=0.; |
5245 | if (CORRECT_FOR_ELOSS){ |
5246 | dedx=GetdEdx(S(state_q_over_p), |
5247 | forward_traj[k].K_rho_Z_over_A, |
5248 | forward_traj[k].rho_Z_over_A, |
5249 | forward_traj[k].LnI,forward_traj[k].Z); |
5250 | } |
5251 | StepBack(dedx,newz,forward_traj[k].z,S0,S,C); |
5252 | } |
5253 | |
5254 | cdc_updates[cdc_index].S=S; |
5255 | cdc_updates[cdc_index].C=C; |
5256 | } |
5257 | |
5258 | // new wire origin and direction |
5259 | if (cdc_index>0){ |
5260 | cdc_index--; |
5261 | origin=my_cdchits[cdc_index]->origin; |
5262 | z0w=my_cdchits[cdc_index]->z0wire; |
5263 | dir=my_cdchits[cdc_index]->dir; |
5264 | } |
5265 | else{ |
5266 | more_measurements=false; |
5267 | } |
5268 | |
5269 | // Update the wire position |
5270 | wirepos=origin; |
5271 | wirepos+=(z-z0w)*dir; |
5272 | |
5273 | // new doca |
5274 | dx=S(state_x)-wirepos.X(); |
5275 | dy=S(state_y)-wirepos.Y(); |
5276 | doca2=dx*dx+dy*dy; |
5277 | } |
5278 | old_doca2=doca2; |
5279 | } |
5280 | |
5281 | // Check that there were enough hits to make this a valid fit |
5282 | if (numdof<6){ |
5283 | chisq=-1.; |
5284 | numdof=0; |
5285 | return PRUNED_TOO_MANY_HITS; |
5286 | } |
5287 | numdof-=5; |
5288 | |
5289 | // Final position for this leg |
5290 | x_=S(state_x); |
5291 | y_=S(state_y); |
5292 | z_=forward_traj[forward_traj.size()-1].z; |
5293 | |
5294 | if (!S.IsFinite()) return FIT_FAILED; |
5295 | |
5296 | // Check if we have a kink in the track or threw away too many cdc hits |
5297 | if (num_cdc>=MIN_HITS_FOR_REFIT){ |
5298 | if (break_point_cdc_index>1){ |
5299 | if (break_point_cdc_index<num_cdc/2){ |
5300 | break_point_cdc_index=(3*num_cdc)/4; |
5301 | } |
5302 | return BREAK_POINT_FOUND; |
5303 | } |
5304 | |
5305 | unsigned int num_good=0; |
5306 | for (unsigned int j=0;j<num_cdc;j++){ |
5307 | if (cdc_used_in_fit[j]) num_good++; |
5308 | } |
5309 | if (double(num_good)/double(num_cdc)<MINIMUM_HIT_FRACTION){ |
5310 | return PRUNED_TOO_MANY_HITS; |
5311 | } |
5312 | } |
5313 | |
5314 | return FIT_SUCCEEDED; |
5315 | } |
5316 | |
5317 | // Extrapolate to the point along z of closest approach to the beam line using |
5318 | // the forward track state vector parameterization. Converts to the central |
5319 | // track representation at the end. |
5320 | jerror_t DTrackFitterKalmanSIMD::ExtrapolateToVertex(DMatrix5x1 &S, |
5321 | DMatrix5x5 &C){ |
5322 | DMatrix5x5 J; // Jacobian matrix |
5323 | DMatrix5x5 Q; // multiple scattering matrix |
5324 | DMatrix5x1 S1(S); // copy of S |
5325 | |
5326 | // position variables |
5327 | double z=z_,newz=z_; |
5328 | |
5329 | DVector2 beam_pos=beam_center+(z-beam_z0)*beam_dir; |
5330 | double r2_old=(DVector2(S(state_x),S(state_y))-beam_pos).Mod2(); |
5331 | double dz_old=0.; |
5332 | double dEdx=0.; |
5333 | double sign=1.; |
5334 | |
5335 | // material properties |
5336 | double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.; |
5337 | double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.; |
5338 | |
5339 | // if (fit_type==kTimeBased)printf("------Extrapolating\n"); |
5340 | |
5341 | // printf("-----------\n"); |
5342 | // Current position |
5343 | DVector3 pos(S(state_x),S(state_y),z); |
5344 | |
5345 | // get material properties from the Root Geometry |
5346 | if (geom->FindMatKalman(pos,K_rho_Z_over_A,rho_Z_over_A,LnI,Z, |
5347 | chi2c_factor,chi2a_factor,chi2a_corr, |
5348 | last_material_map) |
5349 | !=NOERROR){ |
5350 | if (DEBUG_LEVEL>1) |
5351 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5351<<" " << "Material error in ExtrapolateToVertex at (x,y,z)=(" |
5352 | << pos.X() <<"," << pos.y()<<","<< pos.z()<<")"<< endl; |
5353 | return UNRECOVERABLE_ERROR; |
5354 | } |
5355 | |
5356 | // Adjust the step size |
5357 | double ds_dz=sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty)); |
5358 | double dz=-mStepSizeS/ds_dz; |
5359 | if (fabs(dEdx)>EPS3.0e-8){ |
5360 | dz=(-1.)*DE_PER_STEP0.001/fabs(dEdx)/ds_dz; |
5361 | } |
5362 | if(fabs(dz)>mStepSizeZ) dz=-mStepSizeZ; |
5363 | if(fabs(dz)<MIN_STEP_SIZE0.1)dz=-MIN_STEP_SIZE0.1; |
5364 | |
5365 | // Get dEdx for the upcoming step |
5366 | if (CORRECT_FOR_ELOSS){ |
5367 | dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI,Z); |
5368 | } |
5369 | |
5370 | |
5371 | double ztest=endplate_z; |
5372 | if (my_fdchits.size()>0){ |
5373 | ztest =my_fdchits[0]->z-1.; |
5374 | } |
5375 | if (z<ztest) |
5376 | { |
5377 | // Check direction of propagation |
5378 | DMatrix5x1 S2(S); // second copy of S |
5379 | |
5380 | // Step test states through the field and compute squared radii |
5381 | Step(z,z-dz,dEdx,S1); |
5382 | // Bail if the momentum has dropped below some minimum |
5383 | if (fabs(S1(state_q_over_p))>Q_OVER_P_MAX){ |
5384 | if (DEBUG_LEVEL>2) |
5385 | { |
5386 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5386<<" " << "Bailing: P = " << 1./fabs(S1(state_q_over_p)) |
5387 | << endl; |
5388 | } |
5389 | return UNRECOVERABLE_ERROR; |
5390 | } |
5391 | beam_pos=beam_center+(z-dz-beam_z0)*beam_dir; |
5392 | double r2minus=(DVector2(S1(state_x),S1(state_y))-beam_pos).Mod2(); |
5393 | |
5394 | Step(z,z+dz,dEdx,S2); |
5395 | // Bail if the momentum has dropped below some minimum |
5396 | if (fabs(S2(state_q_over_p))>Q_OVER_P_MAX){ |
5397 | if (DEBUG_LEVEL>2) |
5398 | { |
5399 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5399<<" " << "Bailing: P = " << 1./fabs(S2(state_q_over_p)) |
5400 | << endl; |
5401 | } |
5402 | return UNRECOVERABLE_ERROR; |
5403 | } |
5404 | beam_pos=beam_center+(z+dz-beam_z0)*beam_dir; |
5405 | double r2plus=(DVector2(S2(state_x),S2(state_y))-beam_pos).Mod2(); |
5406 | // Check to see if we have already bracketed the minimum |
5407 | if (r2plus>r2_old && r2minus>r2_old){ |
5408 | newz=z+dz; |
5409 | double dz2=0.; |
5410 | if (BrentsAlgorithm(newz,dz,dEdx,0.,beam_center,beam_dir,S2,dz2)!=NOERROR){ |
5411 | if (DEBUG_LEVEL>2) |
5412 | { |
5413 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5413<<" " << "Bailing: P = " << 1./fabs(S2(state_q_over_p)) |
5414 | << endl; |
5415 | } |
5416 | return UNRECOVERABLE_ERROR; |
5417 | } |
5418 | z_=newz+dz2; |
5419 | |
5420 | // Compute the Jacobian matrix |
5421 | StepJacobian(z,z_,S,dEdx,J); |
5422 | |
5423 | // Propagate the covariance matrix |
5424 | C=J*C*J.Transpose(); |
5425 | //C=C.SandwichMultiply(J); |
5426 | |
5427 | // Step to the position of the doca |
5428 | Step(z,z_,dEdx,S); |
5429 | |
5430 | // update internal variables |
5431 | x_=S(state_x); |
5432 | y_=S(state_y); |
5433 | |
5434 | return NOERROR; |
5435 | } |
5436 | |
5437 | // Find direction to propagate toward minimum doca |
5438 | if (r2minus<r2_old && r2_old<r2plus){ |
5439 | newz=z-dz; |
5440 | |
5441 | // Compute the Jacobian matrix |
5442 | StepJacobian(z,newz,S,dEdx,J); |
5443 | |
5444 | // Propagate the covariance matrix |
5445 | C=J*C*J.Transpose(); |
5446 | //C=C.SandwichMultiply(J); |
5447 | |
5448 | S2=S; |
5449 | S=S1; |
5450 | S1=S2; |
5451 | dz*=-1.; |
5452 | sign=-1.; |
5453 | dz_old=dz; |
5454 | r2_old=r2minus; |
5455 | z=z+dz; |
5456 | } |
5457 | if (r2minus>r2_old && r2_old>r2plus){ |
5458 | newz=z+dz; |
5459 | |
5460 | // Compute the Jacobian matrix |
5461 | StepJacobian(z,newz,S,dEdx,J); |
5462 | |
5463 | // Propagate the covariance matrix |
5464 | C=J*C*J.Transpose(); |
5465 | //C=C.SandwichMultiply(J); |
5466 | |
5467 | S1=S; |
5468 | S=S2; |
5469 | dz_old=dz; |
5470 | r2_old=r2plus; |
5471 | z=z+dz; |
5472 | } |
5473 | } |
5474 | |
5475 | double r2=r2_old; |
5476 | while (z>Z_MIN-100. && r2<R2_MAX4225.0 && z<ztest && r2>EPS3.0e-8){ |
5477 | // Bail if the momentum has dropped below some minimum |
5478 | if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){ |
5479 | if (DEBUG_LEVEL>2) |
5480 | { |
5481 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5481<<" " << "Bailing: P = " << 1./fabs(S(state_q_over_p)) |
5482 | << endl; |
5483 | } |
5484 | return UNRECOVERABLE_ERROR; |
5485 | } |
5486 | |
5487 | // Relationship between arc length and z |
5488 | double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty)); |
5489 | |
5490 | // get material properties from the Root Geometry |
5491 | pos.SetXYZ(S(state_x),S(state_y),z); |
5492 | double s_to_boundary=1.e6; |
5493 | if (ENABLE_BOUNDARY_CHECK && fit_type==kTimeBased){ |
5494 | DVector3 mom(S(state_tx),S(state_ty),1.); |
5495 | if (geom->FindMatKalman(pos,mom,K_rho_Z_over_A,rho_Z_over_A,LnI,Z, |
5496 | chi2c_factor,chi2a_factor,chi2a_corr, |
5497 | last_material_map,&s_to_boundary) |
5498 | !=NOERROR){ |
5499 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5499<<" " << "Material error in ExtrapolateToVertex! " << endl; |
5500 | return UNRECOVERABLE_ERROR; |
5501 | } |
5502 | } |
5503 | else{ |
5504 | if (geom->FindMatKalman(pos,K_rho_Z_over_A,rho_Z_over_A,LnI,Z, |
5505 | chi2c_factor,chi2a_factor,chi2a_corr, |
5506 | last_material_map) |
5507 | !=NOERROR){ |
5508 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5508<<" " << "Material error in ExtrapolateToVertex! " << endl; |
5509 | break; |
5510 | } |
5511 | } |
5512 | |
5513 | // Get dEdx for the upcoming step |
5514 | if (CORRECT_FOR_ELOSS){ |
5515 | dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI,Z); |
5516 | } |
5517 | |
5518 | // Adjust the step size |
5519 | //dz=-sign*mStepSizeS*dz_ds; |
5520 | double ds=mStepSizeS; |
5521 | if (fabs(dEdx)>EPS3.0e-8){ |
5522 | ds=DE_PER_STEP0.001/fabs(dEdx); |
5523 | } |
5524 | /* |
5525 | if(fabs(dz)>mStepSizeZ) dz=-sign*mStepSizeZ; |
5526 | if (fabs(dz)<z_to_boundary) dz=-sign*z_to_boundary; |
5527 | if(fabs(dz)<MIN_STEP_SIZE)dz=-sign*MIN_STEP_SIZE; |
5528 | */ |
5529 | if (ds>mStepSizeS) ds=mStepSizeS; |
5530 | if (ds>s_to_boundary) ds=s_to_boundary; |
5531 | if (ds<MIN_STEP_SIZE0.1) ds=MIN_STEP_SIZE0.1; |
5532 | dz=-sign*ds*dz_ds; |
5533 | |
5534 | // Get the contribution to the covariance matrix due to multiple |
5535 | // scattering |
5536 | GetProcessNoise(z,ds,chi2c_factor,chi2a_factor,chi2a_corr,S,Q); |
5537 | |
5538 | if (CORRECT_FOR_ELOSS){ |
5539 | double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p); |
5540 | double one_over_beta2=1.+mass2*q_over_p_sq; |
5541 | double varE=GetEnergyVariance(ds,one_over_beta2,K_rho_Z_over_A); |
5542 | Q(state_q_over_p,state_q_over_p)=varE*q_over_p_sq*q_over_p_sq*one_over_beta2; |
5543 | } |
5544 | |
5545 | |
5546 | newz=z+dz; |
5547 | // Compute the Jacobian matrix |
5548 | StepJacobian(z,newz,S,dEdx,J); |
5549 | |
5550 | // Propagate the covariance matrix |
5551 | C=Q.AddSym(J*C*J.Transpose()); |
5552 | //C=Q.AddSym(C.SandwichMultiply(J)); |
5553 | |
5554 | // Step through field |
5555 | Step(z,newz,dEdx,S); |
5556 | |
5557 | // Check if we passed the minimum doca to the beam line |
5558 | beam_pos=beam_center+(newz-beam_z0)*beam_dir; |
5559 | r2=(DVector2(S(state_x),S(state_y))-beam_pos).Mod2(); |
5560 | //r2=S(state_x)*S(state_x)+S(state_y)*S(state_y); |
5561 | if (r2>r2_old){ |
5562 | double two_step=dz+dz_old; |
5563 | |
5564 | // Find the increment/decrement in z to get to the minimum doca to the |
5565 | // beam line |
5566 | S1=S; |
5567 | if (BrentsAlgorithm(newz,0.5*two_step,dEdx,0.,beam_center,beam_dir,S,dz)!=NOERROR){ |
5568 | //_DBG_<<endl; |
5569 | return UNRECOVERABLE_ERROR; |
5570 | } |
5571 | |
5572 | // Compute the Jacobian matrix |
5573 | z_=newz+dz; |
5574 | StepJacobian(newz,z_,S1,dEdx,J); |
5575 | |
5576 | // Propagate the covariance matrix |
5577 | //C=J*C*J.Transpose()+(dz/(newz-z))*Q; |
5578 | //C=((dz/newz-z)*Q).AddSym(C.SandwichMultiply(J)); |
5579 | //C=C.SandwichMultiply(J); |
5580 | C=J*C*J.Transpose(); |
5581 | |
5582 | // update internal variables |
5583 | x_=S(state_x); |
5584 | y_=S(state_y); |
5585 | |
5586 | return NOERROR; |
5587 | } |
5588 | r2_old=r2; |
5589 | dz_old=dz; |
5590 | S1=S; |
5591 | z=newz; |
5592 | } |
5593 | // update internal variables |
5594 | x_=S(state_x); |
5595 | y_=S(state_y); |
5596 | z_=newz; |
5597 | |
5598 | return NOERROR; |
5599 | } |
5600 | |
5601 | |
5602 | // Extrapolate to the point along z of closest approach to the beam line using |
5603 | // the forward track state vector parameterization. |
5604 | jerror_t DTrackFitterKalmanSIMD::ExtrapolateToVertex(DMatrix5x1 &S){ |
5605 | DMatrix5x5 J; // Jacobian matrix |
5606 | DMatrix5x1 S1(S); // copy of S |
5607 | |
5608 | // position variables |
5609 | double z=z_,newz=z_; |
5610 | DVector2 beam_pos=beam_center+(z-beam_z0)*beam_dir; |
5611 | double r2_old=(DVector2(S(state_x),S(state_y))-beam_pos).Mod2(); |
5612 | double dz_old=0.; |
5613 | double dEdx=0.; |
5614 | |
5615 | // Direction and origin for beam line |
5616 | DVector2 dir; |
5617 | DVector2 origin; |
5618 | |
5619 | // material properties |
5620 | double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.; |
5621 | double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.; |
5622 | DVector3 pos; // current position along trajectory |
5623 | |
5624 | double r2=r2_old; |
5625 | while (z>Z_MIN-100. && r2<R2_MAX4225.0 && z<Z_MAX370.0 && r2>EPS3.0e-8){ |
5626 | // Bail if the momentum has dropped below some minimum |
5627 | if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){ |
5628 | if (DEBUG_LEVEL>2) |
5629 | { |
5630 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5630<<" " << "Bailing: P = " << 1./fabs(S(state_q_over_p)) |
5631 | << endl; |
5632 | } |
5633 | return UNRECOVERABLE_ERROR; |
5634 | } |
5635 | |
5636 | // Relationship between arc length and z |
5637 | double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty)); |
5638 | |
5639 | // get material properties from the Root Geometry |
5640 | pos.SetXYZ(S(state_x),S(state_y),z); |
5641 | if (geom->FindMatKalman(pos,K_rho_Z_over_A,rho_Z_over_A,LnI,Z, |
5642 | chi2c_factor,chi2a_factor,chi2a_corr, |
5643 | last_material_map) |
5644 | !=NOERROR){ |
5645 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5645<<" " << "Material error in ExtrapolateToVertex! " << endl; |
5646 | break; |
5647 | } |
5648 | |
5649 | // Get dEdx for the upcoming step |
5650 | if (CORRECT_FOR_ELOSS){ |
5651 | dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI,Z); |
5652 | } |
5653 | |
5654 | // Adjust the step size |
5655 | double ds=mStepSizeS; |
5656 | if (fabs(dEdx)>EPS3.0e-8){ |
5657 | ds=DE_PER_STEP0.001/fabs(dEdx); |
5658 | } |
5659 | if (ds>mStepSizeS) ds=mStepSizeS; |
5660 | if (ds<MIN_STEP_SIZE0.1) ds=MIN_STEP_SIZE0.1; |
5661 | double dz=-ds*dz_ds; |
5662 | |
5663 | newz=z+dz; |
5664 | |
5665 | |
5666 | // Step through field |
5667 | Step(z,newz,dEdx,S); |
5668 | |
5669 | // Check if we passed the minimum doca to the beam line |
5670 | beam_pos=beam_center+(newz-beam_z0)*beam_dir; |
5671 | r2=(DVector2(S(state_x),S(state_y))-beam_pos).Mod2(); |
5672 | |
5673 | if (r2>r2_old && newz<endplate_z){ |
5674 | double two_step=dz+dz_old; |
5675 | |
5676 | // Find the increment/decrement in z to get to the minimum doca to the |
5677 | // beam line |
5678 | if (BrentsAlgorithm(newz,0.5*two_step,dEdx,0.,beam_center,beam_dir,S,dz)!=NOERROR){ |
5679 | return UNRECOVERABLE_ERROR; |
5680 | } |
5681 | // update internal variables |
5682 | x_=S(state_x); |
5683 | y_=S(state_y); |
5684 | z_=newz+dz; |
5685 | |
5686 | return NOERROR; |
5687 | } |
5688 | r2_old=r2; |
5689 | dz_old=dz; |
5690 | z=newz; |
5691 | } |
5692 | |
5693 | // If we extrapolate beyond the fiducial volume of the detector before |
5694 | // finding the doca, abandon the extrapolation... |
5695 | if (newz<Z_MIN-100.){ |
5696 | //_DBG_ << "Extrapolated z = " << newz << endl; |
5697 | // Restore old state vector |
5698 | S=S1; |
5699 | return VALUE_OUT_OF_RANGE; |
5700 | } |
5701 | |
5702 | // update internal variables |
5703 | x_=S(state_x); |
5704 | y_=S(state_y); |
5705 | z_=newz; |
5706 | |
5707 | |
5708 | return NOERROR; |
5709 | } |
5710 | |
5711 | |
5712 | |
5713 | |
5714 | // Propagate track to point of distance of closest approach to origin |
5715 | jerror_t DTrackFitterKalmanSIMD::ExtrapolateToVertex(DVector2 &xy, |
5716 | DMatrix5x1 &Sc,DMatrix5x5 &Cc){ |
5717 | DMatrix5x5 Jc=I5x5; //Jacobian matrix |
5718 | DMatrix5x5 Q; // multiple scattering matrix |
5719 | |
5720 | // Position and step variables |
5721 | DVector2 beam_pos=beam_center+(Sc(state_z)-beam_z0)*beam_dir; |
5722 | double r2=(xy-beam_pos).Mod2(); |
5723 | double ds=-mStepSizeS; // step along path in cm |
5724 | double r2_old=r2; |
5725 | |
5726 | // Energy loss |
5727 | double dedx=0.; |
5728 | |
5729 | // Check direction of propagation |
5730 | DMatrix5x1 S0; |
5731 | S0=Sc; |
5732 | DVector2 xy0=xy; |
5733 | DVector2 xy1=xy; |
5734 | Step(xy0,ds,S0,dedx); |
5735 | // Bail if the transverse momentum has dropped below some minimum |
5736 | if (fabs(S0(state_q_over_pt))>Q_OVER_PT_MAX100.){ |
5737 | if (DEBUG_LEVEL>2) |
5738 | { |
5739 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5739<<" " << "Bailing: PT = " << 1./fabs(S0(state_q_over_pt)) |
5740 | << endl; |
5741 | } |
5742 | return UNRECOVERABLE_ERROR; |
5743 | } |
5744 | beam_pos=beam_center+(S0(state_z)-beam_z0)*beam_dir; |
5745 | r2=(xy0-beam_pos).Mod2(); |
5746 | if (r2>r2_old) ds*=-1.; |
5747 | double ds_old=ds; |
5748 | |
5749 | // if (fit_type==kTimeBased)printf("------Extrapolating\n"); |
5750 | |
5751 | if (central_traj.size()==0){ |
5752 | if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5752<<" " << "Central trajectory size==0!" << endl; |
5753 | return UNRECOVERABLE_ERROR; |
5754 | } |
5755 | |
5756 | // D is now on the actual trajectory itself |
5757 | Sc(state_D)=0.; |
5758 | |
5759 | // Track propagation loop |
5760 | while (Sc(state_z)>Z_MIN-100. && Sc(state_z)<Z_MAX370.0 |
5761 | && r2<R2_MAX4225.0){ |
5762 | // Bail if the transverse momentum has dropped below some minimum |
5763 | if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){ |
5764 | if (DEBUG_LEVEL>2) |
5765 | { |
5766 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5766<<" " << "Bailing: PT = " << 1./fabs(Sc(state_q_over_pt)) |
5767 | << endl; |
5768 | } |
5769 | return UNRECOVERABLE_ERROR; |
5770 | } |
5771 | |
5772 | // get material properties from the Root Geometry |
5773 | double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.; |
5774 | double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.; |
5775 | DVector3 pos3d(xy.X(),xy.Y(),Sc(state_z)); |
5776 | if (geom->FindMatKalman(pos3d,K_rho_Z_over_A,rho_Z_over_A,LnI,Z, |
5777 | chi2c_factor,chi2a_factor,chi2a_corr, |
5778 | last_material_map) |
5779 | !=NOERROR){ |
5780 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5780<<" " << "Material error in ExtrapolateToVertex! " << endl; |
5781 | break; |
5782 | } |
5783 | |
5784 | // Get dEdx for the upcoming step |
5785 | double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl))); |
5786 | if (CORRECT_FOR_ELOSS){ |
5787 | dedx=-GetdEdx(q_over_p,K_rho_Z_over_A,rho_Z_over_A,LnI,Z); |
5788 | } |
5789 | // Adjust the step size |
5790 | double sign=(ds>0.0)?1.:-1.; |
5791 | if (fabs(dedx)>EPS3.0e-8){ |
5792 | ds=sign*DE_PER_STEP0.001/fabs(dedx); |
5793 | } |
5794 | if(fabs(ds)>mStepSizeS) ds=sign*mStepSizeS; |
5795 | if(fabs(ds)<MIN_STEP_SIZE0.1)ds=sign*MIN_STEP_SIZE0.1; |
5796 | |
5797 | // Multiple scattering |
5798 | GetProcessNoiseCentral(ds,chi2c_factor,chi2a_factor,chi2a_corr,Sc,Q); |
5799 | |
5800 | if (CORRECT_FOR_ELOSS){ |
5801 | double q_over_p_sq=q_over_p*q_over_p; |
5802 | double one_over_beta2=1.+mass2*q_over_p*q_over_p; |
5803 | double varE=GetEnergyVariance(ds,one_over_beta2,K_rho_Z_over_A); |
5804 | Q(state_q_over_pt,state_q_over_pt) |
5805 | +=varE*Sc(state_q_over_pt)*Sc(state_q_over_pt)*one_over_beta2 |
5806 | *q_over_p_sq; |
5807 | } |
5808 | |
5809 | // Propagate the state and covariance through the field |
5810 | S0=Sc; |
5811 | DVector2 old_xy=xy; |
5812 | StepStateAndCovariance(xy,ds,dedx,Sc,Jc,Cc); |
5813 | |
5814 | // Add contribution due to multiple scattering |
5815 | Cc=(sign*Q).AddSym(Cc); |
5816 | |
5817 | beam_pos=beam_center+(Sc(state_z)-beam_z0)*beam_dir; |
5818 | r2=(xy-beam_pos).Mod2(); |
5819 | //printf("r %f r_old %f \n",sqrt(r2),sqrt(r2_old)); |
5820 | if (r2>r2_old) { |
5821 | // We've passed the true minimum; backtrack to find the "vertex" |
5822 | // position |
5823 | double my_ds=0.; |
5824 | if (BrentsAlgorithm(ds,ds_old,dedx,xy,0.,beam_center,beam_dir,Sc,my_ds)!=NOERROR){ |
5825 | //_DBG_ <<endl; |
5826 | return UNRECOVERABLE_ERROR; |
5827 | } |
5828 | //printf ("Brent min r %f\n",xy.Mod()); |
5829 | |
5830 | // Find the field and gradient at (old_x,old_y,old_z) |
5831 | bfield->GetFieldAndGradient(old_xy.X(),old_xy.Y(),S0(state_z),Bx,By,Bz, |
5832 | dBxdx,dBxdy,dBxdz,dBydx, |
5833 | dBydy,dBydz,dBzdx,dBzdy,dBzdz); |
5834 | |
5835 | // Compute the Jacobian matrix |
5836 | my_ds-=ds_old; |
5837 | StepJacobian(old_xy,xy-old_xy,my_ds,S0,dedx,Jc); |
5838 | |
5839 | // Propagate the covariance matrix |
5840 | //Cc=Jc*Cc*Jc.Transpose()+(my_ds/ds_old)*Q; |
5841 | //Cc=((my_ds/ds_old)*Q).AddSym(Cc.SandwichMultiply(Jc)); |
5842 | Cc=((my_ds/ds_old)*Q).AddSym(Jc*Cc*Jc.Transpose()); |
5843 | |
5844 | break; |
5845 | } |
5846 | r2_old=r2; |
5847 | ds_old=ds; |
5848 | } |
5849 | |
5850 | return NOERROR; |
5851 | } |
5852 | |
5853 | // Propagate track to point of distance of closest approach to origin |
5854 | jerror_t DTrackFitterKalmanSIMD::ExtrapolateToVertex(DVector2 &xy, |
5855 | DMatrix5x1 &Sc){ |
5856 | // Save un-extroplated quantities |
5857 | DMatrix5x1 S0(Sc); |
5858 | DVector2 xy0(xy); |
5859 | |
5860 | // Initialize the beam position = center of target, and the direction |
5861 | DVector2 origin; |
5862 | DVector2 dir; |
5863 | |
5864 | // Position and step variables |
5865 | DVector2 beam_pos=beam_center+(Sc(state_z)-beam_z0)*beam_dir; |
5866 | double r2=(xy-beam_pos).Mod2(); |
5867 | double ds=-mStepSizeS; // step along path in cm |
5868 | double r2_old=r2; |
5869 | |
5870 | // Energy loss |
5871 | double dedx=0.; |
5872 | |
5873 | // Check direction of propagation |
5874 | DMatrix5x1 S1=Sc; |
5875 | DVector2 xy1=xy; |
5876 | Step(xy1,ds,S1,dedx); |
5877 | beam_pos=beam_center+(S1(state_z)-beam_z0)*beam_dir; |
5878 | r2=(xy1-beam_pos).Mod2(); |
5879 | if (r2>r2_old) ds*=-1.; |
5880 | double ds_old=ds; |
5881 | |
5882 | // Track propagation loop |
5883 | while (Sc(state_z)>Z_MIN-100. && Sc(state_z)<Z_MAX370.0 |
5884 | && r2<R2_MAX4225.0){ |
5885 | // get material properties from the Root Geometry |
5886 | double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0; |
5887 | double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.; |
5888 | DVector3 pos3d(xy.X(),xy.Y(),Sc(state_z)); |
5889 | if (geom->FindMatKalman(pos3d,K_rho_Z_over_A,rho_Z_over_A,LnI,Z, |
5890 | chi2c_factor,chi2a_factor,chi2a_corr, |
5891 | last_material_map) |
5892 | !=NOERROR){ |
5893 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<5893<<" " << "Material error in ExtrapolateToVertex! " << endl; |
5894 | break; |
5895 | } |
5896 | |
5897 | // Get dEdx for the upcoming step |
5898 | double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl))); |
5899 | if (CORRECT_FOR_ELOSS){ |
5900 | dedx=GetdEdx(q_over_p,K_rho_Z_over_A,rho_Z_over_A,LnI,Z); |
5901 | } |
5902 | // Adjust the step size |
5903 | double sign=(ds>0.0)?1.:-1.; |
5904 | if (fabs(dedx)>EPS3.0e-8){ |
5905 | ds=sign*DE_PER_STEP0.001/fabs(dedx); |
5906 | } |
5907 | if(fabs(ds)>mStepSizeS) ds=sign*mStepSizeS; |
5908 | if(fabs(ds)<MIN_STEP_SIZE0.1)ds=sign*MIN_STEP_SIZE0.1; |
5909 | |
5910 | // Propagate the state through the field |
5911 | Step(xy,ds,Sc,dedx); |
5912 | |
5913 | beam_pos=beam_center+(Sc(state_z)-beam_z0)*beam_dir; |
5914 | r2=(xy-beam_pos).Mod2(); |
5915 | //printf("r %f r_old %f \n",r,r_old); |
5916 | if (r2>r2_old) { |
5917 | // We've passed the true minimum; backtrack to find the "vertex" |
5918 | // position |
5919 | double my_ds=0.; |
5920 | BrentsAlgorithm(ds,ds_old,dedx,xy,0.,beam_center,beam_dir,Sc,my_ds); |
5921 | //printf ("Brent min r %f\n",pos.Perp()); |
5922 | break; |
5923 | } |
5924 | r2_old=r2; |
5925 | ds_old=ds; |
5926 | } |
5927 | |
5928 | // If we extrapolate beyond the fiducial volume of the detector before |
5929 | // finding the doca, abandon the extrapolation... |
5930 | if (Sc(state_z)<Z_MIN-100.){ |
5931 | //_DBG_ << "Extrapolated z = " << Sc(state_z) << endl; |
5932 | // Restore un-extrapolated values |
5933 | Sc=S0; |
5934 | xy=xy0; |
5935 | return VALUE_OUT_OF_RANGE; |
5936 | } |
5937 | |
5938 | return NOERROR; |
5939 | } |
5940 | |
5941 | |
5942 | |
5943 | |
5944 | // Transform the 5x5 tracking error matrix into a 7x7 error matrix in cartesian |
5945 | // coordinates |
5946 | shared_ptr<TMatrixFSym> DTrackFitterKalmanSIMD::Get7x7ErrorMatrixForward(DMatrixDSym C){ |
5947 | auto C7x7 = dResourcePool_TMatrixFSym->Get_SharedResource(); |
5948 | C7x7->ResizeTo(7, 7); |
5949 | DMatrix J(7,5); |
5950 | |
5951 | double p=1./fabs(q_over_p_); |
5952 | double tanl=1./sqrt(tx_*tx_+ty_*ty_); |
5953 | double tanl2=tanl*tanl; |
5954 | double lambda=atan(tanl); |
5955 | double sinl=sin(lambda); |
5956 | double sinl3=sinl*sinl*sinl; |
5957 | |
5958 | J(state_X,state_x)=J(state_Y,state_y)=1.; |
5959 | J(state_Pz,state_ty)=-p*ty_*sinl3; |
5960 | J(state_Pz,state_tx)=-p*tx_*sinl3; |
5961 | J(state_Px,state_ty)=J(state_Py,state_tx)=-p*tx_*ty_*sinl3; |
5962 | J(state_Px,state_tx)=p*(1.+ty_*ty_)*sinl3; |
5963 | J(state_Py,state_ty)=p*(1.+tx_*tx_)*sinl3; |
5964 | J(state_Pz,state_q_over_p)=-p*sinl/q_over_p_; |
5965 | J(state_Px,state_q_over_p)=tx_*J(state_Pz,state_q_over_p); |
5966 | J(state_Py,state_q_over_p)=ty_*J(state_Pz,state_q_over_p); |
5967 | J(state_Z,state_x)=-tx_*tanl2; |
5968 | J(state_Z,state_y)=-ty_*tanl2; |
5969 | double diff=tx_*tx_-ty_*ty_; |
5970 | double frac=tanl2*tanl2; |
5971 | J(state_Z,state_tx)=(x_*diff+2.*tx_*ty_*y_)*frac; |
5972 | J(state_Z,state_ty)=(2.*tx_*ty_*x_-y_*diff)*frac; |
5973 | |
5974 | // C'= JCJ^T |
5975 | *C7x7=C.Similarity(J); |
5976 | |
5977 | return C7x7; |
5978 | } |
5979 | |
5980 | |
5981 | |
5982 | // Transform the 5x5 tracking error matrix into a 7x7 error matrix in cartesian |
5983 | // coordinates |
5984 | shared_ptr<TMatrixFSym> DTrackFitterKalmanSIMD::Get7x7ErrorMatrix(DMatrixDSym C){ |
5985 | auto C7x7 = dResourcePool_TMatrixFSym->Get_SharedResource(); |
5986 | C7x7->ResizeTo(7, 7); |
5987 | DMatrix J(7,5); |
5988 | //double cosl=cos(atan(tanl_)); |
5989 | double pt=1./fabs(q_over_pt_); |
5990 | //double p=pt/cosl; |
5991 | // double p_sq=p*p; |
5992 | // double E=sqrt(mass2+p_sq); |
5993 | double pt_sq=1./(q_over_pt_*q_over_pt_); |
5994 | double cosphi=cos(phi_); |
5995 | double sinphi=sin(phi_); |
5996 | double q=(q_over_pt_>0.0)?1.:-1.; |
5997 | |
5998 | J(state_Px,state_q_over_pt)=-q*pt_sq*cosphi; |
5999 | J(state_Px,state_phi)=-pt*sinphi; |
6000 | |
6001 | J(state_Py,state_q_over_pt)=-q*pt_sq*sinphi; |
6002 | J(state_Py,state_phi)=pt*cosphi; |
6003 | |
6004 | J(state_Pz,state_q_over_pt)=-q*pt_sq*tanl_; |
6005 | J(state_Pz,state_tanl)=pt; |
6006 | |
6007 | J(state_X,state_phi)=-D_*cosphi; |
6008 | J(state_X,state_D)=-sinphi; |
6009 | |
6010 | J(state_Y,state_phi)=-D_*sinphi; |
6011 | J(state_Y,state_D)=cosphi; |
6012 | |
6013 | J(state_Z,state_z)=1.; |
6014 | |
6015 | // C'= JCJ^T |
6016 | *C7x7=C.Similarity(J); |
6017 | // C7x7->Print(); |
6018 | // _DBG_ << " " << C7x7->operator()(3,3) << " " << C7x7->operator()(4,4) << endl; |
6019 | |
6020 | return C7x7; |
6021 | } |
6022 | |
6023 | // Track recovery for Central tracks |
6024 | //----------------------------------- |
6025 | // This code attempts to recover tracks that are "broken". Sometimes the fit fails because too many hits were pruned |
6026 | // such that the number of surviving hits is less than the minimum number of degrees of freedom for a five-parameter fit. |
6027 | // This condition is flagged as PRUNED_TOO_MANY_HITS. It may also be the case that even if we used enough hits for the fit to |
6028 | // be valid (i.e., make sense in terms of the number of degrees of freedom for the number of parameters (5) we are trying |
6029 | // to determine), we throw away a number of hits near the target because the projected trajectory deviates too far away from |
6030 | // the actual hits. This may be an indication of a kink in the trajectory. This condition is flagged as BREAK_POINT_FOUND. |
6031 | // Sometimes the fit may succeed and no break point is found, but the pruning threw out a large number of hits. This |
6032 | // condition is flagged as PRUNED_TOO_MANY_HITS. The recovery code proceeds by truncating the reference trajectory to |
6033 | // to a point just after the hit where a break point was found and all hits are ignored beyond this point subject to a |
6034 | // minimum number of hits set by MIN_HITS_FOR_REFIT. The recovery code always attempts to use the hits closest to the |
6035 | // target. The code is allowed to iterate; with each iteration the trajectory and list of useable hits is further truncated. |
6036 | kalman_error_t DTrackFitterKalmanSIMD::RecoverBrokenTracks(double anneal_factor, |
6037 | DMatrix5x1 &S, |
6038 | DMatrix5x5 &C, |
6039 | const DMatrix5x5 &C0, |
6040 | DVector2 &xy, |
6041 | double &chisq, |
6042 | unsigned int &numdof){ |
6043 | if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<6043<<" " << "Attempting to recover broken track ... " <<endl; |
6044 | |
6045 | // Initialize degrees of freedom and chi^2 |
6046 | double refit_chisq=-1.; |
6047 | unsigned int refit_ndf=0; |
6048 | // State vector and covariance matrix |
6049 | DMatrix5x5 C1; |
6050 | DMatrix5x1 S1; |
6051 | // Position vector |
6052 | DVector2 refit_xy; |
6053 | |
6054 | // save the status of the hits used in the fit |
6055 | unsigned int num_hits=cdc_used_in_fit.size(); |
6056 | vector<bool>old_cdc_used_status(num_hits); |
6057 | for (unsigned int j=0;j<num_hits;j++){ |
6058 | old_cdc_used_status[j]=cdc_used_in_fit[j]; |
6059 | } |
6060 | |
6061 | // Truncate the reference trajectory to just beyond the break point (or the minimum number of hits) |
6062 | unsigned int min_cdc_index_for_refit=MIN_HITS_FOR_REFIT-1; |
6063 | //if (break_point_cdc_index<num_hits/2) |
6064 | // break_point_cdc_index=num_hits/2; |
6065 | if (break_point_cdc_index<min_cdc_index_for_refit){ |
6066 | break_point_cdc_index=min_cdc_index_for_refit; |
6067 | } |
6068 | // Next determine where we need to truncate the trajectory |
6069 | DVector2 origin=my_cdchits[break_point_cdc_index]->origin; |
6070 | DVector2 dir=my_cdchits[break_point_cdc_index]->dir; |
6071 | double z0=my_cdchits[break_point_cdc_index]->z0wire; |
6072 | unsigned int k=0; |
6073 | for (k=central_traj.size()-1;k>1;k--){ |
6074 | double r2=central_traj[k].xy.Mod2(); |
6075 | double r2next=central_traj[k-1].xy.Mod2(); |
6076 | double r2_cdc=(origin+(central_traj[k].S(state_z)-z0)*dir).Mod2(); |
6077 | if (r2next>r2 && r2>r2_cdc) break; |
6078 | } |
6079 | break_point_step_index=k; |
6080 | |
6081 | if (break_point_step_index==central_traj.size()-1){ |
6082 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<6082<<" " << "Invalid reference trajectory in track recovery..." << endl; |
6083 | return FIT_FAILED; |
6084 | } |
6085 | |
6086 | kalman_error_t refit_error=FIT_NOT_DONE; |
6087 | unsigned int old_cdc_index=break_point_cdc_index; |
6088 | unsigned int old_step_index=break_point_step_index; |
6089 | unsigned int refit_iter=0; |
6090 | unsigned int num_cdchits=my_cdchits.size(); |
6091 | while (break_point_cdc_index>4 && break_point_step_index>0 |
6092 | && break_point_step_index<central_traj.size()){ |
6093 | refit_iter++; |
6094 | |
6095 | // Flag the cdc hits within the radius of the break point cdc index |
6096 | // as good, the rest as bad. |
6097 | for (unsigned int j=0;j<=break_point_cdc_index;j++){ |
6098 | if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit; |
6099 | } |
6100 | for (unsigned int j=break_point_cdc_index+1;j<num_cdchits;j++){ |
6101 | my_cdchits[j]->status=bad_hit; |
6102 | } |
6103 | |
6104 | // Now refit with the truncated trajectory and list of hits |
6105 | //C1=C0; |
6106 | //C1=4.0*C0; |
6107 | C1=1.0*C0; |
6108 | S1=central_traj[break_point_step_index].S; |
6109 | refit_chisq=-1.; |
6110 | refit_ndf=0; |
6111 | refit_error=KalmanCentral(anneal_factor,S1,C1,refit_xy, |
6112 | refit_chisq,refit_ndf); |
6113 | if (refit_error==FIT_SUCCEEDED |
6114 | || (refit_error==BREAK_POINT_FOUND |
6115 | && break_point_cdc_index==1 |
6116 | ) |
6117 | //|| refit_error==PRUNED_TOO_MANY_HITS |
6118 | ){ |
6119 | C=C1; |
6120 | S=S1; |
6121 | xy=refit_xy; |
6122 | chisq=refit_chisq; |
6123 | numdof=refit_ndf; |
6124 | |
6125 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<6125<<" " << "Fit recovery succeeded..." << endl; |
6126 | return FIT_SUCCEEDED; |
6127 | } |
6128 | |
6129 | break_point_cdc_index=old_cdc_index-refit_iter; |
6130 | break_point_step_index=old_step_index-refit_iter; |
6131 | } |
6132 | |
6133 | // If the refit did not work, restore the old list hits used in the fit |
6134 | // before the track recovery was attempted. |
6135 | for (unsigned int k=0;k<num_hits;k++){ |
6136 | cdc_used_in_fit[k]=old_cdc_used_status[k]; |
6137 | } |
6138 | |
6139 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<6139<<" " << "Fit recovery failed..." << endl; |
6140 | return FIT_FAILED; |
6141 | } |
6142 | |
6143 | // Track recovery for forward tracks |
6144 | //----------------------------------- |
6145 | // This code attempts to recover tracks that are "broken". Sometimes the fit fails because too many hits were pruned |
6146 | // such that the number of surviving hits is less than the minimum number of degrees of freedom for a five-parameter fit. |
6147 | // This condition is flagged as PRUNED_TOO_MANY_HITS. It may also be the case that even if we used enough hits for the fit to |
6148 | // be valid (i.e., make sense in terms of the number of degrees of freedom for the number of parameters (5) we are trying |
6149 | // to determine), we throw away a number of hits near the target because the projected trajectory deviates too far away from |
6150 | // the actual hits. This may be an indication of a kink in the trajectory. This condition is flagged as BREAK_POINT_FOUND. |
6151 | // Sometimes the fit may succeed and no break point is found, but the pruning threw out a large number of hits. This |
6152 | // condition is flagged as PRUNED_TOO_MANY_HITS. The recovery code proceeds by truncating the reference trajectory to |
6153 | // to a point just after the hit where a break point was found and all hits are ignored beyond this point subject to a |
6154 | // minimum number of hits. The recovery code always attempts to use the hits closest to the target. The code is allowed to |
6155 | // iterate; with each iteration the trajectory and list of useable hits is further truncated. |
6156 | kalman_error_t DTrackFitterKalmanSIMD::RecoverBrokenTracks(double anneal_factor, |
6157 | DMatrix5x1 &S, |
6158 | DMatrix5x5 &C, |
6159 | const DMatrix5x5 &C0, |
6160 | double &chisq, |
6161 | unsigned int &numdof |
6162 | ){ |
6163 | if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<6163<<" " << "Attempting to recover broken track ... " <<endl; |
6164 | |
6165 | unsigned int num_cdchits=my_cdchits.size(); |
6166 | unsigned int num_fdchits=my_fdchits.size(); |
6167 | |
6168 | // Initialize degrees of freedom and chi^2 |
6169 | double refit_chisq=-1.; |
6170 | unsigned int refit_ndf=0; |
6171 | // State vector and covariance matrix |
6172 | DMatrix5x5 C1; |
6173 | DMatrix5x1 S1; |
6174 | |
6175 | // save the status of the hits used in the fit |
6176 | vector<bool>old_cdc_used_status(num_cdchits); |
6177 | vector<bool>old_fdc_used_status(num_fdchits); |
6178 | for (unsigned int j=0;j<num_fdchits;j++){ |
6179 | old_fdc_used_status[j]=fdc_used_in_fit[j]; |
6180 | } |
6181 | for (unsigned int j=0;j<num_cdchits;j++){ |
6182 | old_cdc_used_status[j]=cdc_used_in_fit[j]; |
6183 | } |
6184 | |
6185 | unsigned int min_cdc_index=MIN_HITS_FOR_REFIT-1; |
6186 | if (my_fdchits.size()>0){ |
6187 | if (break_point_cdc_index<5){ |
6188 | break_point_cdc_index=0; |
6189 | min_cdc_index=5; |
6190 | } |
6191 | } |
6192 | /*else{ |
6193 | unsigned int half_num_cdchits=num_cdchits/2; |
6194 | if (break_point_cdc_index<half_num_cdchits |
6195 | && half_num_cdchits>min_cdc_index) |
6196 | break_point_cdc_index=half_num_cdchits; |
6197 | } |
6198 | */ |
6199 | if (break_point_cdc_index<min_cdc_index){ |
6200 | break_point_cdc_index=min_cdc_index; |
6201 | } |
6202 | |
6203 | // Find the index at which to truncate the reference trajectory |
6204 | DVector2 origin=my_cdchits[break_point_cdc_index]->origin; |
6205 | DVector2 dir=my_cdchits[break_point_cdc_index]->dir; |
6206 | double z0=my_cdchits[break_point_cdc_index]->z0wire; |
6207 | unsigned int k=forward_traj.size()-1; |
6208 | for (;k>1;k--){ |
6209 | DMatrix5x1 S1=forward_traj[k].S; |
6210 | double x1=S1(state_x); |
6211 | double y1=S1(state_y); |
6212 | double r2=x1*x1+y1*y1; |
6213 | DMatrix5x1 S2=forward_traj[k-1].S; |
6214 | double x2=S2(state_x); |
6215 | double y2=S2(state_y); |
6216 | double r2next=x2*x2+y2*y2; |
6217 | double r2cdc=(origin+(forward_traj[k].z-z0)*dir).Mod2(); |
6218 | |
6219 | if (r2next>r2 && r2>r2cdc) break; |
6220 | } |
6221 | break_point_step_index=k; |
6222 | |
6223 | if (break_point_step_index==forward_traj.size()-1){ |
6224 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<6224<<" " << "Invalid reference trajectory in track recovery..." << endl; |
6225 | return FIT_FAILED; |
6226 | } |
6227 | |
6228 | // Attemp to refit the track using the abreviated list of hits and the truncated |
6229 | // reference trajectory. Iterates if the fit fails. |
6230 | kalman_error_t refit_error=FIT_NOT_DONE; |
6231 | unsigned int old_cdc_index=break_point_cdc_index; |
6232 | unsigned int old_step_index=break_point_step_index; |
6233 | unsigned int refit_iter=0; |
6234 | while (break_point_cdc_index>4 && break_point_step_index>0 |
6235 | && break_point_step_index<forward_traj.size()){ |
6236 | refit_iter++; |
6237 | |
6238 | // Flag the cdc hits within the radius of the break point cdc index |
6239 | // as good, the rest as bad. |
6240 | for (unsigned int j=0;j<=break_point_cdc_index;j++){ |
6241 | if (my_cdchits[j]->status!=late_hit) my_cdchits[j]->status=good_hit; |
6242 | } |
6243 | for (unsigned int j=break_point_cdc_index+1;j<num_cdchits;j++){ |
6244 | my_cdchits[j]->status=bad_hit; |
6245 | } |
6246 | |
6247 | // Re-initialize the state vector, covariance, chisq and number of degrees of freedom |
6248 | //C1=4.0*C0; |
6249 | C1=1.0*C0; |
6250 | S1=forward_traj[break_point_step_index].S; |
6251 | refit_chisq=-1.; |
6252 | refit_ndf=0; |
6253 | // Now refit with the truncated trajectory and list of hits |
6254 | refit_error=KalmanForwardCDC(anneal_factor,S1,C1,refit_chisq,refit_ndf); |
6255 | if (refit_error==FIT_SUCCEEDED |
6256 | || (refit_error==BREAK_POINT_FOUND |
6257 | && break_point_cdc_index==1 |
6258 | ) |
6259 | //|| refit_error==PRUNED_TOO_MANY_HITS |
6260 | ){ |
6261 | C=C1; |
6262 | S=S1; |
6263 | chisq=refit_chisq; |
6264 | numdof=refit_ndf; |
6265 | return FIT_SUCCEEDED; |
6266 | } |
6267 | break_point_cdc_index=old_cdc_index-refit_iter; |
6268 | break_point_step_index=old_step_index-refit_iter; |
6269 | } |
6270 | // If the refit did not work, restore the old list hits used in the fit |
6271 | // before the track recovery was attempted. |
6272 | for (unsigned int k=0;k<num_cdchits;k++){ |
6273 | cdc_used_in_fit[k]=old_cdc_used_status[k]; |
6274 | } |
6275 | for (unsigned int k=0;k<num_fdchits;k++){ |
6276 | fdc_used_in_fit[k]=old_fdc_used_status[k]; |
6277 | } |
6278 | |
6279 | return FIT_FAILED; |
6280 | } |
6281 | |
6282 | |
6283 | // Track recovery for forward-going tracks with hits in the FDC |
6284 | kalman_error_t |
6285 | DTrackFitterKalmanSIMD::RecoverBrokenForwardTracks(double fdc_anneal, |
6286 | double cdc_anneal, |
6287 | DMatrix5x1 &S, |
6288 | DMatrix5x5 &C, |
6289 | const DMatrix5x5 &C0, |
6290 | double &chisq, |
6291 | unsigned int &numdof){ |
6292 | if (DEBUG_LEVEL>1) |
6293 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<6293<<" " << "Attempting to recover broken track ... " <<endl; |
6294 | unsigned int num_cdchits=my_cdchits.size(); |
6295 | unsigned int num_fdchits=fdc_updates.size(); |
6296 | |
6297 | // Initialize degrees of freedom and chi^2 |
6298 | double refit_chisq=-1.; |
6299 | unsigned int refit_ndf=0; |
6300 | // State vector and covariance matrix |
6301 | DMatrix5x5 C1; |
6302 | DMatrix5x1 S1; |
6303 | |
6304 | // save the status of the hits used in the fit |
6305 | vector<int>old_cdc_used_status(num_cdchits); |
6306 | vector<int>old_fdc_used_status(num_fdchits); |
6307 | for (unsigned int j=0;j<num_fdchits;j++){ |
6308 | old_fdc_used_status[j]=fdc_used_in_fit[j]; |
6309 | } |
6310 | for (unsigned int j=0;j<num_cdchits;j++){ |
6311 | old_cdc_used_status[j]=cdc_used_in_fit[j]; |
6312 | } |
6313 | |
6314 | // Truncate the trajectory |
6315 | double zhit=my_fdchits[break_point_fdc_index]->z; |
6316 | unsigned int k=0; |
6317 | for (;k<forward_traj.size();k++){ |
6318 | double z=forward_traj[k].z; |
6319 | if (z<zhit) break; |
6320 | } |
6321 | for (unsigned int j=0;j<=break_point_fdc_index;j++){ |
6322 | my_fdchits[j]->status=good_hit; |
6323 | } |
6324 | for (unsigned int j=break_point_fdc_index+1;j<num_fdchits;j++){ |
6325 | my_fdchits[j]->status=bad_hit; |
6326 | } |
6327 | |
6328 | if (k==forward_traj.size()) return FIT_NOT_DONE; |
6329 | |
6330 | break_point_step_index=k; |
6331 | |
6332 | // Attemp to refit the track using the abreviated list of hits and the truncated |
6333 | // reference trajectory. |
6334 | kalman_error_t refit_error=FIT_NOT_DONE; |
6335 | int refit_iter=0; |
6336 | unsigned int break_id=break_point_fdc_index; |
6337 | while (break_id+num_cdchits>=MIN_HITS_FOR_REFIT && break_id>0 |
6338 | && break_point_step_index<forward_traj.size() |
6339 | && break_point_step_index>1 |
6340 | && refit_iter<10){ |
6341 | refit_iter++; |
6342 | |
6343 | // Mark the hits as bad if they are not included |
6344 | if (break_id >= 0){ |
6345 | for (unsigned int j=0;j<num_cdchits;j++){ |
6346 | if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit; |
6347 | } |
6348 | for (unsigned int j=0;j<=break_id;j++){ |
6349 | my_fdchits[j]->status=good_hit; |
6350 | } |
6351 | for (unsigned int j=break_id+1;j<num_fdchits;j++){ |
6352 | my_fdchits[j]->status=bad_hit; |
6353 | } |
6354 | } |
6355 | else{ |
6356 | // BreakID should always be 0 or positive, so this should never happen, but could be investigated in the future. |
6357 | for (unsigned int j=0;j<num_cdchits+break_id;j++){ |
6358 | if (my_cdchits[j]->status!=late_hit) my_cdchits[j]->status=good_hit; |
6359 | } |
6360 | for (unsigned int j=num_cdchits+break_id;j<num_cdchits;j++){ |
6361 | my_cdchits[j]->status=bad_hit; |
6362 | } |
6363 | for (unsigned int j=0;j<num_fdchits;j++){ |
6364 | my_fdchits[j]->status=bad_hit; |
6365 | } |
6366 | } |
6367 | |
6368 | // Re-initialize the state vector, covariance, chisq and number of degrees of freedom |
6369 | //C1=4.0*C0; |
6370 | C1=1.0*C0; |
6371 | S1=forward_traj[break_point_step_index].S; |
6372 | refit_chisq=-1.; |
6373 | refit_ndf=0; |
6374 | |
6375 | // Now refit with the truncated trajectory and list of hits |
6376 | refit_error=KalmanForward(fdc_anneal,cdc_anneal,S1,C1,refit_chisq,refit_ndf); |
6377 | if (refit_error==FIT_SUCCEEDED |
6378 | //|| (refit_error==PRUNED_TOO_MANY_HITS) |
6379 | ){ |
6380 | C=C1; |
6381 | S=S1; |
6382 | chisq=refit_chisq; |
6383 | numdof=refit_ndf; |
6384 | |
6385 | if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<6385<<" " << "Refit succeeded" << endl; |
6386 | return FIT_SUCCEEDED; |
6387 | } |
6388 | // Truncate the trajectory |
6389 | if (break_id>0) break_id--; |
6390 | else break; |
6391 | zhit=my_fdchits[break_id]->z; |
6392 | k=0; |
6393 | for (;k<forward_traj.size();k++){ |
6394 | double z=forward_traj[k].z; |
6395 | if (z<zhit) break; |
6396 | } |
6397 | break_point_step_index=k; |
6398 | |
6399 | } |
6400 | |
6401 | // If the refit did not work, restore the old list hits used in the fit |
6402 | // before the track recovery was attempted. |
6403 | for (unsigned int k=0;k<num_cdchits;k++){ |
6404 | cdc_used_in_fit[k]=old_cdc_used_status[k]; |
6405 | } |
6406 | for (unsigned int k=0;k<num_fdchits;k++){ |
6407 | fdc_used_in_fit[k]=old_fdc_used_status[k]; |
6408 | } |
6409 | |
6410 | return FIT_FAILED; |
6411 | } |
6412 | |
6413 | |
6414 | |
6415 | // Routine to fit hits in the FDC and the CDC using the forward parametrization |
6416 | kalman_error_t DTrackFitterKalmanSIMD::ForwardFit(const DMatrix5x1 &S0,const DMatrix5x5 &C0){ |
6417 | unsigned int num_cdchits=my_cdchits.size(); |
6418 | unsigned int num_fdchits=my_fdchits.size(); |
6419 | unsigned int max_fdc_index=num_fdchits-1; |
6420 | |
6421 | // Vectors to keep track of updated state vectors and covariance matrices (after |
6422 | // adding the hit information) |
6423 | vector<bool>last_fdc_used_in_fit(num_fdchits); |
6424 | vector<bool>last_cdc_used_in_fit(num_cdchits); |
6425 | vector<pull_t>forward_pulls; |
6426 | vector<pull_t>last_forward_pulls; |
6427 | |
6428 | // Charge |
6429 | // double q=input_params.charge(); |
6430 | |
6431 | // Covariance matrix and state vector |
6432 | DMatrix5x5 C; |
6433 | DMatrix5x1 S=S0; |
6434 | |
6435 | // Create matrices to store results from previous iteration |
6436 | DMatrix5x1 Slast(S); |
6437 | DMatrix5x5 Clast(C0); |
6438 | // last z position |
6439 | double last_z=z_; |
6440 | |
6441 | double fdc_anneal=FORWARD_ANNEAL_SCALE+1.; // variable for scaling cut for hit pruning |
6442 | double cdc_anneal=ANNEAL_SCALE+1.; // variable for scaling cut for hit pruning |
6443 | |
6444 | // Chi-squared and degrees of freedom |
6445 | double chisq=-1.,chisq_forward=-1.; |
6446 | unsigned int my_ndf=0; |
6447 | unsigned int last_ndf=1; |
6448 | kalman_error_t error=FIT_NOT_DONE,last_error=FIT_NOT_DONE; |
6449 | |
6450 | // Iterate over reference trajectories |
6451 | for (int iter=0; |
6452 | iter<(fit_type==kTimeBased?MAX_TB_PASSES20:MAX_WB_PASSES20); |
6453 | iter++) { |
6454 | // These variables provide the approximate location along the trajectory |
6455 | // where there is an indication of a kink in the track |
6456 | break_point_fdc_index=max_fdc_index; |
6457 | break_point_cdc_index=0; |
6458 | break_point_step_index=0; |
6459 | |
6460 | // Reset material map index |
6461 | last_material_map=0; |
6462 | |
6463 | // Abort if momentum is too low |
6464 | if (fabs(S(state_q_over_p))>Q_OVER_P_MAX) break; |
6465 | |
6466 | // Initialize path length variable and flight time |
6467 | len=0; |
6468 | ftime=0.; |
6469 | var_ftime=0.; |
6470 | |
6471 | // Scale cut for pruning hits according to the iteration number |
6472 | fdc_anneal=(iter<MIN_ITER3)?(FORWARD_ANNEAL_SCALE/pow(FORWARD_ANNEAL_POW_CONST,iter)+1.):1.; |
6473 | cdc_anneal=(iter<MIN_ITER3)?(ANNEAL_SCALE/pow(ANNEAL_POW_CONST,iter)+1.):1.; |
6474 | |
6475 | // Swim through the field out to the most upstream FDC hit |
6476 | jerror_t ref_track_error=SetReferenceTrajectory(S); |
6477 | if (ref_track_error!=NOERROR){ |
6478 | if (iter==0) return FIT_FAILED; |
6479 | break; |
6480 | } |
6481 | |
6482 | // Reset the status of the cdc hits |
6483 | for (unsigned int j=0;j<num_cdchits;j++){ |
6484 | if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit; |
6485 | } |
6486 | |
6487 | // perform the kalman filter |
6488 | C=C0; |
6489 | bool did_second_refit=false; |
6490 | error=KalmanForward(fdc_anneal,cdc_anneal,S,C,chisq,my_ndf); |
6491 | if (DEBUG_LEVEL>1){ |
6492 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<6492<<" " << "Iter: " << iter+1 << " Chi2=" << chisq << " Ndf=" << my_ndf << " Error code: " << error << endl; |
6493 | } |
6494 | // Try to recover tracks that failed the first attempt at fitting by |
6495 | // cutting outer hits |
6496 | if (error!=FIT_SUCCEEDED && RECOVER_BROKEN_TRACKS |
6497 | && num_fdchits>2 // some minimum to make this worthwhile... |
6498 | && break_point_fdc_index<num_fdchits |
6499 | && break_point_fdc_index+num_cdchits>=MIN_HITS_FOR_REFIT |
6500 | && forward_traj.size()>2*MIN_HITS_FOR_REFIT // avoid small track stubs |
6501 | ){ |
6502 | DMatrix5x5 Ctemp=C; |
6503 | DMatrix5x1 Stemp=S; |
6504 | unsigned int temp_ndf=my_ndf; |
6505 | double temp_chi2=chisq; |
6506 | double x=x_,y=y_,z=z_; |
6507 | |
6508 | kalman_error_t refit_error=RecoverBrokenForwardTracks(fdc_anneal, |
6509 | cdc_anneal, |
6510 | S,C,C0,chisq, |
6511 | my_ndf); |
6512 | if (fit_type==kTimeBased && refit_error!=FIT_SUCCEEDED){ |
6513 | fdc_anneal=1000.; |
6514 | cdc_anneal=1000.; |
6515 | refit_error=RecoverBrokenForwardTracks(fdc_anneal, |
6516 | cdc_anneal, |
6517 | S,C,C0,chisq, |
6518 | my_ndf); |
6519 | //chisq=1e6; |
6520 | did_second_refit=true; |
6521 | } |
6522 | if (refit_error!=FIT_SUCCEEDED){ |
6523 | if (error==PRUNED_TOO_MANY_HITS || error==BREAK_POINT_FOUND){ |
6524 | C=Ctemp; |
6525 | S=Stemp; |
6526 | my_ndf=temp_ndf; |
6527 | chisq=temp_chi2; |
6528 | x_=x,y_=y,z_=z; |
6529 | |
6530 | if (num_cdchits<6) error=FIT_SUCCEEDED; |
6531 | } |
6532 | else error=FIT_FAILED; |
6533 | } |
6534 | else error=FIT_SUCCEEDED; |
6535 | } |
6536 | if ((error==POSITION_OUT_OF_RANGE || error==MOMENTUM_OUT_OF_RANGE) |
6537 | && iter==0){ |
6538 | return FIT_FAILED; |
6539 | } |
6540 | if (error==FIT_FAILED || error==INVALID_FIT || my_ndf==0){ |
6541 | if (iter==0) return FIT_FAILED; // first iteration failed |
6542 | break; |
6543 | } |
6544 | |
6545 | if (iter>MIN_ITER3 && did_second_refit==false){ |
6546 | double new_reduced_chisq=chisq/my_ndf; |
6547 | double old_reduced_chisq=chisq_forward/last_ndf; |
6548 | double new_prob=TMath::Prob(chisq,my_ndf); |
6549 | double old_prob=TMath::Prob(chisq_forward,last_ndf); |
6550 | if (new_prob<old_prob |
6551 | || fabs(new_reduced_chisq-old_reduced_chisq)<CHISQ_DELTA0.01){ |
6552 | break; |
6553 | } |
6554 | } |
6555 | |
6556 | chisq_forward=chisq; |
6557 | last_ndf=my_ndf; |
6558 | last_error=error; |
6559 | Slast=S; |
6560 | Clast=C; |
6561 | last_z=z_; |
6562 | |
6563 | last_fdc_used_in_fit=fdc_used_in_fit; |
6564 | last_cdc_used_in_fit=cdc_used_in_fit; |
6565 | } //iteration |
6566 | |
6567 | IsSmoothed=false; |
6568 | if(fit_type==kTimeBased){ |
6569 | forward_pulls.clear(); |
6570 | if (SmoothForward(forward_pulls) == NOERROR){ |
6571 | IsSmoothed = true; |
6572 | pulls.assign(forward_pulls.begin(),forward_pulls.end()); |
6573 | } |
6574 | } |
6575 | |
6576 | // total chisq and ndf |
6577 | chisq_=chisq_forward; |
6578 | ndf_=last_ndf; |
6579 | |
6580 | // output lists of hits used in the fit and fill pull vector |
6581 | cdchits_used_in_fit.clear(); |
6582 | for (unsigned int m=0;m<last_cdc_used_in_fit.size();m++){ |
6583 | if (last_cdc_used_in_fit[m]){ |
6584 | cdchits_used_in_fit.push_back(my_cdchits[m]->hit); |
6585 | } |
6586 | } |
6587 | fdchits_used_in_fit.clear(); |
6588 | for (unsigned int m=0;m<last_fdc_used_in_fit.size();m++){ |
6589 | if (last_fdc_used_in_fit[m] && my_fdchits[m]->hit!=NULL__null){ |
6590 | fdchits_used_in_fit.push_back(my_fdchits[m]->hit); |
6591 | } |
6592 | } |
6593 | // fill pull vector |
6594 | //pulls.assign(last_forward_pulls.begin(),last_forward_pulls.end()); |
6595 | |
6596 | // fill vector of extrapolations |
6597 | ClearExtrapolations(); |
6598 | if (forward_traj.size()>1){ |
6599 | ExtrapolateToInnerDetectors(); |
6600 | if (fit_type==kTimeBased){ |
6601 | double reverse_chisq=1e16,reverse_chisq_old=1e16; |
6602 | unsigned int reverse_ndf=0,reverse_ndf_old=0; |
6603 | |
6604 | // Run the Kalman filter in the reverse direction, to get the best guess |
6605 | // for the state vector at the last FDC point on the track |
6606 | DMatrix5x5 CReverse=C; |
6607 | DMatrix5x1 SReverse=S,SDownstream,SBest; |
6608 | kalman_error_t reverse_error=FIT_NOT_DONE; |
6609 | for (int iter=0;iter<20;iter++){ |
6610 | reverse_chisq_old=reverse_chisq; |
6611 | reverse_ndf_old=reverse_ndf; |
6612 | SBest=SDownstream; |
6613 | reverse_error=KalmanReverse(fdc_anneal,cdc_anneal,SReverse,CReverse, |
6614 | SDownstream,reverse_chisq,reverse_ndf); |
6615 | if (reverse_error!=FIT_SUCCEEDED) break; |
6616 | |
6617 | SReverse=SDownstream; |
6618 | for (unsigned int k=0;k<forward_traj.size()-1;k++){ |
6619 | // Get dEdx for the upcoming step |
6620 | double dEdx=0.; |
6621 | if (CORRECT_FOR_ELOSS){ |
6622 | dEdx=GetdEdx(SReverse(state_q_over_p), |
6623 | forward_traj[k].K_rho_Z_over_A, |
6624 | forward_traj[k].rho_Z_over_A, |
6625 | forward_traj[k].LnI,forward_traj[k].Z); |
6626 | } |
6627 | // Step through field |
6628 | DMatrix5x5 J; |
6629 | double z=forward_traj[k].z; |
6630 | double newz=forward_traj[k+1].z; |
6631 | StepJacobian(z,newz,SReverse,dEdx,J); |
6632 | Step(z,newz,dEdx,SReverse); |
6633 | |
6634 | CReverse=forward_traj[k].Q.AddSym(J*CReverse*J.Transpose()); |
6635 | } |
6636 | |
6637 | double reduced_chisq=reverse_chisq/double(reverse_ndf); |
6638 | double reduced_chisq_old=reverse_chisq_old/double(reverse_ndf_old); |
6639 | if (reduced_chisq>reduced_chisq_old |
6640 | || fabs(reduced_chisq-reduced_chisq_old)<0.01) break; |
6641 | } |
6642 | |
6643 | if (reverse_error!=FIT_SUCCEEDED){ |
6644 | ExtrapolateToOuterDetectors(forward_traj[0].S); |
6645 | } |
6646 | else{ |
6647 | ExtrapolateToOuterDetectors(SBest); |
6648 | } |
6649 | } |
6650 | else{ |
6651 | ExtrapolateToOuterDetectors(forward_traj[0].S); |
6652 | } |
6653 | if (extrapolations.at(SYS_BCAL).size()==1){ |
6654 | // There needs to be some steps inside the the volume of the BCAL for |
6655 | // the extrapolation to be useful. If this is not the case, clear |
6656 | // the extrolation vector. |
6657 | extrapolations[SYS_BCAL].clear(); |
6658 | } |
6659 | } |
6660 | // Extrapolate to the point of closest approach to the beam line |
6661 | z_=last_z; |
6662 | DVector2 beam_pos=beam_center+(z_-beam_z0)*beam_dir; |
6663 | double dx=Slast(state_x)-beam_pos.X(); |
6664 | double dy=Slast(state_y)-beam_pos.Y(); |
6665 | bool extrapolated=false; |
6666 | if (sqrt(dx*dx+dy*dy)>EPS21.e-4){ |
6667 | DMatrix5x5 Ctemp=Clast; |
6668 | DMatrix5x1 Stemp=Slast; |
6669 | double ztemp=z_; |
6670 | if (ExtrapolateToVertex(Stemp,Ctemp)==NOERROR){ |
6671 | Clast=Ctemp; |
6672 | Slast=Stemp; |
6673 | extrapolated=true; |
6674 | } |
6675 | else{ |
6676 | //_DBG_ << endl; |
6677 | z_=ztemp; |
6678 | } |
6679 | } |
6680 | |
6681 | // Final momentum, positions and tangents |
6682 | x_=Slast(state_x), y_=Slast(state_y); |
6683 | tx_=Slast(state_tx),ty_=Slast(state_ty); |
6684 | q_over_p_=Slast(state_q_over_p); |
6685 | |
6686 | // Convert from forward rep. to central rep. |
6687 | double tsquare=tx_*tx_+ty_*ty_; |
6688 | tanl_=1./sqrt(tsquare); |
6689 | double cosl=cos(atan(tanl_)); |
6690 | q_over_pt_=q_over_p_/cosl; |
6691 | phi_=atan2(ty_,tx_); |
6692 | if (FORWARD_PARMS_COV==false){ |
6693 | if (extrapolated){ |
6694 | beam_pos=beam_center+(z_-beam_z0)*beam_dir; |
6695 | dx=x_-beam_pos.X(); |
6696 | dy=y_-beam_pos.Y(); |
6697 | } |
6698 | D_=sqrt(dx*dx+dy*dy)+EPS3.0e-8; |
6699 | x_ = dx; y_ = dy; |
6700 | double cosphi=cos(phi_); |
6701 | double sinphi=sin(phi_); |
6702 | if ((dx>0.0 && sinphi>0.0) || (dy<0.0 && cosphi>0.0) |
6703 | || (dy>0.0 && cosphi<0.0) || (dx<0.0 && sinphi<0.0)) D_*=-1.; |
6704 | TransformCovariance(Clast); |
6705 | } |
6706 | // Covariance matrix |
6707 | vector<double>dummy; |
6708 | for (unsigned int i=0;i<5;i++){ |
6709 | dummy.clear(); |
6710 | for(unsigned int j=0;j<5;j++){ |
6711 | dummy.push_back(Clast(i,j)); |
6712 | } |
6713 | fcov.push_back(dummy); |
6714 | } |
6715 | |
6716 | return last_error; |
6717 | } |
6718 | |
6719 | // Routine to fit hits in the CDC using the forward parametrization |
6720 | kalman_error_t DTrackFitterKalmanSIMD::ForwardCDCFit(const DMatrix5x1 &S0,const DMatrix5x5 &C0){ |
6721 | unsigned int num_cdchits=my_cdchits.size(); |
6722 | unsigned int max_cdc_index=num_cdchits-1; |
6723 | unsigned int min_cdc_index_for_refit=MIN_HITS_FOR_REFIT-1; |
6724 | |
6725 | // Charge |
6726 | // double q=input_params.charge(); |
6727 | |
6728 | // Covariance matrix and state vector |
6729 | DMatrix5x5 C; |
6730 | DMatrix5x1 S=S0; |
6731 | |
6732 | // Create matrices to store results from previous iteration |
6733 | DMatrix5x1 Slast(S); |
6734 | DMatrix5x5 Clast(C0); |
6735 | |
6736 | // Vectors to keep track of updated state vectors and covariance matrices (after |
6737 | // adding the hit information) |
6738 | vector<pull_t>cdc_pulls; |
6739 | vector<pull_t>last_cdc_pulls; |
6740 | vector<bool>last_cdc_used_in_fit; |
6741 | |
6742 | double anneal_factor=ANNEAL_SCALE+1.; |
6743 | kalman_error_t error=FIT_NOT_DONE,last_error=FIT_NOT_DONE; |
6744 | |
6745 | // Chi-squared and degrees of freedom |
6746 | double chisq=-1.,chisq_forward=-1.; |
6747 | unsigned int my_ndf=0; |
6748 | unsigned int last_ndf=1; |
6749 | // last z position |
6750 | double zlast=0.; |
6751 | // unsigned int last_break_point_index=0,last_break_point_step_index=0; |
6752 | |
6753 | // Iterate over reference trajectories |
6754 | for (int iter2=0; |
6755 | iter2<(fit_type==kTimeBased?MAX_TB_PASSES20:MAX_WB_PASSES20); |
6756 | iter2++){ |
6757 | if (DEBUG_LEVEL>1){ |
6758 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<6758<<" " <<"-------- iteration " << iter2+1 << " -----------" <<endl; |
6759 | } |
6760 | |
6761 | // These variables provide the approximate location along the trajectory |
6762 | // where there is an indication of a kink in the track |
6763 | break_point_cdc_index=max_cdc_index; |
6764 | break_point_step_index=0; |
6765 | |
6766 | // Reset material map index |
6767 | last_material_map=0; |
6768 | |
6769 | // Abort if momentum is too low |
6770 | if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){ |
6771 | //printf("Too low momentum? %f\n",1/S(state_q_over_p)); |
6772 | break; |
6773 | } |
6774 | |
6775 | // Scale cut for pruning hits according to the iteration number |
6776 | anneal_factor=(iter2<MIN_ITER3)?(ANNEAL_SCALE/pow(ANNEAL_POW_CONST,iter2)+1.):1.; |
6777 | |
6778 | // Initialize path length variable and flight time |
6779 | len=0; |
6780 | ftime=0.; |
6781 | var_ftime=0.; |
6782 | |
6783 | // Swim to create the reference trajectory |
6784 | jerror_t ref_track_error=SetCDCForwardReferenceTrajectory(S); |
6785 | if (ref_track_error!=NOERROR){ |
6786 | if (iter2==0) return FIT_FAILED; |
6787 | break; |
6788 | } |
6789 | |
6790 | // Reset the status of the cdc hits |
6791 | for (unsigned int j=0;j<num_cdchits;j++){ |
6792 | if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit; |
6793 | } |
6794 | |
6795 | // perform the filter |
6796 | C=C0; |
6797 | bool did_second_refit=false; |
6798 | error=KalmanForwardCDC(anneal_factor,S,C,chisq,my_ndf); |
6799 | |
6800 | // Try to recover tracks that failed the first attempt at fitting by |
6801 | // cutting outer hits |
6802 | if (error!=FIT_SUCCEEDED && RECOVER_BROKEN_TRACKS |
6803 | && num_cdchits>=MIN_HITS_FOR_REFIT){ |
6804 | DMatrix5x5 Ctemp=C; |
6805 | DMatrix5x1 Stemp=S; |
6806 | unsigned int temp_ndf=my_ndf; |
6807 | double temp_chi2=chisq; |
6808 | double x=x_,y=y_,z=z_; |
6809 | |
6810 | if (error==MOMENTUM_OUT_OF_RANGE){ |
6811 | //_DBG_ << "Momentum out of range" <<endl; |
6812 | unsigned int new_index=(3*max_cdc_index)/4; |
6813 | break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit; |
6814 | } |
6815 | |
6816 | if (error==BROKEN_COVARIANCE_MATRIX){ |
6817 | break_point_cdc_index=min_cdc_index_for_refit; |
6818 | //_DBG_ << "Bad Cov" <<endl; |
6819 | } |
6820 | if (error==POSITION_OUT_OF_RANGE){ |
6821 | //_DBG_ << "Bad position" << endl; |
6822 | unsigned int new_index=(max_cdc_index)/2; |
6823 | break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit; |
6824 | } |
6825 | if (error==PRUNED_TOO_MANY_HITS){ |
6826 | // _DBG_ << "Prune" << endl; |
6827 | unsigned int new_index=(3*max_cdc_index)/4; |
6828 | break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit; |
6829 | // anneal_factor*=10.; |
6830 | } |
6831 | |
6832 | kalman_error_t refit_error=RecoverBrokenTracks(anneal_factor,S,C,C0,chisq,my_ndf); |
6833 | if (fit_type==kTimeBased && refit_error!=FIT_SUCCEEDED){ |
6834 | anneal_factor=1000.; |
6835 | refit_error=RecoverBrokenTracks(anneal_factor,S,C,C0,chisq,my_ndf); |
6836 | //chisq=1e6; |
6837 | did_second_refit=true; |
6838 | } |
6839 | |
6840 | if (refit_error!=FIT_SUCCEEDED){ |
6841 | if (error==PRUNED_TOO_MANY_HITS || error==BREAK_POINT_FOUND){ |
6842 | C=Ctemp; |
6843 | S=Stemp; |
6844 | my_ndf=temp_ndf; |
6845 | chisq=temp_chi2; |
6846 | x_=x,y_=y,z_=z; |
6847 | |
6848 | // error=FIT_SUCCEEDED; |
6849 | } |
6850 | else error=FIT_FAILED; |
6851 | } |
6852 | else error=FIT_SUCCEEDED; |
6853 | } |
6854 | if ((error==POSITION_OUT_OF_RANGE || error==MOMENTUM_OUT_OF_RANGE) |
6855 | && iter2==0){ |
6856 | return FIT_FAILED; |
6857 | } |
6858 | if (error==FIT_FAILED || error==INVALID_FIT || my_ndf==0){ |
6859 | if (iter2==0) return error; |
6860 | break; |
6861 | } |
6862 | |
6863 | if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<6863<<" " << "--> Chisq " << chisq << " NDF " |
6864 | << my_ndf |
6865 | << " Prob: " << TMath::Prob(chisq,my_ndf) |
6866 | << endl; |
6867 | |
6868 | if (iter2>MIN_ITER3 && did_second_refit==false){ |
6869 | double new_reduced_chisq=chisq/my_ndf; |
6870 | double old_reduced_chisq=chisq_forward/last_ndf; |
6871 | double new_prob=TMath::Prob(chisq,my_ndf); |
6872 | double old_prob=TMath::Prob(chisq_forward,last_ndf); |
6873 | if (new_prob<old_prob |
6874 | || fabs(new_reduced_chisq-old_reduced_chisq)<CHISQ_DELTA0.01) break; |
6875 | } |
6876 | |
6877 | chisq_forward=chisq; |
6878 | Slast=S; |
6879 | Clast=C; |
6880 | last_error=error; |
6881 | last_ndf=my_ndf; |
6882 | zlast=z_; |
6883 | |
6884 | last_cdc_used_in_fit=cdc_used_in_fit; |
6885 | } //iteration |
6886 | |
6887 | // Run the smoother |
6888 | IsSmoothed=false; |
6889 | if(fit_type==kTimeBased){ |
6890 | cdc_pulls.clear(); |
6891 | if (SmoothForwardCDC(cdc_pulls) == NOERROR){ |
6892 | IsSmoothed = true; |
6893 | pulls.assign(cdc_pulls.begin(),cdc_pulls.end()); |
6894 | } |
6895 | } |
6896 | |
6897 | // total chisq and ndf |
6898 | chisq_=chisq_forward; |
6899 | ndf_=last_ndf; |
6900 | |
6901 | // output lists of hits used in the fit and fill the pull vector |
6902 | cdchits_used_in_fit.clear(); |
6903 | for (unsigned int m=0;m<last_cdc_used_in_fit.size();m++){ |
6904 | if (last_cdc_used_in_fit[m]){ |
6905 | cdchits_used_in_fit.push_back(my_cdchits[m]->hit); |
6906 | } |
6907 | } |
6908 | // output pulls vector |
6909 | //pulls.assign(last_cdc_pulls.begin(),last_cdc_pulls.end()); |
6910 | |
6911 | // Fill extrapolation vector |
6912 | ClearExtrapolations(); |
6913 | if (forward_traj.size()>1){ |
6914 | if (fit_type==kWireBased){ |
6915 | ExtrapolateForwardToOtherDetectors(); |
6916 | } |
6917 | else{ |
6918 | ExtrapolateToInnerDetectors(); |
6919 | |
6920 | double reverse_chisq=1e16,reverse_chisq_old=1e16; |
6921 | unsigned int reverse_ndf=0,reverse_ndf_old=0; |
6922 | |
6923 | // Run the Kalman filter in the reverse direction, to get the best guess |
6924 | // for the state vector at the last FDC point on the track |
6925 | DMatrix5x5 CReverse=C; |
6926 | DMatrix5x1 SReverse=S,SDownstream,SBest; |
6927 | kalman_error_t reverse_error=FIT_NOT_DONE; |
6928 | for (int iter=0;iter<20;iter++){ |
6929 | reverse_chisq_old=reverse_chisq; |
6930 | reverse_ndf_old=reverse_ndf; |
6931 | SBest=SDownstream; |
6932 | reverse_error=KalmanReverse(0.,anneal_factor,SReverse,CReverse, |
6933 | SDownstream,reverse_chisq,reverse_ndf); |
6934 | if (reverse_error!=FIT_SUCCEEDED) break; |
6935 | |
6936 | SReverse=SDownstream; |
6937 | for (unsigned int k=0;k<forward_traj.size()-1;k++){ |
6938 | // Get dEdx for the upcoming step |
6939 | double dEdx=0.; |
6940 | if (CORRECT_FOR_ELOSS){ |
6941 | dEdx=GetdEdx(SReverse(state_q_over_p), |
6942 | forward_traj[k].K_rho_Z_over_A, |
6943 | forward_traj[k].rho_Z_over_A, |
6944 | forward_traj[k].LnI,forward_traj[k].Z); |
6945 | } |
6946 | // Step through field |
6947 | DMatrix5x5 J; |
6948 | double z=forward_traj[k].z; |
6949 | double newz=forward_traj[k+1].z; |
6950 | StepJacobian(z,newz,SReverse,dEdx,J); |
6951 | Step(z,newz,dEdx,SReverse); |
6952 | |
6953 | CReverse=forward_traj[k].Q.AddSym(J*CReverse*J.Transpose()); |
6954 | } |
6955 | |
6956 | double reduced_chisq=reverse_chisq/double(reverse_ndf); |
6957 | double reduced_chisq_old=reverse_chisq_old/double(reverse_ndf_old); |
6958 | if (reduced_chisq>reduced_chisq_old |
6959 | || fabs(reduced_chisq-reduced_chisq_old)<0.01) break; |
6960 | } |
6961 | if (reverse_error!=FIT_SUCCEEDED){ |
6962 | ExtrapolateToOuterDetectors(forward_traj[0].S); |
6963 | } |
6964 | else{ |
6965 | ExtrapolateToOuterDetectors(SBest); |
6966 | } |
6967 | } |
6968 | } |
6969 | if (extrapolations.at(SYS_BCAL).size()==1){ |
6970 | // There needs to be some steps inside the the volume of the BCAL for |
6971 | // the extrapolation to be useful. If this is not the case, clear |
6972 | // the extrolation vector. |
6973 | extrapolations[SYS_BCAL].clear(); |
6974 | } |
6975 | |
6976 | // Extrapolate to the point of closest approach to the beam line |
6977 | z_=zlast; |
6978 | DVector2 beam_pos=beam_center+(z_-beam_z0)*beam_dir; |
6979 | double dx=Slast(state_x)-beam_pos.X(); |
6980 | double dy=Slast(state_y)-beam_pos.Y(); |
6981 | bool extrapolated=false; |
6982 | if (sqrt(dx*dx+dy*dy)>EPS21.e-4){ |
6983 | if (ExtrapolateToVertex(Slast,Clast)!=NOERROR) return EXTRAPOLATION_FAILED; |
6984 | extrapolated=true; |
6985 | } |
6986 | |
6987 | // Final momentum, positions and tangents |
6988 | x_=Slast(state_x), y_=Slast(state_y); |
6989 | tx_=Slast(state_tx),ty_=Slast(state_ty); |
6990 | q_over_p_=Slast(state_q_over_p); |
6991 | |
6992 | // Convert from forward rep. to central rep. |
6993 | double tsquare=tx_*tx_+ty_*ty_; |
6994 | tanl_=1./sqrt(tsquare); |
6995 | double cosl=cos(atan(tanl_)); |
6996 | q_over_pt_=q_over_p_/cosl; |
6997 | phi_=atan2(ty_,tx_); |
6998 | if (FORWARD_PARMS_COV==false){ |
6999 | if (extrapolated){ |
7000 | beam_pos=beam_center+(z_-beam_z0)*beam_dir; |
7001 | dx=x_-beam_pos.X(); |
7002 | dy=y_-beam_pos.Y(); |
7003 | } |
7004 | D_=sqrt(dx*dx+dy*dy)+EPS3.0e-8; |
7005 | x_ = dx; y_ = dy; |
7006 | double cosphi=cos(phi_); |
7007 | double sinphi=sin(phi_); |
7008 | if ((dx>0.0 && sinphi>0.0) || (dy<0.0 && cosphi>0.0) |
7009 | || (dy>0.0 && cosphi<0.0) || (dx<0.0 && sinphi<0.0)) D_*=-1.; |
7010 | TransformCovariance(Clast); |
7011 | } |
7012 | // Covariance matrix |
7013 | vector<double>dummy; |
7014 | // ... forward parameterization |
7015 | fcov.clear(); |
7016 | for (unsigned int i=0;i<5;i++){ |
7017 | dummy.clear(); |
7018 | for(unsigned int j=0;j<5;j++){ |
7019 | dummy.push_back(Clast(i,j)); |
7020 | } |
7021 | fcov.push_back(dummy); |
7022 | } |
7023 | |
7024 | return last_error; |
7025 | } |
7026 | |
7027 | // Routine to fit hits in the CDC using the central parametrization |
7028 | kalman_error_t DTrackFitterKalmanSIMD::CentralFit(const DVector2 &startpos, |
7029 | const DMatrix5x1 &S0, |
7030 | const DMatrix5x5 &C0){ |
7031 | // Initial position in x and y |
7032 | DVector2 pos(startpos); |
7033 | |
7034 | // Charge |
7035 | // double q=input_params.charge(); |
7036 | |
7037 | // Covariance matrix and state vector |
7038 | DMatrix5x5 Cc; |
7039 | DMatrix5x1 Sc=S0; |
7040 | |
7041 | // Variables to store values from previous iterations |
7042 | DMatrix5x1 Sclast(Sc); |
7043 | DMatrix5x5 Cclast(C0); |
7044 | DVector2 last_pos=pos; |
7045 | |
7046 | unsigned int num_cdchits=my_cdchits.size(); |
7047 | unsigned int max_cdc_index=num_cdchits-1; |
7048 | unsigned int min_cdc_index_for_refit=MIN_HITS_FOR_REFIT-1; |
7049 | |
7050 | // Vectors to keep track of updated state vectors and covariance matrices (after |
7051 | // adding the hit information) |
7052 | vector<pull_t>last_cdc_pulls; |
7053 | vector<pull_t>cdc_pulls; |
7054 | vector<bool>last_cdc_used_in_fit(num_cdchits); |
7055 | |
7056 | double anneal_factor=ANNEAL_SCALE+1.; // variable for scaling cut for hit pruning |
7057 | |
7058 | //Initialization of chisq, ndf, and error status |
7059 | double chisq_iter=-1.,chisq=-1.; |
7060 | unsigned int my_ndf=0; |
7061 | ndf_=0.; |
7062 | unsigned int last_ndf=1; |
7063 | kalman_error_t error=FIT_NOT_DONE,last_error=FIT_NOT_DONE; |
7064 | |
7065 | // Iterate over reference trajectories |
7066 | int iter2=0; |
7067 | for (;iter2<(fit_type==kTimeBased?MAX_TB_PASSES20:MAX_WB_PASSES20); |
7068 | iter2++){ |
7069 | if (DEBUG_LEVEL>1){ |
7070 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7070<<" " <<"-------- iteration " << iter2+1 << " -----------" <<endl; |
7071 | } |
7072 | |
7073 | // These variables provide the approximate location along the trajectory |
7074 | // where there is an indication of a kink in the track |
7075 | break_point_cdc_index=max_cdc_index; |
7076 | break_point_step_index=0; |
7077 | |
7078 | // Reset material map index |
7079 | last_material_map=0; |
7080 | |
7081 | // Break out of loop if p is too small |
7082 | double q_over_p=Sc(state_q_over_pt)*cos(atan(Sc(state_tanl))); |
7083 | if (fabs(q_over_p)>Q_OVER_P_MAX) break; |
7084 | |
7085 | // Initialize path length variable and flight time |
7086 | len=0.; |
7087 | ftime=0.; |
7088 | var_ftime=0.; |
7089 | |
7090 | // Scale cut for pruning hits according to the iteration number |
7091 | anneal_factor=(iter2<MIN_ITER3)?(ANNEAL_SCALE/pow(ANNEAL_POW_CONST,iter2)+1.):1.; |
7092 | |
7093 | // Initialize trajectory deque |
7094 | jerror_t ref_track_error=SetCDCReferenceTrajectory(last_pos,Sc); |
7095 | if (ref_track_error!=NOERROR){ |
7096 | if (iter2==0) return FIT_FAILED; |
7097 | break; |
7098 | } |
7099 | |
7100 | // Reset the status of the cdc hits |
7101 | for (unsigned int j=0;j<num_cdchits;j++){ |
7102 | if (my_cdchits[j]->status!=late_hit)my_cdchits[j]->status=good_hit; |
7103 | } |
7104 | |
7105 | // perform the fit |
7106 | Cc=C0; |
7107 | bool did_second_refit=false; |
7108 | error=KalmanCentral(anneal_factor,Sc,Cc,pos,chisq,my_ndf); |
7109 | |
7110 | // Try to recover tracks that failed the first attempt at fitting by |
7111 | // throwing away outer hits. |
7112 | if (error!=FIT_SUCCEEDED && RECOVER_BROKEN_TRACKS |
7113 | && num_cdchits>=MIN_HITS_FOR_REFIT){ |
7114 | DVector2 temp_pos=pos; |
7115 | DMatrix5x1 Stemp=Sc; |
7116 | DMatrix5x5 Ctemp=Cc; |
7117 | unsigned int temp_ndf=my_ndf; |
7118 | double temp_chi2=chisq; |
7119 | |
7120 | if (error==MOMENTUM_OUT_OF_RANGE){ |
7121 | //_DBG_ << "Momentum out of range" <<endl; |
7122 | unsigned int new_index=(3*max_cdc_index)/4; |
7123 | break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit; |
7124 | } |
7125 | |
7126 | if (error==BROKEN_COVARIANCE_MATRIX){ |
7127 | break_point_cdc_index=min_cdc_index_for_refit; |
7128 | //_DBG_ << "Bad Cov" <<endl; |
7129 | } |
7130 | if (error==POSITION_OUT_OF_RANGE){ |
7131 | //_DBG_ << "Bad position" << endl; |
7132 | unsigned int new_index=(max_cdc_index)/2; |
7133 | break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit; |
7134 | } |
7135 | if (error==PRUNED_TOO_MANY_HITS){ |
7136 | unsigned int new_index=(3*max_cdc_index)/4; |
7137 | break_point_cdc_index=(new_index>min_cdc_index_for_refit)?new_index:min_cdc_index_for_refit; |
7138 | //anneal_factor*=10.; |
7139 | //_DBG_ << "Prune" << endl; |
7140 | } |
7141 | |
7142 | kalman_error_t refit_error=RecoverBrokenTracks(anneal_factor,Sc,Cc,C0,pos,chisq,my_ndf); |
7143 | if (fit_type==kTimeBased && refit_error!=FIT_SUCCEEDED){ |
7144 | anneal_factor=1000.; |
7145 | refit_error=RecoverBrokenTracks(anneal_factor,Sc,Cc,C0,pos,chisq,my_ndf); |
7146 | //chisq=1e6; |
7147 | did_second_refit=true; |
7148 | } |
7149 | |
7150 | if (refit_error!=FIT_SUCCEEDED){ |
7151 | //_DBG_ << error << endl; |
7152 | if (error==PRUNED_TOO_MANY_HITS || error==BREAK_POINT_FOUND){ |
7153 | Cc=Ctemp; |
7154 | Sc=Stemp; |
7155 | my_ndf=temp_ndf; |
7156 | chisq=temp_chi2; |
7157 | pos=temp_pos; |
7158 | if (DEBUG_LEVEL > 1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7158<<" " << " Refit did not succeed, but restoring old values" << endl; |
7159 | |
7160 | //error=FIT_SUCCEEDED; |
7161 | } |
7162 | } |
7163 | else error=FIT_SUCCEEDED; |
7164 | } |
7165 | if ((error==POSITION_OUT_OF_RANGE || error==MOMENTUM_OUT_OF_RANGE) |
7166 | && iter2==0){ |
7167 | return FIT_FAILED; |
7168 | } |
7169 | if (error==FIT_FAILED || error==INVALID_FIT || my_ndf==0){ |
7170 | if (iter2==0) return error; |
7171 | break; |
7172 | } |
7173 | |
7174 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7174<<" " << "--> Chisq " << chisq << " Ndof " << my_ndf |
7175 | << " Prob: " << TMath::Prob(chisq,my_ndf) |
7176 | << endl; |
7177 | |
7178 | if (iter2>MIN_ITER3 && did_second_refit==false){ |
7179 | double new_reduced_chisq=chisq/my_ndf; |
7180 | double old_reduced_chisq=chisq_iter/last_ndf; |
7181 | double new_prob=TMath::Prob(chisq,my_ndf); |
7182 | double old_prob=TMath::Prob(chisq_iter,last_ndf); |
7183 | if (new_prob<old_prob |
7184 | || fabs(new_reduced_chisq-old_reduced_chisq)<CHISQ_DELTA0.01) break; |
7185 | } |
7186 | |
7187 | // Save the current state vector and covariance matrix |
7188 | Cclast=Cc; |
7189 | Sclast=Sc; |
7190 | last_pos=pos; |
7191 | chisq_iter=chisq; |
7192 | last_ndf=my_ndf; |
7193 | last_error=error; |
7194 | |
7195 | last_cdc_used_in_fit=cdc_used_in_fit; |
7196 | } |
7197 | |
7198 | // Run smoother and fill pulls vector |
7199 | IsSmoothed=false; |
7200 | if(fit_type==kTimeBased){ |
7201 | cdc_pulls.clear(); |
7202 | if (SmoothCentral(cdc_pulls) == NOERROR){ |
7203 | IsSmoothed = true; |
7204 | pulls.assign(cdc_pulls.begin(),cdc_pulls.end()); |
7205 | } |
7206 | } |
7207 | |
7208 | // Fill extrapolations vector |
7209 | ClearExtrapolations(); |
7210 | ExtrapolateCentralToOtherDetectors(); |
7211 | if (extrapolations.at(SYS_BCAL).size()==1){ |
7212 | // There needs to be some steps inside the the volume of the BCAL for |
7213 | // the extrapolation to be useful. If this is not the case, clear |
7214 | // the extrolation vector. |
7215 | extrapolations[SYS_BCAL].clear(); |
7216 | } |
7217 | |
7218 | // Extrapolate to the point of closest approach to the beam line |
7219 | DVector2 beam_pos=beam_center+(Sclast(state_z)-beam_z0)*beam_dir; |
7220 | bool extrapolated=false; |
7221 | if ((last_pos-beam_pos).Mod()>EPS21.e-4){ // in cm |
7222 | if (ExtrapolateToVertex(last_pos,Sclast,Cclast)!=NOERROR) return EXTRAPOLATION_FAILED; |
7223 | extrapolated=true; |
7224 | } |
7225 | |
7226 | // output lists of hits used in the fit |
7227 | cdchits_used_in_fit.clear(); |
7228 | for (unsigned int m=0;m<last_cdc_used_in_fit.size();m++){ |
7229 | if (last_cdc_used_in_fit[m]){ |
7230 | cdchits_used_in_fit.push_back(my_cdchits[m]->hit); |
7231 | } |
7232 | } |
7233 | // output the pull information |
7234 | //pulls.assign(last_cdc_pulls.begin(),last_cdc_pulls.end()); |
7235 | |
7236 | // Track Parameters at "vertex" |
7237 | phi_=Sclast(state_phi); |
7238 | q_over_pt_=Sclast(state_q_over_pt); |
7239 | tanl_=Sclast(state_tanl); |
7240 | x_=last_pos.X(); |
7241 | y_=last_pos.Y(); |
7242 | z_=Sclast(state_z); |
7243 | // Find the (signed) distance of closest approach to the beam line |
7244 | if (extrapolated){ |
7245 | beam_pos=beam_center+(z_-beam_z0)*beam_dir; |
7246 | } |
7247 | double dx=x_-beam_pos.X(); |
7248 | double dy=y_-beam_pos.Y(); |
7249 | D_=sqrt(dx*dx+dy*dy)+EPS3.0e-8; |
7250 | x_ = dx; y_ = dy; |
7251 | double cosphi=cos(phi_); |
7252 | double sinphi=sin(phi_); |
7253 | if ((dx>0.0 && sinphi>0.0) || (dy <0.0 && cosphi>0.0) |
7254 | || (dy>0.0 && cosphi<0.0) || (dx<0.0 && sinphi<0.0)) D_*=-1.; |
7255 | // Rotate covariance matrix to coordinate system centered on x=0,y=0 in the |
7256 | // lab |
7257 | DMatrix5x5 Jc=I5x5; |
7258 | Jc(state_D,state_D)=(dy*cosphi-dx*sinphi)/D_; |
7259 | //Cclast=Cclast.SandwichMultiply(Jc); |
7260 | Cclast=Jc*Cclast*Jc.Transpose(); |
7261 | |
7262 | if (!isfinite(x_) || !isfinite(y_) || !isfinite(z_) || !isfinite(phi_) |
7263 | || !isfinite(q_over_pt_) || !isfinite(tanl_)){ |
7264 | if (DEBUG_LEVEL>0){ |
7265 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7265<<" " << "At least one parameter is NaN or +-inf!!" <<endl; |
7266 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7266<<" " << "x " << x_ << " y " << y_ << " z " << z_ << " phi " << phi_ |
7267 | << " q/pt " << q_over_pt_ << " tanl " << tanl_ << endl; |
7268 | } |
7269 | return INVALID_FIT; |
7270 | } |
7271 | |
7272 | // Covariance matrix at vertex |
7273 | fcov.clear(); |
7274 | vector<double>dummy; |
7275 | for (unsigned int i=0;i<5;i++){ |
7276 | dummy.clear(); |
7277 | for(unsigned int j=0;j<5;j++){ |
7278 | dummy.push_back(Cclast(i,j)); |
7279 | } |
7280 | cov.push_back(dummy); |
7281 | } |
7282 | |
7283 | // total chisq and ndf |
7284 | chisq_=chisq_iter; |
7285 | ndf_=last_ndf; |
7286 | //printf("NDof %d\n",ndf); |
7287 | |
7288 | return last_error; |
7289 | } |
7290 | |
7291 | // Smoothing algorithm for the forward trajectory. Updates the state vector |
7292 | // at each step (going in the reverse direction to the filter) based on the |
7293 | // information from all the steps and outputs the state vector at the |
7294 | // outermost step. |
7295 | jerror_t DTrackFitterKalmanSIMD::SmoothForward(vector<pull_t>&forward_pulls){ |
7296 | if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE; |
7297 | |
7298 | unsigned int max=forward_traj.size()-1; |
7299 | DMatrix5x1 S=(forward_traj[max].Skk); |
7300 | DMatrix5x5 C=(forward_traj[max].Ckk); |
7301 | DMatrix5x5 JT=forward_traj[max].J.Transpose(); |
7302 | DMatrix5x1 Ss=S; |
7303 | DMatrix5x5 Cs=C; |
7304 | DMatrix5x5 A,dC; |
7305 | |
7306 | if (DEBUG_LEVEL>19){ |
7307 | jout << "---- Smoothed residuals ----" <<endl; |
7308 | jout << setprecision(4); |
7309 | } |
7310 | |
7311 | for (unsigned int m=max-1;m>0;m--){ |
7312 | |
7313 | if (WRITE_ML_TRAINING_OUTPUT){ |
7314 | mlfile << forward_traj[m].z; |
7315 | for (unsigned int k=0;k<5;k++){ |
7316 | mlfile << " " << Ss(k); |
7317 | } |
7318 | for (unsigned int k=0;k<5;k++){ |
7319 | mlfile << " " << Cs(k,k); |
7320 | for (unsigned int j=k+1;j<5;j++){ |
7321 | mlfile <<" " << Cs(k,j); |
7322 | } |
7323 | } |
7324 | mlfile << endl; |
7325 | } |
7326 | |
7327 | if (forward_traj[m].h_id>0){ |
7328 | if (forward_traj[m].h_id<1000){ |
7329 | unsigned int id=forward_traj[m].h_id-1; |
7330 | if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7330<<" " << " Smoothing FDC ID " << id << endl; |
7331 | if (fdc_used_in_fit[id] && my_fdchits[id]->status==good_hit){ |
7332 | if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7332<<" " << " Used in fit " << endl; |
7333 | A=fdc_updates[id].C*JT*C.InvertSym(); |
7334 | Ss=fdc_updates[id].S+A*(Ss-S); |
7335 | |
7336 | if (!Ss.IsFinite()){ |
7337 | if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7337<<" " << "Invalid values for smoothed parameters..." << endl; |
7338 | return VALUE_OUT_OF_RANGE; |
7339 | } |
7340 | dC=A*(Cs-C)*A.Transpose(); |
7341 | Cs=fdc_updates[id].C+dC; |
7342 | if (!Cs.IsPosDef()){ |
7343 | if (DEBUG_LEVEL>1) |
7344 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7344<<" " << "Covariance Matrix not PosDef..." << endl; |
7345 | return VALUE_OUT_OF_RANGE; |
7346 | } |
7347 | |
7348 | // Position and direction from state vector with small angle |
7349 | // alignment correction |
7350 | double x=Ss(state_x) + my_fdchits[id]->phiZ*Ss(state_y); |
7351 | double y=Ss(state_y) - my_fdchits[id]->phiZ*Ss(state_x); |
7352 | double tx=Ss(state_tx)+ my_fdchits[id]->phiZ*Ss(state_ty) |
7353 | - my_fdchits[id]->phiY; |
7354 | double ty=Ss(state_ty) - my_fdchits[id]->phiZ*Ss(state_tx) |
7355 | + my_fdchits[id]->phiX; |
7356 | |
7357 | double cosa=my_fdchits[id]->cosa; |
7358 | double sina=my_fdchits[id]->sina; |
7359 | double u=my_fdchits[id]->uwire; |
7360 | double v=my_fdchits[id]->vstrip; |
7361 | |
7362 | // Projected position along the wire without doca-dependent corrections |
7363 | double vpred_uncorrected=x*sina+y*cosa; |
7364 | |
7365 | // Projected position in the plane of the wires transverse to the wires |
7366 | double upred=x*cosa-y*sina; |
7367 | |
7368 | // Direction tangent in the u-z plane |
7369 | double tu=tx*cosa-ty*sina; |
7370 | double one_plus_tu2=1.+tu*tu; |
7371 | double alpha=atan(tu); |
7372 | double cosalpha=cos(alpha); |
7373 | //double cosalpha2=cosalpha*cosalpha; |
7374 | double sinalpha=sin(alpha); |
7375 | |
7376 | // (signed) distance of closest approach to wire |
7377 | double du=upred-u; |
7378 | double doca=du*cosalpha; |
7379 | |
7380 | // Correction for lorentz effect |
7381 | double nz=my_fdchits[id]->nz; |
7382 | double nr=my_fdchits[id]->nr; |
7383 | double nz_sinalpha_plus_nr_cosalpha=nz*sinalpha+nr*cosalpha; |
7384 | |
7385 | // Difference between measurement and projection |
7386 | double tv=tx*sina+ty*cosa; |
7387 | double resi=v-(vpred_uncorrected+doca*(nz_sinalpha_plus_nr_cosalpha |
7388 | -tv*sinalpha)); |
7389 | double drift_time=my_fdchits[id]->t-mT0 |
7390 | -forward_traj[m].t*TIME_UNIT_CONVERSION3.33564095198152014e-02; |
7391 | double drift = 0.0; |
7392 | int left_right = -999; |
7393 | if (USE_FDC_DRIFT_TIMES) { |
7394 | drift = (du > 0.0 ? 1.0 : -1.0) * fdc_drift_distance(drift_time, forward_traj[m].B); |
7395 | left_right = (du > 0.0 ? +1 : -1); |
7396 | } |
7397 | |
7398 | double resi_a = drift - doca; |
7399 | |
7400 | // Variance from filter step |
7401 | // This V is really "R" in Fruhwirths notation, in the case that the track is used in the fit. |
7402 | DMatrix2x2 V=fdc_updates[id].V; |
7403 | // Compute projection matrix and find the variance for the residual |
7404 | DMatrix5x2 H_T; |
7405 | double temp2=nz_sinalpha_plus_nr_cosalpha-tv*sinalpha; |
7406 | H_T(state_x,1)=sina+cosa*cosalpha*temp2; |
7407 | H_T(state_y,1)=cosa-sina*cosalpha*temp2; |
7408 | |
7409 | double cos2_minus_sin2=cosalpha*cosalpha-sinalpha*sinalpha; |
7410 | double fac=nz*cos2_minus_sin2-2.*nr*cosalpha*sinalpha; |
7411 | double doca_cosalpha=doca*cosalpha; |
7412 | double temp=doca_cosalpha*fac; |
7413 | H_T(state_tx,1)=cosa*temp |
7414 | -doca_cosalpha*(tu*sina+tv*cosa*cos2_minus_sin2) |
7415 | ; |
7416 | H_T(state_ty,1)=-sina*temp |
7417 | -doca_cosalpha*(tu*cosa-tv*sina*cos2_minus_sin2) |
7418 | ; |
7419 | |
7420 | H_T(state_x,0)=cosa*cosalpha; |
7421 | H_T(state_y,0)=-sina*cosalpha; |
7422 | double factor=du*tu/sqrt(one_plus_tu2)/one_plus_tu2; |
7423 | H_T(state_ty,0)=sina*factor; |
7424 | H_T(state_tx,0)=-cosa*factor; |
7425 | |
7426 | // Matrix transpose H_T -> H |
7427 | DMatrix2x5 H=Transpose(H_T); |
7428 | |
7429 | if (my_fdchits[id]->hit!=NULL__null |
7430 | && my_fdchits[id]->hit->wire->layer==PLANE_TO_SKIP){ |
7431 | //V+=Cs.SandwichMultiply(H_T); |
7432 | V=V+H*Cs*H_T; |
7433 | } |
7434 | else{ |
7435 | //V-=dC.SandwichMultiply(H_T); |
7436 | V=V-H*dC*H_T; |
7437 | } |
7438 | |
7439 | |
7440 | vector<double> alignmentDerivatives; |
7441 | if (ALIGNMENT_FORWARD && my_fdchits[id]->hit!=NULL__null){ |
7442 | alignmentDerivatives.resize(FDCTrackD::size); |
7443 | // Let's get the alignment derivatives |
7444 | |
7445 | // Things are assumed to be linear near the wire, derivatives can be determined analytically. |
7446 | // First for the wires |
7447 | |
7448 | //dDOCAW/ddeltax |
7449 | alignmentDerivatives[FDCTrackD::dDOCAW_dDeltaX] = -(1/sqrt(1 + pow(tx*cosa - ty*sina,2))); |
7450 | |
7451 | //dDOCAW/ddeltaz |
7452 | alignmentDerivatives[FDCTrackD::dDOCAW_dDeltaZ] = (tx*cosa - ty*sina)/sqrt(1 + pow(tx*cosa - ty*sina,2)); |
7453 | |
7454 | //dDOCAW/ddeltaPhiX |
7455 | double cos2a = cos(2.*my_fdchits[id]->hit->wire->angle); |
7456 | double sin2a = sin(2.*my_fdchits[id]->hit->wire->angle); |
7457 | double cos3a = cos(3.*my_fdchits[id]->hit->wire->angle); |
7458 | double sin3a = sin(3.*my_fdchits[id]->hit->wire->angle); |
7459 | //double tx2 = tx*tx; |
7460 | //double ty2 = ty*ty; |
7461 | alignmentDerivatives[FDCTrackD::dDOCAW_dDeltaPhiX] = (sina*(-(tx*cosa) + ty*sina)*(u - x*cosa + y*sina))/ |
7462 | pow(1 + pow(tx*cosa - ty*sina,2),1.5); |
7463 | alignmentDerivatives[FDCTrackD::dDOCAW_dDeltaPhiY] = -((cosa*(tx*cosa - ty*sina)*(u - x*cosa + y*sina))/ |
7464 | pow(1 + pow(tx*cosa - ty*sina,2),1.5)); |
7465 | alignmentDerivatives[FDCTrackD::dDOCAW_dDeltaPhiZ] = (tx*ty*u*cos2a + (x + pow(ty,2)*x - tx*ty*y)*sina + |
7466 | cosa*(-(tx*ty*x) + y + pow(tx,2)*y + (tx - ty)*(tx + ty)*u*sina))/ |
7467 | pow(1 + pow(tx*cosa - ty*sina,2),1.5); |
7468 | |
7469 | // dDOCAW/dt0 |
7470 | double t0shift=4.;//ns |
7471 | double drift_shift = 0.0; |
7472 | if(USE_FDC_DRIFT_TIMES){ |
7473 | if (drift_time < 0.) drift_shift = drift; |
7474 | else drift_shift = (du>0.0?1.:-1.)*fdc_drift_distance(drift_time+t0shift,forward_traj[m].B); |
7475 | } |
7476 | alignmentDerivatives[FDCTrackD::dW_dt0]= (drift_shift-drift)/t0shift; |
7477 | |
7478 | // dDOCAW/dx |
7479 | alignmentDerivatives[FDCTrackD::dDOCAW_dx] = cosa/sqrt(1 + pow(tx*cosa - ty*sina,2)); |
7480 | |
7481 | // dDOCAW/dy |
7482 | alignmentDerivatives[FDCTrackD::dDOCAW_dy] = -(sina/sqrt(1 + pow(tx*cosa - ty*sina,2))); |
7483 | |
7484 | // dDOCAW/dtx |
7485 | alignmentDerivatives[FDCTrackD::dDOCAW_dtx] = (cosa*(tx*cosa - ty*sina)*(u - x*cosa + y*sina))/pow(1 + pow(tx*cosa - ty*sina,2),1.5); |
7486 | |
7487 | // dDOCAW/dty |
7488 | alignmentDerivatives[FDCTrackD::dDOCAW_dty] = (sina*(-(tx*cosa) + ty*sina)*(u - x*cosa + y*sina))/ |
7489 | pow(1 + pow(tx*cosa - ty*sina,2),1.5); |
7490 | |
7491 | // Then for the cathodes. The magnetic field correction now correlates the alignment constants for the wires and cathodes. |
7492 | |
7493 | //dDOCAC/ddeltax |
7494 | alignmentDerivatives[FDCTrackD::dDOCAC_dDeltaX] = |
7495 | (-nr + (-nz + ty*cosa + tx*sina)*(tx*cosa - ty*sina))/(1 + pow(tx*cosa - ty*sina,2)); |
7496 | |
7497 | //dDOCAC/ddeltaz |
7498 | alignmentDerivatives[FDCTrackD::dDOCAC_dDeltaZ] = |
7499 | nz + (-nz + (nr*tx + ty)*cosa + (tx - nr*ty)*sina)/(1 + pow(tx*cosa - ty*sina,2)); |
7500 | |
7501 | //dDOCAC/ddeltaPhiX |
7502 | alignmentDerivatives[FDCTrackD::dDOCAC_dDeltaPhiX] = |
7503 | (-2*y*cosa*sina*(tx*cosa - ty*sina) - 2*x*pow(sina,2)*(tx*cosa - ty*sina) - |
7504 | (u - x*cosa + y*sina)*(-(nz*sina) + sina*(ty*cosa + tx*sina) - |
7505 | cosa*(tx*cosa - ty*sina)))/(1 + pow(tx*cosa - ty*sina,2)) + |
7506 | (2*sina*(tx*cosa - ty*sina)*(-((u - x*cosa + y*sina)* |
7507 | (nr + nz*(tx*cosa - ty*sina) - (ty*cosa + tx*sina)*(tx*cosa - ty*sina))) + |
7508 | y*cosa*(1 + pow(tx*cosa - ty*sina,2)) + x*sina*(1 + pow(tx*cosa - ty*sina,2))))/ |
7509 | pow(1 + pow(tx*cosa - ty*sina,2),2); |
7510 | |
7511 | |
7512 | //dDOCAC/ddeltaPhiY |
7513 | alignmentDerivatives[FDCTrackD::dDOCAC_dDeltaPhiY] = (-2*y*pow(cosa,2)*(tx*cosa - ty*sina) - 2*x*cosa*sina*(tx*cosa - ty*sina) - |
7514 | (u - x*cosa + y*sina)*(-(nz*cosa) + cosa*(ty*cosa + tx*sina) + |
7515 | sina*(tx*cosa - ty*sina)))/(1 + pow(tx*cosa - ty*sina,2)) + |
7516 | (2*cosa*(tx*cosa - ty*sina)*(-((u - x*cosa + y*sina)* |
7517 | (nr + nz*(tx*cosa - ty*sina) - (ty*cosa + tx*sina)*(tx*cosa - ty*sina))) + |
7518 | y*cosa*(1 + pow(tx*cosa - ty*sina,2)) + x*sina*(1 + pow(tx*cosa - ty*sina,2))))/ |
7519 | pow(1 + pow(tx*cosa - ty*sina,2),2); |
7520 | |
7521 | //dDOCAC/ddeltaPhiZ |
7522 | alignmentDerivatives[FDCTrackD::dDOCAC_dDeltaPhiZ] = (-2*(ty*cosa + tx*sina)*(tx*cosa - ty*sina)* |
7523 | (-((u - x*cosa + y*sina)*(nr + nz*(tx*cosa - ty*sina) - |
7524 | (ty*cosa + tx*sina)*(tx*cosa - ty*sina))) + |
7525 | y*cosa*(1 + pow(tx*cosa - ty*sina,2)) + x*sina*(1 + pow(tx*cosa - ty*sina,2))))/ |
7526 | pow(1 + pow(tx*cosa - ty*sina,2),2) + |
7527 | (2*y*cosa*(ty*cosa + tx*sina)*(tx*cosa - ty*sina) + |
7528 | 2*x*sina*(ty*cosa + tx*sina)*(tx*cosa - ty*sina) - |
7529 | (-(y*cosa) - x*sina)*(nr + nz*(tx*cosa - ty*sina) - |
7530 | (ty*cosa + tx*sina)*(tx*cosa - ty*sina)) - |
7531 | x*cosa*(1 + pow(tx*cosa - ty*sina,2)) + y*sina*(1 + pow(tx*cosa - ty*sina,2)) - |
7532 | (u - x*cosa + y*sina)*(nz*(ty*cosa + tx*sina) - pow(ty*cosa + tx*sina,2) - |
7533 | (tx*cosa - ty*sina)*(-(tx*cosa) + ty*sina)))/(1 + pow(tx*cosa - ty*sina,2)); |
7534 | |
7535 | //dDOCAC/dx |
7536 | alignmentDerivatives[FDCTrackD::dDOCAC_dx] = (cosa*(nr - tx*ty + nz*tx*cosa) + sina + ty*(ty - nz*cosa)*sina)/ |
7537 | (1 + pow(tx*cosa - ty*sina,2)); |
7538 | |
7539 | //dDOCAC/dy |
7540 | alignmentDerivatives[FDCTrackD::dDOCAC_dy] = ((1 + pow(tx,2))*cosa - (nr + tx*ty + nz*tx*cosa)*sina + nz*ty*pow(sina,2))/ |
7541 | (1 + pow(tx*cosa - ty*sina,2)); |
7542 | |
7543 | //dDOCAC/dtx |
7544 | alignmentDerivatives[FDCTrackD::dDOCAC_dtx] = ((u - x*cosa + y*sina)*(4*nr*tx - 2*ty*(pow(tx,2) + pow(ty,2)) + nz*(-4 + 3*pow(tx,2) + pow(ty,2))*cosa + |
7545 | 2*(2*nr*tx + ty*(2 - pow(tx,2) + pow(ty,2)))*cos2a + nz*(tx - ty)*(tx + ty)*cos3a - 2*nz*tx*ty*sina + |
7546 | 4*(tx - nr*ty + tx*pow(ty,2))*sin2a - 2*nz*tx*ty*sin3a))/ |
7547 | pow(2 + pow(tx,2) + pow(ty,2) + (tx - ty)*(tx + ty)*cos2a - 2*tx*ty*sin2a,2); |
7548 | |
7549 | //dDOCAC/dty |
7550 | alignmentDerivatives[FDCTrackD::dDOCAC_dty] = -(((u - x*cosa + y*sina)*(-2*(pow(tx,3) + 2*nr*ty + tx*pow(ty,2)) - 2*nz*tx*ty*cosa - |
7551 | 2*(2*tx + pow(tx,3) - 2*nr*ty - tx*pow(ty,2))*cos2a + 2*nz*tx*ty*cos3a + |
7552 | nz*(-4 + pow(tx,2) + 3*pow(ty,2))*sina + 4*(ty + tx*(nr + tx*ty))*sin2a + nz*(tx - ty)*(tx + ty)*sin3a)) |
7553 | /pow(2 + pow(tx,2) + pow(ty,2) + (tx - ty)*(tx + ty)*cos2a - 2*tx*ty*sin2a,2)); |
7554 | |
7555 | } |
7556 | |
7557 | if (DEBUG_LEVEL>19 && my_fdchits[id]->hit!=NULL__null){ |
7558 | jout << "Layer " << my_fdchits[id]->hit->wire->layer |
7559 | <<": t " << drift_time << " x "<< x << " y " << y |
7560 | << " coordinate along wire " << v << " resi_c " <<resi |
7561 | << " coordinate transverse to wire " << drift |
7562 | <<" resi_a " << resi_a |
7563 | <<endl; |
7564 | } |
7565 | |
7566 | double scale=1./sqrt(1.+tx*tx+ty*ty); |
7567 | double cosThetaRel=0.; |
7568 | if (my_fdchits[id]->hit!=NULL__null){ |
7569 | my_fdchits[id]->hit->wire->udir.Dot(DVector3(scale*tx,scale*ty,scale)); |
7570 | } |
7571 | DTrackFitter::pull_t thisPull = pull_t(resi_a,sqrt(V(0,0)), |
7572 | forward_traj[m].s, |
7573 | fdc_updates[id].tdrift, |
7574 | fdc_updates[id].doca, |
7575 | NULL__null,my_fdchits[id]->hit, |
7576 | 0., |
7577 | forward_traj[m].z, |
7578 | cosThetaRel,0., |
7579 | resi,sqrt(V(1,1))); |
7580 | thisPull.left_right = left_right; |
7581 | thisPull.AddTrackDerivatives(alignmentDerivatives); |
7582 | forward_pulls.push_back(thisPull); |
7583 | } |
7584 | else{ |
7585 | A=forward_traj[m].Ckk*JT*C.InvertSym(); |
7586 | Ss=forward_traj[m].Skk+A*(Ss-S); |
7587 | Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose(); |
7588 | } |
7589 | |
7590 | } |
7591 | else{ |
7592 | unsigned int id=forward_traj[m].h_id-1000; |
7593 | if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7593<<" " << " Smoothing CDC ID " << id << endl; |
7594 | if (cdc_used_in_fit[id]&&my_cdchits[id]->status==good_hit){ |
7595 | if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7595<<" " << " Used in fit " << endl; |
7596 | A=cdc_updates[id].C*JT*C.InvertSym(); |
7597 | Ss=cdc_updates[id].S+A*(Ss-S); |
7598 | Cs=cdc_updates[id].C+A*(Cs-C)*A.Transpose(); |
7599 | if (!Cs.IsPosDef()){ |
7600 | if (DEBUG_LEVEL>1) |
7601 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7601<<" " << "Covariance Matrix not PosDef..." << endl; |
7602 | return VALUE_OUT_OF_RANGE; |
7603 | } |
7604 | if (!Ss.IsFinite()){ |
7605 | if (DEBUG_LEVEL>5) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7605<<" " << "Invalid values for smoothed parameters..." << endl; |
7606 | return VALUE_OUT_OF_RANGE; |
7607 | } |
7608 | |
7609 | // Fill in pulls information for cdc hits |
7610 | if(FillPullsVectorEntry(Ss,Cs,forward_traj[m],my_cdchits[id], |
7611 | cdc_updates[id],forward_pulls) != NOERROR) return VALUE_OUT_OF_RANGE; |
7612 | } |
7613 | else{ |
7614 | A=forward_traj[m].Ckk*JT*C.InvertSym(); |
7615 | Ss=forward_traj[m].Skk+A*(Ss-S); |
7616 | Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose(); |
7617 | } |
7618 | } |
7619 | } |
7620 | else{ |
7621 | A=forward_traj[m].Ckk*JT*C.InvertSym(); |
7622 | Ss=forward_traj[m].Skk+A*(Ss-S); |
7623 | Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose(); |
7624 | } |
7625 | |
7626 | S=forward_traj[m].Skk; |
7627 | C=forward_traj[m].Ckk; |
7628 | JT=forward_traj[m].J.Transpose(); |
7629 | } |
7630 | |
7631 | return NOERROR; |
7632 | } |
7633 | |
7634 | // at each step (going in the reverse direction to the filter) based on the |
7635 | // information from all the steps. |
7636 | jerror_t DTrackFitterKalmanSIMD::SmoothCentral(vector<pull_t>&cdc_pulls){ |
7637 | if (central_traj.size()<2) return RESOURCE_UNAVAILABLE; |
7638 | |
7639 | unsigned int max = central_traj.size()-1; |
7640 | DMatrix5x1 S=(central_traj[max].Skk); |
7641 | DMatrix5x5 C=(central_traj[max].Ckk); |
7642 | DMatrix5x5 JT=central_traj[max].J.Transpose(); |
7643 | DMatrix5x1 Ss=S; |
7644 | DMatrix5x5 Cs=C; |
7645 | DMatrix5x5 A,dC; |
7646 | |
7647 | if (DEBUG_LEVEL>1) { |
7648 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7648<<" " << " S C JT at start of smoothing " << endl; |
7649 | S.Print(); C.Print(); JT.Print(); |
7650 | } |
7651 | |
7652 | for (unsigned int m=max-1;m>0;m--){ |
7653 | if (central_traj[m].h_id>0){ |
7654 | unsigned int id=central_traj[m].h_id-1; |
7655 | if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7655<<" " << " Encountered Hit ID " << id << " At trajectory position " << m << "/" << max << endl; |
7656 | if (cdc_used_in_fit[id] && my_cdchits[id]->status == good_hit){ |
7657 | if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7657<<" " << " SmoothCentral CDC Hit ID " << id << " used in fit " << endl; |
7658 | |
7659 | A=cdc_updates[id].C*JT*C.InvertSym(); |
7660 | dC=Cs-C; |
7661 | Ss=cdc_updates[id].S+A*(Ss-S); |
7662 | Cs=cdc_updates[id].C+A*dC*A.Transpose(); |
7663 | |
7664 | if (!Ss.IsFinite()){ |
7665 | if (DEBUG_LEVEL>5) |
7666 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7666<<" " << "Invalid values for smoothed parameters..." << endl; |
7667 | return VALUE_OUT_OF_RANGE; |
7668 | } |
7669 | if (!Cs.IsPosDef()){ |
7670 | if (DEBUG_LEVEL>5){ |
7671 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<7671<<" " << "Covariance Matrix not PosDef... Ckk dC A" << endl; |
7672 | cdc_updates[id].C.Print(); dC.Print(); A.Print(); |
7673 | } |
7674 | return VALUE_OUT_OF_RANGE; |
7675 | } |
7676 | |
7677 | // Get estimate for energy loss |
7678 | double q_over_p=Ss(state_q_over_pt)*cos(atan(Ss(state_tanl))); |
7679 | double dEdx=GetdEdx(q_over_p,central_traj[m].K_rho_Z_over_A, |
7680 | central_traj[m].rho_Z_over_A, |
7681 | central_traj[m].LnI,central_traj[m].Z); |
7682 | |
7683 | // Use Brent's algorithm to find doca to the wire |
7684 | DVector2 xy(central_traj[m].xy.X()-Ss(state_D)*sin(Ss(state_phi)), |
7685 | central_traj[m].xy.Y()+Ss(state_D)*cos(Ss(state_phi))); |
7686 | DVector2 old_xy=xy; |
7687 | DMatrix5x1 myS=Ss; |
7688 | double myds; |
7689 | DVector2 origin=my_cdchits[id]->origin; |
7690 | DVector2 dir=my_cdchits[id]->dir; |
7691 | double z0wire=my_cdchits[id]->z0wire; |
7692 | //BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy,z0wire,origin,dir,myS,myds); |
7693 | if(BrentCentral(dEdx,xy,z0wire,origin,dir,myS,myds)!=NOERROR) return VALUE_OUT_OF_RANGE; |
7694 | if(DEBUG_HISTS) alignDerivHists[0]->Fill(myds); |
7695 | DVector2 wirepos=origin+(myS(state_z)-z0wire)*dir; |
7696 | double cosstereo=my_cdchits[id]->cosstereo; |
7697 | DVector2 diff=xy-wirepos; |
7698 | // here we add a small number to avoid division by zero errors |
7699 | double d=cosstereo*diff.Mod()+EPS3.0e-8; |
7700 | |
7701 | // If we are doing the alignment, we need to numerically calculate the derivatives |
7702 | // wrt the wire origin, direction, and the track parameters. |
7703 | vector<double> alignmentDerivatives; |
7704 | if (ALIGNMENT_CENTRAL){ |
7705 | double dscut_min=0., dscut_max=1.; |
7706 | DVector3 wireDir = my_cdchits[id]->hit->wire->udir; |
7707 | double cosstereo_shifted; |
7708 | DMatrix5x1 alignS=Ss; // We will mess with this one |
7709 | double alignds; |
7710 | alignmentDerivatives.resize(12); |
7711 | alignmentDerivatives[CDCTrackD::dDdt0]=cdc_updates[id].dDdt0; |
7712 | // Wire position shift |
7713 | double wposShift=0.025; |
7714 | double wdirShift=0.00005; |
7715 | |
7716 | // Shift each track parameter value |
7717 | double shiftFraction=0.01; |
7718 | double shift_q_over_pt=shiftFraction*Ss(state_q_over_pt); |
7719 | double shift_phi=0.0001; |
7720 | double shift_tanl=shiftFraction*Ss(state_tanl); |
7721 | double shift_D=0.01; |
7722 | double shift_z=0.01; |
7723 | |
7724 | // Some data containers we don't need multiples of |
7725 | double z0_shifted; |
7726 | DVector2 shift, origin_shifted, dir_shifted, wirepos_shifted, diff_shifted, xy_shifted; |
7727 | |
7728 | // The DOCA for the shifted states == f(x+h) |
7729 | double d_dOriginX=0., d_dOriginY=0., d_dOriginZ=0.; |
7730 | double d_dDirX=0., d_dDirY=0., d_dDirZ=0.; |
7731 | double d_dS0=0., d_dS1=0., d_dS2=0., d_dS3=0., d_dS4=0.; |
7732 | // Let's do the wire shifts first |
7733 | |
7734 | //dOriginX |
7735 | alignS=Ss; |
7736 | alignds=0.; |
7737 | shift.Set(wposShift, 0.); |
7738 | origin_shifted=origin+shift; |
7739 | dir_shifted=dir; |
7740 | z0_shifted=z0wire; |
7741 | xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)), |
7742 | central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi))); |
7743 | if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted, |
7744 | dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE; |
7745 | if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE; |
7746 | //if (BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted, |
7747 | // dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE; |
7748 | wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted; |
7749 | diff_shifted=xy_shifted-wirepos_shifted; |
7750 | d_dOriginX=cosstereo*diff_shifted.Mod()+EPS3.0e-8; |
7751 | alignmentDerivatives[CDCTrackD::dDOCAdOriginX] = (d_dOriginX - d)/wposShift; |
7752 | if(DEBUG_HISTS){ |
7753 | alignDerivHists[12]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginX]); |
7754 | alignDerivHists[1]->Fill(alignds); |
7755 | brentCheckHists[1]->Fill(alignds,d_dOriginX); |
7756 | } |
7757 | |
7758 | //dOriginY |
7759 | alignS=Ss; |
7760 | alignds=0.; |
7761 | shift.Set(0.,wposShift); |
7762 | origin_shifted=origin+shift; |
7763 | dir_shifted=dir; |
7764 | z0_shifted=z0wire; |
7765 | xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)), |
7766 | central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi))); |
7767 | if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted, |
7768 | dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE; |
7769 | if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE; |
7770 | //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted, |
7771 | // dir_shifted,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE; |
7772 | wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted; |
7773 | diff_shifted=xy_shifted-wirepos_shifted; |
7774 | d_dOriginY=cosstereo*diff_shifted.Mod()+EPS3.0e-8; |
7775 | alignmentDerivatives[CDCTrackD::dDOCAdOriginY] = (d_dOriginY - d)/wposShift; |
7776 | if(DEBUG_HISTS){ |
7777 | alignDerivHists[13]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginY]); |
7778 | alignDerivHists[2]->Fill(alignds); |
7779 | brentCheckHists[1]->Fill(alignds,d_dOriginY); |
7780 | } |
7781 | |
7782 | //dOriginZ |
7783 | alignS=Ss; |
7784 | alignds=0.; |
7785 | origin_shifted=origin; |
7786 | dir_shifted=dir; |
7787 | z0_shifted=z0wire+wposShift; |
7788 | xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)), |
7789 | central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi))); |
7790 | if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted, |
7791 | dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE; |
7792 | if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE; |
7793 | //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted, |
7794 | // dir_shifted,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE; |
7795 | wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted; |
7796 | diff_shifted=xy_shifted-wirepos_shifted; |
7797 | d_dOriginZ=cosstereo*diff_shifted.Mod()+EPS3.0e-8; |
7798 | alignmentDerivatives[CDCTrackD::dDOCAdOriginZ] = (d_dOriginZ - d)/wposShift; |
7799 | if(DEBUG_HISTS){ |
7800 | alignDerivHists[14]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginZ]); |
7801 | alignDerivHists[3]->Fill(alignds); |
7802 | brentCheckHists[1]->Fill(alignds,d_dOriginZ); |
7803 | } |
7804 | |
7805 | //dDirX |
7806 | alignS=Ss; |
7807 | alignds=0.; |
7808 | shift.Set(wdirShift,0.); |
7809 | origin_shifted=origin; |
7810 | z0_shifted=z0wire; |
7811 | xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)), |
7812 | central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi))); |
7813 | dir_shifted=dir+shift; |
7814 | cosstereo_shifted = cos((wireDir+DVector3(wdirShift,0.,0.)).Angle(DVector3(0.,0.,1.))); |
7815 | if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted, |
7816 | dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE; |
7817 | if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE; |
7818 | //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted, |
7819 | // dir_shifted,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE; |
7820 | wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted; |
7821 | diff_shifted=xy_shifted-wirepos_shifted; |
7822 | d_dDirX=cosstereo_shifted*diff_shifted.Mod()+EPS3.0e-8; |
7823 | alignmentDerivatives[CDCTrackD::dDOCAdDirX] = (d_dDirX - d)/wdirShift; |
7824 | if(DEBUG_HISTS){ |
7825 | alignDerivHists[15]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirX]); |
7826 | alignDerivHists[4]->Fill(alignds); |
7827 | } |
7828 | |
7829 | //dDirY |
7830 | alignS=Ss; |
7831 | alignds=0.; |
7832 | shift.Set(0.,wdirShift); |
7833 | origin_shifted=origin; |
7834 | z0_shifted=z0wire; |
7835 | xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)), |
7836 | central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi))); |
7837 | dir_shifted=dir+shift; |
7838 | cosstereo_shifted = cos((wireDir+DVector3(0.,wdirShift,0.)).Angle(DVector3(0.,0.,1.))); |
7839 | if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted, |
7840 | dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE; |
7841 | if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE; |
7842 | //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted, |
7843 | // dir_shifted,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE; |
7844 | wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted; |
7845 | diff_shifted=xy_shifted-wirepos_shifted; |
7846 | d_dDirY=cosstereo_shifted*diff_shifted.Mod()+EPS3.0e-8; |
7847 | alignmentDerivatives[CDCTrackD::dDOCAdDirY] = (d_dDirY - d)/wdirShift; |
7848 | if(DEBUG_HISTS){ |
7849 | alignDerivHists[16]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirY]); |
7850 | alignDerivHists[5]->Fill(alignds); |
7851 | } |
7852 | |
7853 | //dDirZ |
7854 | alignS=Ss; |
7855 | alignds=0.; |
7856 | origin_shifted=origin; |
7857 | dir_shifted.Set(wireDir.X()/(wireDir.Z()+wdirShift), wireDir.Y()/(wireDir.Z()+wdirShift)); |
7858 | z0_shifted=z0wire; |
7859 | xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)), |
7860 | central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi))); |
7861 | cosstereo_shifted = cos((wireDir+DVector3(0.,0.,wdirShift)).Angle(DVector3(0.,0.,1.))); |
7862 | if (BrentCentral(dEdx,xy_shifted,z0_shifted,origin_shifted, |
7863 | dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE; |
7864 | if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE; |
7865 | //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0_shifted,origin_shifted, |
7866 | // dir_shifted,alignS,alignds)!=NOERROR) return VALUE_OUT_OF_RANGE; |
7867 | wirepos_shifted=origin_shifted+(alignS(state_z)-z0_shifted)*dir_shifted; |
7868 | diff_shifted=xy_shifted-wirepos_shifted; |
7869 | d_dDirZ=cosstereo_shifted*diff_shifted.Mod()+EPS3.0e-8; |
7870 | alignmentDerivatives[CDCTrackD::dDOCAdDirZ] = (d_dDirZ - d)/wdirShift; |
7871 | if(DEBUG_HISTS){ |
7872 | alignDerivHists[17]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirZ]); |
7873 | alignDerivHists[6]->Fill(alignds); |
7874 | } |
7875 | |
7876 | // And now the derivatives wrt the track parameters |
7877 | //DMatrix5x1 trackShift(shift_q_over_pt, shift_phi, shift_tanl, shift_D, shift_z); |
7878 | |
7879 | DMatrix5x1 trackShiftS0(shift_q_over_pt, 0., 0., 0., 0.); |
7880 | DMatrix5x1 trackShiftS1(0., shift_phi, 0., 0., 0.); |
7881 | DMatrix5x1 trackShiftS2(0., 0., shift_tanl, 0., 0.); |
7882 | DMatrix5x1 trackShiftS3(0., 0., 0., shift_D, 0.); |
7883 | DMatrix5x1 trackShiftS4(0., 0., 0., 0., shift_z); |
7884 | |
7885 | // dS0 |
7886 | alignS=Ss+trackShiftS0; |
7887 | alignds=0.; |
7888 | xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)), |
7889 | central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi))); |
7890 | if(BrentCentral(dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE; |
7891 | if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE; |
7892 | //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE; |
7893 | wirepos_shifted=origin+(alignS(state_z)-z0wire)*dir; |
7894 | diff_shifted=xy_shifted-wirepos_shifted; |
7895 | d_dS0=cosstereo*diff_shifted.Mod()+EPS3.0e-8; |
7896 | alignmentDerivatives[CDCTrackD::dDOCAdS0] = (d_dS0 - d)/shift_q_over_pt; |
7897 | if(DEBUG_HISTS){ |
7898 | alignDerivHists[18]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS0]); |
7899 | alignDerivHists[7]->Fill(alignds); |
7900 | } |
7901 | |
7902 | // dS1 |
7903 | alignS=Ss+trackShiftS1; |
7904 | alignds=0.; |
7905 | xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)), |
7906 | central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi))); |
7907 | if(BrentCentral(dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE; |
7908 | if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE; |
7909 | //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE; |
7910 | wirepos_shifted=origin+(alignS(state_z)-z0wire)*dir; |
7911 | diff_shifted=xy_shifted-wirepos_shifted; |
7912 | d_dS1=cosstereo*diff_shifted.Mod()+EPS3.0e-8; |
7913 | alignmentDerivatives[CDCTrackD::dDOCAdS1] = (d_dS1 - d)/shift_phi; |
7914 | if(DEBUG_HISTS){ |
7915 | alignDerivHists[19]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS1]); |
7916 | alignDerivHists[8]->Fill(alignds); |
7917 | } |
7918 | |
7919 | // dS2 |
7920 | alignS=Ss+trackShiftS2; |
7921 | alignds=0.; |
7922 | xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)), |
7923 | central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi))); |
7924 | if(BrentCentral(dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE; |
7925 | if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE; |
7926 | //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE; |
7927 | wirepos_shifted=origin+(alignS(state_z)-z0wire)*dir; |
7928 | diff_shifted=xy_shifted-wirepos_shifted; |
7929 | d_dS2=cosstereo*diff_shifted.Mod()+EPS3.0e-8; |
7930 | alignmentDerivatives[CDCTrackD::dDOCAdS2] = (d_dS2 - d)/shift_tanl; |
7931 | if(DEBUG_HISTS){ |
7932 | alignDerivHists[20]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS2]); |
7933 | alignDerivHists[9]->Fill(alignds); |
7934 | } |
7935 | |
7936 | // dS3 |
7937 | alignS=Ss+trackShiftS3; |
7938 | alignds=0.; |
7939 | xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)), |
7940 | central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi))); |
7941 | if(BrentCentral(dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE; |
7942 | if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE; |
7943 | //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE; |
7944 | wirepos_shifted=origin+(alignS(state_z)-z0wire)*dir; |
7945 | diff_shifted=xy_shifted-wirepos_shifted; |
7946 | d_dS3=cosstereo*diff_shifted.Mod()+EPS3.0e-8; |
7947 | alignmentDerivatives[CDCTrackD::dDOCAdS3] = (d_dS3 - d)/shift_D; |
7948 | if(DEBUG_HISTS){ |
7949 | alignDerivHists[21]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS3]); |
7950 | alignDerivHists[10]->Fill(alignds); |
7951 | } |
7952 | |
7953 | // dS4 |
7954 | alignS=Ss+trackShiftS4; |
7955 | alignds=0.; |
7956 | xy_shifted.Set(central_traj[m].xy.X()-alignS(state_D)*sin(alignS(state_phi)), |
7957 | central_traj[m].xy.Y()+alignS(state_D)*cos(alignS(state_phi))); |
7958 | if(BrentCentral(dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE; |
7959 | if (alignds < dscut_min || alignds > dscut_max) return VALUE_OUT_OF_RANGE; |
7960 | //if(BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dEdx,xy_shifted,z0wire,origin,dir,alignS,alignds) != NOERROR) return VALUE_OUT_OF_RANGE; |
7961 | wirepos_shifted=origin+(alignS(state_z)-z0wire)*dir; |
7962 | diff_shifted=xy_shifted-wirepos_shifted; |
7963 | d_dS4=cosstereo*diff_shifted.Mod()+EPS3.0e-8; |
7964 | alignmentDerivatives[CDCTrackD::dDOCAdS4] = (d_dS4 - d)/shift_z; |
7965 | if(DEBUG_HISTS){ |
7966 | alignDerivHists[22]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS4]); |
7967 | alignDerivHists[11]->Fill(alignds); |
7968 | } |
7969 | } |
7970 | |
7971 | // Compute the Jacobian matrix |
7972 | // Find the field and gradient at (old_x,old_y,old_z) |
7973 | bfield->GetFieldAndGradient(old_xy.X(),old_xy.Y(),Ss(state_z), |
7974 | Bx,By,Bz, |
7975 | dBxdx,dBxdy,dBxdz,dBydx, |
7976 | dBydy,dBydz,dBzdx,dBzdy,dBzdz); |
7977 | DMatrix5x5 Jc; |
7978 | StepJacobian(old_xy,xy-old_xy,myds,Ss,dEdx,Jc); |
7979 | |
7980 | // Projection matrix |
7981 | DMatrix5x1 H_T; |
7982 | double sinphi=sin(myS(state_phi)); |
7983 | double cosphi=cos(myS(state_phi)); |
7984 | double dx=diff.X(); |
7985 | double dy=diff.Y(); |
7986 | double cosstereo2_over_doca=cosstereo*cosstereo/d; |
7987 | H_T(state_D)=(dy*cosphi-dx*sinphi)*cosstereo2_over_doca; |
7988 | H_T(state_phi) |
7989 | =-myS(state_D)*cosstereo2_over_doca*(dx*cosphi+dy*sinphi); |
7990 | H_T(state_z)=-cosstereo2_over_doca*(dx*dir.X()+dy*dir.Y()); |
7991 | DMatrix1x5 H; |
7992 | H(state_D)=H_T(state_D); |
7993 | H(state_phi)=H_T(state_phi); |
7994 | H(state_z)=H_T(state_z); |
7995 | |
7996 | double Vhit=cdc_updates[id].variance; |
7997 | Cs=Jc*Cs*Jc.Transpose(); |
7998 | //double Vtrack = Cs.SandwichMultiply(Jc*H_T); |
7999 | double Vtrack=H*Cs*H_T; |
8000 | double VRes; |
8001 | |
8002 | bool skip_ring=(my_cdchits[id]->hit->wire->ring==RING_TO_SKIP); |
8003 | if (skip_ring) VRes = Vhit + Vtrack; |
8004 | else VRes = Vhit - Vtrack; |
8005 | |
8006 | if (DEBUG_LEVEL>1 && (!isfinite(VRes) || VRes < 0.0) ) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<8006<<" " << " SmoothCentral Problem: VRes is " << VRes << " = " << Vhit << " - " << Vtrack << endl; |
8007 | |
8008 | double lambda=atan(Ss(state_tanl)); |
8009 | double sinl=sin(lambda); |
8010 | double cosl=cos(lambda); |
8011 | double cosThetaRel=my_cdchits[id]->hit->wire->udir.Dot(DVector3(cosphi*cosl, |
8012 | sinphi*cosl, |
8013 | sinl)); |
8014 | pull_t thisPull(cdc_updates[id].doca-d,sqrt(VRes), |
8015 | central_traj[m].s,cdc_updates[id].tdrift, |
8016 | d,my_cdchits[id]->hit,NULL__null, |
8017 | diff.Phi(),myS(state_z),cosThetaRel, |
8018 | cdc_updates[id].tcorr); |
8019 | |
8020 | thisPull.AddTrackDerivatives(alignmentDerivatives); |
8021 | cdc_pulls.push_back(thisPull); |
8022 | } |
8023 | else{ |
8024 | A=central_traj[m].Ckk*JT*C.InvertSym(); |
8025 | Ss=central_traj[m].Skk+A*(Ss-S); |
8026 | Cs=central_traj[m].Ckk+A*(Cs-C)*A.Transpose(); |
8027 | } |
8028 | } |
8029 | else{ |
8030 | A=central_traj[m].Ckk*JT*C.InvertSym(); |
8031 | Ss=central_traj[m].Skk+A*(Ss-S); |
8032 | Cs=central_traj[m].Ckk+A*(Cs-C)*A.Transpose(); |
8033 | } |
8034 | S=central_traj[m].Skk; |
8035 | C=central_traj[m].Ckk; |
8036 | JT=central_traj[m].J.Transpose(); |
8037 | } |
8038 | |
8039 | // ... last entries? |
8040 | // Don't really need since we should have already encountered all of the hits |
8041 | |
8042 | return NOERROR; |
8043 | |
8044 | } |
8045 | |
8046 | // Smoothing algorithm for the forward_traj_cdc trajectory. |
8047 | // Updates the state vector |
8048 | // at each step (going in the reverse direction to the filter) based on the |
8049 | // information from all the steps and outputs the state vector at the |
8050 | // outermost step. |
8051 | jerror_t DTrackFitterKalmanSIMD::SmoothForwardCDC(vector<pull_t>&cdc_pulls){ |
8052 | if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE; |
8053 | |
8054 | unsigned int max=forward_traj.size()-1; |
8055 | DMatrix5x1 S=(forward_traj[max].Skk); |
8056 | DMatrix5x5 C=(forward_traj[max].Ckk); |
8057 | DMatrix5x5 JT=forward_traj[max].J.Transpose(); |
8058 | DMatrix5x1 Ss=S; |
8059 | DMatrix5x5 Cs=C; |
8060 | DMatrix5x5 A; |
8061 | for (unsigned int m=max-1;m>0;m--){ |
8062 | if (forward_traj[m].h_id>999){ |
8063 | unsigned int cdc_index=forward_traj[m].h_id-1000; |
8064 | if(cdc_used_in_fit[cdc_index] && my_cdchits[cdc_index]->status == good_hit){ |
8065 | if (DEBUG_LEVEL > 5) { |
8066 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<8066<<" " << " Smoothing CDC index " << cdc_index << " ring " << my_cdchits[cdc_index]->hit->wire->ring |
8067 | << " straw " << my_cdchits[cdc_index]->hit->wire->straw << endl; |
8068 | } |
8069 | |
8070 | A=cdc_updates[cdc_index].C*JT*C.InvertSym(); |
8071 | Ss=cdc_updates[cdc_index].S+A*(Ss-S); |
8072 | if (!Ss.IsFinite()){ |
8073 | if (DEBUG_LEVEL>5) |
8074 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<8074<<" " << "Invalid values for smoothed parameters..." << endl; |
8075 | return VALUE_OUT_OF_RANGE; |
8076 | } |
8077 | |
8078 | Cs=cdc_updates[cdc_index].C+A*(Cs-C)*A.Transpose(); |
8079 | |
8080 | if (!Cs.IsPosDef()){ |
8081 | if (DEBUG_LEVEL>5){ |
8082 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<8082<<" " << "Covariance Matrix not Pos Def..." << endl; |
8083 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<8083<<" " << " cdc_updates[cdc_index].C A C_ Cs " << endl; |
8084 | cdc_updates[cdc_index].C.Print(); |
8085 | A.Print(); |
8086 | C.Print(); |
8087 | Cs.Print(); |
8088 | } |
8089 | return VALUE_OUT_OF_RANGE; |
8090 | } |
8091 | if(FillPullsVectorEntry(Ss,Cs,forward_traj[m],my_cdchits[cdc_index], |
8092 | cdc_updates[cdc_index],cdc_pulls) != NOERROR) return VALUE_OUT_OF_RANGE; |
8093 | |
8094 | } |
8095 | else{ |
8096 | A=forward_traj[m].Ckk*JT*C.InvertSym(); |
8097 | Ss=forward_traj[m].Skk+A*(Ss-S); |
8098 | Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose(); |
8099 | } |
8100 | } |
8101 | else{ |
8102 | A=forward_traj[m].Ckk*JT*C.InvertSym(); |
8103 | Ss=forward_traj[m].Skk+A*(Ss-S); |
8104 | Cs=forward_traj[m].Ckk+A*(Cs-C)*A.Transpose(); |
8105 | } |
8106 | |
8107 | S=forward_traj[m].Skk; |
8108 | C=forward_traj[m].Ckk; |
8109 | JT=forward_traj[m].J.Transpose(); |
8110 | } |
8111 | |
8112 | return NOERROR; |
8113 | } |
8114 | |
8115 | // Fill the pulls vector with the best residual information using the smoothed |
8116 | // filter results. Uses Brent's algorithm to find the distance of closest |
8117 | // approach to the wire hit. |
8118 | jerror_t DTrackFitterKalmanSIMD::FillPullsVectorEntry(const DMatrix5x1 &Ss, |
8119 | const DMatrix5x5 &Cs, |
8120 | const DKalmanForwardTrajectory_t &traj,const DKalmanSIMDCDCHit_t *hit,const DKalmanUpdate_t &update, |
8121 | vector<pull_t>&my_pulls){ |
8122 | |
8123 | // Get estimate for energy loss |
8124 | double dEdx=GetdEdx(Ss(state_q_over_p),traj.K_rho_Z_over_A,traj.rho_Z_over_A, |
8125 | traj.LnI,traj.Z); |
8126 | |
8127 | // Use Brent's algorithm to find the doca to the wire |
8128 | DMatrix5x1 myS=Ss; |
8129 | DMatrix5x1 myS_temp=Ss; |
8130 | DMatrix5x5 myC=Cs; |
8131 | double mydz; |
8132 | double z=traj.z; |
8133 | DVector2 origin=hit->origin; |
8134 | DVector2 dir=hit->dir; |
8135 | double z0wire=hit->z0wire; |
8136 | if(BrentForward(z,dEdx,z0wire,origin,dir,myS,mydz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8137 | if(DEBUG_HISTS)alignDerivHists[23]->Fill(mydz); |
8138 | double new_z=z+mydz; |
8139 | DVector2 wirepos=origin+(new_z-z0wire)*dir; |
8140 | double cosstereo=hit->cosstereo; |
8141 | DVector2 xy(myS(state_x),myS(state_y)); |
8142 | |
8143 | DVector2 diff=xy-wirepos; |
8144 | double d=cosstereo*diff.Mod(); |
8145 | |
8146 | // If we are doing the alignment, we need to numerically calculate the derivatives |
8147 | // wrt the wire origin, direction, and the track parameters. |
8148 | vector<double> alignmentDerivatives; |
8149 | if (ALIGNMENT_FORWARD && hit->hit!=NULL__null){ |
8150 | double dzcut_min=0., dzcut_max=1.; |
8151 | DMatrix5x1 alignS=Ss; // We will mess with this one |
8152 | DVector3 wireDir = hit->hit->wire->udir; |
8153 | double cosstereo_shifted; |
8154 | double aligndz; |
8155 | alignmentDerivatives.resize(12); |
8156 | |
8157 | // Set t0 derivative |
8158 | alignmentDerivatives[CDCTrackD::dDdt0]=update.dDdt0; |
8159 | |
8160 | // Wire position shift |
8161 | double wposShift=0.025; |
8162 | double wdirShift=0.00005; |
8163 | |
8164 | // Shift each track parameter |
8165 | double shiftFraction=0.01; |
8166 | double shift_x=0.01; |
8167 | double shift_y=0.01; |
8168 | double shift_tx=shiftFraction*Ss(state_tx); |
8169 | double shift_ty=shiftFraction*Ss(state_ty);; |
8170 | double shift_q_over_p=shiftFraction*Ss(state_q_over_p); |
8171 | |
8172 | // Some data containers we don't need multiples of |
8173 | double z0_shifted, new_z_shifted; |
8174 | DVector2 shift, origin_shifted, dir_shifted, wirepos_shifted, diff_shifted, xy_shifted; |
8175 | |
8176 | // The DOCA for the shifted states == f(x+h) |
8177 | double d_dOriginX=0., d_dOriginY=0., d_dOriginZ=0.; |
8178 | double d_dDirX=0., d_dDirY=0., d_dDirZ=0.; |
8179 | double d_dS0=0., d_dS1=0., d_dS2=0., d_dS3=0., d_dS4=0.; |
8180 | // Let's do the wire shifts first |
8181 | |
8182 | //dOriginX |
8183 | alignS=Ss; |
8184 | aligndz=0.; |
8185 | shift.Set(wposShift, 0.); |
8186 | origin_shifted=origin+shift; |
8187 | dir_shifted=dir; |
8188 | z0_shifted=z0wire; |
8189 | if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8190 | if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE; |
8191 | //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8192 | new_z_shifted=z+aligndz; |
8193 | wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted; |
8194 | xy_shifted.Set(alignS(state_x),alignS(state_y)); |
8195 | diff_shifted=xy_shifted-wirepos_shifted; |
8196 | d_dOriginX=cosstereo*diff_shifted.Mod()+EPS3.0e-8; |
8197 | alignmentDerivatives[CDCTrackD::dDOCAdOriginX] = (d_dOriginX - d)/wposShift; |
8198 | if(DEBUG_HISTS){ |
8199 | alignDerivHists[24]->Fill(aligndz); |
8200 | alignDerivHists[35]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginX]); |
8201 | brentCheckHists[0]->Fill(aligndz,d_dOriginX); |
8202 | } |
8203 | |
8204 | //dOriginY |
8205 | alignS=Ss; |
8206 | aligndz=0.; |
8207 | shift.Set(0.,wposShift); |
8208 | origin_shifted=origin+shift; |
8209 | dir_shifted=dir; |
8210 | z0_shifted=z0wire; |
8211 | if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8212 | if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE; |
8213 | //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8214 | new_z_shifted=z+aligndz; |
8215 | wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted; |
8216 | xy_shifted.Set(alignS(state_x),alignS(state_y)); |
8217 | diff_shifted=xy_shifted-wirepos_shifted; |
8218 | d_dOriginY=cosstereo*diff_shifted.Mod()+EPS3.0e-8; |
8219 | alignmentDerivatives[CDCTrackD::dDOCAdOriginY] = (d_dOriginY - d)/wposShift; |
8220 | if(DEBUG_HISTS){ |
8221 | alignDerivHists[25]->Fill(aligndz); |
8222 | alignDerivHists[36]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginY]); |
8223 | brentCheckHists[0]->Fill(aligndz,d_dOriginY); |
8224 | } |
8225 | |
8226 | //dOriginZ |
8227 | alignS=Ss; |
8228 | aligndz=0.; |
8229 | origin_shifted=origin; |
8230 | dir_shifted=dir; |
8231 | z0_shifted=z0wire+wposShift; |
8232 | if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8233 | if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE; |
8234 | //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8235 | new_z_shifted=z+aligndz; |
8236 | wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted; |
8237 | xy_shifted.Set(alignS(state_x),alignS(state_y)); |
8238 | diff_shifted=xy_shifted-wirepos_shifted; |
8239 | d_dOriginZ=cosstereo*diff_shifted.Mod()+EPS3.0e-8; |
8240 | alignmentDerivatives[CDCTrackD::dDOCAdOriginZ] = (d_dOriginZ - d)/wposShift; |
8241 | if(DEBUG_HISTS){ |
8242 | alignDerivHists[26]->Fill(aligndz); |
8243 | alignDerivHists[37]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdOriginZ]); |
8244 | brentCheckHists[0]->Fill(aligndz,d_dOriginZ); |
8245 | } |
8246 | |
8247 | //dDirX |
8248 | alignS=Ss; |
8249 | aligndz=0.; |
8250 | shift.Set(wdirShift,0.); |
8251 | origin_shifted=origin; |
8252 | z0_shifted=z0wire; |
8253 | dir_shifted=dir+shift; |
8254 | cosstereo_shifted = cos((wireDir+DVector3(wdirShift,0.,0.)).Angle(DVector3(0.,0.,1.))); |
8255 | if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8256 | if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE; |
8257 | //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8258 | new_z_shifted=z+aligndz; |
8259 | wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted; |
8260 | xy_shifted.Set(alignS(state_x),alignS(state_y)); |
8261 | diff_shifted=xy_shifted-wirepos_shifted; |
8262 | d_dDirX=cosstereo_shifted*diff_shifted.Mod()+EPS3.0e-8; |
8263 | alignmentDerivatives[CDCTrackD::dDOCAdDirX] = (d_dDirX - d)/wdirShift; |
8264 | if(DEBUG_HISTS){ |
8265 | alignDerivHists[27]->Fill(aligndz); |
8266 | alignDerivHists[38]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirX]); |
8267 | } |
8268 | |
8269 | //dDirY |
8270 | alignS=Ss; |
8271 | aligndz=0.; |
8272 | shift.Set(0.,wdirShift); |
8273 | origin_shifted=origin; |
8274 | z0_shifted=z0wire; |
8275 | dir_shifted=dir+shift; |
8276 | cosstereo_shifted = cos((wireDir+DVector3(0.,wdirShift,0.)).Angle(DVector3(0.,0.,1.))); |
8277 | if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8278 | if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE; |
8279 | //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8280 | new_z_shifted=z+aligndz; |
8281 | wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted; |
8282 | xy_shifted.Set(alignS(state_x),alignS(state_y)); |
8283 | diff_shifted=xy_shifted-wirepos_shifted; |
8284 | d_dDirY=cosstereo_shifted*diff_shifted.Mod()+EPS3.0e-8; |
8285 | alignmentDerivatives[CDCTrackD::dDOCAdDirY] = (d_dDirY - d)/wdirShift; |
8286 | if(DEBUG_HISTS){ |
8287 | alignDerivHists[28]->Fill(aligndz); |
8288 | alignDerivHists[39]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirY]); |
8289 | } |
8290 | |
8291 | //dDirZ - This is divided out in this code |
8292 | alignS=Ss; |
8293 | aligndz=0.; |
8294 | origin_shifted=origin; |
8295 | dir_shifted.Set(wireDir.X()/(wireDir.Z()+wdirShift), wireDir.Y()/(wireDir.Z()+wdirShift)); |
8296 | z0_shifted=z0wire; |
8297 | cosstereo_shifted = cos((wireDir+DVector3(0.,0.,wdirShift)).Angle(DVector3(0.,0.,1.))); |
8298 | if(BrentForward(z,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8299 | if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE; |
8300 | //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0_shifted,origin_shifted,dir_shifted,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8301 | new_z_shifted=z+aligndz; |
8302 | wirepos_shifted=origin_shifted+(new_z_shifted-z0_shifted)*dir_shifted; |
8303 | xy_shifted.Set(alignS(state_x),alignS(state_y)); |
8304 | diff_shifted=xy_shifted-wirepos_shifted; |
8305 | d_dDirZ=cosstereo_shifted*diff_shifted.Mod()+EPS3.0e-8; |
8306 | alignmentDerivatives[CDCTrackD::dDOCAdDirZ] = (d_dDirZ - d)/wdirShift; |
8307 | if(DEBUG_HISTS){ |
8308 | alignDerivHists[29]->Fill(aligndz); |
8309 | alignDerivHists[40]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdDirZ]); |
8310 | } |
8311 | |
8312 | // And now the derivatives wrt the track parameters |
8313 | |
8314 | DMatrix5x1 trackShiftS0(shift_x, 0., 0., 0., 0.); |
8315 | DMatrix5x1 trackShiftS1(0., shift_y, 0., 0., 0.); |
8316 | DMatrix5x1 trackShiftS2(0., 0., shift_tx, 0., 0.); |
8317 | DMatrix5x1 trackShiftS3(0., 0., 0., shift_ty, 0.); |
8318 | DMatrix5x1 trackShiftS4(0., 0., 0., 0., shift_q_over_p); |
8319 | |
8320 | // dS0 |
8321 | alignS=Ss+trackShiftS0; |
8322 | aligndz=0.; |
8323 | if(BrentForward(z,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8324 | if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE; |
8325 | //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8326 | new_z_shifted=z+aligndz; |
8327 | wirepos_shifted=origin+(new_z_shifted-z0wire)*dir; |
8328 | xy_shifted.Set(alignS(state_x),alignS(state_y)); |
8329 | diff_shifted=xy_shifted-wirepos_shifted; |
8330 | d_dS0=cosstereo*diff_shifted.Mod()+EPS3.0e-8; |
8331 | alignmentDerivatives[CDCTrackD::dDOCAdS0] = (d_dS0 - d)/shift_x; |
8332 | if(DEBUG_HISTS){ |
8333 | alignDerivHists[30]->Fill(aligndz); |
8334 | alignDerivHists[41]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS0]); |
8335 | } |
8336 | |
8337 | // dS1 |
8338 | alignS=Ss+trackShiftS1; |
8339 | aligndz=0.; |
8340 | if(BrentForward(z,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8341 | if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE; |
8342 | //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8343 | new_z_shifted=z+aligndz; |
8344 | wirepos_shifted=origin+(new_z_shifted-z0wire)*dir; |
8345 | xy_shifted.Set(alignS(state_x),alignS(state_y)); |
8346 | diff_shifted=xy_shifted-wirepos_shifted; |
8347 | d_dS1=cosstereo*diff_shifted.Mod()+EPS3.0e-8; |
8348 | alignmentDerivatives[CDCTrackD::dDOCAdS1] = (d_dS1 - d)/shift_y; |
8349 | if(DEBUG_HISTS){ |
8350 | alignDerivHists[31]->Fill(aligndz); |
8351 | alignDerivHists[42]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS1]); |
8352 | } |
8353 | |
8354 | // dS2 |
8355 | alignS=Ss+trackShiftS2; |
8356 | aligndz=0.; |
8357 | if(BrentForward(z,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8358 | if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE; |
8359 | //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8360 | new_z_shifted=z+aligndz; |
8361 | wirepos_shifted=origin+(new_z_shifted-z0wire)*dir; |
8362 | xy_shifted.Set(alignS(state_x),alignS(state_y)); |
8363 | diff_shifted=xy_shifted-wirepos_shifted; |
8364 | d_dS2=cosstereo*diff_shifted.Mod()+EPS3.0e-8; |
8365 | alignmentDerivatives[CDCTrackD::dDOCAdS2] = (d_dS2 - d)/shift_tx; |
8366 | if(DEBUG_HISTS){ |
8367 | alignDerivHists[32]->Fill(aligndz); |
8368 | alignDerivHists[43]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS2]); |
8369 | } |
8370 | |
8371 | // dS3 |
8372 | alignS=Ss+trackShiftS3; |
8373 | aligndz=0.; |
8374 | if(BrentForward(z,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8375 | if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE; |
8376 | //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8377 | new_z_shifted=z+aligndz; |
8378 | wirepos_shifted=origin+(new_z_shifted-z0wire)*dir; |
8379 | xy_shifted.Set(alignS(state_x),alignS(state_y)); |
8380 | diff_shifted=xy_shifted-wirepos_shifted; |
8381 | d_dS3=cosstereo*diff_shifted.Mod()+EPS3.0e-8; |
8382 | alignmentDerivatives[CDCTrackD::dDOCAdS3] = (d_dS3 - d)/shift_ty; |
8383 | if(DEBUG_HISTS){ |
8384 | alignDerivHists[33]->Fill(aligndz); |
8385 | alignDerivHists[44]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS3]); |
8386 | } |
8387 | |
8388 | // dS4 |
8389 | alignS=Ss+trackShiftS4; |
8390 | aligndz=0.; |
8391 | if(BrentForward(z,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8392 | if(aligndz < dzcut_min || aligndz > dzcut_max) return VALUE_OUT_OF_RANGE; |
8393 | //if(BrentsAlgorithm(z,-mStepSizeZ,dEdx,z0wire,origin,dir,alignS,aligndz) != NOERROR) return VALUE_OUT_OF_RANGE; |
8394 | new_z_shifted=z+aligndz; |
8395 | wirepos_shifted=origin+(new_z_shifted-z0wire)*dir; |
8396 | xy_shifted.Set(alignS(state_x),alignS(state_y)); |
8397 | diff_shifted=xy_shifted-wirepos_shifted; |
8398 | d_dS4=cosstereo*diff_shifted.Mod()+EPS3.0e-8; |
8399 | alignmentDerivatives[CDCTrackD::dDOCAdS4] = (d_dS4 - d)/shift_q_over_p; |
8400 | if(DEBUG_HISTS){ |
8401 | alignDerivHists[34]->Fill(aligndz); |
8402 | alignDerivHists[45]->Fill(alignmentDerivatives[CDCTrackD::dDOCAdS4]); |
8403 | } |
8404 | } |
8405 | |
8406 | // Find the field and gradient at (old_x,old_y,old_z) and compute the |
8407 | // Jacobian matrix for transforming from S to myS |
8408 | bfield->GetFieldAndGradient(Ss(state_x),Ss(state_y),z, |
8409 | Bx,By,Bz,dBxdx,dBxdy,dBxdz,dBydx, |
8410 | dBydy,dBydz,dBzdx,dBzdy,dBzdz); |
8411 | DMatrix5x5 Jc; |
8412 | StepJacobian(z,new_z,Ss,dEdx,Jc); |
8413 | |
8414 | // Find the projection matrix |
8415 | DMatrix5x1 H_T; |
8416 | double cosstereo2_over_d=cosstereo*cosstereo/d; |
8417 | H_T(state_x)=diff.X()*cosstereo2_over_d; |
8418 | H_T(state_y)=diff.Y()*cosstereo2_over_d; |
8419 | DMatrix1x5 H; |
8420 | H(state_x)=H_T(state_x); |
8421 | H(state_y)=H_T(state_y); |
8422 | |
8423 | // Find the variance for this hit |
8424 | |
8425 | bool skip_ring=(hit->hit->wire->ring==RING_TO_SKIP); |
8426 | |
8427 | double V=update.variance; |
8428 | myC=Jc*myC*Jc.Transpose(); |
8429 | if (skip_ring) V+=H*myC*H_T; |
8430 | else V-=H*myC*H_T; |
8431 | |
8432 | if (DEBUG_LEVEL>1 && (!isfinite(V) || V < 0.0) ) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<8432<<" " << " Problem: V is " << V << endl; |
8433 | |
8434 | double tx=Ss(state_tx); |
8435 | double ty=Ss(state_ty); |
8436 | double scale=1./sqrt(1.+tx*tx+ty*ty); |
8437 | double cosThetaRel=hit->hit->wire->udir.Dot(DVector3(scale*tx,scale*ty,scale)); |
8438 | |
8439 | pull_t thisPull(update.doca-d,sqrt(V),traj.s,update.tdrift,d,hit->hit, |
8440 | NULL__null,diff.Phi(),new_z,cosThetaRel,update.tcorr); |
8441 | thisPull.AddTrackDerivatives(alignmentDerivatives); |
8442 | my_pulls.push_back(thisPull); |
8443 | return NOERROR; |
8444 | } |
8445 | |
8446 | // Transform the 5x5 covariance matrix from the forward parametrization to the |
8447 | // central parametrization. |
8448 | void DTrackFitterKalmanSIMD::TransformCovariance(DMatrix5x5 &C){ |
8449 | DMatrix5x5 J; |
8450 | double tsquare=tx_*tx_+ty_*ty_; |
8451 | double cosl=cos(atan(tanl_)); |
8452 | double tanl2=tanl_*tanl_; |
8453 | double tanl3=tanl2*tanl_; |
8454 | double factor=1./sqrt(1.+tsquare); |
8455 | J(state_z,state_x)=tx_/tsquare; |
8456 | J(state_z,state_y)=ty_/tsquare; |
8457 | double diff=tx_*tx_-ty_*ty_; |
8458 | double frac=1./(tsquare*tsquare); |
8459 | J(state_z,state_tx)=-(x_*diff+2.*tx_*ty_*y_)*frac; |
8460 | J(state_z,state_ty)=-(2.*tx_*ty_*x_-y_*diff)*frac; |
8461 | J(state_tanl,state_tx)=-tx_*tanl3; |
8462 | J(state_tanl,state_ty)=-ty_*tanl3; |
8463 | J(state_q_over_pt,state_q_over_p)=1./cosl; |
8464 | J(state_q_over_pt,state_tx)=-q_over_p_*tx_*tanl3*factor; |
8465 | J(state_q_over_pt,state_ty)=-q_over_p_*ty_*tanl3*factor; |
8466 | J(state_phi,state_tx)=-ty_*tanl2; |
8467 | J(state_phi,state_ty)=tx_*tanl2; |
8468 | J(state_D,state_x)=x_/D_; |
8469 | J(state_D,state_y)=y_/D_; |
8470 | |
8471 | C=J*C*J.Transpose(); |
8472 | |
8473 | } |
8474 | |
8475 | jerror_t DTrackFitterKalmanSIMD::BrentForward(double z, double dedx, const double z0w, |
8476 | const DVector2 &origin, const DVector2 &dir, DMatrix5x1 &S, double &dz){ |
8477 | |
8478 | DVector2 wirepos=origin; |
8479 | wirepos+=(z-z0w)*dir; |
8480 | double dx=S(state_x)-wirepos.X(); |
8481 | double dy=S(state_y)-wirepos.Y(); |
8482 | double doca2 = dx*dx+dy*dy; |
8483 | |
8484 | if (BrentsAlgorithm(z,-mStepSizeZ,dedx,z0w,origin,dir,S,dz)!=NOERROR){ |
8485 | return VALUE_OUT_OF_RANGE; |
8486 | } |
8487 | |
8488 | double newz = z+dz; |
8489 | unsigned int maxSteps=5; |
8490 | unsigned int stepCounter=0; |
8491 | if (fabs(dz)<EPS31.e-2){ |
8492 | // doca |
8493 | double old_doca2=doca2; |
8494 | |
8495 | double ztemp=newz; |
8496 | newz=ztemp-mStepSizeZ; |
8497 | Step(ztemp,newz,dedx,S); |
8498 | // new wire position |
8499 | wirepos=origin; |
8500 | wirepos+=(newz-z0w)*dir; |
8501 | |
8502 | dx=S(state_x)-wirepos.X(); |
8503 | dy=S(state_y)-wirepos.Y(); |
8504 | doca2=dx*dx+dy*dy; |
8505 | ztemp=newz; |
8506 | |
8507 | while(doca2<old_doca2 && stepCounter<maxSteps){ |
8508 | newz=ztemp-mStepSizeZ; |
8509 | old_doca2=doca2; |
8510 | |
8511 | // Step to the new z position |
8512 | Step(ztemp,newz,dedx,S); |
8513 | stepCounter++; |
8514 | |
8515 | // find the new distance to the wire |
8516 | wirepos=origin; |
8517 | wirepos+=(newz-z0w)*dir; |
8518 | |
8519 | dx=S(state_x)-wirepos.X(); |
8520 | dy=S(state_y)-wirepos.Y(); |
8521 | doca2=dx*dx+dy*dy; |
8522 | |
8523 | ztemp=newz; |
8524 | } |
8525 | |
8526 | // Find the true doca |
8527 | double dz2=0.; |
8528 | if (BrentsAlgorithm(newz,-mStepSizeZ,dedx,z0w,origin,dir,S,dz2)!=NOERROR){ |
8529 | return VALUE_OUT_OF_RANGE; |
8530 | } |
8531 | newz=ztemp+dz2; |
8532 | |
8533 | // Change in z relative to where we started for this wire |
8534 | dz=newz-z; |
8535 | } |
8536 | else if (fabs(dz)>2.*mStepSizeZ-EPS31.e-2){ |
8537 | // whoops, looks like we didn't actually bracket the minimum |
8538 | // after all. Swim to make sure we pass the minimum doca. |
8539 | |
8540 | double ztemp=newz; |
8541 | // new wire position |
8542 | wirepos=origin; |
8543 | wirepos+=(ztemp-z0w)*dir; |
8544 | |
8545 | // doca |
8546 | double old_doca2=doca2; |
8547 | |
8548 | dx=S(state_x)-wirepos.X(); |
8549 | dy=S(state_y)-wirepos.Y(); |
8550 | doca2=dx*dx+dy*dy; |
8551 | |
8552 | while(doca2<old_doca2 && stepCounter<10*maxSteps){ |
8553 | newz=ztemp+mStepSizeZ; |
8554 | old_doca2=doca2; |
8555 | |
8556 | // Step to the new z position |
8557 | Step(ztemp,newz,dedx,S); |
8558 | stepCounter++; |
8559 | |
8560 | // find the new distance to the wire |
8561 | wirepos=origin; |
8562 | wirepos+=(newz-z0w)*dir; |
8563 | |
8564 | dx=S(state_x)-wirepos.X(); |
8565 | dy=S(state_y)-wirepos.Y(); |
8566 | doca2=dx*dx+dy*dy; |
8567 | |
8568 | ztemp=newz; |
8569 | } |
8570 | |
8571 | // Find the true doca |
8572 | double dz2=0.; |
8573 | if (BrentsAlgorithm(newz,mStepSizeZ,dedx,z0w,origin,dir,S,dz2)!=NOERROR){ |
8574 | return VALUE_OUT_OF_RANGE; |
8575 | } |
8576 | newz=ztemp+dz2; |
8577 | |
8578 | // Change in z relative to where we started for this wire |
8579 | dz=newz-z; |
8580 | } |
8581 | return NOERROR; |
8582 | } |
8583 | |
8584 | jerror_t DTrackFitterKalmanSIMD::BrentCentral(double dedx, DVector2 &xy, const double z0w, const DVector2 &origin, const DVector2 &dir, DMatrix5x1 &Sc, double &ds){ |
8585 | |
8586 | DVector2 wirexy=origin; |
8587 | wirexy+=(Sc(state_z)-z0w)*dir; |
8588 | |
8589 | // new doca |
8590 | double doca2=(xy-wirexy).Mod2(); |
8591 | double old_doca2=doca2; |
Value stored to 'old_doca2' during its initialization is never read | |
8592 | |
8593 | if (BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dedx,xy,z0w, |
8594 | origin,dir,Sc,ds)!=NOERROR){ |
8595 | return VALUE_OUT_OF_RANGE; |
8596 | } |
8597 | |
8598 | unsigned int maxSteps=3; |
8599 | unsigned int stepCounter=0; |
8600 | |
8601 | if (fabs(ds)<EPS31.e-2){ |
8602 | double my_ds=ds; |
8603 | old_doca2=doca2; |
8604 | Step(xy,-mStepSizeS,Sc,dedx); |
8605 | my_ds-=mStepSizeS; |
8606 | wirexy=origin; |
8607 | wirexy+=(Sc(state_z)-z0w)*dir; |
8608 | doca2=(xy-wirexy).Mod2(); |
8609 | while(doca2<old_doca2 && stepCounter<maxSteps){ |
8610 | old_doca2=doca2; |
8611 | // Bail if the transverse momentum has dropped below some minimum |
8612 | if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){ |
8613 | return VALUE_OUT_OF_RANGE; |
8614 | } |
8615 | |
8616 | // Step through the field |
8617 | Step(xy,-mStepSizeS,Sc,dedx); |
8618 | stepCounter++; |
8619 | |
8620 | wirexy=origin; |
8621 | wirexy+=(Sc(state_z)-z0w)*dir; |
8622 | doca2=(xy-wirexy).Mod2(); |
8623 | |
8624 | my_ds-=mStepSizeS; |
8625 | } |
8626 | // Swim to the "true" doca |
8627 | double ds2=0.; |
8628 | if (BrentsAlgorithm(-mStepSizeS,-mStepSizeS,dedx,xy,z0w, |
8629 | origin,dir,Sc,ds2)!=NOERROR){ |
8630 | return VALUE_OUT_OF_RANGE; |
8631 | } |
8632 | ds=my_ds+ds2; |
8633 | } |
8634 | else if (fabs(ds)>2*mStepSizeS-EPS31.e-2){ |
8635 | double my_ds=ds; |
8636 | |
8637 | // new wire position |
8638 | wirexy=origin; |
8639 | wirexy+=(Sc(state_z)-z0w)*dir; |
8640 | |
8641 | // doca |
8642 | old_doca2=doca2; |
8643 | doca2=(xy-wirexy).Mod2(); |
8644 | |
8645 | while(doca2<old_doca2 && stepCounter<maxSteps){ |
8646 | old_doca2=doca2; |
8647 | |
8648 | // Bail if the transverse momentum has dropped below some minimum |
8649 | if (fabs(Sc(state_q_over_pt))>Q_OVER_PT_MAX100.){ |
8650 | return VALUE_OUT_OF_RANGE; |
8651 | } |
8652 | |
8653 | // Step through the field |
8654 | Step(xy,mStepSizeS,Sc,dedx); |
8655 | stepCounter++; |
8656 | |
8657 | // Find the new distance to the wire |
8658 | wirexy=origin; |
8659 | wirexy+=(Sc(state_z)-z0w)*dir; |
8660 | doca2=(xy-wirexy).Mod2(); |
8661 | |
8662 | my_ds+=mStepSizeS; |
8663 | } |
8664 | // Swim to the "true" doca |
8665 | double ds2=0.; |
8666 | if (BrentsAlgorithm(mStepSizeS,mStepSizeS,dedx,xy,z0w, |
8667 | origin,dir,Sc,ds2)!=NOERROR){ |
8668 | return VALUE_OUT_OF_RANGE; |
8669 | } |
8670 | ds=my_ds+ds2; |
8671 | } |
8672 | return NOERROR; |
8673 | } |
8674 | |
8675 | // Find extrapolations to detectors outside of the tracking volume |
8676 | jerror_t DTrackFitterKalmanSIMD::ExtrapolateToOuterDetectors(const DMatrix5x1 &S0){ |
8677 | DMatrix5x1 S=S0; |
8678 | // Energy loss |
8679 | double dEdx=0.; |
8680 | |
8681 | // material properties |
8682 | double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.; |
8683 | |
8684 | // Position variables |
8685 | double z=forward_traj[0].z; |
8686 | double newz=z,dz=0.; |
8687 | |
8688 | // Current time and path length |
8689 | double t=forward_traj[0].t; |
8690 | double s=forward_traj[0].s; |
8691 | |
8692 | // Store the position and momentum at the exit to the tracking volume |
8693 | AddExtrapolation(SYS_NULL,z,S,t,s); |
8694 | |
8695 | // Loop to propagate track to outer detectors |
8696 | const double z_outer_max=1000.; |
8697 | const double x_max=130.; |
8698 | const double y_max=130.; |
8699 | const double fcal_radius_sq=120.47*120.47; |
8700 | bool hit_tof=false; |
8701 | bool hit_dirc=false; |
8702 | bool hit_fcal=false; |
8703 | bool got_fmwpc=(dFMWPCz_vec.size()>0)?true:false; |
8704 | unsigned int fmwpc_index=0; |
8705 | unsigned int trd_index=0; |
8706 | while (z>Z_MIN-100. && z<z_outer_max && fabs(S(state_x))<x_max |
8707 | && fabs(S(state_y))<y_max){ |
8708 | // Bail if the momentum has dropped below some minimum |
8709 | if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){ |
8710 | if (DEBUG_LEVEL>2) |
8711 | { |
8712 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<8712<<" " << "Bailing: P = " << 1./fabs(S(state_q_over_p)) |
8713 | << endl; |
8714 | } |
8715 | return VALUE_OUT_OF_RANGE; |
8716 | } |
8717 | |
8718 | // Check if we have passed into the BCAL |
8719 | double r2=S(state_x)*S(state_x)+S(state_y)*S(state_y); |
8720 | if (r2>89.*89. && z<400.) return VALUE_OUT_OF_RANGE; |
8721 | if (r2>64.9*64.9 && r2<89.*89.){ |
8722 | if (extrapolations.at(SYS_BCAL).size()>299){ |
8723 | return VALUE_OUT_OF_RANGE; |
8724 | } |
8725 | if (z<406.){ |
8726 | AddExtrapolation(SYS_BCAL,z,S,t,s); |
8727 | } |
8728 | else if (extrapolations.at(SYS_BCAL).size()<5){ |
8729 | // There needs to be some steps inside the the volume of the BCAL for |
8730 | // the extrapolation to be useful. If this is not the case, clear |
8731 | // the extrapolation vector. |
8732 | extrapolations[SYS_BCAL].clear(); |
8733 | } |
8734 | } |
8735 | |
8736 | // Relationship between arc length and z |
8737 | double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx) |
8738 | +S(state_ty)*S(state_ty)); |
8739 | |
8740 | // get material properties from the Root Geometry |
8741 | DVector3 pos(S(state_x),S(state_y),z); |
8742 | DVector3 dir(S(state_tx),S(state_ty),1.); |
8743 | double s_to_boundary=0.; |
8744 | if (geom->FindMatKalman(pos,dir,K_rho_Z_over_A,rho_Z_over_A,LnI,Z, |
8745 | last_material_map,&s_to_boundary) |
8746 | !=NOERROR){ |
8747 | if (DEBUG_LEVEL>0) |
8748 | { |
8749 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<8749<<" " << "Material error in ExtrapolateForwardToOuterDetectors!"<< endl; |
8750 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<8750<<" " << " Position (x,y,z)=("<<pos.x()<<","<<pos.y()<<","<<pos.z()<<")" |
8751 | <<endl; |
8752 | } |
8753 | return VALUE_OUT_OF_RANGE; |
8754 | } |
8755 | |
8756 | // Get dEdx for the upcoming step |
8757 | if (CORRECT_FOR_ELOSS){ |
8758 | dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI,Z); |
8759 | } |
8760 | |
8761 | // Adjust the step size |
8762 | double ds=mStepSizeS; |
8763 | if (fabs(dEdx)>EPS3.0e-8){ |
8764 | ds=DE_PER_STEP0.001/fabs(dEdx); |
8765 | } |
8766 | if (ds>mStepSizeS) ds=mStepSizeS; |
8767 | if (s_to_boundary<ds) ds=s_to_boundary; |
8768 | if (ds<MIN_STEP_SIZE0.1) ds=MIN_STEP_SIZE0.1; |
8769 | if (ds<0.5 && z<406. && r2>65.*65.) ds=0.5; |
8770 | dz=ds*dz_ds; |
8771 | newz=z+dz; |
8772 | if (trd_index<dTRDz_vec.size() && newz>dTRDz_vec[trd_index]){ |
8773 | newz=dTRDz_vec[trd_index]+EPS3.0e-8; |
8774 | ds=(newz-z)/dz_ds; |
8775 | } |
8776 | if (hit_tof==false && newz>dTOFz){ |
8777 | newz=dTOFz+EPS3.0e-8; |
8778 | ds=(newz-z)/dz_ds; |
8779 | } |
8780 | if (hit_dirc==false && newz>dDIRCz){ |
8781 | newz=dDIRCz+EPS3.0e-8; |
8782 | ds=(newz-z)/dz_ds; |
8783 | } |
8784 | if (hit_fcal==false && newz>dFCALz){ |
8785 | newz=dFCALz+EPS3.0e-8; |
8786 | ds=(newz-z)/dz_ds; |
8787 | } |
8788 | if (fmwpc_index<dFMWPCz_vec.size()&&newz>dFMWPCz_vec[fmwpc_index]){ |
8789 | newz=dFMWPCz_vec[fmwpc_index]+EPS3.0e-8; |
8790 | ds=(newz-z)/dz_ds; |
8791 | } |
8792 | if (got_fmwpc&&newz>dCTOFz){ |
8793 | newz=dCTOFz+EPS3.0e-8; |
8794 | ds=(newz-z)/dz_ds; |
8795 | } |
8796 | s+=ds; |
8797 | |
8798 | // Flight time |
8799 | double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p); |
8800 | double one_over_beta2=1.+mass2*q_over_p_sq; |
8801 | if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8; |
8802 | t+=ds*sqrt(one_over_beta2); // in units where c=1 |
8803 | |
8804 | // Step through field |
8805 | Step(z,newz,dEdx,S); |
8806 | z=newz; |
8807 | |
8808 | if (trd_index<dTRDz_vec.size() && newz>dTRDz_vec[trd_index]){ |
8809 | AddExtrapolation(SYS_TRD,z,S,t,s); |
8810 | trd_index++; |
8811 | } |
8812 | if (hit_dirc==false && newz>dDIRCz){ |
8813 | hit_dirc=true; |
8814 | AddExtrapolation(SYS_DIRC,z,S,t,s); |
8815 | } |
8816 | if (hit_tof==false && newz>dTOFz){ |
8817 | hit_tof=true; |
8818 | AddExtrapolation(SYS_TOF,z,S,t,s); |
8819 | } |
8820 | if (hit_fcal==false && newz>dFCALz){ |
8821 | double r2=S(state_x)*S(state_x)+S(state_y)*S(state_y); |
8822 | if (r2>fcal_radius_sq) return NOERROR; |
8823 | |
8824 | hit_fcal=true; |
8825 | AddExtrapolation(SYS_FCAL,z,S,t,s); |
8826 | |
8827 | // Propagate the track to the back of the FCAL block |
8828 | int num=int(45./dz); |
8829 | int m=0; |
8830 | for (;m<num;m++){ |
8831 | // propagate t and s to back of FCAL block |
8832 | double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p); |
8833 | double one_over_beta2=1.+mass2*q_over_p_sq; |
8834 | if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8; |
8835 | ds=dz*sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty)); |
8836 | t+=ds*sqrt(one_over_beta2); // in units where c=1 |
8837 | s+=ds; |
8838 | |
8839 | newz=z+dz; |
8840 | // Step through field |
8841 | Step(z,newz,dEdx,S); |
8842 | z=newz; |
8843 | |
8844 | r2=S(state_x)*S(state_x)+S(state_y)*S(state_y); |
8845 | if (r2>fcal_radius_sq){ |
8846 | // Break out of the loop if the track exits out of the FCAL before |
8847 | // reaching the back end of the block |
8848 | break; |
8849 | } |
8850 | } |
8851 | if (m==num){ |
8852 | newz=dFCALzBack; |
8853 | |
8854 | // Propagate t and s to back of FCAL block |
8855 | double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p); |
8856 | double one_over_beta2=1.+mass2*q_over_p_sq; |
8857 | if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8; |
8858 | dz=newz-z; |
8859 | ds=dz*sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty)); |
8860 | t+=ds*sqrt(one_over_beta2); // in units where c=1 |
8861 | s+=ds; |
8862 | |
8863 | // Step through field |
8864 | Step(z,newz,dEdx,S); |
8865 | z=newz; |
8866 | } |
8867 | // add another extrapolation point at downstream end of FCAL |
8868 | AddExtrapolation(SYS_FCAL,z,S,t,s); |
8869 | // .. and exit if the muon detector is not installed |
8870 | if (got_fmwpc==false) return NOERROR; |
8871 | } |
8872 | // Deal with muon detector |
8873 | if (hit_fcal==true |
8874 | && (fabs(S(state_x))>dFMWPCsize || (fabs(S(state_y))>dFMWPCsize))){ |
8875 | return NOERROR; |
8876 | } |
8877 | if (fmwpc_index<dFMWPCz_vec.size() && newz>dFMWPCz_vec[fmwpc_index]){ |
8878 | AddExtrapolation(SYS_FMWPC,z,S,t,s); |
8879 | fmwpc_index++; |
8880 | } |
8881 | if (got_fmwpc && newz>dCTOFz){ |
8882 | AddExtrapolation(SYS_CTOF,z,S,t,s); |
8883 | return NOERROR; |
8884 | } |
8885 | } |
8886 | |
8887 | return NOERROR; |
8888 | } |
8889 | |
8890 | // Find extrapolations to detector layers within the tracking volume and |
8891 | // inward (toward the target). |
8892 | jerror_t DTrackFitterKalmanSIMD::ExtrapolateToInnerDetectors(){ |
8893 | // First deal with start counter. Only do this if the track has a chance |
8894 | // to intersect with the start counter volume. |
8895 | unsigned int inner_index=forward_traj.size()-1; |
8896 | unsigned int index_beyond_start_counter=inner_index; |
8897 | DMatrix5x1 S=forward_traj[inner_index].S; |
8898 | bool intersected_start_counter=false; |
8899 | if (sc_norm.empty()==false |
8900 | && S(state_x)*S(state_x)+S(state_y)*S(state_y)<SC_BARREL_R2 |
8901 | && forward_traj[inner_index].z<SC_END_NOSE_Z){ |
8902 | double d_old=1000.,d=1000.,z=0.; |
8903 | unsigned int index=0; |
8904 | for (unsigned int m=0;m<12;m++){ |
8905 | unsigned int k=inner_index; |
8906 | for (;k>1;k--){ |
8907 | S=forward_traj[k].S; |
8908 | z=forward_traj[k].z; |
8909 | |
8910 | double dphi=atan2(S(state_y),S(state_x))-SC_PHI_SECTOR1; |
8911 | if (dphi<0) dphi+=2.*M_PI3.14159265358979323846; |
8912 | index=int(floor(dphi/(2.*M_PI3.14159265358979323846/30.))); |
8913 | if (index>29) index=0; |
8914 | d=sc_norm[index][m].Dot(DVector3(S(state_x),S(state_y),z) |
8915 | -sc_pos[index][m]); |
8916 | if (d*d_old<0){ // break if we cross the current plane |
8917 | if (m==0) index_beyond_start_counter=k; |
8918 | break; |
8919 | } |
8920 | d_old=d; |
8921 | } |
8922 | // if the z position would be beyond the current segment along z of |
8923 | // the start counter, move to the next plane |
8924 | if (z>sc_pos[index][m+1].z()&&m<11){ |
8925 | continue; |
8926 | } |
8927 | // allow for a little slop at the end of the nose |
8928 | else if (z<sc_pos[index][sc_pos[0].size()-1].z()+0.1){ |
8929 | // Hone in on intersection with the appropriate segment of the start |
8930 | // counter |
8931 | int count=0; |
8932 | DMatrix5x1 bestS=S; |
8933 | double dmin=d; |
8934 | double bestz=z; |
8935 | double t=forward_traj[k].t; |
8936 | double s=forward_traj[k].s; |
8937 | double bestt=t,bests=s; |
8938 | |
8939 | // Magnetic field |
8940 | bfield->GetField(S(state_x),S(state_y),z,Bx,By,Bz); |
8941 | |
8942 | while (fabs(d)>0.001 && count<20){ |
8943 | // track direction |
8944 | DVector3 phat(S(state_tx),S(state_ty),1); |
8945 | phat.SetMag(1.); |
8946 | |
8947 | // Step to the start counter plane |
8948 | double ds=d/sc_norm[index][m].Dot(phat); |
8949 | FastStep(z,-ds,0.,S); |
8950 | |
8951 | // Flight time |
8952 | double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p); |
8953 | double one_over_beta2=1.+mass2*q_over_p_sq; |
8954 | if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8; |
8955 | t-=ds*sqrt(one_over_beta2); // in units where c=1 |
8956 | s-=ds; |
8957 | |
8958 | // Find the index for the nearest start counter paddle |
8959 | double dphi=atan2(S(state_y),S(state_x))-SC_PHI_SECTOR1; |
8960 | if (dphi<0) dphi+=2.*M_PI3.14159265358979323846; |
8961 | index=int(floor(dphi/(2.*M_PI3.14159265358979323846/30.))); |
8962 | |
8963 | // Find the new distance to the start counter (which could now be to |
8964 | // a plane in the one adjacent to the one before the step...) |
8965 | d=sc_norm[index][m].Dot(DVector3(S(state_x),S(state_y),z) |
8966 | -sc_pos[index][m]); |
8967 | if (fabs(d)<fabs(dmin)){ |
8968 | bestS=S; |
8969 | dmin=d; |
8970 | bestz=z; |
8971 | bests=s; |
8972 | bestt=t; |
8973 | } |
8974 | count++; |
8975 | } |
8976 | AddExtrapolation(SYS_START,bestz,bestS,bestt,bests); |
8977 | intersected_start_counter=true; |
8978 | break; |
8979 | } |
8980 | } |
8981 | } |
8982 | // Accumulate multiple-scattering terms for use in matching routines |
8983 | double s_theta_ms_sum=0.; |
8984 | double theta2ms_sum=0.; |
8985 | if (intersected_start_counter){ |
8986 | for (unsigned int k=inner_index;k>index_beyond_start_counter;k--){ |
8987 | double ds_theta_ms_sq=3.*fabs(forward_traj[k].Q(state_x,state_x)); |
8988 | s_theta_ms_sum+=sqrt(ds_theta_ms_sq); |
8989 | double ds=forward_traj[k].s-forward_traj[k-1].s; |
8990 | theta2ms_sum+=ds_theta_ms_sq/(ds*ds); |
8991 | } |
8992 | } |
8993 | |
8994 | // Deal with points within fiducial volume of chambers |
8995 | unsigned int fdc_plane=0; |
8996 | mT0Detector=SYS_NULL; |
8997 | mT0MinimumDriftTime=1e6; |
8998 | for (int k=intersected_start_counter?index_beyond_start_counter:inner_index;k>=0;k--){ |
8999 | double z=forward_traj[k].z; |
9000 | double t=forward_traj[k].t; |
9001 | double s=forward_traj[k].s; |
9002 | DMatrix5x1 S=forward_traj[k].S; |
9003 | |
9004 | // Find estimate for t0 using earliest drift time |
9005 | if (forward_traj[k].h_id>999){ |
9006 | unsigned int index=forward_traj[k].h_id-1000; |
9007 | double dt=my_cdchits[index]->tdrift-t*TIME_UNIT_CONVERSION3.33564095198152014e-02; |
9008 | if (dt<mT0MinimumDriftTime){ |
9009 | mT0MinimumDriftTime=dt; |
9010 | mT0Detector=SYS_CDC; |
9011 | } |
9012 | } |
9013 | else if (forward_traj[k].h_id>0){ |
9014 | unsigned int index=forward_traj[k].h_id-1; |
9015 | double dt=my_fdchits[index]->t-t*TIME_UNIT_CONVERSION3.33564095198152014e-02; |
9016 | if (dt<mT0MinimumDriftTime){ |
9017 | mT0MinimumDriftTime=dt; |
9018 | mT0Detector=SYS_FDC; |
9019 | } |
9020 | } |
9021 | |
9022 | //multiple scattering terms |
9023 | if (k>0){ |
9024 | double ds_theta_ms_sq=3.*fabs(forward_traj[k].Q(state_x,state_x)); |
9025 | s_theta_ms_sum+=sqrt(ds_theta_ms_sq); |
9026 | double ds=forward_traj[k].s-forward_traj[k-1].s; |
9027 | theta2ms_sum+=ds_theta_ms_sq/(ds*ds); |
9028 | } |
9029 | // Extrapolations in CDC region |
9030 | if (z<endplate_z_downstream){ |
9031 | AddExtrapolation(SYS_CDC,z,S,t,s,s_theta_ms_sum,theta2ms_sum); |
9032 | } |
9033 | else{ // extrapolations in FDC region |
9034 | // output step near wire plane |
9035 | if (z>fdc_z_wires[fdc_plane]-0.25){ |
9036 | double dz=z-fdc_z_wires[fdc_plane]; |
9037 | //printf("extrp dz %f\n",dz); |
9038 | if (fabs(dz)>EPS21.e-4){ |
9039 | Step(z,fdc_z_wires[fdc_plane],0.,S); |
9040 | } |
9041 | AddExtrapolation(SYS_FDC,fdc_z_wires[fdc_plane],S,t,s,s_theta_ms_sum, |
9042 | theta2ms_sum); |
9043 | |
9044 | if (fdc_plane==23){ |
9045 | return NOERROR; |
9046 | } |
9047 | |
9048 | fdc_plane++; |
9049 | } |
9050 | } |
9051 | } |
9052 | |
9053 | |
9054 | //-------------------------------------------------------------------------- |
9055 | // The following code continues the extrapolations to wire planes that were |
9056 | // not included in the forward trajectory |
9057 | //-------------------------------------------------------------------------- |
9058 | |
9059 | // Material properties |
9060 | double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.; |
9061 | double chi2c_factor=0.,chi2a_factor=0.,chi2a_corr=0.; |
9062 | |
9063 | // Energy loss |
9064 | double dEdx=0.; |
9065 | |
9066 | // multiple scattering matrix |
9067 | DMatrix5x5 Q; |
9068 | |
9069 | // Position variables |
9070 | S=forward_traj[0].S; |
9071 | double z=forward_traj[0].z,newz=z,dz=0.; |
9072 | |
9073 | // Current time and path length |
9074 | double t=forward_traj[0].t; |
9075 | double s=forward_traj[0].s; |
9076 | |
9077 | // Find intersection points to FDC planes beyond the exent of the forward |
9078 | // trajectory. |
9079 | while (z>Z_MIN-100. && z<fdc_z_wires[23]+1. && fdc_plane<24){ |
9080 | // Bail if the momentum has dropped below some minimum |
9081 | if (fabs(S(state_q_over_p))>Q_OVER_P_MAX){ |
9082 | if (DEBUG_LEVEL>2) |
9083 | { |
9084 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<9084<<" " << "Bailing: P = " << 1./fabs(S(state_q_over_p)) |
9085 | << endl; |
9086 | } |
9087 | return VALUE_OUT_OF_RANGE; |
9088 | } |
9089 | |
9090 | // Current position |
9091 | DVector3 pos(S(state_x),S(state_y),z); |
9092 | if (pos.Perp()>50.) break; |
9093 | |
9094 | // get material properties from the Root Geometry |
9095 | DVector3 dir(S(state_tx),S(state_ty),1.); |
9096 | double s_to_boundary=0.; |
9097 | if (geom->FindMatKalman(pos,dir,K_rho_Z_over_A,rho_Z_over_A,LnI,Z, |
9098 | chi2c_factor,chi2a_factor,chi2a_corr, |
9099 | last_material_map,&s_to_boundary) |
9100 | !=NOERROR){ |
9101 | if (DEBUG_LEVEL>0) |
9102 | { |
9103 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<9103<<" " << "Material error in ExtrapolateForwardToOuterDetectors!"<< endl; |
9104 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<9104<<" " << " Position (x,y,z)=("<<pos.x()<<","<<pos.y()<<","<<pos.z()<<")" |
9105 | <<endl; |
9106 | } |
9107 | return VALUE_OUT_OF_RANGE; |
9108 | } |
9109 | |
9110 | // Get dEdx for the upcoming step |
9111 | if (CORRECT_FOR_ELOSS){ |
9112 | dEdx=GetdEdx(S(state_q_over_p),K_rho_Z_over_A,rho_Z_over_A,LnI,Z); |
9113 | } |
9114 | |
9115 | // Relationship between arc length and z |
9116 | double dz_ds=1./sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty)); |
9117 | |
9118 | // Adjust the step size |
9119 | double ds=mStepSizeS; |
9120 | if (fabs(dEdx)>EPS3.0e-8){ |
9121 | ds=DE_PER_STEP0.001/fabs(dEdx); |
9122 | } |
9123 | if (ds>mStepSizeS) ds=mStepSizeS; |
9124 | if (s_to_boundary<ds) ds=s_to_boundary; |
9125 | if (ds<MIN_STEP_SIZE0.1) ds=MIN_STEP_SIZE0.1; |
9126 | dz=ds*dz_ds; |
9127 | newz=z+dz; |
9128 | |
9129 | bool got_fdc_hit=false; |
9130 | if (fdc_plane<24 && newz>fdc_z_wires[fdc_plane]){ |
9131 | newz=fdc_z_wires[fdc_plane]; |
9132 | ds=(newz-z)/dz_ds; |
9133 | got_fdc_hit=true; |
9134 | } |
9135 | s+=ds; |
9136 | |
9137 | // Flight time |
9138 | double q_over_p_sq=S(state_q_over_p)*S(state_q_over_p); |
9139 | double one_over_beta2=1.+mass2*q_over_p_sq; |
9140 | if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8; |
9141 | t+=ds*sqrt(one_over_beta2); // in units where c=1 |
9142 | |
9143 | // Get the contribution to the covariance matrix due to multiple |
9144 | // scattering |
9145 | GetProcessNoise(z,ds,chi2c_factor,chi2a_factor,chi2a_corr,S,Q); |
9146 | double ds_theta_ms_sq=3.*fabs(Q(state_x,state_x)); |
9147 | s_theta_ms_sum+=sqrt(ds_theta_ms_sq); |
9148 | theta2ms_sum+=ds_theta_ms_sq/(ds*ds); |
9149 | |
9150 | // Step through field |
9151 | Step(z,newz,dEdx,S); |
9152 | z=newz; |
9153 | |
9154 | if (got_fdc_hit){ |
9155 | AddExtrapolation(SYS_FDC,z,S,s,t,s_theta_ms_sum,theta2ms_sum); |
9156 | fdc_plane++; |
9157 | } |
9158 | } |
9159 | |
9160 | return NOERROR; |
9161 | } |
9162 | |
9163 | // Routine to find intersections with surfaces useful at a later stage for track |
9164 | // matching |
9165 | jerror_t DTrackFitterKalmanSIMD::ExtrapolateForwardToOtherDetectors(){ |
9166 | if (forward_traj.size()<2) return RESOURCE_UNAVAILABLE; |
9167 | //-------------------------------- |
9168 | // First swim to Start counter and CDC/FDC layers |
9169 | //-------------------------------- |
9170 | jerror_t error=ExtrapolateToInnerDetectors(); |
9171 | |
9172 | //-------------------------------- |
9173 | // Next swim to outer detectors... |
9174 | //-------------------------------- |
9175 | if (error==NOERROR){ |
9176 | return ExtrapolateToOuterDetectors(forward_traj[0].S); |
9177 | } |
9178 | |
9179 | return error; |
9180 | } |
9181 | |
9182 | // Routine to find intersections with surfaces useful at a later stage for track |
9183 | // matching |
9184 | jerror_t DTrackFitterKalmanSIMD::ExtrapolateCentralToOtherDetectors(){ |
9185 | if (central_traj.size()<2) return RESOURCE_UNAVAILABLE; |
9186 | |
9187 | // First deal with start counter. Only do this if the track has a chance |
9188 | // to intersect with the start counter volume. |
9189 | unsigned int inner_index=central_traj.size()-1; |
9190 | unsigned int index_beyond_start_counter=inner_index; |
9191 | DVector2 xy=central_traj[inner_index].xy; |
9192 | DMatrix5x1 S=central_traj[inner_index].S; |
9193 | if (sc_norm.empty()==false |
9194 | &&xy.Mod2()<SC_BARREL_R2&& S(state_z)<SC_END_NOSE_Z){ |
9195 | double d_old=1000.,d=1000.,z=0.; |
9196 | unsigned int index=0; |
9197 | for (unsigned int m=0;m<12;m++){ |
9198 | unsigned int k=inner_index; |
9199 | for (;k>1;k--){ |
9200 | S=central_traj[k].S; |
9201 | z=S(state_z); |
9202 | xy=central_traj[k].xy; |
9203 | |
9204 | double dphi=xy.Phi()-SC_PHI_SECTOR1; |
9205 | if (dphi<0) dphi+=2.*M_PI3.14159265358979323846; |
9206 | index=int(floor(dphi/(2.*M_PI3.14159265358979323846/30.))); |
9207 | if (index>29) index=0; |
9208 | //cout << "dphi " << dphi << " " << index << endl; |
9209 | |
9210 | d=sc_norm[index][m].Dot(DVector3(xy.X(),xy.Y(),z) |
9211 | -sc_pos[index][m]); |
9212 | |
9213 | if (d*d_old<0){ // break if we cross the current plane |
9214 | if (m==0) index_beyond_start_counter=k; |
9215 | break; |
9216 | } |
9217 | d_old=d; |
9218 | } |
9219 | // if the z position would be beyond the current segment along z of |
9220 | // the start counter, move to the next plane |
9221 | if (z>sc_pos[index][m+1].z()&&m<11){ |
9222 | continue; |
9223 | } |
9224 | // allow for a little slop at the end of the nose |
9225 | else if (z<sc_pos[index][sc_pos[0].size()-1].z()+0.1){ |
9226 | // Propagate the state and covariance through the field |
9227 | // using a straight-line approximation for each step to zero in on the |
9228 | // start counter paddle |
9229 | int count=0; |
9230 | DMatrix5x1 bestS=S; |
9231 | double dmin=d; |
9232 | DVector2 bestXY=central_traj[k].xy; |
9233 | double t=central_traj[k].t; |
9234 | double s=central_traj[k].s; |
9235 | double bests=s,bestt=t; |
9236 | // Magnetic field |
9237 | bfield->GetField(xy.X(),xy.Y(),S(state_z),Bx,By,Bz); |
9238 | |
9239 | while (fabs(d)>0.05 && count<20){ |
9240 | // track direction |
9241 | DVector3 phat(cos(S(state_phi)),sin(S(state_phi)),S(state_tanl)); |
9242 | phat.SetMag(1.); |
9243 | |
9244 | // path length increment |
9245 | double ds=d/sc_norm[index][m].Dot(phat); |
9246 | s-=ds; |
9247 | |
9248 | // Flight time |
9249 | double q_over_p=S(state_q_over_pt)*cos(atan(S(state_tanl))); |
9250 | double q_over_p_sq=q_over_p*q_over_p; |
9251 | double one_over_beta2=1.+mass2*q_over_p_sq; |
9252 | if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8; |
9253 | t-=ds*sqrt(one_over_beta2); // in units where c=1 |
9254 | |
9255 | // Step along the trajectory using d to estimate path length |
9256 | FastStep(xy,-ds,0.,S); |
9257 | // Find the index for the nearest start counter paddle |
9258 | double dphi=xy.Phi()-SC_PHI_SECTOR1; |
9259 | if (dphi<0) dphi+=2.*M_PI3.14159265358979323846; |
9260 | index=int(floor(dphi/(2.*M_PI3.14159265358979323846/30.))); |
9261 | if (index>29) index=0; |
9262 | |
9263 | // Find the new distance to the start counter (which could now be to |
9264 | // a plane in the one adjacent to the one before the step...) |
9265 | d=sc_norm[index][m].Dot(DVector3(xy.X(),xy.Y(),S(state_z)) |
9266 | -sc_pos[index][m]); |
9267 | if (fabs(d)<fabs(dmin)){ |
9268 | bestS=S; |
9269 | dmin=d; |
9270 | bestXY=xy; |
9271 | bests=s; |
9272 | bestt=t; |
9273 | } |
9274 | count++; |
9275 | } |
9276 | |
9277 | if (bestS(state_z)>sc_pos[0][0].z()-0.1){ |
9278 | AddExtrapolation(SYS_START,bestS,bestXY,bestt,bests); |
9279 | } |
9280 | break; |
9281 | } |
9282 | } |
9283 | } |
9284 | |
9285 | // Accumulate multiple-scattering terms for use in matching routines |
9286 | double s_theta_ms_sum=0.,theta2ms_sum=0.; |
9287 | for (unsigned int k=inner_index;k>index_beyond_start_counter;k--){ |
9288 | double ds_theta_ms_sq=3.*fabs(central_traj[k].Q(state_D,state_D)); |
9289 | s_theta_ms_sum+=sqrt(ds_theta_ms_sq); |
9290 | double ds=central_traj[k].s-central_traj[k-1].s; |
9291 | theta2ms_sum+=ds_theta_ms_sq/(ds*ds); |
9292 | } |
9293 | |
9294 | // Deal with points within fiducial volume of chambers |
9295 | mT0Detector=SYS_NULL; |
9296 | mT0MinimumDriftTime=1e6; |
9297 | for (int k=index_beyond_start_counter;k>=0;k--){ |
9298 | S=central_traj[k].S; |
9299 | xy=central_traj[k].xy; |
9300 | double t=central_traj[k].t; |
9301 | double s=central_traj[k].s; |
9302 | |
9303 | // Find estimate for t0 using earliest drift time |
9304 | if (central_traj[k].h_id>0){ |
9305 | unsigned int index=central_traj[k].h_id-1; |
9306 | double dt=my_cdchits[index]->tdrift-t*TIME_UNIT_CONVERSION3.33564095198152014e-02; |
9307 | if (dt<mT0MinimumDriftTime){ |
9308 | mT0MinimumDriftTime=dt; |
9309 | mT0Detector=SYS_CDC; |
9310 | } |
9311 | } |
9312 | |
9313 | //multiple scattering terms |
9314 | if (k>0){ |
9315 | double ds_theta_ms_sq=3.*fabs(central_traj[k].Q(state_D,state_D)); |
9316 | s_theta_ms_sum+=sqrt(ds_theta_ms_sq); |
9317 | double ds=central_traj[k].s-central_traj[k-1].s; |
9318 | theta2ms_sum+=ds_theta_ms_sq/(ds*ds); |
9319 | } |
9320 | if (S(state_z)<endplate_z){ |
9321 | AddExtrapolation(SYS_CDC,S,xy,t,s,s_theta_ms_sum,theta2ms_sum); |
9322 | } |
9323 | } |
9324 | // Save the extrapolation at the exit of the tracking volume |
9325 | S=central_traj[0].S; |
9326 | xy=central_traj[0].xy; |
9327 | double t=central_traj[0].t; |
9328 | double s=central_traj[0].s; |
9329 | AddExtrapolation(SYS_NULL,S,xy,t,s); |
9330 | |
9331 | //------------------------------ |
9332 | // Next swim to outer detectors |
9333 | //------------------------------ |
9334 | // Position and step variables |
9335 | double r2=xy.Mod2(); |
9336 | double ds=mStepSizeS; // step along path in cm |
9337 | |
9338 | // Energy loss |
9339 | double dedx=0.; |
9340 | |
9341 | // Track propagation loop |
9342 | //if (false) |
9343 | while (S(state_z)>0. && S(state_z)<Z_MAX370.0 |
9344 | && r2<89.*89.){ |
9345 | // Bail if the transverse momentum has dropped below some minimum |
9346 | if (fabs(S(state_q_over_pt))>Q_OVER_PT_MAX100.){ |
9347 | if (DEBUG_LEVEL>2) |
9348 | { |
9349 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<9349<<" " << "Bailing: PT = " << 1./fabs(S(state_q_over_pt)) |
9350 | << endl; |
9351 | } |
9352 | return VALUE_OUT_OF_RANGE; |
9353 | } |
9354 | |
9355 | // get material properties from the Root Geometry |
9356 | double rho_Z_over_A=0.,LnI=0.,K_rho_Z_over_A=0.,Z=0.; |
9357 | DVector3 pos3d(xy.X(),xy.Y(),S(state_z)); |
9358 | double s_to_boundary=0.; |
9359 | DVector3 dir(cos(S(state_phi)),sin(S(state_phi)),S(state_tanl)); |
9360 | if (geom->FindMatKalman(pos3d,dir,K_rho_Z_over_A,rho_Z_over_A,LnI,Z, |
9361 | last_material_map,&s_to_boundary) |
9362 | !=NOERROR){ |
9363 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<9363<<" " << "Material error in ExtrapolateToVertex! " << endl; |
9364 | _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<9364<<" " << " Position (x,y,z)=("<<pos3d.x()<<","<<pos3d.y()<<"," |
9365 | << pos3d.z()<<")" |
9366 | <<endl; |
9367 | break; |
9368 | } |
9369 | |
9370 | // Get dEdx for the upcoming step |
9371 | double q_over_p=S(state_q_over_pt)*cos(atan(S(state_tanl))); |
9372 | if (CORRECT_FOR_ELOSS){ |
9373 | dedx=GetdEdx(q_over_p,K_rho_Z_over_A,rho_Z_over_A,LnI,Z); |
9374 | } |
9375 | // Adjust the step size |
9376 | if (fabs(dedx)>EPS3.0e-8){ |
9377 | ds=DE_PER_STEP0.001/fabs(dedx); |
9378 | } |
9379 | |
9380 | if (ds>mStepSizeS) ds=mStepSizeS; |
9381 | if (s_to_boundary<ds) ds=s_to_boundary; |
9382 | if (ds<MIN_STEP_SIZE0.1)ds=MIN_STEP_SIZE0.1; |
9383 | if (ds<0.5 && S(state_z)<400. && pos3d.Perp()>65.) ds=0.5; |
9384 | s+=ds; |
9385 | |
9386 | // Flight time |
9387 | double q_over_p_sq=q_over_p*q_over_p; |
9388 | double one_over_beta2=1.+mass2*q_over_p_sq; |
9389 | if (one_over_beta2>BIG1.0e8) one_over_beta2=BIG1.0e8; |
9390 | t+=ds*sqrt(one_over_beta2); // in units where c=1 |
9391 | |
9392 | // Propagate the state through the field |
9393 | Step(xy,ds,S,dedx); |
9394 | |
9395 | r2=xy.Mod2(); |
9396 | // Check if we have passed into the BCAL |
9397 | if (r2>64.9*64.9){ |
9398 | if (extrapolations.at(SYS_BCAL).size()>299){ |
9399 | return VALUE_OUT_OF_RANGE; |
9400 | } |
9401 | if (S(state_z)<406.&&S(state_z)>17.0){ |
9402 | AddExtrapolation(SYS_BCAL,S,xy,t,s); |
9403 | } |
9404 | else if (extrapolations.at(SYS_BCAL).size()<5){ |
9405 | // There needs to be some steps inside the the volume of the BCAL for |
9406 | // the extrapolation to be useful. If this is not the case, clear |
9407 | // the extrolation vector. |
9408 | extrapolations[SYS_BCAL].clear(); |
9409 | } |
9410 | } |
9411 | } |
9412 | |
9413 | return NOERROR; |
9414 | } |
9415 | |
9416 | /*---------------------------------------------------------------------------*/ |
9417 | |
9418 | // Kalman engine for forward tracks, propagating from near the beam line to |
9419 | // the outermost hits (opposite to regular direction). |
9420 | kalman_error_t DTrackFitterKalmanSIMD::KalmanReverse(double fdc_anneal_factor, |
9421 | double cdc_anneal_factor, |
9422 | const DMatrix5x1 &Sstart, |
9423 | DMatrix5x5 &C, |
9424 | DMatrix5x1 &S, |
9425 | double &chisq, |
9426 | unsigned int &numdof){ |
9427 | DMatrix2x1 Mdiff; // difference between measurement and prediction |
9428 | DMatrix2x5 H; // Track projection matrix |
9429 | DMatrix5x2 H_T; // Transpose of track projection matrix |
9430 | DMatrix1x5 Hc; // Track projection matrix for cdc hits |
9431 | DMatrix5x1 Hc_T; // Transpose of track projection matrix for cdc hits |
9432 | DMatrix5x5 J; // State vector Jacobian matrix |
9433 | //DMatrix5x5 J_T; // transpose of this matrix |
9434 | DMatrix5x5 Q; // Process noise covariance matrix |
9435 | DMatrix5x2 K; // Kalman gain matrix |
9436 | DMatrix5x1 Kc; // Kalman gain matrix for cdc hits |
9437 | DMatrix2x2 V(0.0833,0.,0.,FDC_CATHODE_VARIANCE0.000225); // Measurement covariance matrix |
9438 | DMatrix5x1 S0,S0_; //State vector |
9439 | DMatrix5x5 Ctest; // Covariance matrix |
9440 | |
9441 | double Vc=0.0507; |
9442 | |
9443 | unsigned int cdc_index=0; |
9444 | unsigned int num_cdc_hits=my_cdchits.size(); |
9445 | bool more_cdc_measurements=(num_cdc_hits>0); |
9446 | double old_doca2=1e6; |
9447 | |
9448 | // Initialize chi squared |
9449 | chisq=0; |
9450 | |
9451 | // Initialize number of degrees of freedom |
9452 | numdof=0; |
9453 | |
9454 | // Cuts for pruning hits |
9455 | double fdc_chi2cut=NUM_FDC_SIGMA_CUT*NUM_FDC_SIGMA_CUT; |
9456 | double cdc_chi2cut=NUM_CDC_SIGMA_CUT*NUM_CDC_SIGMA_CUT; |
9457 | |
9458 | // Vectors for cdc wires |
9459 | DVector2 origin,dir,wirepos; |
9460 | double z0w=0.; // origin in z for wire |
9461 | |
9462 | deque<DKalmanForwardTrajectory_t>::reverse_iterator rit = forward_traj.rbegin(); |
9463 | S0_=(*rit).S; |
9464 | S=Sstart; |
9465 | |
9466 | if (more_cdc_measurements){ |
9467 | origin=my_cdchits[0]->origin; |
9468 | dir=my_cdchits[0]->dir; |
9469 | z0w=my_cdchits[0]->z0wire; |
9470 | wirepos=origin+((*rit).z-z0w)*dir; |
9471 | } |
9472 | |
9473 | for (rit=forward_traj.rbegin()+1;rit!=forward_traj.rend();++rit){ |
9474 | // Get the state vector, jacobian matrix, and multiple scattering matrix |
9475 | // from reference trajectory |
9476 | S0=(*rit).S; |
9477 | J=2.*I5x5-(*rit).J; // We only want to change the signs of the parts that depend on dz ... |
9478 | Q=(*rit).Q; |
9479 | |
9480 | // Check that the position is within the tracking volume! |
9481 | if (S(state_x)*S(state_x)+S(state_y)*S(state_y)>65.*65.){ |
9482 | return POSITION_OUT_OF_RANGE; |
9483 | } |
9484 | // Update the actual state vector and covariance matrix |
9485 | S=S0+J*(S-S0_); |
9486 | C=Q.AddSym(J*C*J.Transpose()); |
9487 | //C.Print(); |
9488 | |
9489 | // Save the current state of the reference trajectory |
9490 | S0_=S0; |
9491 | |
9492 | // Z position along the trajectory |
9493 | double z=(*rit).z; |
9494 | |
9495 | if (more_cdc_measurements){ |
9496 | // new wire position |
9497 | wirepos=origin; |
9498 | wirepos+=(z-z0w)*dir; |
9499 | |
9500 | // doca variables |
9501 | double dx=S(state_x)-wirepos.X(); |
9502 | double dy=S(state_y)-wirepos.Y(); |
9503 | double doca2=dx*dx+dy*dy; |
9504 | |
9505 | if (doca2>old_doca2){ |
9506 | if(my_cdchits[cdc_index]->status==good_hit){ |
9507 | find_doca_error_t swimmed_to_doca=DOCA_NO_BRENT; |
9508 | double newz=endplate_z; |
9509 | double dz=newz-z; |
9510 | // Sometimes the true doca would correspond to the case where the |
9511 | // wire would need to extend beyond the physical volume of the straw. |
9512 | // In this case, find the doca at the cdc endplate. |
9513 | if (z>endplate_z){ |
9514 | swimmed_to_doca=DOCA_ENDPLATE; |
9515 | SwimToEndplate(z,*rit,S); |
9516 | |
9517 | // wire position at the endplate |
9518 | wirepos=origin; |
9519 | wirepos+=(endplate_z-z0w)*dir; |
9520 | |
9521 | dx=S(state_x)-wirepos.X(); |
9522 | dy=S(state_y)-wirepos.Y(); |
9523 | } |
9524 | else{ |
9525 | // Find the true doca to the wire. If we had to use Brent's |
9526 | // algorithm, the routine returns USED_BRENT |
9527 | swimmed_to_doca=FindDoca(my_cdchits[cdc_index],*rit,mStepSizeZ, |
9528 | mStepSizeZ,S0,S,C,dx,dy,dz,true); |
9529 | if (swimmed_to_doca==BRENT_FAILED){ |
9530 | //_DBG_ << "Brent's algorithm failed" <<endl; |
9531 | return MOMENTUM_OUT_OF_RANGE; |
9532 | } |
9533 | |
9534 | newz=z+dz; |
9535 | } |
9536 | double cosstereo=my_cdchits[cdc_index]->cosstereo; |
9537 | double d=sqrt(dx*dx+dy*dy)*cosstereo+EPS3.0e-8; |
9538 | |
9539 | // Track projection |
9540 | double cosstereo2_over_d=cosstereo*cosstereo/d; |
9541 | Hc_T(state_x)=dx*cosstereo2_over_d; |
9542 | Hc(state_x)=Hc_T(state_x); |
9543 | Hc_T(state_y)=dy*cosstereo2_over_d; |
9544 | Hc(state_y)=Hc_T(state_y); |
9545 | if (swimmed_to_doca==DOCA_NO_BRENT){ |
9546 | Hc_T(state_ty)=Hc_T(state_y)*dz; |
9547 | Hc(state_ty)=Hc_T(state_ty); |
9548 | Hc_T(state_tx)=Hc_T(state_x)*dz; |
9549 | Hc(state_tx)=Hc_T(state_tx); |
9550 | } |
9551 | else{ |
9552 | Hc_T(state_ty)=0.; |
9553 | Hc(state_ty)=0.; |
9554 | Hc_T(state_tx)=0.; |
9555 | Hc(state_tx)=0.; |
9556 | } |
9557 | // Find offset of wire with respect to the center of the |
9558 | // straw at this z position |
9559 | double delta=0.,dphi=0.; |
9560 | FindSag(dx,dy,newz-z0w,my_cdchits[cdc_index]->hit->wire,delta,dphi); |
9561 | |
9562 | // Find drift time and distance |
9563 | double tdrift=my_cdchits[cdc_index]->tdrift-mT0 |
9564 | -(*rit).t*TIME_UNIT_CONVERSION3.33564095198152014e-02; |
9565 | double tcorr=0.,dmeas=0.; |
9566 | double B=(*rit).B; |
9567 | ComputeCDCDrift(dphi,delta,tdrift,B,dmeas,Vc,tcorr); |
9568 | |
9569 | // Residual |
9570 | double res=dmeas-d; |
9571 | |
9572 | // inverse variance including prediction |
9573 | double Vproj=Hc*C*Hc_T; |
9574 | double InvV1=1./(Vc+Vproj); |
9575 | |
9576 | // Check if this hit is an outlier |
9577 | double chi2_hit=res*res*InvV1; |
9578 | if (chi2_hit<cdc_chi2cut){ |
9579 | // Compute KalmanSIMD gain matrix |
9580 | Kc=InvV1*(C*Hc_T); |
9581 | |
9582 | // Update state vector covariance matrix |
9583 | //C=C-K*(H*C); |
9584 | Ctest=C.SubSym(Kc*(Hc*C)); |
9585 | |
9586 | if (!Ctest.IsPosDef()){ |
9587 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackFitterKalmanSIMD.cc" <<":"<<9587<<" " << "Broken covariance matrix!" <<endl; |
9588 | return BROKEN_COVARIANCE_MATRIX; |
9589 | } |
9590 | |
9591 | if (tdrift >= CDC_T_DRIFT_MIN){ |
9592 | C=Ctest; |
9593 | S+=res*Kc; |
9594 | |
9595 | chisq+=(1.-Hc*Kc)*res*res/Vc; |
9596 | numdof++; |
9597 | } |
9598 | } |
9599 | |
9600 | // If we had to use Brent's algorithm to find the true doca or the |
9601 | // doca to the line corresponding to the wire is downstream of the |
9602 | // cdc endplate, we need to swim the state vector and covariance |
9603 | // matrix back to the appropriate position along the reference |
9604 | // trajectory. |
9605 | if (swimmed_to_doca!=DOCA_NO_BRENT){ |
9606 | double dedx=0.; |
9607 | if (CORRECT_FOR_ELOSS){ |
9608 | dedx=GetdEdx(S(state_q_over_p),(*rit).K_rho_Z_over_A, |
9609 | (*rit).rho_Z_over_A,(*rit).LnI,(*rit).Z); |
9610 | } |
9611 | StepBack(dedx,newz,z,S0,S,C); |
9612 | } |
9613 | } |
9614 | |
9615 | // new wire origin and direction |
9616 | if (cdc_index<num_cdc_hits-1){ |
9617 | cdc_index++; |
9618 | origin=my_cdchits[cdc_index]->origin; |
9619 | z0w=my_cdchits[cdc_index]->z0wire; |
9620 | dir=my_cdchits[cdc_index]->dir; |
9621 | } |
9622 | else more_cdc_measurements=false; |
9623 | |
9624 | // Update the wire position |
9625 | wirepos=origin+(z-z0w)*dir; |
9626 | |
9627 | // new doca |
9628 | dx=S(state_x)-wirepos.X(); |
9629 | dy=S(state_y)-wirepos.Y(); |
9630 | doca2=dx*dx+dy*dy; |
9631 | } |
9632 | old_doca2=doca2; |
9633 | } |
9634 | if ((*rit).h_id>0&&(*rit).h_id<1000){ |
9635 | unsigned int id=(*rit).h_id-1; |
9636 | |
9637 | // Variance in coordinate transverse to wire |
9638 | V(0,0)=my_fdchits[id]->uvar; |
9639 | |
9640 | // Variance in coordinate along wire |
9641 | V(1,1)=my_fdchits[id]->vvar; |
9642 | |
9643 | double upred=0,vpred=0.,doca=0.,cosalpha=0.,lorentz_factor=0.; |
9644 | FindDocaAndProjectionMatrix(my_fdchits[id],S,upred,vpred,doca,cosalpha, |
9645 | lorentz_factor,H_T); |
9646 | // Matrix transpose H_T -> H |
9647 | H=Transpose(H_T); |
9648 | |
9649 | |
9650 | DMatrix2x2 Vtemp=V+H*C*H_T; |
9651 | |
9652 | // Residual for coordinate along wire |
9653 | Mdiff(1)=my_fdchits[id]->vstrip-vpred-doca*lorentz_factor; |
9654 | |
9655 | // Residual for coordinate transverse to wire |
9656 | double drift_time=my_fdchits[id]->t-mT0-(*rit).t*TIME_UNIT_CONVERSION3.33564095198152014e-02; |
9657 | if (my_fdchits[id]->hit!=NULL__null){ |
9658 | double drift=(doca>0.0?1.:-1.)*fdc_drift_distance(drift_time,(*rit).B); |
9659 | Mdiff(0)=drift-doca; |
9660 | |
9661 | // Variance in drift distance |
9662 | V(0,0)=fdc_drift_variance(drift_time); |
9663 | } |
9664 | else if (USE_TRD_DRIFT_TIMES&&my_fdchits[id]->status==trd_hit){ |
9665 | double drift =(doca>0.0?1.:-1.)*0.1*pow(drift_time/8./0.91,1./1.556); |
9666 | Mdiff(0)=drift-doca; |
9667 | |
9668 | // Variance in drift distance |
9669 | V(0,0)=0.05*0.05; |
9670 | } |
9671 | if ((*rit).num_hits==1){ |
9672 | // Add contribution of track covariance from state vector propagation |
9673 | // to measurement errors |
9674 | DMatrix2x2 Vtemp=V+H*C*H_T; |
9675 | double chi2_hit=Vtemp.Chi2(Mdiff); |
9676 | if (chi2_hit<fdc_chi2cut){ |
9677 | // Compute Kalman gain matrix |
9678 | DMatrix2x2 InvV=Vtemp.Invert(); |
9679 | DMatrix5x2 K=C*H_T*InvV; |
9680 | |
9681 | // Update the state vector |
9682 | S+=K*Mdiff; |
9683 | |
9684 | // Update state vector covariance matrix |
9685 | //C=C-K*(H*C); |
9686 | C=C.SubSym(K*(H*C)); |
9687 | |
9688 | if (DEBUG_LEVEL > 35) { |
9689 | jout << "S Update: " << endl; S.Print(); |
9690 | jout << "C Update: " << endl; C.Print(); |
9691 | } |
9692 | |
9693 | // Filtered residual and covariance of filtered residual |
9694 | DMatrix2x1 R=Mdiff-H*K*Mdiff; |
9695 | DMatrix2x2 RC=V-H*(C*H_T); |
9696 | |
9697 | // Update chi2 for this segment |
9698 | chisq+=RC.Chi2(R); |
9699 | |
9700 | if (DEBUG_LEVEL>30) |
9701 | { |
9702 | printf("hit %d p %5.2f dm %5.4f %5.4f sig %5.4f %5.4f chi2 %5.2f\n", |
9703 | id,1./S(state_q_over_p),Mdiff(0),Mdiff(1), |
9704 | sqrt(V(0,0)),sqrt(V(1,1)),RC.Chi2(R)); |
9705 | } |
9706 | |
9707 | numdof+=2; |
9708 | } |
9709 | } |
9710 | // Handle the case where there are multiple adjacent hits in the plane |
9711 | else { |
9712 | UpdateSandCMultiHit(*rit,upred,vpred,doca,cosalpha,lorentz_factor,V, |
9713 | Mdiff,H,H_T,S,C,fdc_chi2cut,false,chisq,numdof); |
9714 | } |
9715 | } |
9716 | |
9717 | //printf("chisq %f ndof %d prob %f\n",chisq,numdof,TMath::Prob(chisq,numdof)); |
9718 | } |
9719 | |
9720 | return FIT_SUCCEEDED; |
9721 | } |
9722 | |
9723 | // Finds the distance of closest approach between a CDC wire and the trajectory |
9724 | // of the track and updates the state vector and covariance matrix at this point. |
9725 | find_doca_error_t |
9726 | DTrackFitterKalmanSIMD::FindDoca(const DKalmanSIMDCDCHit_t *hit, |
9727 | const DKalmanForwardTrajectory_t &traj, |
9728 | double step1,double step2, |
9729 | DMatrix5x1 &S0,DMatrix5x1 &S, |
9730 | DMatrix5x5 &C, |
9731 | double &dx,double &dy,double &dz, |
9732 | bool do_reverse){ |
9733 | double z=traj.z,newz=z; |
9734 | DMatrix5x5 J; |
9735 | |
9736 | // wire position and direction |
9737 | DVector2 origin=hit->origin; |
9738 | double z0w=hit->z0wire; |
9739 | DVector2 dir=hit->dir; |
9740 | |
9741 | // energy loss |
9742 | double dedx=0.; |
9743 | |
9744 | // track direction variables |
9745 | double tx=S(state_tx); |
9746 | double ty=S(state_ty); |
9747 | double tanl=1./sqrt(tx*tx+ty*ty); |
9748 | double sinl=sin(atan(tanl)); |
9749 | |
9750 | // Wire direction variables |
9751 | double ux=dir.X(); |
9752 | double uy=dir.Y(); |
9753 | // Variables relating wire direction and track direction |
9754 | double my_ux=tx-ux; |
9755 | double my_uy=ty-uy; |
9756 | double denom=my_ux*my_ux+my_uy*my_uy; |
9757 | |
9758 | // variables for dealing with propagation of S and C if we |
9759 | // need to use Brent's algorithm to find the doca to the wire |
9760 | int num_steps=0; |
9761 | double my_dz=0.; |
9762 | |
9763 | // if the path length increment is small relative to the radius |
9764 | // of curvature, use a linear approximation to find dz |
9765 | bool do_brent=false; |
9766 | double sign=do_reverse?-1.:1.; |
9767 | double two_step=sign*(step1+step2); |
9768 | if (fabs(qBr2p0.003*S(state_q_over_p) |
9769 | *bfield->GetBz(S(state_x),S(state_y),z) |
9770 | *two_step/sinl)<0.05 |
9771 | && denom>EPS3.0e-8){ |
9772 | double dzw=z-z0w; |
9773 | dz=-((S(state_x)-origin.X()-ux*dzw)*my_ux |
9774 | +(S(state_y)-origin.Y()-uy*dzw)*my_uy)/denom; |
9775 | if (fabs(dz)>fabs(two_step) || sign*dz<0){ |
9776 | do_brent=true; |
9777 | } |
9778 | else{ |
9779 | newz=z+dz; |
9780 | // Check for exiting the straw |
9781 | if (newz>endplate_z){ |
9782 | dz=endplate_z-z; |
9783 | } |
9784 | } |
9785 | } |
9786 | else do_brent=true; |
9787 | if (do_brent){ |
9788 | if (CORRECT_FOR_ELOSS){ |
9789 | dedx=GetdEdx(S(state_q_over_p),traj.K_rho_Z_over_A,traj.rho_Z_over_A, |
9790 | traj.LnI,traj.Z); |
9791 | } |
9792 | |
9793 | // We have bracketed the minimum doca: use Brent's agorithm |
9794 | if (BrentForward(z,dedx,z0w,origin,dir,S,dz)!=NOERROR){ |
9795 | return BRENT_FAILED; |
9796 | } |
9797 | // Step the state and covariance through the field |
9798 | if (fabs(dz)>mStepSizeZ){ |
9799 | my_dz=(dz>0?1.0:-1.)*mStepSizeZ; |
9800 | num_steps=int(fabs(dz/my_dz)); |
9801 | double dz3=dz-num_steps*my_dz; |
9802 | |
9803 | double my_z=z; |
9804 | for (int m=0;m<num_steps;m++){ |
9805 | newz=my_z+my_dz; |
9806 | |
9807 | // propagate error matrix to z-position of hit |
9808 | StepJacobian(my_z,newz,S0,dedx,J); |
9809 | C=J*C*J.Transpose(); |
9810 | //C=C.SandwichMultiply(J); |
9811 | |
9812 | // Step reference trajectory by my_dz |
9813 | Step(my_z,newz,dedx,S0); |
9814 | |
9815 | my_z=newz; |
9816 | } |
9817 | |
9818 | newz=my_z+dz3; |
9819 | // propagate error matrix to z-position of hit |
9820 | StepJacobian(my_z,newz,S0,dedx,J); |
9821 | C=J*C*J.Transpose(); |
9822 | //C=C.SandwichMultiply(J); |
9823 | |
9824 | // Step reference trajectory by dz3 |
9825 | Step(my_z,newz,dedx,S0); |
9826 | } |
9827 | else{ |
9828 | newz = z + dz; |
9829 | |
9830 | // propagate error matrix to z-position of hit |
9831 | StepJacobian(z,newz,S0,dedx,J); |
9832 | C=J*C*J.Transpose(); |
9833 | //C=C.SandwichMultiply(J); |
9834 | |
9835 | // Step reference trajectory by dz |
9836 | Step(z,newz,dedx,S0); |
9837 | } |
9838 | } |
9839 | |
9840 | // Wire position at current z |
9841 | DVector2 wirepos=origin; |
9842 | wirepos+=(newz-z0w)*dir; |
9843 | |
9844 | double xw=wirepos.X(); |
9845 | double yw=wirepos.Y(); |
9846 | |
9847 | // predicted doca taking into account the orientation of the wire |
9848 | if (do_brent==false){ |
9849 | // In this case we did not have to swim to find the doca and |
9850 | // the transformation from the state vector space to the |
9851 | // measurement space is straight-forward. |
9852 | dy=S(state_y)+S(state_ty)*dz-yw; |
9853 | dx=S(state_x)+S(state_tx)*dz-xw; |
9854 | } |
9855 | else{ |
9856 | // In this case we swam the state vector to the position of the doca |
9857 | dy=S(state_y)-yw; |
9858 | dx=S(state_x)-xw; |
9859 | } |
9860 | |
9861 | if (do_brent) return USED_BRENT; |
9862 | return DOCA_NO_BRENT; |
9863 | } |
9864 | |
9865 | // Swim along a trajectory to the z-position z. |
9866 | void DTrackFitterKalmanSIMD::StepBack(double dedx,double newz,double z, |
9867 | DMatrix5x1 &S0,DMatrix5x1 &S, |
9868 | DMatrix5x5 &C){ |
9869 | double dz=newz-z; |
9870 | DMatrix5x5 J; |
9871 | int num_steps=int(fabs(dz/mStepSizeZ)); |
9872 | if (num_steps==0){ |
9873 | // Step C back to the z-position on the reference trajectory |
9874 | StepJacobian(newz,z,S0,dedx,J); |
9875 | C=J*C*J.Transpose(); |
9876 | //C=C.SandwichMultiply(J); |
9877 | |
9878 | // Step S to current position on the reference trajectory |
9879 | Step(newz,z,dedx,S); |
9880 | |
9881 | // Step S0 to current position on the reference trajectory |
9882 | Step(newz,z,dedx,S0); |
9883 | } |
9884 | else{ |
9885 | double my_z=newz; |
9886 | double my_dz=(dz>0.0?1.0:-1.)*mStepSizeZ; |
9887 | double dz3=dz-num_steps*my_dz; |
9888 | for (int m=0;m<num_steps;m++){ |
9889 | z=my_z-my_dz; |
9890 | |
9891 | // Step C along z |
9892 | StepJacobian(my_z,z,S0,dedx,J); |
9893 | C=J*C*J.Transpose(); |
9894 | //C=C.SandwichMultiply(J); |
9895 | |
9896 | // Step S along z |
9897 | Step(my_z,z,dedx,S); |
9898 | |
9899 | // Step S0 along z |
9900 | Step(my_z,z,dedx,S0); |
9901 | |
9902 | my_z=z; |
9903 | } |
9904 | z=my_z-dz3; |
9905 | |
9906 | // Step C back to the z-position on the reference trajectory |
9907 | StepJacobian(my_z,z,S0,dedx,J); |
9908 | C=J*C*J.Transpose(); |
9909 | //C=C.SandwichMultiply(J); |
9910 | |
9911 | // Step S to current position on the reference trajectory |
9912 | Step(my_z,z,dedx,S); |
9913 | |
9914 | // Step S0 to current position on the reference trajectory |
9915 | Step(my_z,z,dedx,S0); |
9916 | } |
9917 | } |
9918 | |
9919 | // Swim a track to the CDC endplate given starting z position |
9920 | void DTrackFitterKalmanSIMD::SwimToEndplate(double z, |
9921 | const DKalmanForwardTrajectory_t &traj, |
9922 | DMatrix5x1 &S){ |
9923 | double dedx=0.; |
9924 | if (CORRECT_FOR_ELOSS){ |
9925 | dedx=GetdEdx(S(state_q_over_p),traj.K_rho_Z_over_A,traj.rho_Z_over_A, |
9926 | traj.LnI,traj.Z); |
9927 | } |
9928 | double my_z=z; |
9929 | int num_steps=int(fabs((endplate_z-z)/mStepSizeZ)); |
9930 | for (int m=0;m<num_steps;m++){ |
9931 | my_z=z-mStepSizeZ; |
9932 | Step(z,my_z,dedx,S); |
9933 | z=my_z; |
9934 | } |
9935 | Step(z,endplate_z,dedx,S); |
9936 | } |
9937 | |
9938 | // Find the sag parameters (delta,dphi) for the given straw at the local z |
9939 | // position |
9940 | void DTrackFitterKalmanSIMD::FindSag(double dx,double dy, double zlocal, |
9941 | const DCDCWire *mywire,double &delta, |
9942 | double &dphi) const{ |
9943 | int ring_index=mywire->ring-1; |
9944 | int straw_index=mywire->straw-1; |
9945 | double phi_d=atan2(dy,dx); |
9946 | delta=max_sag[ring_index][straw_index]*(1.-zlocal*zlocal/5625.) |
9947 | *cos(phi_d + sag_phi_offset[ring_index][straw_index]); |
9948 | |
9949 | dphi=phi_d-mywire->origin.Phi(); |
9950 | while (dphi>M_PI3.14159265358979323846) dphi-=2*M_PI3.14159265358979323846; |
9951 | while (dphi<-M_PI3.14159265358979323846) dphi+=2*M_PI3.14159265358979323846; |
9952 | if (mywire->origin.Y()<0) dphi*=-1.; |
9953 | } |
9954 | |
9955 | void DTrackFitterKalmanSIMD::FindDocaAndProjectionMatrix(const DKalmanSIMDFDCHit_t *hit, |
9956 | const DMatrix5x1 &S, |
9957 | double &upred, |
9958 | double &vpred, |
9959 | double &doca, |
9960 | double &cosalpha, |
9961 | double &lorentz_factor, |
9962 | DMatrix5x2 &H_T){ |
9963 | // Make the small alignment rotations |
9964 | // Use small-angle form. |
9965 | |
9966 | // Position and direction from state vector |
9967 | double x=S(state_x) + hit->phiZ*S(state_y); |
9968 | double y=S(state_y) - hit->phiZ*S(state_x); |
9969 | double tx =S(state_tx) + hit->phiZ*S(state_ty) - hit->phiY; |
9970 | double ty =S(state_ty) - hit->phiZ*S(state_tx) + hit->phiX; |
9971 | |
9972 | // Plane orientation and measurements |
9973 | double cosa=hit->cosa; |
9974 | double sina=hit->sina; |
9975 | double u=hit->uwire; |
9976 | |
9977 | // Projected coordinate along wire |
9978 | vpred=x*sina+y*cosa; |
9979 | |
9980 | // Direction tangent in the u-z plane |
9981 | double tu=tx*cosa-ty*sina; |
9982 | double tv=tx*sina+ty*cosa; |
9983 | double alpha=atan(tu); |
9984 | cosalpha=cos(alpha); |
9985 | double cosalpha2=cosalpha*cosalpha; |
9986 | double sinalpha=sin(alpha); |
9987 | |
9988 | // (signed) distance of closest approach to wire |
9989 | upred=x*cosa-y*sina; |
9990 | if (hit->status==gem_hit){ |
9991 | doca=upred-u; |
9992 | } |
9993 | else{ |
9994 | doca=(upred-u)*cosalpha; |
9995 | } |
9996 | |
9997 | // Correction for lorentz effect |
9998 | double nz=hit->nz; |
9999 | double nr=hit->nr; |
10000 | double nz_sinalpha_plus_nr_cosalpha=nz*sinalpha+nr*cosalpha; |
10001 | lorentz_factor=nz_sinalpha_plus_nr_cosalpha-tv*sinalpha; |
10002 | |
10003 | // To transform from (x,y) to (u,v), need to do a rotation: |
10004 | // u = x*cosa-y*sina |
10005 | // v = y*cosa+x*sina |
10006 | if (hit->status!=gem_hit){ |
10007 | H_T(state_x,1)=sina+cosa*cosalpha*lorentz_factor; |
10008 | H_T(state_y,1)=cosa-sina*cosalpha*lorentz_factor; |
10009 | |
10010 | double cos2_minus_sin2=cosalpha2-sinalpha*sinalpha; |
10011 | double fac=nz*cos2_minus_sin2-2.*nr*cosalpha*sinalpha; |
10012 | double doca_cosalpha=doca*cosalpha; |
10013 | double temp=doca_cosalpha*fac; |
10014 | H_T(state_tx,1)=cosa*temp-doca_cosalpha*(tu*sina+tv*cosa*cos2_minus_sin2); |
10015 | H_T(state_ty,1)=-sina*temp-doca_cosalpha*(tu*cosa-tv*sina*cos2_minus_sin2); |
10016 | |
10017 | H_T(state_x,0)=cosa*cosalpha; |
10018 | H_T(state_y,0)=-sina*cosalpha; |
10019 | |
10020 | double factor=doca*tu*cosalpha2; |
10021 | H_T(state_ty,0)=sina*factor; |
10022 | H_T(state_tx,0)=-cosa*factor; |
10023 | } |
10024 | else{ |
10025 | H_T(state_x,1)=sina; |
10026 | H_T(state_y,1)=cosa; |
10027 | H_T(state_x,0)=cosa; |
10028 | H_T(state_y,0)=-sina; |
10029 | } |
10030 | } |
10031 | |
10032 | // Update S and C using all the good adjacent hits in a particular FDC plane |
10033 | void DTrackFitterKalmanSIMD::UpdateSandCMultiHit(const DKalmanForwardTrajectory_t &traj, |
10034 | double upred,double vpred, |
10035 | double doca,double cosalpha, |
10036 | double lorentz_factor, |
10037 | DMatrix2x2 &V, |
10038 | DMatrix2x1 &Mdiff, |
10039 | DMatrix2x5 &H, |
10040 | const DMatrix5x2 &H_T, |
10041 | DMatrix5x1 &S,DMatrix5x5 &C, |
10042 | double fdc_chi2cut, |
10043 | bool skip_plane,double &chisq, |
10044 | unsigned int &numdof, |
10045 | double fdc_anneal_factor){ |
10046 | // If we do have multiple hits, then all of the hits within some |
10047 | // validation region are included with weights determined by how |
10048 | // close the hits are to the track projection of the state to the |
10049 | // "hit space". |
10050 | vector<DMatrix5x2> Klist; |
10051 | vector<DMatrix2x1> Mlist; |
10052 | vector<DMatrix2x5> Hlist; |
10053 | vector<DMatrix5x2> HTlist; |
10054 | vector<DMatrix2x2> Vlist; |
10055 | vector<double>probs; |
10056 | vector<unsigned int>used_ids; |
10057 | |
10058 | // use a Gaussian model for the probability for the hit |
10059 | DMatrix2x2 Vtemp=V+H*C*H_T; |
10060 | double chi2_hit=Vtemp.Chi2(Mdiff); |
10061 | double prob_hit=0.; |
10062 | |
10063 | // Add the first hit to the list, cutting out outliers |
10064 | unsigned int id=traj.h_id-1; |
10065 | if (chi2_hit<fdc_chi2cut && my_fdchits[id]->status==good_hit){ |
10066 | DMatrix2x2 InvV=Vtemp.Invert(); |
10067 | |
10068 | prob_hit=exp(-0.5*chi2_hit)/(M_TWO_PI6.28318530717958647692*sqrt(Vtemp.Determinant())); |
10069 | probs.push_back(prob_hit); |
10070 | Vlist.push_back(V); |
10071 | Hlist.push_back(H); |
10072 | HTlist.push_back(H_T); |
10073 | Mlist.push_back(Mdiff); |
10074 | Klist.push_back(C*H_T*InvV); // Kalman gain |
10075 | |
10076 | used_ids.push_back(id); |
10077 | fdc_used_in_fit[id]=true; |
10078 | } |
10079 | // loop over the remaining hits |
10080 | for (unsigned int m=1;m<traj.num_hits;m++){ |
10081 | unsigned int my_id=id-m; |
10082 | if (my_fdchits[my_id]->status==good_hit){ |
10083 | double u=my_fdchits[my_id]->uwire; |
10084 | double v=my_fdchits[my_id]->vstrip; |
10085 | |
10086 | // Doca to this wire |
10087 | double mydoca=(upred-u)*cosalpha; |
10088 | |
10089 | // variance for coordinate along the wire |
10090 | V(1,1)=my_fdchits[my_id]->vvar*fdc_anneal_factor; |
10091 | |
10092 | // Difference between measurement and projection |
10093 | Mdiff(1)=v-(vpred+mydoca*lorentz_factor); |
10094 | Mdiff(0)=-mydoca; |
10095 | if (fit_type==kTimeBased && USE_FDC_DRIFT_TIMES){ |
10096 | double drift_time=my_fdchits[my_id]->t-mT0-traj.t*TIME_UNIT_CONVERSION3.33564095198152014e-02; |
10097 | double sign=(doca>0.0)?1.:-1.; |
10098 | if (my_fdchits[my_id]->hit!=NULL__null){ |
10099 | double drift=sign*fdc_drift_distance(drift_time,traj.B); |
10100 | Mdiff(0)+=drift; |
10101 | |
10102 | // Variance in drift distance |
10103 | V(0,0)=fdc_drift_variance(drift_time)*fdc_anneal_factor; |
10104 | } |
10105 | else if (USE_TRD_DRIFT_TIMES&&my_fdchits[my_id]->status==trd_hit){ |
10106 | double drift = sign*0.1*pow(drift_time/8./0.91,1./1.556); |
10107 | Mdiff(0)+=drift; |
10108 | V(0,0)=0.05*0.05; |
10109 | } |
10110 | |
10111 | // H_T contains terms that are proportional to doca, so we only need |
10112 | // to scale the appropriate elements for the current hit. |
10113 | if (fabs(doca)<EPS3.0e-8){ |
10114 | doca=(doca>0)?EPS3.0e-8:-EPS3.0e-8; |
10115 | } |
10116 | double doca_ratio=mydoca/doca; |
10117 | DMatrix5x2 H_T_temp=H_T; |
10118 | H_T_temp(state_tx,1)*=doca_ratio; |
10119 | H_T_temp(state_ty,1)*=doca_ratio; |
10120 | H_T_temp(state_tx,0)*=doca_ratio; |
10121 | H_T_temp(state_ty,0)*=doca_ratio; |
10122 | H=Transpose(H_T_temp); |
10123 | |
10124 | // Update error matrix with state vector propagation covariance contrib. |
10125 | Vtemp=V+H*C*H_T_temp; |
10126 | // Cut out outliers and compute probability |
10127 | chi2_hit=Vtemp.Chi2(Mdiff); |
10128 | if (chi2_hit<fdc_chi2cut){ |
10129 | DMatrix2x2 InvV=Vtemp.Invert(); |
10130 | |
10131 | prob_hit=exp(-0.5*chi2_hit)/(M_TWO_PI6.28318530717958647692*sqrt(Vtemp.Determinant())); |
10132 | probs.push_back(prob_hit); |
10133 | Mlist.push_back(Mdiff); |
10134 | Vlist.push_back(V); |
10135 | Hlist.push_back(H); |
10136 | HTlist.push_back(H_T_temp); |
10137 | Klist.push_back(C*H_T_temp*InvV); |
10138 | |
10139 | used_ids.push_back(my_id); |
10140 | fdc_used_in_fit[my_id]=true; |
10141 | |
10142 | // Add some hit info to the update vector for this plane |
10143 | fdc_updates[my_id].tdrift=drift_time; |
10144 | fdc_updates[my_id].tcorr=fdc_updates[my_id].tdrift; |
10145 | fdc_updates[my_id].doca=mydoca; |
10146 | } |
10147 | } |
10148 | } // check that the hit is "good" |
10149 | } // loop over remaining hits |
10150 | if (probs.size()==0) return; |
10151 | |
10152 | double prob_tot=probs[0]; |
10153 | for (unsigned int m=1;m<probs.size();m++){ |
10154 | prob_tot+=probs[m]; |
10155 | } |
10156 | |
10157 | if (skip_plane==false){ |
10158 | DMatrix5x5 sum=I5x5; |
10159 | DMatrix5x5 sum2; |
10160 | for (unsigned int m=0;m<Klist.size();m++){ |
10161 | double my_prob=probs[m]/prob_tot; |
10162 | S+=my_prob*(Klist[m]*Mlist[m]); |
10163 | sum-=my_prob*(Klist[m]*Hlist[m]); |
10164 | sum2+=(my_prob*my_prob)*(Klist[m]*Vlist[m]*Transpose(Klist[m])); |
10165 | |
10166 | // Update chi2 |
10167 | DMatrix2x2 HK=Hlist[m]*Klist[m]; |
10168 | DMatrix2x1 R=Mlist[m]-HK*Mlist[m]; |
10169 | DMatrix2x2 RC=Vlist[m]-HK*Vlist[m]; |
10170 | chisq+=my_prob*RC.Chi2(R); |
10171 | |
10172 | unsigned int my_id=used_ids[m]; |
10173 | fdc_updates[my_id].V=RC; |
10174 | |
10175 | if (DEBUG_LEVEL > 25) |
10176 | { |
10177 | jout << " Adjusting state vector for FDC hit " << m << " with prob " << my_prob << " S:" << endl; |
10178 | S.Print(); |
10179 | } |
10180 | } |
10181 | // Update the covariance matrix C |
10182 | C=sum2.AddSym(sum*C*sum.Transpose()); |
10183 | |
10184 | if (DEBUG_LEVEL > 25) |
10185 | { jout << " C: " << endl; C.Print();} |
10186 | } |
10187 | |
10188 | // Save some information about the track at this plane in the update vector |
10189 | for (unsigned int m=0;m<Hlist.size();m++){ |
10190 | unsigned int my_id=used_ids[m]; |
10191 | fdc_updates[my_id].S=S; |
10192 | fdc_updates[my_id].C=C; |
10193 | if (skip_plane){ |
10194 | fdc_updates[my_id].V=Vlist[m]; |
10195 | } |
10196 | } |
10197 | // update number of degrees of freedom |
10198 | if (skip_plane==false){ |
10199 | numdof+=2; |
10200 | } |
10201 | } |
10202 | |
10203 | // Add extrapolation information for the given detector |
10204 | void DTrackFitterKalmanSIMD::AddExtrapolation(DetectorSystem_t detector, |
10205 | double z,const DMatrix5x1 &S, |
10206 | double t,double s, |
10207 | double s_theta_ms_sum, |
10208 | double theta2ms_sum){ |
10209 | double tsquare=S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty); |
10210 | double tanl=1./sqrt(tsquare); |
10211 | double cosl=cos(atan(tanl)); |
10212 | double pt=cosl/fabs(S(state_q_over_p)); |
10213 | double phi=atan2(S(state_ty),S(state_tx)); |
10214 | DVector3 position(S(state_x),S(state_y),z); |
10215 | DVector3 momentum(pt*cos(phi),pt*sin(phi),pt*tanl); |
10216 | extrapolations[detector].push_back(Extrapolation_t(position,momentum, |
10217 | t*TIME_UNIT_CONVERSION3.33564095198152014e-02,s, |
10218 | s_theta_ms_sum, |
10219 | theta2ms_sum)); |
10220 | if (DEBUG_LEVEL>0){ |
10221 | cout << SystemName(detector) << ": s=" << s |
10222 | << " t=" << t*TIME_UNIT_CONVERSION3.33564095198152014e-02 << " (x,y,z)=(" |
10223 | << position.x() <<","<<position.y()<<","<<position.z()<<") (px,py,pz)=" |
10224 | << momentum.x() <<","<<momentum.y()<<","<<momentum.z()<<")" |
10225 | << endl; |
10226 | } |
10227 | } |
10228 | |
10229 | // Add extrapolation information for the given detector |
10230 | void DTrackFitterKalmanSIMD::AddExtrapolation(DetectorSystem_t detector, |
10231 | const DMatrix5x1 &S, |
10232 | const DVector2 &xy, |
10233 | double t,double s, |
10234 | double s_theta_ms_sum, |
10235 | double theta2ms_sum){ |
10236 | double tanl=S(state_tanl); |
10237 | double pt=1/fabs(S(state_q_over_pt)); |
10238 | double phi=S(state_phi); |
10239 | DVector3 position(xy.X(),xy.Y(),S(state_z)); |
10240 | DVector3 momentum(pt*cos(phi),pt*sin(phi),pt*tanl); |
10241 | extrapolations[detector].push_back(Extrapolation_t(position,momentum, |
10242 | t*TIME_UNIT_CONVERSION3.33564095198152014e-02,s, |
10243 | s_theta_ms_sum, |
10244 | theta2ms_sum)); |
10245 | if (DEBUG_LEVEL>0){ |
10246 | cout << SystemName(detector) << ": s=" << s |
10247 | << " t=" << t*TIME_UNIT_CONVERSION3.33564095198152014e-02 << " (x,y,z)=("<< position.x() |
10248 | <<","<<position.y()<<","<<position.z()<<") (px,py,pz)=" |
10249 | << momentum.x() <<","<<momentum.y()<<","<<momentum.z()<<")" |
10250 | << endl; |
10251 | } |
10252 | } |