File: | alld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h |
Warning: | line 398, column 7 Null pointer passed to 2nd parameter expecting 'nonnull' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | #include <cmath> | |||
10 | using namespace std; | |||
11 | ||||
12 | // some of these aren't being used anymore, so I've commented them out - sdobbs, 6/3/14 | |||
13 | //#define HALF_CELL 0.5 | |||
14 | //#define MAX_DEFLECTION 0.15 | |||
15 | #define EPS1e-8 1e-8 | |||
16 | //#define KILL_RADIUS 5.0 | |||
17 | #define MATCH_RADIUS2.0 2.0 | |||
18 | #define ADJACENT_MATCH_DISTANCE0.3 0.3 | |||
19 | //#define SIGN_CHANGE_CHISQ_CUT 10.0 | |||
20 | //#define USED_IN_SEGMENT 0x8 | |||
21 | //#define CORRECTED 0x10 | |||
22 | //#define MAX_ITER 10 | |||
23 | //#define MIN_TANL 2.0 | |||
24 | #define ONE_THIRD0.33333333333333333 0.33333333333333333 | |||
25 | #define SQRT31.73205080756887719 1.73205080756887719 | |||
26 | ||||
27 | ||||
28 | ||||
29 | // Variance for position along wire using PHENIX angle dependence, transverse | |||
30 | // diffusion, and an intrinsic resolution of 127 microns. | |||
31 | // Deprecated! | |||
32 | //inline double fdc_y_variance(double alpha,double x){ | |||
33 | // return 0.00060+0.0064*tan(alpha)*tan(alpha)+0.0004*fabs(x); | |||
34 | //} | |||
35 | ||||
36 | bool DFDCSegment_package_cmp(const DFDCPseudo* a, const DFDCPseudo* b) { | |||
37 | if(a->wire->layer == b->wire->layer) { | |||
38 | if (fabs(a->time-b->time)<EPS1e-8){ | |||
39 | double tsum_1=a->t_u+a->t_v; | |||
40 | double tsum_2=b->t_u+b->t_v; | |||
41 | return (tsum_1<tsum_2); | |||
42 | } | |||
43 | return(a->time<b->time); | |||
44 | } | |||
45 | return a->wire->layer>b->wire->layer; | |||
46 | } | |||
47 | ||||
48 | ||||
49 | DFDCSegment_factory::DFDCSegment_factory() { | |||
50 | _log = new JStreamLog(std::cout, "FDCSEGMENT >>"); | |||
51 | *_log << "File initialized." << endMsg; | |||
52 | } | |||
53 | ||||
54 | ||||
55 | /// | |||
56 | /// DFDCSegment_factory::~DFDCSegment_factory(): | |||
57 | /// default destructor -- closes log file | |||
58 | /// | |||
59 | DFDCSegment_factory::~DFDCSegment_factory() { | |||
60 | delete _log; | |||
61 | } | |||
62 | /// | |||
63 | /// DFDCSegment_factory::brun(): | |||
64 | /// Initialization: read in deflection map, get magnetic field map | |||
65 | /// | |||
66 | jerror_t DFDCSegment_factory::brun(JEventLoop* eventLoop, int32_t runnumber) { | |||
67 | DApplication* dapp=dynamic_cast<DApplication*>(eventLoop->GetJApplication()); | |||
68 | const DMagneticFieldMap *bfield = dapp->GetBfield(runnumber); | |||
69 | double Bz=bfield->GetBz(0.,0.,65.); | |||
70 | RotationSenseToCharge=(Bz>0.)?-1.:1.; | |||
71 | ||||
72 | // get the geometry | |||
73 | const DGeometry *geom = dapp->GetDGeometry(runnumber); | |||
74 | ||||
75 | geom->GetTargetZ(TARGET_Z); | |||
76 | /* | |||
77 | bfield = dapp->GetBfield(); | |||
78 | lorentz_def=dapp->GetLorentzDeflections(); | |||
79 | ||||
80 | *_log << "Table of Lorentz deflections initialized." << endMsg; | |||
81 | */ | |||
82 | DEBUG_LEVEL=0; | |||
83 | gPARMS->SetDefaultParameter("FDC:DEBUG_LEVEL", DEBUG_LEVEL); | |||
84 | ||||
85 | BEAM_VARIANCE=1.0; | |||
86 | gPARMS->SetDefaultParameter("FDC:BEAM_VARIANCE",BEAM_VARIANCE); | |||
87 | ||||
88 | ||||
89 | return NOERROR; | |||
90 | } | |||
91 | ||||
92 | /// | |||
93 | /// DFDCSegment_factory::evnt(): | |||
94 | /// Routine where pseudopoints are combined into track segments | |||
95 | /// | |||
96 | jerror_t DFDCSegment_factory::evnt(JEventLoop* eventLoop, uint64_t eventNo) { | |||
97 | myeventno=eventNo; | |||
98 | ||||
99 | vector<const DFDCPseudo*>pseudopoints; | |||
100 | eventLoop->Get(pseudopoints); | |||
| ||||
101 | ||||
102 | // Skip segment finding if there aren't enough points to form a sensible | |||
103 | // segment | |||
104 | if (pseudopoints.size()>=3){ | |||
105 | // Group pseudopoints by package | |||
106 | vector<const DFDCPseudo*>package[4]; | |||
107 | for (vector<const DFDCPseudo*>::const_iterator i=pseudopoints.begin(); | |||
108 | i!=pseudopoints.end();i++){ | |||
109 | package[((*i)->wire->layer-1)/6].push_back(*i); | |||
110 | } | |||
111 | ||||
112 | // Find the segments in each package | |||
113 | for (int j=0;j<4;j++){ | |||
114 | std::stable_sort(package[j].begin(),package[j].end(),DFDCSegment_package_cmp); | |||
115 | // We need at least 3 points to define a circle, so skip if we don't | |||
116 | // have enough points. | |||
117 | if (package[j].size()>2) FindSegments(package[j]); | |||
118 | } | |||
119 | } // pseudopoints>2 | |||
120 | ||||
121 | return NOERROR; | |||
122 | } | |||
123 | ||||
124 | // Riemann Line fit: linear regression of s on z to determine the tangent of | |||
125 | // the dip angle and the z position of the closest approach to the beam line. | |||
126 | // Also returns predicted positions along the helical path. | |||
127 | // | |||
128 | jerror_t DFDCSegment_factory::RiemannLineFit(vector<const DFDCPseudo *>&points, | |||
129 | DMatrix &CR,vector<xyz_t>&XYZ){ | |||
130 | unsigned int n=points.size()+1; | |||
131 | vector<int>bad(n); // Keep track of "bad" intersection points | |||
132 | bool got_bad_intersection=false; | |||
133 | // Fill matrix of intersection points | |||
134 | for (unsigned int m=0;m<n-1;m++){ | |||
135 | double r2=points[m]->xy.Mod2(); | |||
136 | double denom= N[0]*N[0]+N[1]*N[1]; | |||
137 | double numer=dist_to_origin+r2*N[2]; | |||
138 | double ratio=numer/denom; | |||
139 | ||||
140 | DVector2 xy_int0(-N[0]*ratio,-N[1]*ratio); | |||
141 | double temp=denom*r2-numer*numer; | |||
142 | if (temp<0){ | |||
143 | got_bad_intersection=true; | |||
144 | bad[m]=1; | |||
145 | XYZ[m].xy=points[m]->xy; | |||
146 | continue; | |||
147 | } | |||
148 | temp=sqrt(temp)/denom; | |||
149 | ||||
150 | // Choose sign of square root based on proximity to actual measurements | |||
151 | DVector2 delta(N[1]*temp,-N[0]*temp); | |||
152 | DVector2 xy1=xy_int0+delta; | |||
153 | DVector2 xy2=xy_int0-delta; | |||
154 | double diff1=(xy1-points[m]->xy).Mod2(); | |||
155 | double diff2=(xy2-points[m]->xy).Mod2(); | |||
156 | if (diff1>diff2){ | |||
157 | XYZ[m].xy=xy2; | |||
158 | } | |||
159 | else{ | |||
160 | XYZ[m].xy=xy1; | |||
161 | } | |||
162 | } | |||
163 | // Fake target point | |||
164 | XYZ[n-1].xy.Set(0.,0.); | |||
165 | ||||
166 | // Linear regression to find z0, tanl | |||
167 | double sumv=0.,sumx=0.; | |||
168 | double sumy=0.,sumxx=0.,sumxy=0.; | |||
169 | double sperp=0.,sperp_old=0.,ratio,Delta; | |||
170 | double z=0,zlast=0; | |||
171 | double two_rc=2.*rc; | |||
172 | DVector2 oldxy=XYZ[0].xy; | |||
173 | unsigned int num_z=0; | |||
174 | for (unsigned int k=0;k<n;k++){ | |||
175 | zlast=z; | |||
176 | z=XYZ[k].z; | |||
177 | if (fabs(z-zlast)<0.01) continue; | |||
178 | num_z++; | |||
179 | ||||
180 | DVector2 diffxy=XYZ[k].xy-oldxy; | |||
181 | double var=CR(k,k); | |||
182 | if (bad[k]) var=XYZ[k].covr; | |||
183 | ||||
184 | sperp_old=sperp; | |||
185 | ratio=diffxy.Mod()/(two_rc); | |||
186 | // Make sure the argument for the arcsin does not go out of range... | |||
187 | sperp=sperp_old+(ratio>1?two_rc*(M_PI_21.57079632679489661923):two_rc*asin(ratio)); | |||
188 | //z=XYZ(k,2); | |||
189 | ||||
190 | // Assume errors in s dominated by errors in R | |||
191 | double inv_var=1./var; | |||
192 | sumv+=inv_var; | |||
193 | sumy+=sperp*inv_var; | |||
194 | sumx+=z*inv_var; | |||
195 | sumxx+=z*z*inv_var; | |||
196 | sumxy+=sperp*z*inv_var; | |||
197 | ||||
198 | // Save the current x and y coordinates | |||
199 | //oldx=XYZ(k,0); | |||
200 | //oldy=XYZ(k,1); | |||
201 | oldxy=XYZ[k].xy; | |||
202 | } | |||
203 | ||||
204 | Delta=sumv*sumxx-sumx*sumx; | |||
205 | double denom=sumv*sumxy-sumy*sumx; | |||
206 | if (fabs(Delta)>EPS1e-8 && fabs(denom)>EPS1e-8){ | |||
207 | // Track parameters z0 and tan(lambda) | |||
208 | tanl=-Delta/denom; | |||
209 | //z0=(sumxx*sumy-sumx*sumxy)/Delta*tanl; | |||
210 | // Error in tanl | |||
211 | var_tanl=sumv/Delta*(tanl*tanl*tanl*tanl); | |||
212 | ||||
213 | // Vertex position | |||
214 | sperp-=sperp_old; | |||
215 | zvertex=zlast-tanl*sperp; | |||
216 | } | |||
217 | else{ | |||
218 | // assume that the particle came from the target | |||
219 | zvertex=TARGET_Z; | |||
220 | if (sperp<EPS1e-8){ | |||
221 | // This is a rare failure mode where it seems that the arc length data | |||
222 | // cannot be reliably used. Provide some default value of tanl to | |||
223 | // avoid division by zero errors | |||
224 | tanl=57.3; // theta=1 degree | |||
225 | } | |||
226 | else tanl=(zlast-zvertex)/sperp; | |||
227 | var_tanl=100.; // guess for now | |||
228 | } | |||
229 | if (num_z<3){ | |||
230 | //_DBG_ << "Too few z points..." << endl; | |||
231 | return VALUE_OUT_OF_RANGE; | |||
232 | } | |||
233 | if (got_bad_intersection) return VALUE_OUT_OF_RANGE; | |||
234 | return NOERROR; | |||
235 | } | |||
236 | ||||
237 | // Use predicted positions (propagating from plane 1 using a helical model) to | |||
238 | // update the R and RPhi covariance matrices. | |||
239 | // | |||
240 | jerror_t DFDCSegment_factory::UpdatePositionsAndCovariance(unsigned int n, | |||
241 | double r1sq,vector<xyz_t>&XYZ,DMatrix &CRPhi,DMatrix &CR){ | |||
242 | double delta_x=XYZ[ref_plane].xy.X()-xc; | |||
243 | double delta_y=XYZ[ref_plane].xy.Y()-yc; | |||
244 | double r1=sqrt(r1sq); | |||
245 | double denom=delta_x*delta_x+delta_y*delta_y; | |||
246 | ||||
247 | // Auxiliary matrices for correcting for non-normal track incidence to FDC | |||
248 | // The correction is | |||
249 | // CRPhi'= C*CRPhi*C+S*CR*S, where S(i,i)=R_i*kappa/2 | |||
250 | // and C(i,i)=sqrt(1-S(i,i)^2) | |||
251 | DMatrix C(n,n); | |||
252 | DMatrix S(n,n); | |||
253 | ||||
254 | // Predicted positions | |||
255 | Phi1=atan2(delta_y,delta_x); | |||
256 | double z1=XYZ[ref_plane].z; | |||
257 | double y1=XYZ[ref_plane].xy.X(); | |||
258 | double x1=XYZ[ref_plane].xy.Y(); | |||
259 | double var_R1=CR(ref_plane,ref_plane); | |||
260 | for (unsigned int k=0;k<n;k++){ | |||
261 | double sperp=rotation_sense*(XYZ[k].z-z1)/tanl; | |||
262 | double phi_s=Phi1+sperp/rc; | |||
263 | double sinp=sin(phi_s); | |||
264 | double cosp=cos(phi_s); | |||
265 | XYZ[k].xy.Set(xc+rc*cosp,yc+rc*sinp); | |||
266 | ||||
267 | // Error analysis. We ignore errors in N because there doesn't seem to | |||
268 | // be any obvious established way to estimate errors in eigenvalues for | |||
269 | // small eigenvectors. We assume that most of the error comes from | |||
270 | // the measurement for the reference plane radius and the dip angle anyway. | |||
271 | double Phi=XYZ[k].xy.Phi(); | |||
272 | double sinPhi=sin(Phi); | |||
273 | double cosPhi=cos(Phi); | |||
274 | double dRPhi_dx=Phi*cosPhi-sinPhi; | |||
275 | double dRPhi_dy=Phi*sinPhi+cosPhi; | |||
276 | ||||
277 | double rc_sinphi_over_denom=rc*sinp/denom; | |||
278 | //double dx_dx1=rc*sinp*delta_y/denom; | |||
279 | //double dx_dy1=-rc*sinp*delta_x/denom; | |||
280 | double dx_dx1=rc_sinphi_over_denom*delta_y; | |||
281 | double dx_dy1=-rc_sinphi_over_denom*delta_x; | |||
282 | double dx_dtanl=sinp*sperp/tanl; | |||
283 | ||||
284 | double rc_cosphi_over_denom=rc*cosp/denom; | |||
285 | //double dy_dx1=-rc*cosp*delta_y/denom; | |||
286 | //double dy_dy1=rc*cosp*delta_x/denom; | |||
287 | double dy_dx1=-rc_cosphi_over_denom*delta_y; | |||
288 | double dy_dy1=rc_cosphi_over_denom*delta_x; | |||
289 | double dy_dtanl=-cosp*sperp/tanl; | |||
290 | ||||
291 | double dRPhi_dx1=dRPhi_dx*dx_dx1+dRPhi_dy*dy_dx1; | |||
292 | double dRPhi_dy1=dRPhi_dx*dx_dy1+dRPhi_dy*dy_dy1; | |||
293 | double dRPhi_dtanl=dRPhi_dx*dx_dtanl+dRPhi_dy*dy_dtanl; | |||
294 | ||||
295 | double dR_dx1=cosPhi*dx_dx1+sinPhi*dy_dx1; | |||
296 | double dR_dy1=cosPhi*dx_dy1+sinPhi*dy_dy1; | |||
297 | double dR_dtanl=cosPhi*dx_dtanl+sinPhi*dy_dtanl; | |||
298 | ||||
299 | double cdist=dist_to_origin+r1sq*N[2]; | |||
300 | double n2=N[0]*N[0]+N[1]*N[1]; | |||
301 | ||||
302 | double ydenom=y1*n2+N[1]*cdist; | |||
303 | double dy1_dr1=-r1*(2.*N[1]*N[2]*y1+2.*N[2]*cdist-N[0]*N[0])/ydenom; | |||
304 | double var_y1=dy1_dr1*dy1_dr1*var_R1; | |||
305 | ||||
306 | double xdenom=x1*n2+N[0]*cdist; | |||
307 | double dx1_dr1=-r1*(2.*N[0]*N[2]*x1+2.*N[2]*cdist-N[1]*N[1])/xdenom; | |||
308 | double var_x1=dx1_dr1*dx1_dr1*var_R1; | |||
309 | ||||
310 | CRPhi(k,k)=dRPhi_dx1*dRPhi_dx1*var_x1+dRPhi_dy1*dRPhi_dy1*var_y1 | |||
311 | +dRPhi_dtanl*dRPhi_dtanl*var_tanl; | |||
312 | CR(k,k)=dR_dx1*dR_dx1*var_x1+dR_dy1*dR_dy1*var_y1 | |||
313 | +dR_dtanl*dR_dtanl*var_tanl; | |||
314 | ||||
315 | // double stemp=sqrt(XYZ(k,0)*XYZ(k,0)+XYZ(k,1)*XYZ(k,1))/(4.*rc); | |||
316 | double stemp=XYZ[k].xy.Mod()/(4.*rc); | |||
317 | double ctemp=1.-stemp*stemp; | |||
318 | if (ctemp>0){ | |||
319 | S(k,k)=stemp; | |||
320 | C(k,k)=sqrt(ctemp); | |||
321 | } | |||
322 | else{ | |||
323 | S(k,k)=0.; | |||
324 | C(k,k)=1.; | |||
325 | } | |||
326 | } | |||
327 | ||||
328 | // Correction for non-normal incidence of track on FDC | |||
329 | CRPhi=C*CRPhi*C+S*CR*S; | |||
330 | ||||
331 | return NOERROR; | |||
332 | } | |||
333 | ||||
334 | // Riemann Circle fit: points on a circle in x,y project onto a plane cutting | |||
335 | // the circular paraboloid surface described by (x,y,x^2+y^2). Therefore the | |||
336 | // task of fitting points in (x,y) to a circle is transormed to the taks of | |||
337 | // fitting planes in (x,y, w=x^2+y^2) space | |||
338 | // | |||
339 | jerror_t DFDCSegment_factory::RiemannCircleFit(vector<const DFDCPseudo *>&points, | |||
340 | DMatrix &CRPhi){ | |||
341 | unsigned int n=points.size()+1; | |||
342 | DMatrix X(n,3); | |||
343 | DMatrix Xavg(1,3); | |||
344 | DMatrix A(3,3); | |||
345 | // vector of ones | |||
346 | DMatrix OnesT(1,n); | |||
347 | double W_sum=0.; | |||
348 | DMatrix W(n,n); | |||
349 | ||||
350 | // The goal is to find the eigenvector corresponding to the smallest | |||
351 | // eigenvalue of the equation | |||
352 | // lambda=n^T (X^T W X - W_sum Xavg^T Xavg)n | |||
353 | // where n is the normal vector to the plane slicing the cylindrical | |||
354 | // paraboloid described by the parameterization (x,y,w=x^2+y^2), | |||
355 | // and W is the weight matrix, assumed for now to be diagonal. | |||
356 | // In the absence of multiple scattering, W_sum is the sum of all the | |||
357 | // diagonal elements in W. | |||
358 | // At this stage we ignore the multiple scattering. | |||
359 | unsigned int last_index=n-1; | |||
360 | for (unsigned int i=0;i<last_index;i++){ | |||
361 | X(i,0)=points[i]->xy.X(); | |||
362 | X(i,1)=points[i]->xy.Y(); | |||
363 | X(i,2)=points[i]->xy.Mod2(); | |||
364 | OnesT(0,i)=1.; | |||
365 | W(i,i)=1./CRPhi(i,i); | |||
366 | W_sum+=W(i,i); | |||
367 | } | |||
368 | OnesT(0,last_index)=1.; | |||
369 | W(last_index,last_index)=1./CRPhi(last_index,last_index); | |||
370 | W_sum+=W(last_index,last_index); | |||
371 | var_avg=1./W_sum; | |||
372 | Xavg=var_avg*(OnesT*(W*X)); | |||
373 | // Store in private array for use in other routines | |||
374 | xavg[0]=Xavg(0,0); | |||
375 | xavg[1]=Xavg(0,1); | |||
376 | xavg[2]=Xavg(0,2); | |||
377 | ||||
378 | A=DMatrix(DMatrix::kTransposed,X)*(W*X) | |||
379 | -W_sum*(DMatrix(DMatrix::kTransposed,Xavg)*Xavg); | |||
380 | if(!A.IsValid())return UNRECOVERABLE_ERROR; | |||
381 | ||||
382 | // The characteristic equation is | |||
383 | // lambda^3+B2*lambda^2+lambda*B1+B0=0 | |||
384 | // | |||
385 | double B2=-(A(0,0)+A(1,1)+A(2,2)); | |||
386 | 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) | |||
387 | +A(1,1)*A(2,2)-A(2,1)*A(1,2); | |||
388 | double B0=-A.Determinant(); | |||
389 | if(B0==0 || !isfinite(B0))return UNRECOVERABLE_ERROR; | |||
390 | ||||
391 | // The roots of the cubic equation are given by | |||
392 | // lambda1= -B2/3 + S+T | |||
393 | // lambda2= -B2/3 - (S+T)/2 + i sqrt(3)/2. (S-T) | |||
394 | // lambda3= -B2/3 - (S+T)/2 - i sqrt(3)/2. (S-T) | |||
395 | // where we define some temporary variables: | |||
396 | // S= (R+sqrt(Q^3+R^2))^(1/3) | |||
397 | // T= (R-sqrt(Q^3+R^2))^(1/3) | |||
398 | // Q=(3*B1-B2^2)/9 | |||
399 | // R=(9*B2*B1-27*B0-2*B2^3)/54 | |||
400 | // sum=S+T; | |||
401 | // diff=i*(S-T) | |||
402 | // We divide Q and R by a safety factor to prevent multiplying together | |||
403 | // enormous numbers that cause unreliable results. | |||
404 | ||||
405 | double Q=(3.*B1-B2*B2)/9.e4; | |||
406 | double R=(9.*B2*B1-27.*B0-2.*B2*B2*B2)/54.e6; | |||
407 | double Q1=Q*Q*Q+R*R; | |||
408 | if (Q1<0) Q1=sqrt(-Q1); | |||
409 | else{ | |||
410 | return VALUE_OUT_OF_RANGE; | |||
411 | } | |||
412 | ||||
413 | // DeMoivre's theorem for fractional powers of complex numbers: | |||
414 | // (r*(cos(theta)+i sin(theta)))^(p/q) | |||
415 | // = r^(p/q)*(cos(p*theta/q)+i sin(p*theta/q)) | |||
416 | // | |||
417 | //double temp=100.*pow(R*R+Q1*Q1,0.16666666666666666667); | |||
418 | double temp=100.*sqrt(cbrt(R*R+Q1*Q1)); | |||
419 | double theta1=ONE_THIRD0.33333333333333333*atan2(Q1,R); | |||
420 | double sum_over_2=temp*cos(theta1); | |||
421 | double diff_over_2=-temp*sin(theta1); | |||
422 | // Third root | |||
423 | double lambda_min=-ONE_THIRD0.33333333333333333*B2-sum_over_2+SQRT31.73205080756887719*diff_over_2; | |||
424 | ||||
425 | // Normal vector to plane | |||
426 | N[0]=1.; | |||
427 | double A11_minus_lambda_min=A(1,1)-lambda_min; | |||
428 | N[1]=(A(1,0)*A(0,2)-(A(0,0)-lambda_min)*A(1,2)) | |||
429 | /(A(0,1)*A(2,1)-(A11_minus_lambda_min)*A(0,2)); | |||
430 | N[2]=(A(2,0)*A11_minus_lambda_min-A(1,0)*A(2,1)) | |||
431 | /(A(1,2)*A(2,1)-(A(2,2)-lambda_min)*A11_minus_lambda_min); | |||
432 | ||||
433 | // Normalize: n1^2+n2^2+n3^2=1 | |||
434 | double denom=sqrt(N[0]*N[0]+N[1]*N[1]+N[2]*N[2]); | |||
435 | for (int i=0;i<3;i++){ | |||
436 | N[i]/=denom; | |||
437 | } | |||
438 | ||||
439 | // Distance to origin | |||
440 | dist_to_origin=-(N[0]*Xavg(0,0)+N[1]*Xavg(0,1)+N[2]*Xavg(0,2)); | |||
441 | ||||
442 | // Center and radius of the circle | |||
443 | double two_N2=2.*N[2]; | |||
444 | xc=-N[0]/two_N2; | |||
445 | yc=-N[1]/two_N2; | |||
446 | rc=sqrt(1.-N[2]*N[2]-4.*dist_to_origin*N[2])/fabs(two_N2); | |||
447 | ||||
448 | return NOERROR; | |||
449 | } | |||
450 | ||||
451 | // Riemann Helical Fit based on transforming points on projection to x-y plane | |||
452 | // to a circular paraboloid surface combined with a linear fit of the arc | |||
453 | // length versus z. Uses RiemannCircleFit and RiemannLineFit. | |||
454 | // | |||
455 | jerror_t | |||
456 | DFDCSegment_factory::RiemannHelicalFit(vector<const DFDCPseudo*>&points){ | |||
457 | double Phi; | |||
458 | unsigned int num_measured=points.size(); | |||
459 | unsigned int last_index=num_measured; | |||
460 | unsigned int num_points=num_measured+1; | |||
461 | Ndof=num_points-3; | |||
462 | // list of points on track and corresponding covariance matrices | |||
463 | vector<xyz_t>XYZ(num_points); | |||
464 | DMatrix CR(num_points,num_points); | |||
465 | DMatrix CRPhi(num_points,num_points); | |||
466 | ||||
467 | ||||
468 | // Fill initial matrices for R and RPhi measurements | |||
469 | for (unsigned int m=0;m<num_measured;m++){ | |||
470 | XYZ[m].z=points[m]->wire->origin.z(); | |||
471 | ||||
472 | //Phi=atan2(points[m]->y,points[m]->x); | |||
473 | Phi=points[m]->xy.Phi(); | |||
474 | ||||
475 | double u=points[m]->w; | |||
476 | double v=points[m]->s; | |||
477 | double temp1=u*Phi-v; | |||
478 | double temp2=v*Phi+u; | |||
479 | double var_u=0.08333; | |||
480 | double var_v=0.0075; | |||
481 | double one_over_R2=1./points[m]->xy.Mod2(); | |||
482 | CRPhi(m,m)=one_over_R2*(var_v*temp1*temp1+var_u*temp2*temp2); | |||
483 | CR(m,m)=one_over_R2*(var_u*u*u+var_v*v*v); | |||
484 | ||||
485 | XYZ[m].covr=CR(m,m); | |||
486 | XYZ[m].covrphi=CRPhi(m,m); | |||
487 | } | |||
488 | XYZ[last_index].z=TARGET_Z; | |||
489 | CR(last_index,last_index)=BEAM_VARIANCE; | |||
490 | CRPhi(last_index,last_index)=BEAM_VARIANCE; | |||
491 | ||||
492 | // Reference track: | |||
493 | jerror_t error=NOERROR; | |||
494 | // First find the center and radius of the projected circle | |||
495 | error=RiemannCircleFit(points,CRPhi); | |||
496 | if (error!=NOERROR){ | |||
497 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/FDC/DFDCSegment_factory.cc"<< ":"<<497<<" " << "Circle fit failed..." << endl; | |||
498 | return error; | |||
499 | } | |||
500 | ||||
501 | // Get reference track estimates for z0 and tanl and intersection points | |||
502 | // (stored in XYZ) | |||
503 | error=RiemannLineFit(points,CR,XYZ); | |||
504 | if (error!=NOERROR){ | |||
505 | // The circle fit is inconsistent with at least one of the measured points | |||
506 | // (i.e., the calcuation of the intersection point failed). Relax the | |||
507 | // emphasis on the "target" point and refit. | |||
508 | for (unsigned int i=0;i<last_index;i++){ | |||
509 | CR(i,i)=XYZ[i].covr; | |||
510 | CRPhi(i,i)=XYZ[i].covrphi; | |||
511 | } | |||
512 | CRPhi(last_index,last_index)=1e6; | |||
513 | CR(last_index,last_index)=1e6; | |||
514 | ||||
515 | // First find the center and radius of the projected circle | |||
516 | error=RiemannCircleFit(points,CRPhi); | |||
517 | if (error!=NOERROR){ | |||
518 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/FDC/DFDCSegment_factory.cc"<< ":"<<518<<" " << "Circle fit failed..." << endl; | |||
519 | return error; | |||
520 | } | |||
521 | ||||
522 | // Get reference track estimates for z0 and tanl and intersection points | |||
523 | // (stored in XYZ) | |||
524 | error=RiemannLineFit(points,CR,XYZ); | |||
525 | if (error!=NOERROR){ | |||
526 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/FDC/DFDCSegment_factory.cc"<< ":"<<526<<" " << "Line fit failed..." << endl; | |||
527 | return error; | |||
528 | } | |||
529 | } | |||
530 | ||||
531 | // Guess particle sense of rotation (+/-1); | |||
532 | rotation_sense=GetRotationSense(points.size(),XYZ,CR,CRPhi,points); | |||
533 | ||||
534 | double r1sq=XYZ[ref_plane].xy.Mod2(); | |||
535 | UpdatePositionsAndCovariance(num_points,r1sq,XYZ,CRPhi,CR); | |||
536 | ||||
537 | // Compute the chi-square value for this iteration | |||
538 | double chisq0=0.; | |||
539 | double rc0=rc,xc0=xc,yc0=yc,tanl0=tanl,zvertex0=zvertex,Phi1_0=Phi1; | |||
540 | double rotation_sense0=rotation_sense; | |||
541 | for (unsigned int m=0;m<points.size();m++){ | |||
542 | double sperp=rotation_sense*(XYZ[m].z-XYZ[ref_plane].z)/tanl; | |||
543 | double phi_s=Phi1+sperp/rc; | |||
544 | DVector2 XY(xc+rc*cos(phi_s),yc+rc*sin(phi_s)); | |||
545 | chisq0+=(XY-points[m]->xy).Mod2()/CR(m,m); | |||
546 | } | |||
547 | ||||
548 | // Preliminary circle fit | |||
549 | error=RiemannCircleFit(points,CRPhi); | |||
550 | if (error!=NOERROR){ | |||
551 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/FDC/DFDCSegment_factory.cc"<< ":"<<551<<" " << "Circle fit failed..." << endl; | |||
552 | return error; | |||
553 | } | |||
554 | ||||
555 | // Preliminary line fit | |||
556 | error=RiemannLineFit(points,CR,XYZ); | |||
557 | if (error!=NOERROR){ | |||
558 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/FDC/DFDCSegment_factory.cc"<< ":"<<558<<" " << "Line fit failed..." << endl; | |||
559 | return error; | |||
560 | } | |||
561 | ||||
562 | // Guess particle sense of rotation (+/-1); | |||
563 | rotation_sense=GetRotationSense(points.size(),XYZ,CR,CRPhi,points); | |||
564 | ||||
565 | r1sq=XYZ[ref_plane].xy.Mod2(); | |||
566 | UpdatePositionsAndCovariance(num_points,r1sq,XYZ,CRPhi,CR); | |||
567 | ||||
568 | // Compute the chi-square value for this iteration | |||
569 | double chisq_=0.; | |||
570 | double rotation_sense_=rotation_sense; | |||
571 | double rc_=rc,xc_=xc,yc_=yc,tanl_=tanl,zvertex_=zvertex,Phi1_=Phi1; | |||
572 | for (unsigned int m=0;m<points.size();m++){ | |||
573 | double sperp=rotation_sense*(XYZ[m].z-XYZ[ref_plane].z)/tanl; | |||
574 | double phi_s=Phi1+sperp/rc; | |||
575 | DVector2 XY(xc+rc*cos(phi_s),yc+rc*sin(phi_s)); | |||
576 | chisq_+=(XY-points[m]->xy).Mod2()/CR(m,m); | |||
577 | } | |||
578 | // If we did not improve the fit, bail from this routine... | |||
579 | if (chisq_>chisq0){ | |||
580 | chisq=chisq0; | |||
581 | rotation_sense=rotation_sense0; | |||
582 | rc=rc0,xc=xc0,yc=yc0,tanl=tanl0,zvertex=zvertex0,Phi1=Phi1_0; | |||
583 | ||||
584 | return NOERROR; | |||
585 | } | |||
586 | ||||
587 | // Final circle fit | |||
588 | error=RiemannCircleFit(points,CRPhi); | |||
589 | if (error!=NOERROR){ | |||
590 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/FDC/DFDCSegment_factory.cc"<< ":"<<590<<" " << "Circle fit failed..." << endl; | |||
591 | return error; | |||
592 | } | |||
593 | ||||
594 | // Final line fit | |||
595 | error=RiemannLineFit(points,CR,XYZ); | |||
596 | if (error!=NOERROR){ | |||
597 | if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/FDC/DFDCSegment_factory.cc"<< ":"<<597<<" " << "Line fit failed..." << endl; | |||
598 | return error; | |||
599 | } | |||
600 | ||||
601 | // Guess particle sense of rotation (+/-1) | |||
602 | rotation_sense=GetRotationSense(num_measured,XYZ,CR,CRPhi,points); | |||
603 | ||||
604 | // Final update to covariance matrices | |||
605 | r1sq=XYZ[ref_plane].xy.Mod2(); | |||
606 | UpdatePositionsAndCovariance(num_points,r1sq,XYZ,CRPhi,CR); | |||
607 | ||||
608 | // Store residuals and path length for each measurement | |||
609 | chisq=0.; | |||
610 | for (unsigned int m=0;m<num_points;m++){ | |||
611 | double sperp=rotation_sense*(XYZ[m].z-XYZ[ref_plane].z)/tanl; | |||
612 | double phi_s=Phi1+sperp/rc; | |||
613 | DVector2 XY(xc+rc*cos(phi_s),yc+rc*sin(phi_s)); | |||
614 | ||||
615 | if (m<num_measured){ | |||
616 | chisq+=(XY-points[m]->xy).Mod2()/CR(m,m); | |||
617 | } | |||
618 | else{ | |||
619 | chisq+=XY.Mod2()/CR(m,m); | |||
620 | } | |||
621 | } | |||
622 | ||||
623 | // If the last iteration did not improve the results, restore the previously | |||
624 | // saved values for the parameters and chi-square. | |||
625 | if (chisq>chisq_){ | |||
626 | chisq=chisq_; | |||
627 | rotation_sense=rotation_sense_; | |||
628 | rc=rc_,xc=xc_,yc=yc_,tanl=tanl_,zvertex=zvertex_,Phi1=Phi1_; | |||
629 | } | |||
630 | ||||
631 | return NOERROR; | |||
632 | } | |||
633 | ||||
634 | ||||
635 | // DFDCSegment_factory::FindSegments | |||
636 | // Associate nearest neighbors within a package with track segment candidates. | |||
637 | // Provide guess for (seed) track parameters | |||
638 | // | |||
639 | jerror_t DFDCSegment_factory::FindSegments(vector<const DFDCPseudo*>&points){ | |||
640 | // Create a vector to store whether or not a hit has been used | |||
641 | vector<bool>used(points.size()); | |||
642 | unsigned int total_num_used=0; | |||
643 | ||||
644 | // Put indices for the first point in each plane before the most downstream | |||
645 | // plane in the vector x_list. | |||
646 | double old_z=points[0]->wire->origin.z(); | |||
647 | vector<unsigned int>x_list; | |||
648 | x_list.push_back(0); | |||
649 | for (unsigned int i=0;i<points.size();i++){ | |||
650 | if (points[i]->wire->origin.z()!=old_z){ | |||
651 | x_list.push_back(i); | |||
652 | } | |||
653 | old_z=points[i]->wire->origin.z(); | |||
654 | } | |||
655 | x_list.push_back(points.size()); | |||
656 | ||||
657 | unsigned int start=0; | |||
658 | // loop over the start indices, starting with the first plane | |||
659 | while (start<x_list.size()-1){ | |||
660 | int num_used=0; | |||
661 | // For each iteration, count how many hits we have used already in segments | |||
662 | for (unsigned int i=0;i<points.size();i++){ | |||
663 | if(used[i]==true) num_used++; | |||
664 | } | |||
665 | // Break out of loop if we don't have enough hits left to fit a circle | |||
666 | if (points.size()-num_used<3) break; | |||
667 | ||||
668 | // Now loop over the list of track segment start points | |||
669 | for (unsigned int i=x_list[start];i<x_list[start+1];i++){ | |||
670 | if (used[i]==false){ | |||
671 | used[i]=true; | |||
672 | total_num_used++; | |||
673 | chisq=1.e8; | |||
674 | ||||
675 | // Clear track parameters | |||
676 | tanl=D=z0=phi0=Phi1=xc=yc=rc=0.; | |||
677 | rotation_sense=1.; | |||
678 | ||||
679 | // Point in the current plane in the package | |||
680 | DVector2 XY=points[i]->xy; | |||
681 | ||||
682 | // Create list of nearest neighbors | |||
683 | vector<const DFDCPseudo*>neighbors; | |||
684 | neighbors.push_back(points[i]); | |||
685 | unsigned int match=0; | |||
686 | double delta,delta_min=1000.; | |||
687 | for (unsigned int k=0;k<x_list.size()-1;k++){ | |||
688 | delta_min=1000.; | |||
689 | match=0; | |||
690 | if (x_list[k]>0){ | |||
691 | for (unsigned int m=x_list[k];m<x_list[k+1];m++){ | |||
692 | delta=(XY-points[m]->xy).Mod(); | |||
693 | if (delta<delta_min && delta<MATCH_RADIUS2.0){ | |||
694 | delta_min=delta; | |||
695 | match=m; | |||
696 | } | |||
697 | } | |||
698 | } | |||
699 | if (match!=0 | |||
700 | && used[match]==false | |||
701 | ){ | |||
702 | XY=points[match]->xy; | |||
703 | used[match]=true; | |||
704 | total_num_used++; | |||
705 | neighbors.push_back(points[match]); | |||
706 | } | |||
707 | } | |||
708 | unsigned int num_neighbors=neighbors.size(); | |||
709 | ||||
710 | // Skip to next segment seed if we don't have enough points to fit a | |||
711 | // circle | |||
712 | if (num_neighbors<3) continue; | |||
713 | ||||
714 | bool do_sort=false; | |||
715 | // Look for hits adjacent to the ones we have in our segment candidate | |||
716 | for (unsigned int k=0;k<points.size();k++){ | |||
717 | if (!used[k]){ | |||
718 | for (unsigned int j=0;j<num_neighbors;j++){ | |||
719 | delta=fabs(points[k]->xy.Y()-neighbors[j]->xy.Y()); | |||
720 | ||||
721 | if (delta<ADJACENT_MATCH_DISTANCE0.3 && | |||
722 | abs(neighbors[j]->wire->wire-points[k]->wire->wire)<=1 | |||
723 | && neighbors[j]->wire->origin.z()==points[k]->wire->origin.z()){ | |||
724 | used[k]=true; | |||
725 | total_num_used++; | |||
726 | neighbors.push_back(points[k]); | |||
727 | do_sort=true; | |||
728 | } | |||
729 | } | |||
730 | } | |||
731 | } | |||
732 | // Sort if we added another point | |||
733 | if (do_sort) | |||
734 | std::stable_sort(neighbors.begin(),neighbors.end(),DFDCSegment_package_cmp); | |||
735 | ||||
736 | // Arc lengths in helical model are referenced relative to the plane | |||
737 | // ref_plane within a segment. For a 6 hit segment, ref_plane=2 is | |||
738 | // roughly in the center of the segment. | |||
739 | ref_plane=0; | |||
740 | ||||
741 | // Perform the Riemann Helical Fit on the track segment | |||
742 | jerror_t error=RiemannHelicalFit(neighbors); | |||
743 | ||||
744 | if (error==NOERROR){ | |||
745 | // Since the cell size is 0.5 cm and the Lorentz deflection can be | |||
746 | // mm scale, a circle radius on the order of 1 cm is at the level of | |||
747 | // how well the points are defined at this stage. Use a simple circle | |||
748 | // fit assuming the circle goes through the origin. | |||
749 | if (rc<1.0) { | |||
750 | if (CircleFit(neighbors)==NOERROR){ | |||
751 | if (LineFit(neighbors)==NOERROR){ | |||
752 | chisq=ComputeCircleChiSq(neighbors); | |||
753 | } | |||
754 | } | |||
755 | } | |||
756 | ||||
757 | // Create a new segment | |||
758 | DFDCSegment *segment = new DFDCSegment; | |||
759 | segment->hits=neighbors; | |||
760 | segment->package=(neighbors[0]->wire->layer-1)/6; | |||
761 | FillSegmentData(segment); | |||
762 | ||||
763 | _data.push_back(segment); | |||
764 | } | |||
765 | else { | |||
766 | // Fit assuming particle came from (x,y)=(0,0) | |||
767 | if (CircleFit(neighbors)==NOERROR){ | |||
768 | if (LineFit(neighbors)==NOERROR){ | |||
769 | chisq=ComputeCircleChiSq(neighbors); | |||
770 | } | |||
771 | } | |||
772 | ||||
773 | // Create a new segment | |||
774 | DFDCSegment *segment = new DFDCSegment; | |||
775 | segment->hits=neighbors; | |||
776 | segment->package=(neighbors[0]->wire->layer-1)/6; | |||
777 | FillSegmentData(segment); | |||
778 | ||||
779 | _data.push_back(segment); | |||
780 | } | |||
781 | ||||
782 | } | |||
783 | } | |||
784 | ||||
785 | // Move on to the next plane to start looking for segments | |||
786 | start++; | |||
787 | } //while loop over x_list planes | |||
788 | ||||
789 | // Use fitted segment results to look for additional stray hits to add to | |||
790 | // segments. | |||
791 | if (total_num_used<used.size()){ | |||
792 | for (unsigned int k=0;k<_data.size();k++){ | |||
793 | if (total_num_used==used.size()) break; | |||
794 | DFDCSegment *segment=_data[k]; | |||
795 | bool added_hits=false; | |||
796 | for (unsigned int i=0;i<used.size();i++){ | |||
797 | if (total_num_used==used.size()) break; | |||
798 | if (used[i]==0){ | |||
799 | unsigned int packNo=(points[i]->wire->layer-1)/6; | |||
800 | if (packNo==segment->package){ | |||
801 | double z=points[i]->wire->origin.z(); | |||
802 | double z0=segment->hits[0]->wire->origin.z(); | |||
803 | double phi_s=segment->Phi1 | |||
804 | +rotation_sense*(z-z0)/(segment->rc*segment->tanl); | |||
805 | ||||
806 | double dx=segment->xc+segment->rc*cos(phi_s)-points[i]->xy.X(); | |||
807 | double dy=segment->yc+segment->rc*sin(phi_s)-points[i]->xy.Y(); | |||
808 | double dr=sqrt(dx*dx+dy*dy); | |||
809 | if (dr<MATCH_RADIUS2.0){ | |||
810 | used[i]=1; | |||
811 | added_hits=true; | |||
812 | total_num_used++; | |||
813 | segment->hits.push_back(points[i]); | |||
814 | } | |||
815 | } // check z position of hit | |||
816 | ||||
817 | } // check if hit used already | |||
818 | }// loop over hits | |||
819 | if (added_hits){ | |||
820 | stable_sort(segment->hits.begin(),segment->hits.end(),DFDCSegment_package_cmp); | |||
821 | if (RiemannHelicalFit(segment->hits)==NOERROR){ | |||
822 | // Since the cell size is 0.5 cm and the Lorentz deflection can be | |||
823 | // mm scale, a circle radius on the order of 1 cm is at the level of | |||
824 | // how well the points are defined at this stage. Use a simple circle | |||
825 | // fit assuming the circle goes through the origin. | |||
826 | if (rc<1.0) { | |||
827 | if (CircleFit(segment->hits)==NOERROR){ | |||
828 | if (LineFit(segment->hits)==NOERROR){ | |||
829 | chisq=ComputeCircleChiSq(segment->hits); | |||
830 | } | |||
831 | } | |||
832 | } | |||
833 | ||||
834 | FillSegmentData(segment); | |||
835 | } | |||
836 | } | |||
837 | } // loop over segments | |||
838 | } | |||
839 | ||||
840 | return NOERROR; | |||
841 | } | |||
842 | ||||
843 | // Linear regression to find charge | |||
844 | double DFDCSegment_factory::GetRotationSense(unsigned int n,vector<xyz_t>&XYZ, | |||
845 | DMatrix &CR, | |||
846 | DMatrix &CRPhi, | |||
847 | vector<const DFDCPseudo *>&points){ | |||
848 | double Phi1=atan2(points[0]->xy.Y()-yc,points[0]->xy.X()-xc); | |||
849 | double z0=points[0]->wire->origin.z(); | |||
850 | double plus_sum=0.,minus_sum=0.; | |||
851 | for (unsigned int j=1;j<points.size();j++){ | |||
852 | double dphi=(points[j]->wire->origin.z()-z0)/(rc*tanl); | |||
853 | double my_x=points[j]->xy.X(); | |||
854 | double my_y=points[j]->xy.Y(); | |||
855 | ||||
856 | double phiplus=Phi1+dphi; | |||
857 | double dxplus=xc+rc*cos(phiplus)-my_x; | |||
858 | double dyplus=yc+rc*sin(phiplus)-my_y; | |||
859 | double dxplus2=dxplus*dxplus; | |||
860 | double dyplus2=dyplus*dyplus; | |||
861 | double d2plus=dxplus2+dyplus2; | |||
862 | double varplus=(dxplus2*points[j]->covxx+dyplus2*points[j]->covyy | |||
863 | +2.*dxplus*dyplus*points[j]->covxy)/d2plus; | |||
864 | ||||
865 | plus_sum+=d2plus/varplus; | |||
866 | ||||
867 | double phiminus=Phi1-dphi; | |||
868 | double dxminus=xc+rc*cos(phiminus)-my_x; | |||
869 | double dyminus=yc+rc*sin(phiminus)-my_y; | |||
870 | double dxminus2=dxminus*dxminus; | |||
871 | double dyminus2=dyminus*dyminus; | |||
872 | double d2minus=dxminus2+dyminus2; | |||
873 | double varminus=(dxminus2*points[j]->covxx+dyminus2*points[j]->covyy | |||
874 | +2.*dxminus*dyminus*points[j]->covxy)/d2minus; | |||
875 | ||||
876 | minus_sum+=d2minus/varminus; | |||
877 | } | |||
878 | ||||
879 | // Look for smallest sum to determine q | |||
880 | if (minus_sum<plus_sum) return -1.; | |||
881 | return 1.; | |||
882 | } | |||
883 | ||||
884 | // Linear regression to find z0, tanl | |||
885 | jerror_t DFDCSegment_factory::LineFit(vector<const DFDCPseudo *>&points){ | |||
886 | double sumv=0.,sumx=0.; | |||
887 | double sumy=0.,sumxx=0.,sumxy=0.; | |||
888 | double sperp=0.,sperp_old=0.,ratio,Delta; | |||
889 | double z=0,zlast=0; | |||
890 | double two_rc=2.*rc; | |||
891 | DVector2 oldxy=points[0]->xy; | |||
892 | for (unsigned int k=1;k<points.size();k++){ | |||
893 | zlast=z; | |||
894 | z=points[k]->wire->origin.z(); | |||
895 | if (fabs(z-zlast)<0.01) continue; | |||
896 | ||||
897 | DVector2 diffxy=points[k]->xy-oldxy; | |||
898 | double Phi=points[k]->xy.Phi(); | |||
899 | double cosPhi=cos(Phi); | |||
900 | double sinPhi=sin(Phi); | |||
901 | double var=cosPhi*cosPhi*points[k]->covxx | |||
902 | +sinPhi*sinPhi*points[k]->covyy | |||
903 | +2.*sinPhi*cosPhi*points[k]->covxy; | |||
904 | ||||
905 | sperp_old=sperp; | |||
906 | ratio=diffxy.Mod()/(two_rc); | |||
907 | // Make sure the argument for the arcsin does not go out of range... | |||
908 | sperp=sperp_old+(ratio>1?two_rc*(M_PI_21.57079632679489661923):two_rc*asin(ratio)); | |||
909 | ||||
910 | // Assume errors in s dominated by errors in R | |||
911 | double inv_var=1./var; | |||
912 | sumv+=inv_var; | |||
913 | sumy+=sperp*inv_var; | |||
914 | sumx+=z*inv_var; | |||
915 | sumxx+=z*z*inv_var; | |||
916 | sumxy+=sperp*z*inv_var; | |||
917 | ||||
918 | // Save the current x and y coordinates | |||
919 | oldxy=points[k]->xy; | |||
920 | } | |||
921 | // last point is at "vertex" --> give it a large error... | |||
922 | sperp+=oldxy.Mod()/two_rc; | |||
923 | double inv_var=0.01; | |||
924 | sumv+=inv_var; | |||
925 | sumy+=sperp*inv_var; | |||
926 | sumx+=TARGET_Z*inv_var; | |||
927 | sumxx+=TARGET_Z*TARGET_Z*inv_var; | |||
928 | sumxy+=sperp*TARGET_Z*inv_var; | |||
929 | ||||
930 | Delta=sumv*sumxx-sumx*sumx; | |||
931 | double denom=sumv*sumxy-sumy*sumx; | |||
932 | if (fabs(Delta)>EPS1e-8 && fabs(denom)>EPS1e-8){ | |||
933 | // Track parameters z0 and tan(lambda) | |||
934 | tanl=-Delta/denom; | |||
935 | // Vertex position | |||
936 | sperp-=sperp_old; | |||
937 | zvertex=zlast-tanl*sperp; | |||
938 | ||||
939 | return NOERROR; | |||
940 | } | |||
941 | ||||
942 | return VALUE_OUT_OF_RANGE; | |||
943 | } | |||
944 | ||||
945 | // Simple least squares circle fit forcing the circle to go through (0,0) | |||
946 | jerror_t DFDCSegment_factory::CircleFit(vector<const DFDCPseudo *>&points){ | |||
947 | double alpha=0.0, beta=0.0, gamma=0.0, deltax=0.0, deltay=0.0; | |||
948 | // Loop over hits to calculate alpha, beta, gamma, and delta | |||
949 | for(unsigned int i=0;i<points.size();i++){ | |||
950 | const DFDCPseudo *hit = points[i]; | |||
951 | double x=hit->xy.X(); | |||
952 | double y=hit->xy.Y(); | |||
953 | double x_sq=x*x; | |||
954 | double y_sq=y*y; | |||
955 | double x_sq_plus_y_sq=x_sq+y_sq; | |||
956 | alpha += x_sq; | |||
957 | beta += y_sq; | |||
958 | gamma += x*y; | |||
959 | deltax += 0.5*x*x_sq_plus_y_sq; | |||
960 | deltay += 0.5*y*x_sq_plus_y_sq; | |||
961 | } | |||
962 | ||||
963 | // Calculate xc,yc - the center of the circle | |||
964 | double denom = alpha*beta-gamma*gamma; | |||
965 | if(fabs(denom)<1.0E-20)return UNRECOVERABLE_ERROR; | |||
966 | xc = (deltax*beta-deltay*gamma)/denom; | |||
967 | yc = (deltay*alpha-deltax*gamma)/denom; | |||
968 | rc = sqrt(xc*xc + yc*yc); | |||
969 | Ndof=points.size()-2; | |||
970 | ||||
971 | return NOERROR; | |||
972 | } | |||
973 | ||||
974 | // Crude chi^2 calculation for circle fit that was forced to go through (0,0) | |||
975 | double DFDCSegment_factory::ComputeCircleChiSq(vector<const DFDCPseudo *>&neighbors) { | |||
976 | chisq=0.; | |||
977 | Phi1=atan2(neighbors[0]->xy.Y()-yc,neighbors[0]->xy.X()-xc); | |||
978 | double z0=neighbors[0]->wire->origin.z(); | |||
979 | for (unsigned int m=0;m<neighbors.size();m++){ | |||
980 | double sperp=rotation_sense*(neighbors[m]->wire->origin.z()-z0)/tanl; | |||
981 | double phi_s=Phi1+sperp/rc; | |||
982 | DVector2 XY(xc+rc*cos(phi_s),yc+rc*sin(phi_s)); | |||
983 | chisq+=(XY-neighbors[m]->xy).Mod2(); | |||
984 | // Very crude estimate: we assumed errors of size 1. in circle fit... | |||
985 | } | |||
986 | ||||
987 | return chisq; | |||
988 | } | |||
989 | ||||
990 | ||||
991 | // Put fit results into the segment | |||
992 | void DFDCSegment_factory::FillSegmentData(DFDCSegment *segment){ | |||
993 | // the particle's charge | |||
994 | double charge=RotationSenseToCharge*rotation_sense; | |||
995 | ||||
996 | // Estimate for azimuthal angle | |||
997 | phi0=atan2(-xc,yc); | |||
998 | if (rotation_sense<0) phi0+=M_PI3.14159265358979323846; | |||
999 | ||||
1000 | // Look for distance of closest approach nearest to target | |||
1001 | D=-rotation_sense*rc-xc/sin(phi0); | |||
1002 | ||||
1003 | segment->q=charge; //charge | |||
1004 | segment->phi0=phi0; // Phi | |||
1005 | segment->D=D; // D=distance of closest approach to origin | |||
1006 | segment->tanl=tanl; // tan(lambda), lambda=dip angle | |||
1007 | segment->z_vertex=zvertex;// z-position at closest approach to origin | |||
1008 | segment->xc=xc; | |||
1009 | segment->yc=yc; | |||
1010 | segment->rc=rc; | |||
1011 | segment->Phi1=Phi1; | |||
1012 | segment->chisq=chisq; | |||
1013 | segment->Ndof=Ndof; | |||
1014 | } | |||
1015 | ||||
1016 | ||||
1017 | //---------------------------------------------------------------------------- | |||
1018 | // The following routine is no longer in use: | |||
1019 | // Correct avalanche position along wire and incorporate drift data for | |||
1020 | // coordinate away from the wire using results of preliminary hit-based fit | |||
1021 | // | |||
1022 | //#define R_START 7.6 | |||
1023 | //#define Z_TOF 617.4 | |||
1024 | //#include "HDGEOMETRY/DLorentzMapCalibDB.h | |||
1025 | //#define SC_V_EFF 15. | |||
1026 | //#define SC_LIGHT_GUIDE 140. | |||
1027 | //#define SC_CENTER 38.75 | |||
1028 | //#define TOF_BAR_LENGTH 252.0 | |||
1029 | //#define TOF_V_EFF 15. | |||
1030 | //#define FDC_X_RESOLUTION 0.028 | |||
1031 | //#define FDC_Y_RESOLUTION 0.02 //cm | |||
1032 | /* | |||
1033 | jerror_t DFDCSegment_factory::CorrectPoints(vector<DFDCPseudo*>points, | |||
1034 | DMatrix XYZ){ | |||
1035 | // dip angle | |||
1036 | double lambda=atan(tanl); | |||
1037 | double alpha=M_PI/2.-lambda; | |||
1038 | ||||
1039 | if (alpha == 0. || rc==0.) return VALUE_OUT_OF_RANGE; | |||
1040 | ||||
1041 | // Get Bfield, needed to guess particle momentum | |||
1042 | double Bx,By,Bz,B; | |||
1043 | double x=XYZ(ref_plane,0); | |||
1044 | double y=XYZ(ref_plane,1); | |||
1045 | double z=XYZ(ref_plane,2); | |||
1046 | ||||
1047 | bfield->GetField(x,y,z,Bx,By,Bz); | |||
1048 | B=sqrt(Bx*Bx+By*By+Bz*Bz); | |||
1049 | ||||
1050 | // Momentum and beta | |||
1051 | double p=0.002998*B*rc/cos(lambda); | |||
1052 | double beta=p/sqrt(p*p+0.140*0.140); | |||
1053 | ||||
1054 | // Correct start time for propagation from (0,0) | |||
1055 | double my_start_time=0.; | |||
1056 | if (use_tof){ | |||
1057 | //my_start_time=ref_time-(Z_TOF-TARGET_Z)/sin(lambda)/beta/29.98; | |||
1058 | // If we need to use the tof, the angle relative to the beam line is | |||
1059 | // small enough that sin(lambda) ~ 1. | |||
1060 | my_start_time=ref_time-(Z_TOF-TARGET_Z)/beta/29.98; | |||
1061 | //my_start_time=0; | |||
1062 | } | |||
1063 | else{ | |||
1064 | double ratio=R_START/2./rc; | |||
1065 | if (ratio<=1.) | |||
1066 | my_start_time=ref_time | |||
1067 | -2.*rc*asin(R_START/2./rc)*(1./cos(lambda)/beta/29.98); | |||
1068 | else | |||
1069 | my_start_time=ref_time | |||
1070 | -rc*M_PI*(1./cos(lambda)/beta/29.98); | |||
1071 | ||||
1072 | } | |||
1073 | //my_start_time=0.; | |||
1074 | ||||
1075 | for (unsigned int m=0;m<points.size();m++){ | |||
1076 | DFDCPseudo *point=points[m]; | |||
1077 | ||||
1078 | double cosangle=point->wire->udir(1); | |||
1079 | double sinangle=point->wire->udir(0); | |||
1080 | x=XYZ(m,0); | |||
1081 | y=XYZ(m,1); | |||
1082 | z=point->wire->origin.z(); | |||
1083 | double delta_x=0,delta_y=0; | |||
1084 | // Variances based on expected resolution | |||
1085 | double sigx2=FDC_X_RESOLUTION*FDC_X_RESOLUTION; | |||
1086 | ||||
1087 | // Find difference between point on helical path and wire | |||
1088 | double w=x*cosangle-y*sinangle-point->w; | |||
1089 | // .. and use it to determine which sign to use for the drift time data | |||
1090 | double sign=(w>0?1.:-1.); | |||
1091 | ||||
1092 | // Correct the drift time for the flight path and convert to distance units | |||
1093 | // assuming the particle is a pion | |||
1094 | delta_x=sign*(point->time-fdc_track[m].s/beta/29.98-my_start_time)*55E-4; | |||
1095 | ||||
1096 | // Variance for position along wire. Includes angle dependence from PHENIX | |||
1097 | // and transverse diffusion | |||
1098 | double sigy2=fdc_y_variance(alpha,delta_x); | |||
1099 | ||||
1100 | // Next find correction to y from table of deflections | |||
1101 | delta_y=lorentz_def->GetLorentzCorrection(x,y,z,alpha,delta_x); | |||
1102 | ||||
1103 | // Fill x and y elements with corrected values | |||
1104 | point->ds =-delta_y; | |||
1105 | point->dw =delta_x; | |||
1106 | point->x=(point->w+point->dw)*cosangle+(point->s+point->ds)*sinangle; | |||
1107 | point->y=-(point->w+point->dw)*sinangle+(point->s+point->ds)*cosangle; | |||
1108 | point->covxx=sigx2*cosangle*cosangle+sigy2*sinangle*sinangle; | |||
1109 | point->covyy=sigx2*sinangle*sinangle+sigy2*cosangle*cosangle; | |||
1110 | point->covxy=(sigy2-sigx2)*sinangle*cosangle; | |||
1111 | point->status|=CORRECTED; | |||
1112 | } | |||
1113 | return NOERROR; | |||
1114 | } | |||
1115 | */ |
1 | // $Id: JEventLoop.h 1763 2006-05-10 14:29:25Z davidl $ | ||||||
2 | // | ||||||
3 | // File: JEventLoop.h | ||||||
4 | // Created: Wed Jun 8 12:30:51 EDT 2005 | ||||||
5 | // Creator: davidl (on Darwin wire129.jlab.org 7.8.0 powerpc) | ||||||
6 | // | ||||||
7 | |||||||
8 | #ifndef _JEventLoop_ | ||||||
9 | #define _JEventLoop_ | ||||||
10 | |||||||
11 | #include <sys/time.h> | ||||||
12 | |||||||
13 | #include <vector> | ||||||
14 | #include <list> | ||||||
15 | #include <string> | ||||||
16 | #include <utility> | ||||||
17 | #include <typeinfo> | ||||||
18 | #include <string.h> | ||||||
19 | #include <map> | ||||||
20 | #include <utility> | ||||||
21 | using std::vector; | ||||||
22 | using std::list; | ||||||
23 | using std::string; | ||||||
24 | using std::type_info; | ||||||
25 | |||||||
26 | #include <JANA/jerror.h> | ||||||
27 | #include <JANA/JObject.h> | ||||||
28 | #include <JANA/JException.h> | ||||||
29 | #include <JANA/JEvent.h> | ||||||
30 | #include <JANA/JThread.h> | ||||||
31 | #include <JANA/JFactory_base.h> | ||||||
32 | #include <JANA/JCalibration.h> | ||||||
33 | #include <JANA/JGeometry.h> | ||||||
34 | #include <JANA/JResourceManager.h> | ||||||
35 | #include <JANA/JStreamLog.h> | ||||||
36 | |||||||
37 | // The following is here just so we can use ROOT's THtml class to generate documentation. | ||||||
38 | #include "cint.h" | ||||||
39 | |||||||
40 | |||||||
41 | // Place everything in JANA namespace | ||||||
42 | namespace jana{ | ||||||
43 | |||||||
44 | |||||||
45 | template<class T> class JFactory; | ||||||
46 | class JApplication; | ||||||
47 | class JEventProcessor; | ||||||
48 | |||||||
49 | |||||||
50 | class JEventLoop{ | ||||||
51 | public: | ||||||
52 | |||||||
53 | friend class JApplication; | ||||||
54 | |||||||
55 | enum data_source_t{ | ||||||
56 | DATA_NOT_AVAILABLE = 1, | ||||||
57 | DATA_FROM_CACHE, | ||||||
58 | DATA_FROM_SOURCE, | ||||||
59 | DATA_FROM_FACTORY | ||||||
60 | }; | ||||||
61 | |||||||
62 | typedef struct{ | ||||||
63 | string caller_name; | ||||||
64 | string caller_tag; | ||||||
65 | string callee_name; | ||||||
66 | string callee_tag; | ||||||
67 | double start_time; | ||||||
68 | double end_time; | ||||||
69 | data_source_t data_source; | ||||||
70 | }call_stack_t; | ||||||
71 | |||||||
72 | typedef struct{ | ||||||
73 | const char* factory_name; | ||||||
74 | string tag; | ||||||
75 | const char* filename; | ||||||
76 | int line; | ||||||
77 | }error_call_stack_t; | ||||||
78 | |||||||
79 | JEventLoop(JApplication *app); ///< Constructor | ||||||
80 | virtual ~JEventLoop(); ////< Destructor | ||||||
81 | virtual const char* className(void){return static_className();} | ||||||
82 | static const char* static_className(void){return "JEventLoop";} | ||||||
83 | |||||||
84 | JApplication* GetJApplication(void) const {return app;} ///< Get pointer to the JApplication object | ||||||
85 | void RefreshProcessorListFromJApplication(void); ///< Re-copy the list of JEventProcessors from JApplication | ||||||
86 | virtual jerror_t AddFactory(JFactory_base* factory); ///< Add a factory | ||||||
87 | jerror_t RemoveFactory(JFactory_base* factory); ///< Remove a factory | ||||||
88 | JFactory_base* GetFactory(const string data_name, const char *tag="", bool allow_deftag=true); ///< Get a specific factory pointer | ||||||
89 | vector<JFactory_base*> GetFactories(void) const {return factories;} ///< Get all factory pointers | ||||||
90 | void GetFactoryNames(vector<string> &factorynames); ///< Get names of all factories in name:tag format | ||||||
91 | void GetFactoryNames(map<string,string> &factorynames); ///< Get names of all factories in map with key=name, value=tag | ||||||
92 | map<string,string> GetDefaultTags(void) const {return default_tags;} | ||||||
93 | jerror_t ClearFactories(void); ///< Reset all factories in preparation for next event. | ||||||
94 | jerror_t PrintFactories(int sparsify=0); ///< Print a list of all factories. | ||||||
95 | jerror_t Print(const string data_name, const char *tag=""); ///< Print the data of the given type | ||||||
96 | |||||||
97 | JCalibration* GetJCalibration(); | ||||||
98 | template<class T> bool GetCalib(string namepath, map<string,T> &vals); | ||||||
99 | template<class T> bool GetCalib(string namepath, vector<T> &vals); | ||||||
100 | template<class T> bool GetCalib(string namepath, T &val); | ||||||
101 | |||||||
102 | JGeometry* GetJGeometry(); | ||||||
103 | template<class T> bool GetGeom(string namepath, map<string,T> &vals); | ||||||
104 | template<class T> bool GetGeom(string namepath, T &val); | ||||||
105 | |||||||
106 | JResourceManager* GetJResourceManager(void); | ||||||
107 | string GetResource(string namepath); | ||||||
108 | template<class T> bool GetResource(string namepath, T vals, int event_number=0); | ||||||
109 | |||||||
110 | void Initialize(void); ///< Do initializations just before event processing starts | ||||||
111 | jerror_t Loop(void); ///< Loop over events | ||||||
112 | jerror_t OneEvent(uint64_t event_number); ///< Process a specific single event (if source supports it) | ||||||
113 | jerror_t OneEvent(void); ///< Process a single event | ||||||
114 | inline void Pause(void){pause = 1;} ///< Pause event processing | ||||||
115 | inline void Resume(void){pause = 0;} ///< Resume event processing | ||||||
116 | inline void Quit(void){quit = 1;} ///< Clean up and exit the event loop | ||||||
117 | inline bool GetQuit(void) const {return quit;} | ||||||
118 | void QuitProgram(void); | ||||||
119 | |||||||
120 | // Support for random access of events | ||||||
121 | bool HasRandomAccess(void); | ||||||
122 | void AddToEventQueue(uint64_t event_number){ next_events_to_process.push_back(event_number); } | ||||||
123 | void AddToEventQueue(list<uint64_t> &event_numbers) { next_events_to_process.insert(next_events_to_process.end(), event_numbers.begin(), event_numbers.end()); } | ||||||
124 | list<uint64_t> GetEventQueue(void){ return next_events_to_process; } | ||||||
125 | void ClearEventQueue(void){ next_events_to_process.clear(); } | ||||||
126 | |||||||
127 | template<class T> JFactory<T>* GetSingle(const T* &t, const char *tag="", bool exception_if_not_one=true); ///< Get pointer to first data object from (source or factory). | ||||||
128 | template<class T> JFactory<T>* Get(vector<const T*> &t, const char *tag="", bool allow_deftag=true); ///< Get data object pointers from (source or factory) | ||||||
129 | template<class T> JFactory<T>* GetFromFactory(vector<const T*> &t, const char *tag="", data_source_t &data_source=null_data_source, bool allow_deftag=true); ///< Get data object pointers from factory | ||||||
130 | template<class T> jerror_t GetFromSource(vector<const T*> &t, JFactory_base *factory=NULL__null); ///< Get data object pointers from source. | ||||||
131 | inline JEvent& GetJEvent(void){return event;} ///< Get pointer to the current JEvent object. | ||||||
132 | inline void SetJEvent(JEvent *event){this->event = *event;} ///< Set the JEvent pointer. | ||||||
133 | inline void SetAutoFree(int auto_free){this->auto_free = auto_free;} ///< Set the Auto-Free flag on/off | ||||||
134 | inline pthread_t GetPThreadID(void) const {return pthread_id;} ///< Get the pthread of the thread to which this JEventLoop belongs | ||||||
135 | double GetInstantaneousRate(void) const {return rate_instantaneous;} ///< Get the current event processing rate | ||||||
136 | double GetIntegratedRate(void) const {return rate_integrated;} ///< Get the current event processing rate | ||||||
137 | double GetLastEventProcessingTime(void) const {return delta_time_single;} | ||||||
138 | unsigned int GetNevents(void) const {return Nevents;} | ||||||
139 | |||||||
140 | inline bool CheckEventBoundary(uint64_t event_numberA, uint64_t event_numberB); | ||||||
141 | |||||||
142 | inline bool GetCallStackRecordingStatus(void){ return record_call_stack; } | ||||||
143 | inline void DisableCallStackRecording(void){ record_call_stack = false; } | ||||||
144 | inline void EnableCallStackRecording(void){ record_call_stack = true; } | ||||||
145 | inline void CallStackStart(JEventLoop::call_stack_t &cs, const string &caller_name, const string &caller_tag, const string callee_name, const string callee_tag); | ||||||
146 | inline void CallStackEnd(JEventLoop::call_stack_t &cs); | ||||||
147 | inline vector<call_stack_t> GetCallStack(void){return call_stack;} ///< Get the current factory call stack | ||||||
148 | inline void AddToCallStack(call_stack_t &cs){if(record_call_stack) call_stack.push_back(cs);} ///< Add specified item to call stack record but only if record_call_stack is true | ||||||
149 | inline void AddToErrorCallStack(error_call_stack_t &cs){error_call_stack.push_back(cs);} ///< Add layer to the factory call stack | ||||||
150 | inline vector<error_call_stack_t> GetErrorCallStack(void){return error_call_stack;} ///< Get the current factory error call stack | ||||||
151 | void PrintErrorCallStack(void); ///< Print the current factory call stack | ||||||
152 | |||||||
153 | const JObject* FindByID(JObject::oid_t id); ///< Find a data object by its identifier. | ||||||
154 | template<class T> const T* FindByID(JObject::oid_t id); ///< Find a data object by its type and identifier | ||||||
155 | JFactory_base* FindOwner(const JObject *t); ///< Find the factory that owns a data object by pointer | ||||||
156 | JFactory_base* FindOwner(JObject::oid_t id); ///< Find a factory that owns a data object by identifier | ||||||
157 | |||||||
158 | // User defined references | ||||||
159 | template<class T> void SetRef(T *t); ///< Add a user reference to this JEventLoop (must be a pointer) | ||||||
160 | template<class T> T* GetRef(void); ///< Get a user-defined reference of a specific type | ||||||
161 | template<class T> vector<T*> GetRefsT(void); ///< Get all user-defined refrences of a specicif type | ||||||
162 | vector<pair<const char*, void*> > GetRefs(void){ return user_refs; } ///< Get copy of full list of user-defined references | ||||||
163 | template<class T> void RemoveRef(T *t); ///< Remove user reference from list | ||||||
164 | |||||||
165 | // Convenience methods wrapping JEvent methods of same name | ||||||
166 | uint64_t GetStatus(void){return event.GetStatus();} | ||||||
167 | bool GetStatusBit(uint32_t bit){return event.GetStatusBit(bit);} | ||||||
168 | bool SetStatusBit(uint32_t bit, bool val=true){return event.SetStatusBit(bit, val);} | ||||||
169 | bool ClearStatusBit(uint32_t bit){return event.ClearStatusBit(bit);} | ||||||
170 | void ClearStatus(void){event.ClearStatus();} | ||||||
171 | void SetStatusBitDescription(uint32_t bit, string description){event.SetStatusBitDescription(bit, description);} | ||||||
172 | string GetStatusBitDescription(uint32_t bit){return event.GetStatusBitDescription(bit);} | ||||||
173 | void GetStatusBitDescriptions(map<uint32_t, string> &status_bit_descriptions){return event.GetStatusBitDescriptions(status_bit_descriptions);} | ||||||
174 | string StatusWordToString(void); | ||||||
175 | |||||||
176 | private: | ||||||
177 | JEvent event; | ||||||
178 | vector<JFactory_base*> factories; | ||||||
179 | vector<JEventProcessor*> processors; | ||||||
180 | vector<error_call_stack_t> error_call_stack; | ||||||
181 | vector<call_stack_t> call_stack; | ||||||
182 | JApplication *app; | ||||||
183 | JThread *jthread; | ||||||
184 | bool initialized; | ||||||
185 | bool print_parameters_called; | ||||||
186 | int pause; | ||||||
187 | int quit; | ||||||
188 | int auto_free; | ||||||
189 | pthread_t pthread_id; | ||||||
190 | map<string, string> default_tags; | ||||||
191 | vector<pair<string,string> > auto_activated_factories; | ||||||
192 | bool record_call_stack; | ||||||
193 | string caller_name; | ||||||
194 | string caller_tag; | ||||||
195 | vector<uint64_t> event_boundaries; | ||||||
196 | int32_t event_boundaries_run; ///< Run number boundaries were retrieved from (possbily 0) | ||||||
197 | list<uint64_t> next_events_to_process; | ||||||
198 | |||||||
199 | uint64_t Nevents; ///< Total events processed (this thread) | ||||||
200 | uint64_t Nevents_rate; ///< Num. events accumulated for "instantaneous" rate | ||||||
201 | double delta_time_single; ///< Time spent processing last event | ||||||
202 | double delta_time_rate; ///< Integrated time accumulated "instantaneous" rate (partial number of events) | ||||||
203 | double delta_time; ///< Total time spent processing events (this thread) | ||||||
204 | double rate_instantaneous; ///< Latest instantaneous rate | ||||||
205 | double rate_integrated; ///< Rate integrated over all events | ||||||
206 | |||||||
207 | static data_source_t null_data_source; | ||||||
208 | |||||||
209 | vector<pair<const char*, void*> > user_refs; | ||||||
210 | }; | ||||||
211 | |||||||
212 | |||||||
213 | // The following is here just so we can use ROOT's THtml class to generate documentation. | ||||||
214 | #ifdef G__DICTIONARY | ||||||
215 | typedef JEventLoop::call_stack_t call_stack_t; | ||||||
216 | typedef JEventLoop::error_call_stack_t error_call_stack_t; | ||||||
217 | #endif | ||||||
218 | |||||||
219 | #if !defined(__CINT__) && !defined(__CLING__) | ||||||
220 | |||||||
221 | //------------- | ||||||
222 | // GetSingle | ||||||
223 | //------------- | ||||||
224 | template<class T> | ||||||
225 | JFactory<T>* JEventLoop::GetSingle(const T* &t, const char *tag, bool exception_if_not_one) | ||||||
226 | { | ||||||
227 | /// This is a convenience method that can be used to get a pointer to the single | ||||||
228 | /// object of type T from the specified factory. It simply calls the Get(vector<...>) method | ||||||
229 | /// and copies the first pointer into "t" (or NULL if something other than 1 object is returned). | ||||||
230 | /// | ||||||
231 | /// This is intended to address the common situation in which there is an interest | ||||||
232 | /// in the event if and only if there is exactly 1 object of type T. If the event | ||||||
233 | /// has no objects of that type or more than 1 object of that type (for the specified | ||||||
234 | /// factory) then an exception of type "unsigned long" is thrown with the value | ||||||
235 | /// being the number of objects of type T. You can supress the exception by setting | ||||||
236 | /// exception_if_not_one to false. In that case, you will have to check if t==NULL to | ||||||
237 | /// know if the call succeeded. | ||||||
238 | vector<const T*> v; | ||||||
239 | JFactory<T> *fac = Get(v, tag); | ||||||
240 | |||||||
241 | if(v.size()!=1){ | ||||||
242 | t = NULL__null; | ||||||
243 | if(exception_if_not_one) throw v.size(); | ||||||
244 | } | ||||||
245 | |||||||
246 | t = v[0]; | ||||||
247 | |||||||
248 | return fac; | ||||||
249 | } | ||||||
250 | |||||||
251 | //------------- | ||||||
252 | // Get | ||||||
253 | //------------- | ||||||
254 | template<class T> | ||||||
255 | JFactory<T>* JEventLoop::Get(vector<const T*> &t, const char *tag, bool allow_deftag) | ||||||
256 | { | ||||||
257 | /// Retrieve or generate the array of objects of | ||||||
258 | /// type T for the curent event being processed | ||||||
259 | /// by this thread. | ||||||
260 | /// | ||||||
261 | /// By default, preference is given to reading the | ||||||
262 | /// objects from the data source(e.g. file) before generating | ||||||
263 | /// them in the factory. A flag exists in the factory | ||||||
264 | /// however to change this so that the factory is | ||||||
265 | /// given preference. | ||||||
266 | /// | ||||||
267 | /// Note that regardless of the setting of this flag, | ||||||
268 | /// the data are only either read in or generated once. | ||||||
269 | /// Ownership of the objects will always be with the | ||||||
270 | /// factory so subsequent calls will always return pointers to | ||||||
271 | /// the same data. | ||||||
272 | /// | ||||||
273 | /// If the factory is called on to generate the data, | ||||||
274 | /// it is done by calling the factory's Get() method | ||||||
275 | /// which, in turn, calls the evnt() method. | ||||||
276 | /// | ||||||
277 | /// First, we just call the GetFromFactory() method. | ||||||
278 | /// It will make the initial decision as to whether | ||||||
279 | /// it should look in the source first or not. If | ||||||
280 | /// it returns NULL, then the factory couldn't be | ||||||
281 | /// found so we automatically try the file. | ||||||
282 | /// | ||||||
283 | /// Note that if no factory exists to hold the objects | ||||||
284 | /// from the file, one can be created automatically | ||||||
285 | /// providing the <i>JANA:AUTOFACTORYCREATE</i> | ||||||
286 | /// configuration parameter is set. | ||||||
287 | |||||||
288 | // Check if a tag was specified for this data type to use for the | ||||||
289 | // default. | ||||||
290 | const char *mytag = tag
| ||||||
291 | if(strlen(mytag)==0 && allow_deftag
| ||||||
292 | map<string, string>::const_iterator iter = default_tags.find(T::static_className()); | ||||||
293 | if(iter!=default_tags.end())tag = iter->second.c_str(); | ||||||
294 | } | ||||||
295 | |||||||
296 | |||||||
297 | // If we are trying to keep track of the call stack then we | ||||||
298 | // need to add a new call_stack_t object to the the list | ||||||
299 | // and initialize it with the start time and caller/callee | ||||||
300 | // info. | ||||||
301 | call_stack_t cs; | ||||||
302 | |||||||
303 | // Optionally record starting info of call stack entry | ||||||
304 | if(record_call_stack) CallStackStart(cs, caller_name, caller_tag, T::static_className(), tag); | ||||||
305 | |||||||
306 | // Get the data (or at least try to) | ||||||
307 | JFactory<T>* factory=NULL__null; | ||||||
308 | try{ | ||||||
309 | factory = GetFromFactory(t, tag, cs.data_source, allow_deftag); | ||||||
310 | if(!factory){ | ||||||
311 | // No factory exists for this type and tag. It's possible | ||||||
312 | // that the source may be able to provide the objects | ||||||
313 | // but it will need a place to put them. We can create a | ||||||
314 | // dumb JFactory just to hold the data in case the source | ||||||
315 | // can provide the objects. Before we do though, make sure | ||||||
316 | // the user condones this via the presence of the | ||||||
317 | // "JANA:AUTOFACTORYCREATE" config parameter. | ||||||
318 | string p; | ||||||
319 | try{ | ||||||
320 | gPARMS->GetParameter("JANA:AUTOFACTORYCREATE", p); | ||||||
321 | }catch(...){} | ||||||
322 | if(p.size()==0){ | ||||||
323 | jout<<std::endl; | ||||||
324 | _DBG__std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h" <<":"<<324<<std::endl; | ||||||
325 | jout<<"No factory of type \""<<T::static_className()<<"\" with tag \""<<tag<<"\" exists."<<std::endl; | ||||||
326 | jout<<"If you are reading objects from a file, I can auto-create a factory"<<std::endl; | ||||||
327 | jout<<"of the appropriate type to hold the objects, but this feature is turned"<<std::endl; | ||||||
328 | jout<<"off by default. To turn it on, set the \"JANA:AUTOFACTORYCREATE\""<<std::endl; | ||||||
329 | jout<<"configuration parameter. This can usually be done by passing the"<<std::endl; | ||||||
330 | jout<<"following argument to the program from the command line:"<<std::endl; | ||||||
331 | jout<<std::endl; | ||||||
332 | jout<<" -PJANA:AUTOFACTORYCREATE=1"<<std::endl; | ||||||
333 | jout<<std::endl; | ||||||
334 | jout<<"Note that since the most commonly expected occurance of this situation."<<std::endl; | ||||||
335 | jout<<"is an error, the program will now throw an exception so that the factory."<<std::endl; | ||||||
336 | jout<<"call stack can be printed."<<std::endl; | ||||||
337 | jout<<std::endl; | ||||||
338 | throw exception(); | ||||||
339 | }else{ | ||||||
340 | AddFactory(new JFactory<T>(tag)); | ||||||
341 | jout<<__FILE__"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h"<<":"<<__LINE__341<<" Auto-created "<<T::static_className()<<":"<<tag<<" factory"<<std::endl; | ||||||
342 | |||||||
343 | // Now try once more. The GetFromFactory method will call | ||||||
344 | // GetFromSource since it's empty. | ||||||
345 | factory = GetFromFactory(t, tag, cs.data_source, allow_deftag); | ||||||
346 | } | ||||||
347 | } | ||||||
348 | }catch(exception &e){ | ||||||
349 | // Uh-oh, an exception was thrown. Add us to the call stack | ||||||
350 | // and re-throw the exception | ||||||
351 | error_call_stack_t ecs; | ||||||
352 | ecs.factory_name = T::static_className(); | ||||||
353 | ecs.tag = tag; | ||||||
354 | ecs.filename = NULL__null; | ||||||
355 | error_call_stack.push_back(ecs); | ||||||
356 | throw e; | ||||||
357 | } | ||||||
358 | |||||||
359 | // If recording the call stack, update the end_time field and add to stack | ||||||
360 | if(record_call_stack) CallStackEnd(cs); | ||||||
361 | |||||||
362 | return factory; | ||||||
363 | } | ||||||
364 | |||||||
365 | //------------- | ||||||
366 | // GetFromFactory | ||||||
367 | //------------- | ||||||
368 | template<class T> | ||||||
369 | JFactory<T>* JEventLoop::GetFromFactory(vector<const T*> &t, const char *tag, data_source_t &data_source, bool allow_deftag) | ||||||
370 | { | ||||||
371 | // We need to find the factory providing data type T with | ||||||
372 | // tag given by "tag". | ||||||
373 | vector<JFactory_base*>::iterator iter=factories.begin(); | ||||||
374 | JFactory<T> *factory = NULL__null; | ||||||
375 | string className(T::static_className()); | ||||||
376 | |||||||
377 | // Check if a tag was specified for this data type to use for the | ||||||
378 | // default. | ||||||
379 | const char *mytag = tag==NULL__null ? "":tag; // protection against NULL tags | ||||||
380 | if(strlen(mytag)==0 && allow_deftag
| ||||||
381 | map<string, string>::const_iterator iter = default_tags.find(className); | ||||||
382 | if(iter!=default_tags.end())tag = iter->second.c_str(); | ||||||
383 | } | ||||||
384 | |||||||
385 | for(; iter!=factories.end(); iter++){ | ||||||
386 | // It turns out a long standing bug in g++ makes dynamic_cast return | ||||||
387 | // zero improperly when used on objects created on one side of | ||||||
388 | // a dynamically shared object (DSO) and the cast occurs on the | ||||||
389 | // other side. I saw bug reports ranging from 2001 to 2004. I saw | ||||||
390 | // saw it first-hand on LinuxEL4 using g++ 3.4.5. This is too bad | ||||||
391 | // since it is much more elegant (and safe) to use dynamic_cast. | ||||||
392 | // To avoid this problem which can occur with plugins, we check | ||||||
393 | // the name of the data classes are the same. (sigh) | ||||||
394 | //factory = dynamic_cast<JFactory<T> *>(*iter); | ||||||
395 | if(className == (*iter)->GetDataClassName())factory = (JFactory<T>*)(*iter); | ||||||
396 | if(factory == NULL__null)continue; | ||||||
397 | const char *factag = factory->Tag()==NULL__null ? "":factory->Tag(); | ||||||
398 | if(!strcmp(factag, tag)){ | ||||||
| |||||||
399 | break; | ||||||
400 | }else{ | ||||||
401 | factory=NULL__null; | ||||||
402 | } | ||||||
403 | } | ||||||
404 | |||||||
405 | // If factory not found, just return now | ||||||
406 | if(!factory){ | ||||||
407 | data_source = DATA_NOT_AVAILABLE; | ||||||
408 | return NULL__null; | ||||||
409 | } | ||||||
410 | |||||||
411 | // OK, we found the factory. If the evnt() routine has already | ||||||
412 | // been called, then just call the factory's Get() routine | ||||||
413 | // to return a copy of the existing data | ||||||
414 | if(factory->evnt_was_called()){ | ||||||
415 | factory->CopyFrom(t); | ||||||
416 | data_source = DATA_FROM_CACHE; | ||||||
417 | return factory; | ||||||
418 | } | ||||||
419 | |||||||
420 | // Next option is to get the objects from the data source | ||||||
421 | if(factory->GetCheckSourceFirst()){ | ||||||
422 | // If the object type/tag is found in the source, it | ||||||
423 | // will return NOERROR, even if there are zero instances | ||||||
424 | // of it. If it is not available in the source then it | ||||||
425 | // will return OBJECT_NOT_AVAILABLE. | ||||||
426 | |||||||
427 | jerror_t err = GetFromSource(t, factory); | ||||||
428 | if(err == NOERROR){ | ||||||
429 | // A return value of NOERROR means the source had the objects | ||||||
430 | // even if there were zero of them.(If the source had no | ||||||
431 | // information about the objects OBJECT_NOT_AVAILABLE would | ||||||
432 | // have been returned.) | ||||||
433 | // The GetFromSource() call will eventually lead to a call to | ||||||
434 | // the GetObjects() method of the concrete class derived | ||||||
435 | // from JEventSource. That routine should copy the object | ||||||
436 | // pointers into the factory using the factory's CopyTo() | ||||||
437 | // method which also sets the evnt_called flag for the factory. | ||||||
438 | // Note also that the "t" vector is then filled with a call | ||||||
439 | // to the factory's CopyFrom() method in JEvent::GetObjects(). | ||||||
440 | // All we need to do now is just set the factory pointers in | ||||||
441 | // the newly generated JObjects and return the factory pointer. | ||||||
442 | |||||||
443 | factory->SetFactoryPointers(); | ||||||
444 | data_source = DATA_FROM_SOURCE; | ||||||
445 | |||||||
446 | return factory; | ||||||
447 | } | ||||||
448 | } | ||||||
449 | |||||||
450 | // OK. It looks like we have to have the factory make this. | ||||||
451 | // Get pointers to data from the factory. | ||||||
452 | factory->Get(t); | ||||||
453 | factory->SetFactoryPointers(); | ||||||
454 | data_source = DATA_FROM_FACTORY; | ||||||
455 | |||||||
456 | return factory; | ||||||
457 | } | ||||||
458 | |||||||
459 | //------------- | ||||||
460 | // GetFromSource | ||||||
461 | //------------- | ||||||
462 | template<class T> | ||||||
463 | jerror_t JEventLoop::GetFromSource(vector<const T*> &t, JFactory_base *factory) | ||||||
464 | { | ||||||
465 | /// This tries to get objects from the event source. | ||||||
466 | /// "factory" must be a valid pointer to a JFactory | ||||||
467 | /// object since that will take ownership of the objects | ||||||
468 | /// created by the source. | ||||||
469 | /// This should usually be called from JEventLoop::GetFromFactory | ||||||
470 | /// which is called from JEventLoop::Get. The latter will | ||||||
471 | /// create a dummy JFactory of the proper flavor and tag if | ||||||
472 | /// one does not already exist so if objects exist in the | ||||||
473 | /// file without a corresponding factory to create them, they | ||||||
474 | /// can still be used. | ||||||
475 | if(!factory)throw OBJECT_NOT_AVAILABLE; | ||||||
476 | |||||||
477 | return event.GetObjects(t, factory); | ||||||
478 | } | ||||||
479 | |||||||
480 | //------------- | ||||||
481 | // CallStackStart | ||||||
482 | //------------- | ||||||
483 | inline void JEventLoop::CallStackStart(JEventLoop::call_stack_t &cs, const string &caller_name, const string &caller_tag, const string callee_name, const string callee_tag) | ||||||
484 | { | ||||||
485 | /// This is used to fill initial info into a call_stack_t stucture | ||||||
486 | /// for recording the call stack. It should be matched with a call | ||||||
487 | /// to CallStackEnd. It is normally called from the Get() method | ||||||
488 | /// above, but may also be used by external actors to manipulate | ||||||
489 | /// the call stack (presumably for good and not evil). | ||||||
490 | |||||||
491 | struct itimerval tmr; | ||||||
492 | getitimer(ITIMER_PROFITIMER_PROF, &tmr); | ||||||
493 | |||||||
494 | cs.caller_name = this->caller_name; | ||||||
495 | cs.caller_tag = this->caller_tag; | ||||||
496 | this->caller_name = cs.callee_name = callee_name; | ||||||
497 | this->caller_tag = cs.callee_tag = callee_tag; | ||||||
498 | cs.start_time = tmr.it_value.tv_sec + tmr.it_value.tv_usec/1.0E6; | ||||||
499 | } | ||||||
500 | |||||||
501 | //------------- | ||||||
502 | // CallStackEnd | ||||||
503 | //------------- | ||||||
504 | inline void JEventLoop::CallStackEnd(JEventLoop::call_stack_t &cs) | ||||||
505 | { | ||||||
506 | /// Complete a call stack entry. This should be matched | ||||||
507 | /// with a previous call to CallStackStart which was | ||||||
508 | /// used to fill the cs structure. | ||||||
509 | |||||||
510 | struct itimerval tmr; | ||||||
511 | getitimer(ITIMER_PROFITIMER_PROF, &tmr); | ||||||
512 | cs.end_time = tmr.it_value.tv_sec + tmr.it_value.tv_usec/1.0E6; | ||||||
513 | caller_name = cs.caller_name; | ||||||
514 | caller_tag = cs.caller_tag; | ||||||
515 | call_stack.push_back(cs); | ||||||
516 | } | ||||||
517 | |||||||
518 | //------------- | ||||||
519 | // CheckEventBoundary | ||||||
520 | //------------- | ||||||
521 | inline bool JEventLoop::CheckEventBoundary(uint64_t event_numberA, uint64_t event_numberB) | ||||||
522 | { | ||||||
523 | /// Check whether the two event numbers span one or more boundaries | ||||||
524 | /// in the calibration/conditions database for the current run number. | ||||||
525 | /// Return true if they do and false if they don't. The first parameter | ||||||
526 | /// "event_numberA" is also checked if it lands on a boundary in which | ||||||
527 | /// case true is also returned. If event_numberB lands on a boundary, | ||||||
528 | /// but event_numberA does not, then false is returned. | ||||||
529 | /// | ||||||
530 | /// This method is not expected to be called by a user. It is, however called, | ||||||
531 | /// everytime a JFactory's Get() method is called. | ||||||
532 | |||||||
533 | // Make sure our copy of the boundaries is up to date | ||||||
534 | if(event.GetRunNumber()!=event_boundaries_run){ | ||||||
535 | event_boundaries.clear(); // in case we can't get the JCalibration pointer | ||||||
536 | JCalibration *jcalib = GetJCalibration(); | ||||||
537 | if(jcalib)jcalib->GetEventBoundaries(event_boundaries); | ||||||
538 | event_boundaries_run = event.GetRunNumber(); | ||||||
539 | } | ||||||
540 | |||||||
541 | // Loop over boundaries | ||||||
542 | for(unsigned int i=0; i<event_boundaries.size(); i++){ | ||||||
543 | uint64_t eb = event_boundaries[i]; | ||||||
544 | if((eb - event_numberA)*(eb - event_numberB) < 0.0 || eb==event_numberA){ // think about it .... | ||||||
545 | // events span a boundary or is on a boundary. Return true | ||||||
546 | return true; | ||||||
547 | } | ||||||
548 | } | ||||||
549 | |||||||
550 | return false; | ||||||
551 | } | ||||||
552 | |||||||
553 | //------------- | ||||||
554 | // FindByID | ||||||
555 | //------------- | ||||||
556 | template<class T> | ||||||
557 | const T* JEventLoop::FindByID(JObject::oid_t id) | ||||||
558 | { | ||||||
559 | /// This is a templated method that can be used in place | ||||||
560 | /// of the non-templated FindByID(oid_t) method if one knows | ||||||
561 | /// the class of the object with the specified id. | ||||||
562 | /// This method is faster than calling the non-templated | ||||||
563 | /// FindByID and dynamic_cast-ing the JObject since | ||||||
564 | /// this will only search the objects of factories that | ||||||
565 | /// produce the desired data type. | ||||||
566 | /// This method will cast the JObject pointer to one | ||||||
567 | /// of the specified type. To use this method, | ||||||
568 | /// a type is specified in the call as follows: | ||||||
569 | /// | ||||||
570 | /// const DMyType *t = loop->FindByID<DMyType>(id); | ||||||
571 | |||||||
572 | // Loop over factories looking for ones that provide | ||||||
573 | // specified data type. | ||||||
574 | for(unsigned int i=0; i<factories.size(); i++){ | ||||||
575 | if(factories[i]->GetDataClassName() != T::static_className())continue; | ||||||
576 | |||||||
577 | // This factory provides data of type T. Search it for | ||||||
578 | // the object with the specified id. | ||||||
579 | const JObject *my_obj = factories[i]->GetByID(id); | ||||||
580 | if(my_obj)return dynamic_cast<const T*>(my_obj); | ||||||
581 | } | ||||||
582 | |||||||
583 | return NULL__null; | ||||||
584 | } | ||||||
585 | |||||||
586 | //------------- | ||||||
587 | // GetCalib (map) | ||||||
588 | //------------- | ||||||
589 | template<class T> | ||||||
590 | bool JEventLoop::GetCalib(string namepath, map<string,T> &vals) | ||||||
591 | { | ||||||
592 | /// Get the JCalibration object from JApplication for the run number of | ||||||
593 | /// the current event and call its Get() method to get the constants. | ||||||
594 | |||||||
595 | // Note that we could do this by making "vals" a generic type T thus, combining | ||||||
596 | // this with the vector version below. However, doing this explicitly will make | ||||||
597 | // it easier for the user to understand how to call us. | ||||||
598 | |||||||
599 | vals.clear(); | ||||||
600 | |||||||
601 | JCalibration *calib = GetJCalibration(); | ||||||
602 | if(!calib){ | ||||||
603 | _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h" <<":"<<603<<" "<<"Unable to get JCalibration object for run "<<event.GetRunNumber()<<std::endl; | ||||||
604 | return true; | ||||||
605 | } | ||||||
606 | |||||||
607 | return calib->Get(namepath, vals, event.GetEventNumber()); | ||||||
608 | } | ||||||
609 | |||||||
610 | //------------- | ||||||
611 | // GetCalib (vector) | ||||||
612 | //------------- | ||||||
613 | template<class T> bool JEventLoop::GetCalib(string namepath, vector<T> &vals) | ||||||
614 | { | ||||||
615 | /// Get the JCalibration object from JApplication for the run number of | ||||||
616 | /// the current event and call its Get() method to get the constants. | ||||||
617 | |||||||
618 | vals.clear(); | ||||||
619 | |||||||
620 | JCalibration *calib = GetJCalibration(); | ||||||
621 | if(!calib){ | ||||||
622 | _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h" <<":"<<622<<" "<<"Unable to get JCalibration object for run "<<event.GetRunNumber()<<std::endl; | ||||||
623 | return true; | ||||||
624 | } | ||||||
625 | |||||||
626 | return calib->Get(namepath, vals, event.GetEventNumber()); | ||||||
627 | } | ||||||
628 | |||||||
629 | //------------- | ||||||
630 | // GetCalib (single) | ||||||
631 | //------------- | ||||||
632 | template<class T> bool JEventLoop::GetCalib(string namepath, T &val) | ||||||
633 | { | ||||||
634 | /// This is a convenience method for getting a single entry. It | ||||||
635 | /// simply calls the vector version and returns the first entry. | ||||||
636 | /// It returns true if the vector version returns true AND there | ||||||
637 | /// is at least one entry in the vector. No check is made for there | ||||||
638 | /// there being more than one entry in the vector. | ||||||
639 | |||||||
640 | vector<T> vals; | ||||||
641 | bool ret = GetCalib(namepath, vals); | ||||||
642 | if(vals.empty()) return true; | ||||||
643 | val = vals[0]; | ||||||
644 | |||||||
645 | return ret; | ||||||
646 | } | ||||||
647 | |||||||
648 | //------------- | ||||||
649 | // GetGeom (map) | ||||||
650 | //------------- | ||||||
651 | template<class T> | ||||||
652 | bool JEventLoop::GetGeom(string namepath, map<string,T> &vals) | ||||||
653 | { | ||||||
654 | /// Get the JGeometry object from JApplication for the run number of | ||||||
655 | /// the current event and call its Get() method to get the constants. | ||||||
656 | |||||||
657 | // Note that we could do this by making "vals" a generic type T thus, combining | ||||||
658 | // this with the vector version below. However, doing this explicitly will make | ||||||
659 | // it easier for the user to understand how to call us. | ||||||
660 | |||||||
661 | vals.clear(); | ||||||
662 | |||||||
663 | JGeometry *geom = GetJGeometry(); | ||||||
664 | if(!geom){ | ||||||
665 | _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h" <<":"<<665<<" "<<"Unable to get JGeometry object for run "<<event.GetRunNumber()<<std::endl; | ||||||
666 | return true; | ||||||
667 | } | ||||||
668 | |||||||
669 | return geom->Get(namepath, vals); | ||||||
670 | } | ||||||
671 | |||||||
672 | //------------- | ||||||
673 | // GetGeom (atomic) | ||||||
674 | //------------- | ||||||
675 | template<class T> bool JEventLoop::GetGeom(string namepath, T &val) | ||||||
676 | { | ||||||
677 | /// Get the JCalibration object from JApplication for the run number of | ||||||
678 | /// the current event and call its Get() method to get the constants. | ||||||
679 | |||||||
680 | JGeometry *geom = GetJGeometry(); | ||||||
681 | if(!geom){ | ||||||
682 | _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h" <<":"<<682<<" "<<"Unable to get JGeometry object for run "<<event.GetRunNumber()<<std::endl; | ||||||
683 | return true; | ||||||
684 | } | ||||||
685 | |||||||
686 | return geom->Get(namepath, val); | ||||||
687 | } | ||||||
688 | |||||||
689 | //------------- | ||||||
690 | // SetRef | ||||||
691 | //------------- | ||||||
692 | template<class T> | ||||||
693 | void JEventLoop::SetRef(T *t) | ||||||
694 | { | ||||||
695 | pair<const char*, void*> p(typeid(T).name(), (void*)t); | ||||||
696 | user_refs.push_back(p); | ||||||
697 | } | ||||||
698 | |||||||
699 | //------------- | ||||||
700 | // GetResource | ||||||
701 | //------------- | ||||||
702 | template<class T> bool JEventLoop::GetResource(string namepath, T vals, int event_number) | ||||||
703 | { | ||||||
704 | JResourceManager *resource_manager = GetJResourceManager(); | ||||||
705 | if(!resource_manager){ | ||||||
706 | string mess = string("Unable to get the JResourceManager object (namepath=\"")+namepath+"\")"; | ||||||
707 | throw JException(mess); | ||||||
708 | } | ||||||
709 | |||||||
710 | return resource_manager->Get(namepath, vals, event_number); | ||||||
711 | } | ||||||
712 | |||||||
713 | //------------- | ||||||
714 | // GetRef | ||||||
715 | //------------- | ||||||
716 | template<class T> | ||||||
717 | T* JEventLoop::GetRef(void) | ||||||
718 | { | ||||||
719 | /// Get a user-defined reference (a pointer) | ||||||
720 | for(unsigned int i=0; i<user_refs.size(); i++){ | ||||||
721 | if(user_refs[i].first == typeid(T).name()) return (T*)user_refs[i].second; | ||||||
722 | } | ||||||
723 | |||||||
724 | return NULL__null; | ||||||
725 | } | ||||||
726 | |||||||
727 | //------------- | ||||||
728 | // GetRefsT | ||||||
729 | //------------- | ||||||
730 | template<class T> | ||||||
731 | vector<T*> JEventLoop::GetRefsT(void) | ||||||
732 | { | ||||||
733 | vector<T*> refs; | ||||||
734 | for(unsigned int i=0; i<user_refs.size(); i++){ | ||||||
735 | if(user_refs[i].first == typeid(T).name()){ | ||||||
736 | refs.push_back((T*)user_refs[i].second); | ||||||
737 | } | ||||||
738 | } | ||||||
739 | |||||||
740 | return refs; | ||||||
741 | } | ||||||
742 | |||||||
743 | //------------- | ||||||
744 | // RemoveRef | ||||||
745 | //------------- | ||||||
746 | template<class T> | ||||||
747 | void JEventLoop::RemoveRef(T *t) | ||||||
748 | { | ||||||
749 | vector<pair<const char*, void*> >::iterator iter; | ||||||
750 | for(iter=user_refs.begin(); iter!= user_refs.end(); iter++){ | ||||||
751 | if(iter->second == (void*)t){ | ||||||
752 | user_refs.erase(iter); | ||||||
753 | return; | ||||||
754 | } | ||||||
755 | } | ||||||
756 | _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h" <<":"<<756<<" "<<" Attempt to remove user reference not in event loop!" << std::endl; | ||||||
757 | } | ||||||
758 | |||||||
759 | |||||||
760 | #endif //__CINT__ __CLING__ | ||||||
761 | |||||||
762 | } // Close JANA namespace | ||||||
763 | |||||||
764 | |||||||
765 | |||||||
766 | #endif // _JEventLoop_ | ||||||
767 |
1 | // Iterators -*- C++ -*- |
2 | |
3 | // Copyright (C) 2001-2013 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the |
7 | // terms of the GNU General Public License as published by the |
8 | // Free Software Foundation; either version 3, or (at your option) |
9 | // any later version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /* |
26 | * |
27 | * Copyright (c) 1994 |
28 | * Hewlett-Packard Company |
29 | * |
30 | * Permission to use, copy, modify, distribute and sell this software |
31 | * and its documentation for any purpose is hereby granted without fee, |
32 | * provided that the above copyright notice appear in all copies and |
33 | * that both that copyright notice and this permission notice appear |
34 | * in supporting documentation. Hewlett-Packard Company makes no |
35 | * representations about the suitability of this software for any |
36 | * purpose. It is provided "as is" without express or implied warranty. |
37 | * |
38 | * |
39 | * Copyright (c) 1996-1998 |
40 | * Silicon Graphics Computer Systems, Inc. |
41 | * |
42 | * Permission to use, copy, modify, distribute and sell this software |
43 | * and its documentation for any purpose is hereby granted without fee, |
44 | * provided that the above copyright notice appear in all copies and |
45 | * that both that copyright notice and this permission notice appear |
46 | * in supporting documentation. Silicon Graphics makes no |
47 | * representations about the suitability of this software for any |
48 | * purpose. It is provided "as is" without express or implied warranty. |
49 | */ |
50 | |
51 | /** @file bits/stl_iterator.h |
52 | * This is an internal header file, included by other library headers. |
53 | * Do not attempt to use it directly. @headername{iterator} |
54 | * |
55 | * This file implements reverse_iterator, back_insert_iterator, |
56 | * front_insert_iterator, insert_iterator, __normal_iterator, and their |
57 | * supporting functions and overloaded operators. |
58 | */ |
59 | |
60 | #ifndef _STL_ITERATOR_H1 |
61 | #define _STL_ITERATOR_H1 1 |
62 | |
63 | #include <bits/cpp_type_traits.h> |
64 | #include <ext/type_traits.h> |
65 | #include <bits/move.h> |
66 | |
67 | namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default"))) |
68 | { |
69 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
70 | |
71 | /** |
72 | * @addtogroup iterators |
73 | * @{ |
74 | */ |
75 | |
76 | // 24.4.1 Reverse iterators |
77 | /** |
78 | * Bidirectional and random access iterators have corresponding reverse |
79 | * %iterator adaptors that iterate through the data structure in the |
80 | * opposite direction. They have the same signatures as the corresponding |
81 | * iterators. The fundamental relation between a reverse %iterator and its |
82 | * corresponding %iterator @c i is established by the identity: |
83 | * @code |
84 | * &*(reverse_iterator(i)) == &*(i - 1) |
85 | * @endcode |
86 | * |
87 | * <em>This mapping is dictated by the fact that while there is always a |
88 | * pointer past the end of an array, there might not be a valid pointer |
89 | * before the beginning of an array.</em> [24.4.1]/1,2 |
90 | * |
91 | * Reverse iterators can be tricky and surprising at first. Their |
92 | * semantics make sense, however, and the trickiness is a side effect of |
93 | * the requirement that the iterators must be safe. |
94 | */ |
95 | template<typename _Iterator> |
96 | class reverse_iterator |
97 | : public iterator<typename iterator_traits<_Iterator>::iterator_category, |
98 | typename iterator_traits<_Iterator>::value_type, |
99 | typename iterator_traits<_Iterator>::difference_type, |
100 | typename iterator_traits<_Iterator>::pointer, |
101 | typename iterator_traits<_Iterator>::reference> |
102 | { |
103 | protected: |
104 | _Iterator current; |
105 | |
106 | typedef iterator_traits<_Iterator> __traits_type; |
107 | |
108 | public: |
109 | typedef _Iterator iterator_type; |
110 | typedef typename __traits_type::difference_type difference_type; |
111 | typedef typename __traits_type::pointer pointer; |
112 | typedef typename __traits_type::reference reference; |
113 | |
114 | /** |
115 | * The default constructor value-initializes member @p current. |
116 | * If it is a pointer, that means it is zero-initialized. |
117 | */ |
118 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
119 | // 235 No specification of default ctor for reverse_iterator |
120 | reverse_iterator() : current() { } |
121 | |
122 | /** |
123 | * This %iterator will move in the opposite direction that @p x does. |
124 | */ |
125 | explicit |
126 | reverse_iterator(iterator_type __x) : current(__x) { } |
127 | |
128 | /** |
129 | * The copy constructor is normal. |
130 | */ |
131 | reverse_iterator(const reverse_iterator& __x) |
132 | : current(__x.current) { } |
133 | |
134 | /** |
135 | * A %reverse_iterator across other types can be copied if the |
136 | * underlying %iterator can be converted to the type of @c current. |
137 | */ |
138 | template<typename _Iter> |
139 | reverse_iterator(const reverse_iterator<_Iter>& __x) |
140 | : current(__x.base()) { } |
141 | |
142 | /** |
143 | * @return @c current, the %iterator used for underlying work. |
144 | */ |
145 | iterator_type |
146 | base() const |
147 | { return current; } |
148 | |
149 | /** |
150 | * @return A reference to the value at @c --current |
151 | * |
152 | * This requires that @c --current is dereferenceable. |
153 | * |
154 | * @warning This implementation requires that for an iterator of the |
155 | * underlying iterator type, @c x, a reference obtained by |
156 | * @c *x remains valid after @c x has been modified or |
157 | * destroyed. This is a bug: http://gcc.gnu.org/PR51823 |
158 | */ |
159 | reference |
160 | operator*() const |
161 | { |
162 | _Iterator __tmp = current; |
163 | return *--__tmp; |
164 | } |
165 | |
166 | /** |
167 | * @return A pointer to the value at @c --current |
168 | * |
169 | * This requires that @c --current is dereferenceable. |
170 | */ |
171 | pointer |
172 | operator->() const |
173 | { return &(operator*()); } |
174 | |
175 | /** |
176 | * @return @c *this |
177 | * |
178 | * Decrements the underlying iterator. |
179 | */ |
180 | reverse_iterator& |
181 | operator++() |
182 | { |
183 | --current; |
184 | return *this; |
185 | } |
186 | |
187 | /** |
188 | * @return The original value of @c *this |
189 | * |
190 | * Decrements the underlying iterator. |
191 | */ |
192 | reverse_iterator |
193 | operator++(int) |
194 | { |
195 | reverse_iterator __tmp = *this; |
196 | --current; |
197 | return __tmp; |
198 | } |
199 | |
200 | /** |
201 | * @return @c *this |
202 | * |
203 | * Increments the underlying iterator. |
204 | */ |
205 | reverse_iterator& |
206 | operator--() |
207 | { |
208 | ++current; |
209 | return *this; |
210 | } |
211 | |
212 | /** |
213 | * @return A reverse_iterator with the previous value of @c *this |
214 | * |
215 | * Increments the underlying iterator. |
216 | */ |
217 | reverse_iterator |
218 | operator--(int) |
219 | { |
220 | reverse_iterator __tmp = *this; |
221 | ++current; |
222 | return __tmp; |
223 | } |
224 | |
225 | /** |
226 | * @return A reverse_iterator that refers to @c current - @a __n |
227 | * |
228 | * The underlying iterator must be a Random Access Iterator. |
229 | */ |
230 | reverse_iterator |
231 | operator+(difference_type __n) const |
232 | { return reverse_iterator(current - __n); } |
233 | |
234 | /** |
235 | * @return *this |
236 | * |
237 | * Moves the underlying iterator backwards @a __n steps. |
238 | * The underlying iterator must be a Random Access Iterator. |
239 | */ |
240 | reverse_iterator& |
241 | operator+=(difference_type __n) |
242 | { |
243 | current -= __n; |
244 | return *this; |
245 | } |
246 | |
247 | /** |
248 | * @return A reverse_iterator that refers to @c current - @a __n |
249 | * |
250 | * The underlying iterator must be a Random Access Iterator. |
251 | */ |
252 | reverse_iterator |
253 | operator-(difference_type __n) const |
254 | { return reverse_iterator(current + __n); } |
255 | |
256 | /** |
257 | * @return *this |
258 | * |
259 | * Moves the underlying iterator forwards @a __n steps. |
260 | * The underlying iterator must be a Random Access Iterator. |
261 | */ |
262 | reverse_iterator& |
263 | operator-=(difference_type __n) |
264 | { |
265 | current += __n; |
266 | return *this; |
267 | } |
268 | |
269 | /** |
270 | * @return The value at @c current - @a __n - 1 |
271 | * |
272 | * The underlying iterator must be a Random Access Iterator. |
273 | */ |
274 | reference |
275 | operator[](difference_type __n) const |
276 | { return *(*this + __n); } |
277 | }; |
278 | |
279 | //@{ |
280 | /** |
281 | * @param __x A %reverse_iterator. |
282 | * @param __y A %reverse_iterator. |
283 | * @return A simple bool. |
284 | * |
285 | * Reverse iterators forward many operations to their underlying base() |
286 | * iterators. Others are implemented in terms of one another. |
287 | * |
288 | */ |
289 | template<typename _Iterator> |
290 | inline bool |
291 | operator==(const reverse_iterator<_Iterator>& __x, |
292 | const reverse_iterator<_Iterator>& __y) |
293 | { return __x.base() == __y.base(); } |
294 | |
295 | template<typename _Iterator> |
296 | inline bool |
297 | operator<(const reverse_iterator<_Iterator>& __x, |
298 | const reverse_iterator<_Iterator>& __y) |
299 | { return __y.base() < __x.base(); } |
300 | |
301 | template<typename _Iterator> |
302 | inline bool |
303 | operator!=(const reverse_iterator<_Iterator>& __x, |
304 | const reverse_iterator<_Iterator>& __y) |
305 | { return !(__x == __y); } |
306 | |
307 | template<typename _Iterator> |
308 | inline bool |
309 | operator>(const reverse_iterator<_Iterator>& __x, |
310 | const reverse_iterator<_Iterator>& __y) |
311 | { return __y < __x; } |
312 | |
313 | template<typename _Iterator> |
314 | inline bool |
315 | operator<=(const reverse_iterator<_Iterator>& __x, |
316 | const reverse_iterator<_Iterator>& __y) |
317 | { return !(__y < __x); } |
318 | |
319 | template<typename _Iterator> |
320 | inline bool |
321 | operator>=(const reverse_iterator<_Iterator>& __x, |
322 | const reverse_iterator<_Iterator>& __y) |
323 | { return !(__x < __y); } |
324 | |
325 | template<typename _Iterator> |
326 | inline typename reverse_iterator<_Iterator>::difference_type |
327 | operator-(const reverse_iterator<_Iterator>& __x, |
328 | const reverse_iterator<_Iterator>& __y) |
329 | { return __y.base() - __x.base(); } |
330 | |
331 | template<typename _Iterator> |
332 | inline reverse_iterator<_Iterator> |
333 | operator+(typename reverse_iterator<_Iterator>::difference_type __n, |
334 | const reverse_iterator<_Iterator>& __x) |
335 | { return reverse_iterator<_Iterator>(__x.base() - __n); } |
336 | |
337 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
338 | // DR 280. Comparison of reverse_iterator to const reverse_iterator. |
339 | template<typename _IteratorL, typename _IteratorR> |
340 | inline bool |
341 | operator==(const reverse_iterator<_IteratorL>& __x, |
342 | const reverse_iterator<_IteratorR>& __y) |
343 | { return __x.base() == __y.base(); } |
344 | |
345 | template<typename _IteratorL, typename _IteratorR> |
346 | inline bool |
347 | operator<(const reverse_iterator<_IteratorL>& __x, |
348 | const reverse_iterator<_IteratorR>& __y) |
349 | { return __y.base() < __x.base(); } |
350 | |
351 | template<typename _IteratorL, typename _IteratorR> |
352 | inline bool |
353 | operator!=(const reverse_iterator<_IteratorL>& __x, |
354 | const reverse_iterator<_IteratorR>& __y) |
355 | { return !(__x == __y); } |
356 | |
357 | template<typename _IteratorL, typename _IteratorR> |
358 | inline bool |
359 | operator>(const reverse_iterator<_IteratorL>& __x, |
360 | const reverse_iterator<_IteratorR>& __y) |
361 | { return __y < __x; } |
362 | |
363 | template<typename _IteratorL, typename _IteratorR> |
364 | inline bool |
365 | operator<=(const reverse_iterator<_IteratorL>& __x, |
366 | const reverse_iterator<_IteratorR>& __y) |
367 | { return !(__y < __x); } |
368 | |
369 | template<typename _IteratorL, typename _IteratorR> |
370 | inline bool |
371 | operator>=(const reverse_iterator<_IteratorL>& __x, |
372 | const reverse_iterator<_IteratorR>& __y) |
373 | { return !(__x < __y); } |
374 | |
375 | template<typename _IteratorL, typename _IteratorR> |
376 | #if __cplusplus201103L >= 201103L |
377 | // DR 685. |
378 | inline auto |
379 | operator-(const reverse_iterator<_IteratorL>& __x, |
380 | const reverse_iterator<_IteratorR>& __y) |
381 | -> decltype(__y.base() - __x.base()) |
382 | #else |
383 | inline typename reverse_iterator<_IteratorL>::difference_type |
384 | operator-(const reverse_iterator<_IteratorL>& __x, |
385 | const reverse_iterator<_IteratorR>& __y) |
386 | #endif |
387 | { return __y.base() - __x.base(); } |
388 | //@} |
389 | |
390 | // 24.4.2.2.1 back_insert_iterator |
391 | /** |
392 | * @brief Turns assignment into insertion. |
393 | * |
394 | * These are output iterators, constructed from a container-of-T. |
395 | * Assigning a T to the iterator appends it to the container using |
396 | * push_back. |
397 | * |
398 | * Tip: Using the back_inserter function to create these iterators can |
399 | * save typing. |
400 | */ |
401 | template<typename _Container> |
402 | class back_insert_iterator |
403 | : public iterator<output_iterator_tag, void, void, void, void> |
404 | { |
405 | protected: |
406 | _Container* container; |
407 | |
408 | public: |
409 | /// A nested typedef for the type of whatever container you used. |
410 | typedef _Container container_type; |
411 | |
412 | /// The only way to create this %iterator is with a container. |
413 | explicit |
414 | back_insert_iterator(_Container& __x) : container(&__x) { } |
415 | |
416 | /** |
417 | * @param __value An instance of whatever type |
418 | * container_type::const_reference is; presumably a |
419 | * reference-to-const T for container<T>. |
420 | * @return This %iterator, for chained operations. |
421 | * |
422 | * This kind of %iterator doesn't really have a @a position in the |
423 | * container (you can think of the position as being permanently at |
424 | * the end, if you like). Assigning a value to the %iterator will |
425 | * always append the value to the end of the container. |
426 | */ |
427 | #if __cplusplus201103L < 201103L |
428 | back_insert_iterator& |
429 | operator=(typename _Container::const_reference __value) |
430 | { |
431 | container->push_back(__value); |
432 | return *this; |
433 | } |
434 | #else |
435 | back_insert_iterator& |
436 | operator=(const typename _Container::value_type& __value) |
437 | { |
438 | container->push_back(__value); |
439 | return *this; |
440 | } |
441 | |
442 | back_insert_iterator& |
443 | operator=(typename _Container::value_type&& __value) |
444 | { |
445 | container->push_back(std::move(__value)); |
446 | return *this; |
447 | } |
448 | #endif |
449 | |
450 | /// Simply returns *this. |
451 | back_insert_iterator& |
452 | operator*() |
453 | { return *this; } |
454 | |
455 | /// Simply returns *this. (This %iterator does not @a move.) |
456 | back_insert_iterator& |
457 | operator++() |
458 | { return *this; } |
459 | |
460 | /// Simply returns *this. (This %iterator does not @a move.) |
461 | back_insert_iterator |
462 | operator++(int) |
463 | { return *this; } |
464 | }; |
465 | |
466 | /** |
467 | * @param __x A container of arbitrary type. |
468 | * @return An instance of back_insert_iterator working on @p __x. |
469 | * |
470 | * This wrapper function helps in creating back_insert_iterator instances. |
471 | * Typing the name of the %iterator requires knowing the precise full |
472 | * type of the container, which can be tedious and impedes generic |
473 | * programming. Using this function lets you take advantage of automatic |
474 | * template parameter deduction, making the compiler match the correct |
475 | * types for you. |
476 | */ |
477 | template<typename _Container> |
478 | inline back_insert_iterator<_Container> |
479 | back_inserter(_Container& __x) |
480 | { return back_insert_iterator<_Container>(__x); } |
481 | |
482 | /** |
483 | * @brief Turns assignment into insertion. |
484 | * |
485 | * These are output iterators, constructed from a container-of-T. |
486 | * Assigning a T to the iterator prepends it to the container using |
487 | * push_front. |
488 | * |
489 | * Tip: Using the front_inserter function to create these iterators can |
490 | * save typing. |
491 | */ |
492 | template<typename _Container> |
493 | class front_insert_iterator |
494 | : public iterator<output_iterator_tag, void, void, void, void> |
495 | { |
496 | protected: |
497 | _Container* container; |
498 | |
499 | public: |
500 | /// A nested typedef for the type of whatever container you used. |
501 | typedef _Container container_type; |
502 | |
503 | /// The only way to create this %iterator is with a container. |
504 | explicit front_insert_iterator(_Container& __x) : container(&__x) { } |
505 | |
506 | /** |
507 | * @param __value An instance of whatever type |
508 | * container_type::const_reference is; presumably a |
509 | * reference-to-const T for container<T>. |
510 | * @return This %iterator, for chained operations. |
511 | * |
512 | * This kind of %iterator doesn't really have a @a position in the |
513 | * container (you can think of the position as being permanently at |
514 | * the front, if you like). Assigning a value to the %iterator will |
515 | * always prepend the value to the front of the container. |
516 | */ |
517 | #if __cplusplus201103L < 201103L |
518 | front_insert_iterator& |
519 | operator=(typename _Container::const_reference __value) |
520 | { |
521 | container->push_front(__value); |
522 | return *this; |
523 | } |
524 | #else |
525 | front_insert_iterator& |
526 | operator=(const typename _Container::value_type& __value) |
527 | { |
528 | container->push_front(__value); |
529 | return *this; |
530 | } |
531 | |
532 | front_insert_iterator& |
533 | operator=(typename _Container::value_type&& __value) |
534 | { |
535 | container->push_front(std::move(__value)); |
536 | return *this; |
537 | } |
538 | #endif |
539 | |
540 | /// Simply returns *this. |
541 | front_insert_iterator& |
542 | operator*() |
543 | { return *this; } |
544 | |
545 | /// Simply returns *this. (This %iterator does not @a move.) |
546 | front_insert_iterator& |
547 | operator++() |
548 | { return *this; } |
549 | |
550 | /// Simply returns *this. (This %iterator does not @a move.) |
551 | front_insert_iterator |
552 | operator++(int) |
553 | { return *this; } |
554 | }; |
555 | |
556 | /** |
557 | * @param __x A container of arbitrary type. |
558 | * @return An instance of front_insert_iterator working on @p x. |
559 | * |
560 | * This wrapper function helps in creating front_insert_iterator instances. |
561 | * Typing the name of the %iterator requires knowing the precise full |
562 | * type of the container, which can be tedious and impedes generic |
563 | * programming. Using this function lets you take advantage of automatic |
564 | * template parameter deduction, making the compiler match the correct |
565 | * types for you. |
566 | */ |
567 | template<typename _Container> |
568 | inline front_insert_iterator<_Container> |
569 | front_inserter(_Container& __x) |
570 | { return front_insert_iterator<_Container>(__x); } |
571 | |
572 | /** |
573 | * @brief Turns assignment into insertion. |
574 | * |
575 | * These are output iterators, constructed from a container-of-T. |
576 | * Assigning a T to the iterator inserts it in the container at the |
577 | * %iterator's position, rather than overwriting the value at that |
578 | * position. |
579 | * |
580 | * (Sequences will actually insert a @e copy of the value before the |
581 | * %iterator's position.) |
582 | * |
583 | * Tip: Using the inserter function to create these iterators can |
584 | * save typing. |
585 | */ |
586 | template<typename _Container> |
587 | class insert_iterator |
588 | : public iterator<output_iterator_tag, void, void, void, void> |
589 | { |
590 | protected: |
591 | _Container* container; |
592 | typename _Container::iterator iter; |
593 | |
594 | public: |
595 | /// A nested typedef for the type of whatever container you used. |
596 | typedef _Container container_type; |
597 | |
598 | /** |
599 | * The only way to create this %iterator is with a container and an |
600 | * initial position (a normal %iterator into the container). |
601 | */ |
602 | insert_iterator(_Container& __x, typename _Container::iterator __i) |
603 | : container(&__x), iter(__i) {} |
604 | |
605 | /** |
606 | * @param __value An instance of whatever type |
607 | * container_type::const_reference is; presumably a |
608 | * reference-to-const T for container<T>. |
609 | * @return This %iterator, for chained operations. |
610 | * |
611 | * This kind of %iterator maintains its own position in the |
612 | * container. Assigning a value to the %iterator will insert the |
613 | * value into the container at the place before the %iterator. |
614 | * |
615 | * The position is maintained such that subsequent assignments will |
616 | * insert values immediately after one another. For example, |
617 | * @code |
618 | * // vector v contains A and Z |
619 | * |
620 | * insert_iterator i (v, ++v.begin()); |
621 | * i = 1; |
622 | * i = 2; |
623 | * i = 3; |
624 | * |
625 | * // vector v contains A, 1, 2, 3, and Z |
626 | * @endcode |
627 | */ |
628 | #if __cplusplus201103L < 201103L |
629 | insert_iterator& |
630 | operator=(typename _Container::const_reference __value) |
631 | { |
632 | iter = container->insert(iter, __value); |
633 | ++iter; |
634 | return *this; |
635 | } |
636 | #else |
637 | insert_iterator& |
638 | operator=(const typename _Container::value_type& __value) |
639 | { |
640 | iter = container->insert(iter, __value); |
641 | ++iter; |
642 | return *this; |
643 | } |
644 | |
645 | insert_iterator& |
646 | operator=(typename _Container::value_type&& __value) |
647 | { |
648 | iter = container->insert(iter, std::move(__value)); |
649 | ++iter; |
650 | return *this; |
651 | } |
652 | #endif |
653 | |
654 | /// Simply returns *this. |
655 | insert_iterator& |
656 | operator*() |
657 | { return *this; } |
658 | |
659 | /// Simply returns *this. (This %iterator does not @a move.) |
660 | insert_iterator& |
661 | operator++() |
662 | { return *this; } |
663 | |
664 | /// Simply returns *this. (This %iterator does not @a move.) |
665 | insert_iterator& |
666 | operator++(int) |
667 | { return *this; } |
668 | }; |
669 | |
670 | /** |
671 | * @param __x A container of arbitrary type. |
672 | * @return An instance of insert_iterator working on @p __x. |
673 | * |
674 | * This wrapper function helps in creating insert_iterator instances. |
675 | * Typing the name of the %iterator requires knowing the precise full |
676 | * type of the container, which can be tedious and impedes generic |
677 | * programming. Using this function lets you take advantage of automatic |
678 | * template parameter deduction, making the compiler match the correct |
679 | * types for you. |
680 | */ |
681 | template<typename _Container, typename _Iterator> |
682 | inline insert_iterator<_Container> |
683 | inserter(_Container& __x, _Iterator __i) |
684 | { |
685 | return insert_iterator<_Container>(__x, |
686 | typename _Container::iterator(__i)); |
687 | } |
688 | |
689 | // @} group iterators |
690 | |
691 | _GLIBCXX_END_NAMESPACE_VERSION |
692 | } // namespace |
693 | |
694 | namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default"))) |
695 | { |
696 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
697 | |
698 | // This iterator adapter is @a normal in the sense that it does not |
699 | // change the semantics of any of the operators of its iterator |
700 | // parameter. Its primary purpose is to convert an iterator that is |
701 | // not a class, e.g. a pointer, into an iterator that is a class. |
702 | // The _Container parameter exists solely so that different containers |
703 | // using this template can instantiate different types, even if the |
704 | // _Iterator parameter is the same. |
705 | using std::iterator_traits; |
706 | using std::iterator; |
707 | template<typename _Iterator, typename _Container> |
708 | class __normal_iterator |
709 | { |
710 | protected: |
711 | _Iterator _M_current; |
712 | |
713 | typedef iterator_traits<_Iterator> __traits_type; |
714 | |
715 | public: |
716 | typedef _Iterator iterator_type; |
717 | typedef typename __traits_type::iterator_category iterator_category; |
718 | typedef typename __traits_type::value_type value_type; |
719 | typedef typename __traits_type::difference_type difference_type; |
720 | typedef typename __traits_type::reference reference; |
721 | typedef typename __traits_type::pointer pointer; |
722 | |
723 | _GLIBCXX_CONSTEXPRconstexpr __normal_iterator() : _M_current(_Iterator()) { } |
724 | |
725 | explicit |
726 | __normal_iterator(const _Iterator& __i) : _M_current(__i) { } |
727 | |
728 | // Allow iterator to const_iterator conversion |
729 | template<typename _Iter> |
730 | __normal_iterator(const __normal_iterator<_Iter, |
731 | typename __enable_if< |
732 | (std::__are_same<_Iter, typename _Container::pointer>::__value), |
733 | _Container>::__type>& __i) |
734 | : _M_current(__i.base()) { } |
735 | |
736 | // Forward iterator requirements |
737 | reference |
738 | operator*() const |
739 | { return *_M_current; } |
740 | |
741 | pointer |
742 | operator->() const |
743 | { return _M_current; } |
744 | |
745 | __normal_iterator& |
746 | operator++() |
747 | { |
748 | ++_M_current; |
749 | return *this; |
750 | } |
751 | |
752 | __normal_iterator |
753 | operator++(int) |
754 | { return __normal_iterator(_M_current++); } |
755 | |
756 | // Bidirectional iterator requirements |
757 | __normal_iterator& |
758 | operator--() |
759 | { |
760 | --_M_current; |
761 | return *this; |
762 | } |
763 | |
764 | __normal_iterator |
765 | operator--(int) |
766 | { return __normal_iterator(_M_current--); } |
767 | |
768 | // Random access iterator requirements |
769 | reference |
770 | operator[](const difference_type& __n) const |
771 | { return _M_current[__n]; } |
772 | |
773 | __normal_iterator& |
774 | operator+=(const difference_type& __n) |
775 | { _M_current += __n; return *this; } |
776 | |
777 | __normal_iterator |
778 | operator+(const difference_type& __n) const |
779 | { return __normal_iterator(_M_current + __n); } |
780 | |
781 | __normal_iterator& |
782 | operator-=(const difference_type& __n) |
783 | { _M_current -= __n; return *this; } |
784 | |
785 | __normal_iterator |
786 | operator-(const difference_type& __n) const |
787 | { return __normal_iterator(_M_current - __n); } |
788 | |
789 | const _Iterator& |
790 | base() const |
791 | { return _M_current; } |
792 | }; |
793 | |
794 | // Note: In what follows, the left- and right-hand-side iterators are |
795 | // allowed to vary in types (conceptually in cv-qualification) so that |
796 | // comparison between cv-qualified and non-cv-qualified iterators be |
797 | // valid. However, the greedy and unfriendly operators in std::rel_ops |
798 | // will make overload resolution ambiguous (when in scope) if we don't |
799 | // provide overloads whose operands are of the same type. Can someone |
800 | // remind me what generic programming is about? -- Gaby |
801 | |
802 | // Forward iterator requirements |
803 | template<typename _IteratorL, typename _IteratorR, typename _Container> |
804 | inline bool |
805 | operator==(const __normal_iterator<_IteratorL, _Container>& __lhs, |
806 | const __normal_iterator<_IteratorR, _Container>& __rhs) |
807 | { return __lhs.base() == __rhs.base(); } |
808 | |
809 | template<typename _Iterator, typename _Container> |
810 | inline bool |
811 | operator==(const __normal_iterator<_Iterator, _Container>& __lhs, |
812 | const __normal_iterator<_Iterator, _Container>& __rhs) |
813 | { return __lhs.base() == __rhs.base(); } |
814 | |
815 | template<typename _IteratorL, typename _IteratorR, typename _Container> |
816 | inline bool |
817 | operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs, |
818 | const __normal_iterator<_IteratorR, _Container>& __rhs) |
819 | { return __lhs.base() != __rhs.base(); } |
820 | |
821 | template<typename _Iterator, typename _Container> |
822 | inline bool |
823 | operator!=(const __normal_iterator<_Iterator, _Container>& __lhs, |
824 | const __normal_iterator<_Iterator, _Container>& __rhs) |
825 | { return __lhs.base() != __rhs.base(); } |
826 | |
827 | // Random access iterator requirements |
828 | template<typename _IteratorL, typename _IteratorR, typename _Container> |
829 | inline bool |
830 | operator<(const __normal_iterator<_IteratorL, _Container>& __lhs, |
831 | const __normal_iterator<_IteratorR, _Container>& __rhs) |
832 | { return __lhs.base() < __rhs.base(); } |
833 | |
834 | template<typename _Iterator, typename _Container> |
835 | inline bool |
836 | operator<(const __normal_iterator<_Iterator, _Container>& __lhs, |
837 | const __normal_iterator<_Iterator, _Container>& __rhs) |
838 | { return __lhs.base() < __rhs.base(); } |
839 | |
840 | template<typename _IteratorL, typename _IteratorR, typename _Container> |
841 | inline bool |
842 | operator>(const __normal_iterator<_IteratorL, _Container>& __lhs, |
843 | const __normal_iterator<_IteratorR, _Container>& __rhs) |
844 | { return __lhs.base() > __rhs.base(); } |
845 | |
846 | template<typename _Iterator, typename _Container> |
847 | inline bool |
848 | operator>(const __normal_iterator<_Iterator, _Container>& __lhs, |
849 | const __normal_iterator<_Iterator, _Container>& __rhs) |
850 | { return __lhs.base() > __rhs.base(); } |
851 | |
852 | template<typename _IteratorL, typename _IteratorR, typename _Container> |
853 | inline bool |
854 | operator<=(const __normal_iterator<_IteratorL, _Container>& __lhs, |
855 | const __normal_iterator<_IteratorR, _Container>& __rhs) |
856 | { return __lhs.base() <= __rhs.base(); } |
857 | |
858 | template<typename _Iterator, typename _Container> |
859 | inline bool |
860 | operator<=(const __normal_iterator<_Iterator, _Container>& __lhs, |
861 | const __normal_iterator<_Iterator, _Container>& __rhs) |
862 | { return __lhs.base() <= __rhs.base(); } |
863 | |
864 | template<typename _IteratorL, typename _IteratorR, typename _Container> |
865 | inline bool |
866 | operator>=(const __normal_iterator<_IteratorL, _Container>& __lhs, |
867 | const __normal_iterator<_IteratorR, _Container>& __rhs) |
868 | { return __lhs.base() >= __rhs.base(); } |
869 | |
870 | template<typename _Iterator, typename _Container> |
871 | inline bool |
872 | operator>=(const __normal_iterator<_Iterator, _Container>& __lhs, |
873 | const __normal_iterator<_Iterator, _Container>& __rhs) |
874 | { return __lhs.base() >= __rhs.base(); } |
875 | |
876 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
877 | // According to the resolution of DR179 not only the various comparison |
878 | // operators but also operator- must accept mixed iterator/const_iterator |
879 | // parameters. |
880 | template<typename _IteratorL, typename _IteratorR, typename _Container> |
881 | #if __cplusplus201103L >= 201103L |
882 | // DR 685. |
883 | inline auto |
884 | operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, |
885 | const __normal_iterator<_IteratorR, _Container>& __rhs) |
886 | -> decltype(__lhs.base() - __rhs.base()) |
887 | #else |
888 | inline typename __normal_iterator<_IteratorL, _Container>::difference_type |
889 | operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, |
890 | const __normal_iterator<_IteratorR, _Container>& __rhs) |
891 | #endif |
892 | { return __lhs.base() - __rhs.base(); } |
893 | |
894 | template<typename _Iterator, typename _Container> |
895 | inline typename __normal_iterator<_Iterator, _Container>::difference_type |
896 | operator-(const __normal_iterator<_Iterator, _Container>& __lhs, |
897 | const __normal_iterator<_Iterator, _Container>& __rhs) |
898 | { return __lhs.base() - __rhs.base(); } |
899 | |
900 | template<typename _Iterator, typename _Container> |
901 | inline __normal_iterator<_Iterator, _Container> |
902 | operator+(typename __normal_iterator<_Iterator, _Container>::difference_type |
903 | __n, const __normal_iterator<_Iterator, _Container>& __i) |
904 | { return __normal_iterator<_Iterator, _Container>(__i.base() + __n); } |
905 | |
906 | _GLIBCXX_END_NAMESPACE_VERSION |
907 | } // namespace |
908 | |
909 | #if __cplusplus201103L >= 201103L |
910 | |
911 | namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default"))) |
912 | { |
913 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
914 | |
915 | /** |
916 | * @addtogroup iterators |
917 | * @{ |
918 | */ |
919 | |
920 | // 24.4.3 Move iterators |
921 | /** |
922 | * Class template move_iterator is an iterator adapter with the same |
923 | * behavior as the underlying iterator except that its dereference |
924 | * operator implicitly converts the value returned by the underlying |
925 | * iterator's dereference operator to an rvalue reference. Some |
926 | * generic algorithms can be called with move iterators to replace |
927 | * copying with moving. |
928 | */ |
929 | template<typename _Iterator> |
930 | class move_iterator |
931 | { |
932 | protected: |
933 | _Iterator _M_current; |
934 | |
935 | typedef iterator_traits<_Iterator> __traits_type; |
936 | |
937 | public: |
938 | typedef _Iterator iterator_type; |
939 | typedef typename __traits_type::iterator_category iterator_category; |
940 | typedef typename __traits_type::value_type value_type; |
941 | typedef typename __traits_type::difference_type difference_type; |
942 | // NB: DR 680. |
943 | typedef _Iterator pointer; |
944 | typedef value_type&& reference; |
945 | |
946 | move_iterator() |
947 | : _M_current() { } |
948 | |
949 | explicit |
950 | move_iterator(iterator_type __i) |
951 | : _M_current(__i) { } |
952 | |
953 | template<typename _Iter> |
954 | move_iterator(const move_iterator<_Iter>& __i) |
955 | : _M_current(__i.base()) { } |
956 | |
957 | iterator_type |
958 | base() const |
959 | { return _M_current; } |
960 | |
961 | reference |
962 | operator*() const |
963 | { return std::move(*_M_current); } |
964 | |
965 | pointer |
966 | operator->() const |
967 | { return _M_current; } |
968 | |
969 | move_iterator& |
970 | operator++() |
971 | { |
972 | ++_M_current; |
973 | return *this; |
974 | } |
975 | |
976 | move_iterator |
977 | operator++(int) |
978 | { |
979 | move_iterator __tmp = *this; |
980 | ++_M_current; |
981 | return __tmp; |
982 | } |
983 | |
984 | move_iterator& |
985 | operator--() |
986 | { |
987 | --_M_current; |
988 | return *this; |
989 | } |
990 | |
991 | move_iterator |
992 | operator--(int) |
993 | { |
994 | move_iterator __tmp = *this; |
995 | --_M_current; |
996 | return __tmp; |
997 | } |
998 | |
999 | move_iterator |
1000 | operator+(difference_type __n) const |
1001 | { return move_iterator(_M_current + __n); } |
1002 | |
1003 | move_iterator& |
1004 | operator+=(difference_type __n) |
1005 | { |
1006 | _M_current += __n; |
1007 | return *this; |
1008 | } |
1009 | |
1010 | move_iterator |
1011 | operator-(difference_type __n) const |
1012 | { return move_iterator(_M_current - __n); } |
1013 | |
1014 | move_iterator& |
1015 | operator-=(difference_type __n) |
1016 | { |
1017 | _M_current -= __n; |
1018 | return *this; |
1019 | } |
1020 | |
1021 | reference |
1022 | operator[](difference_type __n) const |
1023 | { return std::move(_M_current[__n]); } |
1024 | }; |
1025 | |
1026 | // Note: See __normal_iterator operators note from Gaby to understand |
1027 | // why there are always 2 versions for most of the move_iterator |
1028 | // operators. |
1029 | template<typename _IteratorL, typename _IteratorR> |
1030 | inline bool |
1031 | operator==(const move_iterator<_IteratorL>& __x, |
1032 | const move_iterator<_IteratorR>& __y) |
1033 | { return __x.base() == __y.base(); } |
1034 | |
1035 | template<typename _Iterator> |
1036 | inline bool |
1037 | operator==(const move_iterator<_Iterator>& __x, |
1038 | const move_iterator<_Iterator>& __y) |
1039 | { return __x.base() == __y.base(); } |
1040 | |
1041 | template<typename _IteratorL, typename _IteratorR> |
1042 | inline bool |
1043 | operator!=(const move_iterator<_IteratorL>& __x, |
1044 | const move_iterator<_IteratorR>& __y) |
1045 | { return !(__x == __y); } |
1046 | |
1047 | template<typename _Iterator> |
1048 | inline bool |
1049 | operator!=(const move_iterator<_Iterator>& __x, |
1050 | const move_iterator<_Iterator>& __y) |
1051 | { return !(__x == __y); } |
1052 | |
1053 | template<typename _IteratorL, typename _IteratorR> |
1054 | inline bool |
1055 | operator<(const move_iterator<_IteratorL>& __x, |
1056 | const move_iterator<_IteratorR>& __y) |
1057 | { return __x.base() < __y.base(); } |
1058 | |
1059 | template<typename _Iterator> |
1060 | inline bool |
1061 | operator<(const move_iterator<_Iterator>& __x, |
1062 | const move_iterator<_Iterator>& __y) |
1063 | { return __x.base() < __y.base(); } |
1064 | |
1065 | template<typename _IteratorL, typename _IteratorR> |
1066 | inline bool |
1067 | operator<=(const move_iterator<_IteratorL>& __x, |
1068 | const move_iterator<_IteratorR>& __y) |
1069 | { return !(__y < __x); } |
1070 | |
1071 | template<typename _Iterator> |
1072 | inline bool |
1073 | operator<=(const move_iterator<_Iterator>& __x, |
1074 | const move_iterator<_Iterator>& __y) |
1075 | { return !(__y < __x); } |
1076 | |
1077 | template<typename _IteratorL, typename _IteratorR> |
1078 | inline bool |
1079 | operator>(const move_iterator<_IteratorL>& __x, |
1080 | const move_iterator<_IteratorR>& __y) |
1081 | { return __y < __x; } |
1082 | |
1083 | template<typename _Iterator> |
1084 | inline bool |
1085 | operator>(const move_iterator<_Iterator>& __x, |
1086 | const move_iterator<_Iterator>& __y) |
1087 | { return __y < __x; } |
1088 | |
1089 | template<typename _IteratorL, typename _IteratorR> |
1090 | inline bool |
1091 | operator>=(const move_iterator<_IteratorL>& __x, |
1092 | const move_iterator<_IteratorR>& __y) |
1093 | { return !(__x < __y); } |
1094 | |
1095 | template<typename _Iterator> |
1096 | inline bool |
1097 | operator>=(const move_iterator<_Iterator>& __x, |
1098 | const move_iterator<_Iterator>& __y) |
1099 | { return !(__x < __y); } |
1100 | |
1101 | // DR 685. |
1102 | template<typename _IteratorL, typename _IteratorR> |
1103 | inline auto |
1104 | operator-(const move_iterator<_IteratorL>& __x, |
1105 | const move_iterator<_IteratorR>& __y) |
1106 | -> decltype(__x.base() - __y.base()) |
1107 | { return __x.base() - __y.base(); } |
1108 | |
1109 | template<typename _Iterator> |
1110 | inline auto |
1111 | operator-(const move_iterator<_Iterator>& __x, |
1112 | const move_iterator<_Iterator>& __y) |
1113 | -> decltype(__x.base() - __y.base()) |
1114 | { return __x.base() - __y.base(); } |
1115 | |
1116 | template<typename _Iterator> |
1117 | inline move_iterator<_Iterator> |
1118 | operator+(typename move_iterator<_Iterator>::difference_type __n, |
1119 | const move_iterator<_Iterator>& __x) |
1120 | { return __x + __n; } |
1121 | |
1122 | template<typename _Iterator> |
1123 | inline move_iterator<_Iterator> |
1124 | make_move_iterator(_Iterator __i) |
1125 | { return move_iterator<_Iterator>(__i); } |
1126 | |
1127 | template<typename _Iterator, typename _ReturnType |
1128 | = typename conditional<__move_if_noexcept_cond |
1129 | <typename iterator_traits<_Iterator>::value_type>::value, |
1130 | _Iterator, move_iterator<_Iterator>>::type> |
1131 | inline _ReturnType |
1132 | __make_move_if_noexcept_iterator(_Iterator __i) |
1133 | { return _ReturnType(__i); } |
1134 | |
1135 | // @} group iterators |
1136 | |
1137 | _GLIBCXX_END_NAMESPACE_VERSION |
1138 | } // namespace |
1139 | |
1140 | #define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter)std::make_move_iterator(_Iter) std::make_move_iterator(_Iter) |
1141 | #define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter)std::__make_move_if_noexcept_iterator(_Iter) \ |
1142 | std::__make_move_if_noexcept_iterator(_Iter) |
1143 | #else |
1144 | #define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter)std::make_move_iterator(_Iter) (_Iter) |
1145 | #define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter)std::__make_move_if_noexcept_iterator(_Iter) (_Iter) |
1146 | #endif // C++11 |
1147 | |
1148 | #endif |