1 package org.lcsim.fit.circle;
2
3
4
5
6
7
8 public class CircleFitter
9 {
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 private double _xref;
44 private double _yref;
45
46 private double _rho;
47 private double _phi;
48 private double _dca;
49 private double _chicir;
50
51 private double _xpca;
52 private double _ypca;
53 private double [] _covrfd;
54 private double _xx0;
55 private double _yy0;
56 private double S1, S2, S3, S4, S5, S6, S7, S8, S9;
57
58
59
60
61 public CircleFitter()
62 {
63 _xref=0.;
64 _yref=0.;
65
66 _covrfd = new double[6];
67 }
68
69
70
71
72
73
74 public void setreferenceposition( double xref, double yref)
75 {
76 _xref = xref;
77 _yref = yref;
78 }
79
80
81
82
83
84
85
86
87
88 public boolean fit(double[] XX, double[] YY, double[] WW, int NP)
89 {
90
91
92
93 double SR,HSR,S1I,XMEAN,YMEAN,RRMEAN,XC,YC,WT,WX,WY,RR,WR;
94 double COV1,COV2,COV3,COV4,COV5,COV6,Y2FI,X2FI,HAPFIT,DELFIT,RHOF,DFT;
95 double FIFIT,SINF,COSF,SA,SB,SG,SAA,APU,SXYR,ROD1,ROD2,SINF2,COSF2,SIN;
96
97
98 if(NP<3) return false;
99
100 S1=0.;
101 S2=0.;
102 S3=0.;
103 S4=0.;
104 S5=0.;
105 S6=0.;
106 S7=0.;
107 S8=0.;
108 S9=0.;
109
110
111 int M3=NP/3;
112
113 _xx0=XX[M3];
114 _yy0=YY[M3];
115
116 double DIRTX=_xx0-XX[0];
117 double DIRTY=_yy0-YY[0];
118
119
120
121
122
123
124
125 for(int IP = 0; IP<NP; ++IP)
126 {
127 XC=XX[IP]-_xx0;
128 YC=YY[IP]-_yy0;
129 WT=WW[IP];
130 WX=WT*XC;
131 WY=WT*YC;
132 RR=XC*XC+YC*YC;
133 WR=WT*RR;
134 S1+=WT;
135 S2+=WX;
136 S3+=WY;
137 S4+=WX*XC;
138 S5+=WX*YC;
139 S6+=WY*YC;
140 S7+=WX*RR;
141 S8+=WY*RR;
142 S9+=WR*RR;
143 }
144 if(S1<0.) return false;
145
146
147
148 S1I=1./S1;
149 SR=S4+S6;
150 HSR=0.5*SR;
151 XMEAN=S1I*S2;
152 YMEAN=S1I*S3;
153 RRMEAN=S1I*SR;
154 COV1=S1I*(S4-S2*XMEAN);
155 COV2=S1I*(S5-S2*YMEAN);
156 COV3=S1I*(S6-S3*YMEAN);
157 COV4=S1I*(S7-S2*RRMEAN);
158 COV5=S1I*(S8-S3*RRMEAN);
159 COV6=S1I*(S9-SR*RRMEAN);
160 if(COV6<0.) return false;
161 Y2FI=2.*(COV2*COV6-COV4*COV5);
162 X2FI=COV6*(COV1-COV3)-COV4*COV4+COV5*COV5;
163 FIFIT=0.5*Math.atan2(Y2FI,X2FI);
164 COSF=Math.cos(FIFIT);
165 SINF=Math.sin(FIFIT);
166 HAPFIT=(SINF*COV4-COSF*COV5)/COV6;
167 DELFIT=-HAPFIT*RRMEAN+SINF*XMEAN-COSF*YMEAN;
168 APU=Math.sqrt(1.-4.*HAPFIT*DELFIT);
169 RHOF=2.*HAPFIT/APU;
170 DFT=2.*DELFIT/(1.+APU);
171 ROD1=1./APU;
172 ROD2=ROD1*ROD1;
173 SINF2=SINF*SINF;
174 COSF2=COSF*COSF;
175 double SINFF=2.*SINF*COSF;
176 SA=SINF*S2-COSF*S3;
177 SAA=SINF2*S4-SINFF*S5+COSF2*S6;
178 SXYR=SINF*S7-COSF*S8;
179
180 _rho=RHOF;
181 _phi=FIFIT;
182 _dca=DFT;
183 _chicir=ROD2*(-DELFIT*SA-HAPFIT*SXYR+SAA);
184 _xpca=_xx0+_dca*SINF;
185 _ypca=_yy0-_dca*COSF;
186
187
188
189
190 SB=COSF*S2+SINF*S3;
191 SG=(SINF2-COSF2)*S5+SINF*COSF*(S4-S6);
192 double W1=.25*S9-DFT*(SXYR-DFT*(SAA+HSR-DFT*(SA-.25*DFT*S1)));
193 double W2=-ROD1*(0.5*(COSF*S7+SINF*S8)-DFT*(SG-0.5*DFT*SB));
194 double W3=ROD2*(COSF2*S4+SINFF*S5+SINF2*S6);
195 double W4=RHOF*(-0.5*SXYR+DFT*SAA)+ROD1*HSR-0.5*DFT*((2.*ROD1+RHOF*DFT)*SA-DFT*ROD1*S1);
196 double W5=ROD1*RHOF*SG-ROD2*SB;
197 double W6=RHOF*(RHOF*SAA-2.*ROD1*SA)+ROD2*S1;
198 double SD1=W3*W6-W5*W5;
199 double SD2=-W2*W6+W4*W5;
200 double SD3=W2*W5-W3*W4;
201 double DETINV=1./(W1*SD1+W2*SD2+W4*SD3);
202 _covrfd[0]=DETINV*SD1;
203 _covrfd[1]=DETINV*SD2;
204 _covrfd[2]=DETINV*(W1*W6-W4*W4);
205 _covrfd[3]=DETINV*SD3;
206 _covrfd[4]=DETINV*(W2*W4-W1*W5);
207 _covrfd[5]=DETINV*(W1*W3-W2*W2);
208 double XDERO=0.5*(RHOF*SXYR-2.*ROD1*SAA+(1.+ROD1)*DFT*SA);
209 double EDERO=DFT*XDERO;
210 double EDEDI=RHOF*XDERO;
211 double DROF=_covrfd[0]*EDERO+_covrfd[3]*EDEDI;
212 double DFIF=_covrfd[1]*EDERO+_covrfd[4]*EDEDI;
213 double DDIF=_covrfd[3]*EDERO+_covrfd[5]*EDEDI;
214 _rho+=DROF;
215 _dca+=DDIF;
216 _phi+=DFIF;
217 _chicir=(1.+_rho*_dca)*(1.+_rho*_dca)*_chicir/ROD2;
218
219
220
221
222
223
224 propagate(_xref, _yref, SINF, COSF, DIRTX, DIRTY);
225 return true;
226
227 }
228
229
230
231
232
233 public CircleFit getfit()
234 {
235 return new CircleFit(_xref, _yref, _rho, _phi, _dca, _chicir, _covrfd);
236 }
237
238 void propagate(double x, double y, double SINF, double COSF, double DIRTX, double DIRTY)
239 {
240
241
242
243 double[] XJACOB = new double[9];
244 double ROD1;
245
246 setreferenceposition(x, y);
247 double XMOVE=_xpca-_xref;
248 double YMOVE=_ypca-_yref;
249 ROD1=1.+_rho*_dca;
250 double DPERP=XMOVE*SINF-YMOVE*COSF;
251 double DPARA=XMOVE*COSF+YMOVE*SINF;
252 double ZEE=DPERP*DPERP+DPARA*DPARA;
253 double AA=2.*DPERP+_rho*ZEE;
254 double UU=Math.sqrt(1.+_rho*AA);
255 double SQ1AI=1./(1.+UU);
256 double BB= _rho*XMOVE+SINF;
257 double CC=-_rho*YMOVE+COSF;
258 _phi=Math.atan2(BB,CC);
259 _dca=AA*SQ1AI;
260
261
262
263
264 double VV=1.+_rho*DPERP;
265 double XEE=1./(CC*CC+BB*BB);
266 double XLA=0.5*AA*SQ1AI*SQ1AI/UU;
267 double XMU=SQ1AI/UU+_rho*XLA;
268 XJACOB[0]=1.;
269 XJACOB[1]=0.;
270 XJACOB[2]=0.;
271 XJACOB[3]=XEE*DPARA;
272 XJACOB[4]=XEE*ROD1*VV;
273 XJACOB[5]=-XJACOB[3]*_rho*_rho;
274 XJACOB[6]=XMU*ZEE-XLA*AA;
275 XJACOB[7]=2.*XMU*ROD1*DPARA;
276 XJACOB[8]=2.*XMU*VV;
277
278 abatranspose(XJACOB,_covrfd);
279 SINF=Math.sin(_phi);
280 COSF=Math.cos(_phi);
281
282
283
284
285 double DIRTES=COSF*DIRTX+SINF*DIRTY;
286 if(DIRTES<0.)
287 {
288 _phi=_phi+Math.PI;
289 COSF=-COSF;
290 SINF=-SINF;
291 _dca= -_dca;
292 _rho= -_rho;
293 _covrfd[1]=-_covrfd[1];
294 _covrfd[4]=-_covrfd[4];
295 }
296 if(_phi>=2.*Math.PI) _phi-=2.*Math.PI;
297 if(_phi<0. ) _phi+=2.*Math.PI;
298 _xpca=_xref+_dca*SINF;
299 _ypca=_yref-_dca*COSF;
300 }
301
302
303
304
305
306
307 public CircleFit propagatefit(double x, double y)
308 {
309 double DIRTX=Math.cos(_phi);
310 double DIRTY=Math.sin(_phi) ;
311 double SINF=Math.sin(_phi);
312 double COSF=Math.cos(_phi);
313 propagate(x, y, SINF, COSF, DIRTX, DIRTY);
314 return new CircleFit(_xref, _yref, _rho, _phi, _dca, _chicir, _covrfd);
315 }
316
317 private void abatranspose(double[] A, double[] B)
318 {
319
320
321
322
323
324
325
326 double[] C = new double[6];
327 double E1, E2, E3, E4, E5, E6, E7, E8, E9;
328
329 System.arraycopy(B,0,C,0,6);
330 E1=A[0]*C[0]+A[1]*C[1]+A[2]*C[3];
331 E2=A[0]*C[1]+A[1]*C[2]+A[2]*C[4];
332 E3=A[0]*C[3]+A[1]*C[4]+A[2]*C[5];
333 E4=A[3]*C[0]+A[4]*C[1]+A[5]*C[3];
334 E5=A[3]*C[1]+A[4]*C[2]+A[5]*C[4];
335 E6=A[3]*C[3]+A[4]*C[4]+A[5]*C[5];
336 E7=A[6]*C[0]+A[7]*C[1]+A[8]*C[3];
337 E8=A[6]*C[1]+A[7]*C[2]+A[8]*C[4];
338 E9=A[6]*C[3]+A[7]*C[4]+A[8]*C[5];
339 B[0]=A[0]*E1+A[1]*E2+A[2]*E3;
340 B[1]=A[3]*E1+A[4]*E2+A[5]*E3;
341 B[2]=A[3]*E4+A[4]*E5+A[5]*E6;
342 B[3]=A[6]*E1+A[7]*E2+A[8]*E3;
343 B[4]=A[6]*E4+A[7]*E5+A[8]*E6;
344 B[5]=A[6]*E7+A[7]*E8+A[8]*E9;
345 }
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444 }
445