Bug Summary

File:libraries/FDC/DFDCSegment_factory.cc
Location:line 601, column 29
Description:Dereference of null pointer

Annotated Source Code

1//************************************************************************
2// DFDCSegment_factory.cc - factory producing track segments from pseudopoints
3//************************************************************************
4
5#include "DFDCSegment_factory.h"
6#include "DANA/DApplication.h"
7//#include "HDGEOMETRY/DLorentzMapCalibDB.h"
8#include <math.h>
9
10#define HALF_CELL0.5 0.5
11#define MAX_DEFLECTION0.15 0.15
12#define EPS1e-8 1e-8
13#define KILL_RADIUS5.0 5.0
14#define MATCH_RADIUS5.0 5.0
15#define ADJACENT_MATCH_RADIUS2.0 2.0
16#define SIGN_CHANGE_CHISQ_CUT10.0 10.0
17#define BEAM_VARIANCE0.01 0.01 // cm^2
18#define USED_IN_SEGMENT0x8 0x8
19#define CORRECTED0x10 0x10
20#define MAX_ITER10 10
21#define MIN_TANL2.0 2.0
22#define ONE_THIRD0.33333333333333333 0.33333333333333333
23#define SQRT31.73205080756887719 1.73205080756887719
24
25// Variance for position along wire using PHENIX angle dependence, transverse
26// diffusion, and an intrinsic resolution of 127 microns.
27inline double fdc_y_variance(double alpha,double x){
28 return 0.00060+0.0064*tan(alpha)*tan(alpha)+0.0004*fabs(x);
29}
30
31bool DFDCSegment_package_cmp(const DFDCPseudo* a, const DFDCPseudo* b) {
32 return a->wire->layer>b->wire->layer;
33}
34
35DFDCSegment_factory::DFDCSegment_factory() {
36 _log = new JStreamLog(std::cout, "FDCSEGMENT >>");
37 *_log << "File initialized." << endMsg;
38}
39
40
41///
42/// DFDCSegment_factory::~DFDCSegment_factory():
43/// default destructor -- closes log file
44///
45DFDCSegment_factory::~DFDCSegment_factory() {
46 delete _log;
47}
48///
49/// DFDCSegment_factory::brun():
50/// Initialization: read in deflection map, get magnetic field map
51///
52jerror_t DFDCSegment_factory::brun(JEventLoop* eventLoop, int runnumber) {
53 DApplication* dapp=dynamic_cast<DApplication*>(eventLoop->GetJApplication());
54 // get the geometry
55 const DGeometry *geom = dapp->GetDGeometry(runnumber);
56
57 geom->GetTargetZ(TARGET_Z);
58 /*
59 bfield = dapp->GetBfield();
60 lorentz_def=dapp->GetLorentzDeflections();
61
62 *_log << "Table of Lorentz deflections initialized." << endMsg;
63 */
64 return NOERROR;
65}
66
67///
68/// DFDCSegment_factory::evnt():
69/// Routine where pseudopoints are combined into track segments
70///
71jerror_t DFDCSegment_factory::evnt(JEventLoop* eventLoop, int eventNo) {
72 myeventno=eventNo;
73
74 vector<const DFDCPseudo*>pseudopoints;
75 eventLoop->Get(pseudopoints);
76
77 // Skip segment finding if there aren't enough points to form a sensible
78 // segment
79 if (pseudopoints.size()>=3){
1
Taking true branch
80 // Group pseudopoints by package
81 vector<const DFDCPseudo*>package[4];
82 for (vector<const DFDCPseudo*>::const_iterator i=pseudopoints.begin();
2
Loop condition is false. Execution continues on line 88
83 i!=pseudopoints.end();i++){
84 package[((*i)->wire->layer-1)/6].push_back(*i);
85 }
86
87 // Find the segments in each package
88 for (int j=0;j<4;j++){
3
Loop condition is true. Entering loop body
5
Loop condition is true. Entering loop body
7
Loop condition is true. Entering loop body
9
Loop condition is true. Entering loop body
89 std::sort(package[j].begin(),package[j].end(),DFDCSegment_package_cmp);
90 // We need at least 3 points to define a circle, so skip if we don't
91 // have enough points.
92 if (package[j].size()>2) FindSegments(package[j]);
4
Taking false branch
6
Taking false branch
8
Taking false branch
10
Taking true branch
11
Calling 'FindSegments'
93 }
94 } // pseudopoints>2
95
96 return NOERROR;
97}
98
99// Riemann Line fit: linear regression of s on z to determine the tangent of
100// the dip angle and the z position of the closest approach to the beam line.
101// Also returns predicted positions along the helical path.
102//
103jerror_t DFDCSegment_factory::RiemannLineFit(vector<const DFDCPseudo *>points,
104 DMatrix &CR,vector<xyz_t>&XYZ){
105 unsigned int n=points.size()+1;
106 vector<int>bad(n); // Keep track of "bad" intersection points
107 // Fill matrix of intersection points
108 for (unsigned int m=0;m<n-1;m++){
109 double r2=points[m]->xy.Mod2();
110 double denom= N[0]*N[0]+N[1]*N[1];
111 double numer=dist_to_origin+r2*N[2];
112 double ratio=numer/denom;
113
114 DVector2 xy_int0(-N[0]*ratio,-N[1]*ratio);
115 double temp=denom*r2-numer*numer;
116 if (temp<0){
117 bad[m]=1;
118 XYZ[m].xy=xy_int0;
119 continue;
120 }
121 temp=sqrt(temp)/denom;
122
123 // Choose sign of square root based on proximity to actual measurements
124 DVector2 delta(N[1]*temp,-N[0]*temp);
125 DVector2 xy1=xy_int0+delta;
126 DVector2 xy2=xy_int0-delta;
127 double diff1=(xy1-points[m]->xy).Mod2();
128 double diff2=(xy2-points[m]->xy).Mod2();
129 if (diff1>diff2){
130 XYZ[m].xy=xy2;
131 }
132 else{
133 XYZ[m].xy=xy1;
134 }
135 }
136 // Fake target point
137 XYZ[n-1].xy.Set(0.,0.);
138
139 // All arc lengths are measured relative to some reference plane with a hit.
140 // Don't use a "bad" hit for the reference...
141 unsigned int start=0;
142 for (unsigned int i=0;i<bad.size();i++){
143 if (!bad[i]){
144 start=i;
145 break;
146 }
147 }
148 if ((start!=0 && ref_plane==0) || (start!=2&&ref_plane==2)) ref_plane=start;
149
150 // Linear regression to find z0, tanl
151 double sumv=0.,sumx=0.;
152 double sumy=0.,sumxx=0.,sumxy=0.;
153 double sperp=0.,sperp_old=0.,ratio,Delta;
154 double z=0,zlast=0;
155 double two_rc=2.*rc;
156 DVector2 oldxy=XYZ[start].xy;
157 for (unsigned int k=start;k<n;k++){
158 zlast=z;
159 sperp_old=sperp;
160 if (!bad[k]){
161 DVector2 diffxy=XYZ[k].xy-oldxy;
162 ratio=diffxy.Mod()/(two_rc);
163 // Make sure the argument for the arcsin does not go out of range...
164 sperp=sperp_old+(ratio>1?two_rc*(M_PI_21.57079632679489661923):two_rc*asin(ratio));
165 //z=XYZ(k,2);
166 z=XYZ[k].z;
167
168 // Assume errors in s dominated by errors in R
169 double inv_var=1./CR(k,k);
170 sumv+=inv_var;
171 sumy+=sperp*inv_var;
172 sumx+=z*inv_var;
173 sumxx+=z*z*inv_var;
174 sumxy+=sperp*z*inv_var;
175
176 // Save the current x and y coordinates
177 //oldx=XYZ(k,0);
178 //oldy=XYZ(k,1);
179 oldxy=XYZ[k].xy;
180 }
181 }
182
183 Delta=sumv*sumxx-sumx*sumx;
184 double denom=sumv*sumxy-sumy*sumx;
185 if (fabs(Delta)>EPS1e-8 && fabs(denom)>EPS1e-8){
186 // Track parameters z0 and tan(lambda)
187 tanl=-Delta/denom;
188 //z0=(sumxx*sumy-sumx*sumxy)/Delta*tanl;
189 // Error in tanl
190 var_tanl=sumv/Delta*(tanl*tanl*tanl*tanl);
191
192 // Vertex position
193 sperp-=sperp_old;
194 zvertex=zlast-tanl*sperp;
195 }
196 else{
197 // assume that the particle came from the target
198 zvertex=TARGET_Z;
199 if (sperp<EPS1e-8){
200 // This is a rare failure mode where it seems that the arc length data
201 // cannot be reliably used. Provide some default value of tanl to
202 // avoid division by zero errors
203 tanl=57.3; // theta=1 degree
204 }
205 else tanl=(zlast-zvertex)/sperp;
206 var_tanl=100.; // guess for now
207
208
209 }
210
211 return NOERROR;
212}
213
214// Use predicted positions (propagating from plane 1 using a helical model) to
215// update the R and RPhi covariance matrices.
216//
217jerror_t DFDCSegment_factory::UpdatePositionsAndCovariance(unsigned int n,
218 double r1sq,vector<xyz_t>&XYZ,DMatrix &CRPhi,DMatrix &CR){
219 double delta_x=XYZ[ref_plane].xy.X()-xc;
220 double delta_y=XYZ[ref_plane].xy.Y()-yc;
221 double r1=sqrt(r1sq);
222 double denom=delta_x*delta_x+delta_y*delta_y;
223
224 // Auxiliary matrices for correcting for non-normal track incidence to FDC
225 // The correction is
226 // CRPhi'= C*CRPhi*C+S*CR*S, where S(i,i)=R_i*kappa/2
227 // and C(i,i)=sqrt(1-S(i,i)^2)
228 DMatrix C(n,n);
229 DMatrix S(n,n);
230
231 // Predicted positions
232 Phi1=atan2(delta_y,delta_x);
233 double z1=XYZ[ref_plane].z;
234 double y1=XYZ[ref_plane].xy.X();
235 double x1=XYZ[ref_plane].xy.Y();
236 double var_R1=CR(ref_plane,ref_plane);
237 for (unsigned int k=0;k<n;k++){
238 double sperp=charge*(XYZ[k].z-z1)/tanl;
239 double phi_s=Phi1+sperp/rc;
240 double sinp=sin(phi_s);
241 double cosp=cos(phi_s);
242 XYZ[k].xy.Set(xc+rc*cosp,yc+rc*sinp);
243
244 // Error analysis. We ignore errors in N because there doesn't seem to
245 // be any obvious established way to estimate errors in eigenvalues for
246 // small eigenvectors. We assume that most of the error comes from
247 // the measurement for the reference plane radius and the dip angle anyway.
248 double Phi=XYZ[k].xy.Phi();
249 double sinPhi=sin(Phi);
250 double cosPhi=cos(Phi);
251 double dRPhi_dx=Phi*cosPhi-sinPhi;
252 double dRPhi_dy=Phi*sinPhi+cosPhi;
253
254 double rc_sinphi_over_denom=rc*sinp/denom;
255 //double dx_dx1=rc*sinp*delta_y/denom;
256 //double dx_dy1=-rc*sinp*delta_x/denom;
257 double dx_dx1=rc_sinphi_over_denom*delta_y;
258 double dx_dy1=-rc_sinphi_over_denom*delta_x;
259 double dx_dtanl=sinp*sperp/tanl;
260
261 double rc_cosphi_over_denom=rc*cosp/denom;
262 //double dy_dx1=-rc*cosp*delta_y/denom;
263 //double dy_dy1=rc*cosp*delta_x/denom;
264 double dy_dx1=-rc_cosphi_over_denom*delta_y;
265 double dy_dy1=rc_cosphi_over_denom*delta_x;
266 double dy_dtanl=-cosp*sperp/tanl;
267
268 double dRPhi_dx1=dRPhi_dx*dx_dx1+dRPhi_dy*dy_dx1;
269 double dRPhi_dy1=dRPhi_dx*dx_dy1+dRPhi_dy*dy_dy1;
270 double dRPhi_dtanl=dRPhi_dx*dx_dtanl+dRPhi_dy*dy_dtanl;
271
272 double dR_dx1=cosPhi*dx_dx1+sinPhi*dy_dx1;
273 double dR_dy1=cosPhi*dx_dy1+sinPhi*dy_dy1;
274 double dR_dtanl=cosPhi*dx_dtanl+sinPhi*dy_dtanl;
275
276 double cdist=dist_to_origin+r1sq*N[2];
277 double n2=N[0]*N[0]+N[1]*N[1];
278
279 double ydenom=y1*n2+N[1]*cdist;
280 double dy1_dr1=-r1*(2.*N[1]*N[2]*y1+2.*N[2]*cdist-N[0]*N[0])/ydenom;
281 double var_y1=dy1_dr1*dy1_dr1*var_R1;
282
283 double xdenom=x1*n2+N[0]*cdist;
284 double dx1_dr1=-r1*(2.*N[0]*N[2]*x1+2.*N[2]*cdist-N[1]*N[1])/xdenom;
285 double var_x1=dx1_dr1*dx1_dr1*var_R1;
286
287 CRPhi(k,k)=dRPhi_dx1*dRPhi_dx1*var_x1+dRPhi_dy1*dRPhi_dy1*var_y1
288 +dRPhi_dtanl*dRPhi_dtanl*var_tanl;
289 CR(k,k)=dR_dx1*dR_dx1*var_x1+dR_dy1*dR_dy1*var_y1
290 +dR_dtanl*dR_dtanl*var_tanl;
291
292 // double stemp=sqrt(XYZ(k,0)*XYZ(k,0)+XYZ(k,1)*XYZ(k,1))/(4.*rc);
293 double stemp=XYZ[k].xy.Mod()/(4.*rc);
294 double ctemp=1.-stemp*stemp;
295 if (ctemp>0){
296 S(k,k)=stemp;
297 C(k,k)=sqrt(ctemp);
298 }
299 else{
300 S(k,k)=0.;
301 C(k,k)=1.;
302 }
303 }
304
305 // Correction for non-normal incidence of track on FDC
306 CRPhi=C*CRPhi*C+S*CR*S;
307
308 return NOERROR;
309}
310
311// Riemann Circle fit: points on a circle in x,y project onto a plane cutting
312// the circular paraboloid surface described by (x,y,x^2+y^2). Therefore the
313// task of fitting points in (x,y) to a circle is transormed to the taks of
314// fitting planes in (x,y, w=x^2+y^2) space
315//
316jerror_t DFDCSegment_factory::RiemannCircleFit(vector<const DFDCPseudo *>points,
317 DMatrix &CRPhi){
318 unsigned int n=points.size()+1;
319 DMatrix X(n,3);
320 DMatrix Xavg(1,3);
321 DMatrix A(3,3);
322 // vector of ones
323 DMatrix OnesT(1,n);
324 double W_sum=0.;
325 DMatrix W(n,n);
326
327 // The goal is to find the eigenvector corresponding to the smallest
328 // eigenvalue of the equation
329 // lambda=n^T (X^T W X - W_sum Xavg^T Xavg)n
330 // where n is the normal vector to the plane slicing the cylindrical
331 // paraboloid described by the parameterization (x,y,w=x^2+y^2),
332 // and W is the weight matrix, assumed for now to be diagonal.
333 // In the absence of multiple scattering, W_sum is the sum of all the
334 // diagonal elements in W.
335 // At this stage we ignore the multiple scattering.
336 for (unsigned int i=0;i<n-1;i++){
337 X(i,0)=points[i]->xy.X();
338 X(i,1)=points[i]->xy.Y();
339 X(i,2)=points[i]->xy.Mod2();
340 OnesT(0,i)=1.;
341 W(i,i)=1./CRPhi(i,i);
342 W_sum+=W(i,i);
343 }
344 unsigned int last_index=n-1;
345 OnesT(0,last_index)=1.;
346 W(last_index,last_index)=1./CRPhi(last_index,last_index);
347 W_sum+=W(last_index,last_index);
348 var_avg=1./W_sum;
349 Xavg=var_avg*(OnesT*(W*X));
350 // Store in private array for use in other routines
351 xavg[0]=Xavg(0,0);
352 xavg[1]=Xavg(0,1);
353 xavg[2]=Xavg(0,2);
354
355 A=DMatrix(DMatrix::kTransposed,X)*(W*X)
356 -W_sum*(DMatrix(DMatrix::kTransposed,Xavg)*Xavg);
357 if(!A.IsValid())return UNRECOVERABLE_ERROR;
358
359 // The characteristic equation is
360 // lambda^3+B2*lambda^2+lambda*B1+B0=0
361 //
362 double B2=-(A(0,0)+A(1,1)+A(2,2));
363 double B1=A(0,0)*A(1,1)-A(1,0)*A(0,1)+A(0,0)*A(2,2)-A(2,0)*A(0,2)
364 +A(1,1)*A(2,2)-A(2,1)*A(1,2);
365 double B0=-A.Determinant();
366 if(B0==0 || !finite(B0))return UNRECOVERABLE_ERROR;
367
368 // The roots of the cubic equation are given by
369 // lambda1= -B2/3 + S+T
370 // lambda2= -B2/3 - (S+T)/2 + i sqrt(3)/2. (S-T)
371 // lambda3= -B2/3 - (S+T)/2 - i sqrt(3)/2. (S-T)
372 // where we define some temporary variables:
373 // S= (R+sqrt(Q^3+R^2))^(1/3)
374 // T= (R-sqrt(Q^3+R^2))^(1/3)
375 // Q=(3*B1-B2^2)/9
376 // R=(9*B2*B1-27*B0-2*B2^3)/54
377 // sum=S+T;
378 // diff=i*(S-T)
379 // We divide Q and R by a safety factor to prevent multiplying together
380 // enormous numbers that cause unreliable results.
381
382 double Q=(3.*B1-B2*B2)/9.e4;
383 double R=(9.*B2*B1-27.*B0-2.*B2*B2*B2)/54.e6;
384 double Q1=Q*Q*Q+R*R;
385 if (Q1<0) Q1=sqrt(-Q1);
386 else{
387 return VALUE_OUT_OF_RANGE;
388 }
389
390 // DeMoivre's theorem for fractional powers of complex numbers:
391 // (r*(cos(theta)+i sin(theta)))^(p/q)
392 // = r^(p/q)*(cos(p*theta/q)+i sin(p*theta/q))
393 //
394 //double temp=100.*pow(R*R+Q1*Q1,0.16666666666666666667);
395 double temp=100.*sqrt(cbrt(R*R+Q1*Q1));
396 double theta1=ONE_THIRD0.33333333333333333*atan2(Q1,R);
397 double sum_over_2=temp*cos(theta1);
398 double diff_over_2=-temp*sin(theta1);
399 // Third root
400 double lambda_min=-ONE_THIRD0.33333333333333333*B2-sum_over_2+SQRT31.73205080756887719*diff_over_2;
401
402 // Normal vector to plane
403 N[0]=1.;
404 N[1]=(A(1,0)*A(0,2)-(A(0,0)-lambda_min)*A(1,2))
405 /(A(0,1)*A(2,1)-(A(1,1)-lambda_min)*A(0,2));
406 N[2]=(A(2,0)*(A(1,1)-lambda_min)-A(1,0)*A(2,1))
407 /(A(1,2)*A(2,1)-(A(2,2)-lambda_min)*(A(1,1)-lambda_min));
408
409 // Normalize: n1^2+n2^2+n3^2=1
410 double denom=sqrt(N[0]*N[0]+N[1]*N[1]+N[2]*N[2]);
411 for (int i=0;i<3;i++){
412 N[i]/=denom;
413 }
414
415 // Distance to origin
416 dist_to_origin=-(N[0]*Xavg(0,0)+N[1]*Xavg(0,1)+N[2]*Xavg(0,2));
417
418 // Center and radius of the circle
419 double two_N2=2.*N[2];
420 xc=-N[0]/two_N2;
421 yc=-N[1]/two_N2;
422 rc=sqrt(1.-N[2]*N[2]-4.*dist_to_origin*N[2])/fabs(two_N2);
423
424 return NOERROR;
425}
426
427// Riemann Helical Fit based on transforming points on projection to x-y plane
428// to a circular paraboloid surface combined with a linear fit of the arc
429// length versus z. Uses RiemannCircleFit and RiemannLineFit.
430//
431jerror_t DFDCSegment_factory::RiemannHelicalFit(vector<const DFDCPseudo*>points,
432 DMatrix &CR,vector<xyz_t>&XYZ){
433 double Phi;
434 unsigned int num_points=points.size()+1;
435 DMatrix CRPhi(num_points,num_points);
436
437 // Fill initial matrices for R and RPhi measurements
438 XYZ[num_points-1].z=TARGET_Z;
439 for (unsigned int m=0;m<points.size();m++){
440 XYZ[m].z=points[m]->wire->origin.z();
441
442 //Phi=atan2(points[m]->y,points[m]->x);
443 Phi=points[m]->xy.Phi();
444 double cosPhi=cos(Phi);
445 double sinPhi=sin(Phi);
446 double Phi_cosPhi=Phi*cosPhi;
447 double Phi_sinPhi=Phi*sinPhi;
448 double Phi_cosPhi_minus_sinPhi=Phi_cosPhi-sinPhi;
449 double Phi_sinPhi_plus_cosPhi=Phi_sinPhi+cosPhi;
450 CRPhi(m,m)
451 =Phi_cosPhi_minus_sinPhi*Phi_cosPhi_minus_sinPhi*points[m]->covxx
452 +Phi_sinPhi_plus_cosPhi*Phi_sinPhi_plus_cosPhi*points[m]->covyy
453 +2.*Phi_sinPhi_plus_cosPhi*Phi_cosPhi_minus_sinPhi*points[m]->covxy;
454
455 CR(m,m)=cosPhi*cosPhi*points[m]->covxx
456 +sinPhi*sinPhi*points[m]->covyy
457 +2.*sinPhi*cosPhi*points[m]->covxy;
458 }
459 CR(points.size(),points.size())=BEAM_VARIANCE0.01;
460 CRPhi(points.size(),points.size())=BEAM_VARIANCE0.01;
461
462 // Reference track:
463 jerror_t error=NOERROR;
464 // First find the center and radius of the projected circle
465 error=RiemannCircleFit(points,CRPhi);
466 if (error!=NOERROR) return error;
467
468 // Get reference track estimates for z0 and tanl and intersection points
469 // (stored in XYZ)
470 error=RiemannLineFit(points,CR,XYZ);
471 if (error!=NOERROR) return error;
472
473 // Guess particle charge (+/-1);
474 charge=GetCharge(points.size(),XYZ,CR,CRPhi);
475
476 double r1sq=XYZ[ref_plane].xy.Mod2();
477 UpdatePositionsAndCovariance(num_points,r1sq,XYZ,CRPhi,CR);
478
479 // Preliminary circle fit
480 error=RiemannCircleFit(points,CRPhi);
481 if (error!=NOERROR) return error;
482
483 // Preliminary line fit
484 error=RiemannLineFit(points,CR,XYZ);
485 if (error!=NOERROR) return error;
486
487 // Guess particle charge (+/-1);
488 charge=GetCharge(points.size(),XYZ,CR,CRPhi);
489
490 r1sq=XYZ[ref_plane].xy.Mod2();
491 UpdatePositionsAndCovariance(num_points,r1sq,XYZ,CRPhi,CR);
492
493 // Final circle fit
494 error=RiemannCircleFit(points,CRPhi);
495 if (error!=NOERROR) return error;
496
497 // Final line fit
498 error=RiemannLineFit(points,CR,XYZ);
499 if (error!=NOERROR) return error;
500
501 // Guess particle charge (+/-1)
502 charge=GetCharge(points.size(),XYZ,CR,CRPhi);
503
504 // Final update to covariance matrices
505 ref_plane=0;
506 r1sq=XYZ[ref_plane].xy.Mod2();
507 UpdatePositionsAndCovariance(num_points,r1sq,XYZ,CRPhi,CR);
508
509 // Store residuals and path length for each measurement
510 chisq=0.;
511 for (unsigned int m=0;m<points.size();m++){
512 double sperp=charge*(XYZ[m].z-XYZ[ref_plane].z)/tanl;
513 double phi_s=Phi1+sperp/rc;
514 DVector2 XY(xc+rc*cos(phi_s),yc+rc*sin(phi_s));
515 chisq+=(XY-points[m]->xy).Mod2()/CR(m,m);
516 }
517 return NOERROR;
518}
519
520
521// DFDCSegment_factory::FindSegments
522// Associate nearest neighbors within a package with track segment candidates.
523// Provide guess for (seed) track parameters
524//
525jerror_t DFDCSegment_factory::FindSegments(vector<const DFDCPseudo*>points){
526 // Clear all the "used" flags;
527 used.clear();
528
529 // Put indices for the first point in each plane before the most downstream
530 // plane in the vector x_list.
531 double old_z=points[0]->wire->origin.z();
532 vector<unsigned int>x_list;
533 x_list.push_back(0);
534 for (unsigned int i=0;i<points.size();i++){
12
Loop condition is false. Execution continues on line 541
535 used.push_back(false);
536 if (points[i]->wire->origin.z()!=old_z){
537 x_list.push_back(i);
538 }
539 old_z=points[i]->wire->origin.z();
540 }
541 x_list.push_back(points.size());
542
543 unsigned int start=0;
544 // loop over the start indices, starting with the first plane
545 while (start<x_list.size()-1){
13
Loop condition is true. Entering loop body
18
Loop condition is true. Entering loop body
27
Loop condition is true. Entering loop body
546 int num_used=0;
547 // For each iteration, count how many hits we have used already in segments
548 for (unsigned int i=0;i<points.size();i++){
14
Loop condition is false. Execution continues on line 552
19
Loop condition is true. Entering loop body
21
Loop condition is false. Execution continues on line 552
28
Loop condition is false. Execution continues on line 552
549 if(used[i]==true) num_used++;
20
Taking false branch
550 }
551 // Break out of loop if we don't have enough hits left to fit a circle
552 if (points.size()-num_used<3) break;
15
Taking false branch
22
Taking false branch
29
Taking false branch
553
554 // Now loop over the list of track segment start points
555 for (unsigned int i=x_list[start];i<x_list[start+1];i++){
16
Loop condition is false. Execution continues on line 663
23
Loop condition is false. Execution continues on line 663
30
Loop condition is true. Entering loop body
32
Loop condition is true. Entering loop body
556 if (used[i]==false){
31
Taking false branch
33
Taking true branch
557 used[i]=true;
558 chisq=1.e8;
559
560 // Clear track parameters
561 tanl=D=z0=phi0=Phi1=xc=yc=rc=0.;
562 charge=1.;
563
564 // Point in the current plane in the package
565 DVector2 XY=points[i]->xy;
566
567 // Create list of nearest neighbors
568 vector<const DFDCPseudo*>neighbors;
569 neighbors.push_back(points[i]);
570 unsigned int match=0;
571 double delta,delta_min=1000.;
572 for (unsigned int k=0;k<x_list.size()-1;k++){
34
Loop condition is false. Execution continues on line 590
573 delta_min=1000.;
574 match=0;
575 for (unsigned int m=x_list[k];m<x_list[k+1];m++){
576 delta=(XY-points[m]->xy).Mod();
577 if (delta<delta_min && delta<MATCH_RADIUS5.0){
578 delta_min=delta;
579 match=m;
580 }
581 }
582 if (match!=0
583 && used[match]==false
584 ){
585 XY=points[match]->xy;
586 used[match]=true;
587 neighbors.push_back(points[match]);
588 }
589 }
590 unsigned int num_neighbors=neighbors.size();
591
592 // Skip to next segment seed if we don't have enough points to fit a
593 // circle
594 if (num_neighbors<3) continue;
35
Taking false branch
595
596 bool do_sort=false;
597 // Look for hits adjacent to the ones we have in our segment candidate
598 for (unsigned int k=0;k<points.size();k++){
36
Loop condition is true. Entering loop body
599 if (!used[k]){
37
Taking true branch
600 for (unsigned int j=0;j<num_neighbors;j++){
38
Loop condition is true. Entering loop body
601 delta=(points[k]->xy-neighbors[j]->xy).Mod();
39
Dereference of null pointer
602
603 if (delta<ADJACENT_MATCH_RADIUS2.0 &&
604 abs(neighbors[j]->wire->wire-points[k]->wire->wire)<=1
605 && neighbors[j]->wire->origin.z()==points[k]->wire->origin.z()){
606 used[k]=true;
607 neighbors.push_back(points[k]);
608 do_sort=true;
609 }
610 }
611 }
612 }
613 // Sort if we added another point
614 if (do_sort)
615 std::sort(neighbors.begin(),neighbors.end(),DFDCSegment_package_cmp);
616
617 // list of points on track and the corresponding covariances
618 unsigned int num_points_on_segment=neighbors.size()+1;
619 vector<xyz_t>XYZ(num_points_on_segment);
620 DMatrix CR(num_points_on_segment,num_points_on_segment);
621
622 // Arc lengths in helical model are referenced relative to the plane
623 // ref_plane within a segment. For a 6 hit segment, ref_plane=2 is
624 // roughly in the center of the segment.
625 ref_plane=2;
626
627 // Perform the Riemann Helical Fit on the track segment
628 jerror_t error=RiemannHelicalFit(neighbors,CR,XYZ); /// initial hit-based fit
629
630 if (error==NOERROR){
631 // Estimate for azimuthal angle
632 phi0=atan2(-xc,yc);
633 if (charge<0) phi0+=M_PI3.14159265358979323846;
634
635 // Look for distance of closest approach nearest to target
636 D=-charge*rc-xc/sin(phi0);
637
638 // Creat a new segment
639 DFDCSegment *segment = new DFDCSegment;
640
641 // Initialize seed track parameters
642 segment->q=charge; //charge
643 segment->phi0=phi0; // Phi
644 segment->D=D; // D=distance of closest approach to origin
645 segment->tanl=tanl; // tan(lambda), lambda=dip angle
646 segment->z_vertex=zvertex;// z-position at closest approach to origin
647
648 segment->hits=neighbors;
649 segment->xc=xc;
650 segment->yc=yc;
651 segment->rc=rc;
652 segment->Phi1=Phi1;
653 segment->chisq=chisq;
654
655 //printf("tanl %f \n",tanl);
656 //printf("xc %f yc %f rc %f\n",xc,yc,rc);
657
658 _data.push_back(segment);
659 }
660 }
661 }
662 // Look for a new plane to start looking for a segment
663 while (start<x_list.size()-1){
17
Loop condition is false. Execution continues on line 545
24
Loop condition is true. Entering loop body
26
Loop condition is false. Execution continues on line 545
664 if (used[x_list[start]]==false) break;
25
Taking false branch
665 start++;
666 }
667 } //while loop over x_list planes
668
669 return NOERROR;
670}
671
672// Linear regression to find charge
673double DFDCSegment_factory::GetCharge(unsigned int n,vector<xyz_t>&XYZ,
674 DMatrix &CR,
675 DMatrix &CRPhi){
676 double inv_var=0.;
677 double sumv=0.;
678 double sumy=0.;
679 double sumx=0.;
680 double sumxx=0.,sumxy=0,Delta;
681 double slope,r2;
682 double phi_old=XYZ[0].xy.Phi();
683 for (unsigned int k=0;k<n;k++){
684 double tempz=XYZ[k].z;
685 double phi_z=XYZ[k].xy.Phi();
686 // Check for problem regions near +pi and -pi
687 if (fabs(phi_z-phi_old)>M_PI3.14159265358979323846){
688 if (phi_old<0) phi_z-=2.*M_PI3.14159265358979323846;
689 else phi_z+=2.*M_PI3.14159265358979323846;
690 }
691 r2=XYZ[k].xy.Mod2();
692 inv_var=r2/(CRPhi(k,k)+phi_z*phi_z*CR(k,k));
693 sumv+=inv_var;
694 sumy+=phi_z*inv_var;
695 sumx+=tempz*inv_var;
696 sumxx+=tempz*tempz*inv_var;
697 sumxy+=phi_z*tempz*inv_var;
698 phi_old=phi_z;
699 }
700 Delta=sumv*sumxx-sumx*sumx;
701 slope=(sumv*sumxy-sumy*sumx)/Delta;
702
703 // Guess particle charge (+/-1);
704 if (slope<0.) return -1.;
705 return 1.;
706}
707
708//----------------------------------------------------------------------------
709// The following routine is no longer in use:
710// Correct avalanche position along wire and incorporate drift data for
711// coordinate away from the wire using results of preliminary hit-based fit
712//
713//#define R_START 7.6
714//#define Z_TOF 617.4
715//#include "HDGEOMETRY/DLorentzMapCalibDB.h
716//#define SC_V_EFF 15.
717//#define SC_LIGHT_GUIDE 140.
718//#define SC_CENTER 38.75
719//#define TOF_BAR_LENGTH 252.0
720//#define TOF_V_EFF 15.
721//#define FDC_X_RESOLUTION 0.028
722//#define FDC_Y_RESOLUTION 0.02 //cm
723/*
724jerror_t DFDCSegment_factory::CorrectPoints(vector<DFDCPseudo*>points,
725 DMatrix XYZ){
726 // dip angle
727 double lambda=atan(tanl);
728 double alpha=M_PI/2.-lambda;
729
730 if (alpha == 0. || rc==0.) return VALUE_OUT_OF_RANGE;
731
732 // Get Bfield, needed to guess particle momentum
733 double Bx,By,Bz,B;
734 double x=XYZ(ref_plane,0);
735 double y=XYZ(ref_plane,1);
736 double z=XYZ(ref_plane,2);
737
738 bfield->GetField(x,y,z,Bx,By,Bz);
739 B=sqrt(Bx*Bx+By*By+Bz*Bz);
740
741 // Momentum and beta
742 double p=0.002998*B*rc/cos(lambda);
743 double beta=p/sqrt(p*p+0.140*0.140);
744
745 // Correct start time for propagation from (0,0)
746 double my_start_time=0.;
747 if (use_tof){
748 //my_start_time=ref_time-(Z_TOF-TARGET_Z)/sin(lambda)/beta/29.98;
749 // If we need to use the tof, the angle relative to the beam line is
750 // small enough that sin(lambda) ~ 1.
751 my_start_time=ref_time-(Z_TOF-TARGET_Z)/beta/29.98;
752 //my_start_time=0;
753 }
754 else{
755 double ratio=R_START/2./rc;
756 if (ratio<=1.)
757 my_start_time=ref_time
758 -2.*rc*asin(R_START/2./rc)*(1./cos(lambda)/beta/29.98);
759 else
760 my_start_time=ref_time
761 -rc*M_PI*(1./cos(lambda)/beta/29.98);
762
763 }
764 //my_start_time=0.;
765
766 for (unsigned int m=0;m<points.size();m++){
767 DFDCPseudo *point=points[m];
768
769 double cosangle=point->wire->udir(1);
770 double sinangle=point->wire->udir(0);
771 x=XYZ(m,0);
772 y=XYZ(m,1);
773 z=point->wire->origin.z();
774 double delta_x=0,delta_y=0;
775 // Variances based on expected resolution
776 double sigx2=FDC_X_RESOLUTION*FDC_X_RESOLUTION;
777
778 // Find difference between point on helical path and wire
779 double w=x*cosangle-y*sinangle-point->w;
780 // .. and use it to determine which sign to use for the drift time data
781 double sign=(w>0?1.:-1.);
782
783 // Correct the drift time for the flight path and convert to distance units
784 // assuming the particle is a pion
785 delta_x=sign*(point->time-fdc_track[m].s/beta/29.98-my_start_time)*55E-4;
786
787 // Variance for position along wire. Includes angle dependence from PHENIX
788 // and transverse diffusion
789 double sigy2=fdc_y_variance(alpha,delta_x);
790
791 // Next find correction to y from table of deflections
792 delta_y=lorentz_def->GetLorentzCorrection(x,y,z,alpha,delta_x);
793
794 // Fill x and y elements with corrected values
795 point->ds =-delta_y;
796 point->dw =delta_x;
797 point->x=(point->w+point->dw)*cosangle+(point->s+point->ds)*sinangle;
798 point->y=-(point->w+point->dw)*sinangle+(point->s+point->ds)*cosangle;
799 point->covxx=sigx2*cosangle*cosangle+sigy2*sinangle*sinangle;
800 point->covyy=sigx2*sinangle*sinangle+sigy2*cosangle*cosangle;
801 point->covxy=(sigy2-sigx2)*sinangle*cosangle;
802 point->status|=CORRECTED;
803 }
804 return NOERROR;
805}
806*/