233{
234 bool debug = false;
235
236 int state = 0;
237
238 double tension = 9999.;
239
240 int nPar=5;
241 if(myFitCircleOnly) nPar=3;
242
243
244
245 for(int i=0; i<43; i++) myNumMdcDigiPerLayer[i]=0;
246 myNActiveHits=0;
247 myNFittedHits=0;
248 int nXHits[3]={0,0,0}, nVHits[3]={0,0,0};
249 int nDigi=myVecMdcDigi.size();
250
251 vector<double> vec_zini(nDigi);
252 int maxLayer = 0;
253 int i_digi=0;
254 vector<const MdcDigi*>::iterator iter_mdcDigi = myVecMdcDigi.begin();
255 for(; iter_mdcDigi!=myVecMdcDigi.end(); iter_mdcDigi++, i_digi++)
256 {
257
258 vec_zini[i_digi]=0;
259
263
264 if(myMdcDigiIsActive[i_digi]==1)
265 {
266 myNActiveHits++;
267
268 int hitFlag = myWireFlag[layer];
269 if(hitFlag==0)
270 {
271 nXHits[0]++;
272 nXHits[1]++;
273 }
274 else
275 {
276 nVHits[0]++;
277 nVHits[1]++;
278 }
279 }
280 if(maxLayer<layer) maxLayer=layer;
281 int nHits = myNumMdcDigiPerLayer[layer];
282 if(nHits<2) {
283 myIdxMdcDigiNeighbour[layer][nHits]=i_digi;
284 myWireIdMdcDigiNeighbour[layer][nHits]=wire;
285 }
286 myNumMdcDigiPerLayer[layer]++;
287 }
288
290 double maxRTrk = farPoint.perp();
291 for(int i=0; i<43; i++)
292 {
293 if(maxRTrk<myRWires[i]+2) break;
294 if(myNumMdcDigiPerLayer[i]==2)
295 {
296 int wire_1 = myWireIdMdcDigiNeighbour[i][0];
297 int wire_2 = myWireIdMdcDigiNeighbour[i][1];
298 int delta_n =
abs(wire_1-wire_2);
299 int ambi_1 = 0;
300 int ambi_2 = 0;
301 if(delta_n==1)
302 {
303 ambi_1 = wire_1>wire_2? 1:-1;
304 ambi_2 = wire_1>wire_2? -1:1;
305 }
306 else if(delta_n==myNWire[i]-1)
307 {
308 ambi_1 = wire_1<=1? 1:-1;
309 ambi_2 = wire_2<=1? 1:-1;
310 }
311
312
313
314
315
316
317
318
319
320
321
322 }
323 }
324 i_digi=0;
325 vector<const RecCgemCluster*>::iterator iter_cluster = myVecCgemCluster.begin();
326 for(; iter_cluster!=myVecCgemCluster.end(); iter_cluster++, i_digi++)
327 {
328 int flag = (*iter_cluster)->getflag();
329 if(flag==0)
330 {
331 nXHits[0]++;
332 nXHits[2]++;
333 }
334 else if(flag==1)
335 {
336 nVHits[0]++;
337 nVHits[2]++;
338 }
339 myNActiveHits++;
340 }
341 if(myFitCircleOnly)
342 {
343 if(nXHits[0]<myMinXhitsInCircleFit) return 1;
344 }
345 else
346 {
347 if((nXHits[0]+nVHits[0])<myMinHitsInHelixFit) return 2;
348 if(nVHits[0]<myMinVhitsInHelixFit) return 3;
349 }
350
351
352
353
354
355 double lastTotChi2 = 999999;
356 double secLastTotChi2 = 999999;
357 double thirdLastTotChi2 = 999999;
358 int nIterations = 0;
359 int n_chi2_increase = 0;
360 int n_oscillation=0;
361
362 while(1)
363 {
364 myNFittedHits=0;
365 myMapFlylenIdx.clear();
366
367 HepSymMatrix U(nPar, 0);
368
369
370
371 HepMatrix
P(nPar,1,0);
372 HepMatrix J(nPar,1,0), JT(1,nPar,0);
373 HepMatrix J_dmdx(1,3,0), J_dxda(3,nPar,0);
374
375
376 double totChi2=0;
377 i_digi=0;
378 vector<const MdcDigi*>::iterator iter_mdcDigi = myVecMdcDigi.begin();
379 for(; iter_mdcDigi!=myVecMdcDigi.end(); iter_mdcDigi++, i_digi++)
380 {
381
385 double charge = (*iter_mdcDigi)->getChargeChannel();
386
387
388
389 double wpos[7]={myEastPosWires[layer][wire][0], myEastPosWires[layer][wire][1], myEastPosWires[layer][wire][2]
390 , myWestPosWires[layer][wire][0], myWestPosWires[layer][wire][1], myWestPosWires[layer][wire][2], tension};
391 double doca_trk;
392 double whitPos[3];
393 if(debug)
394 {
395
396 cout<<"* layer "<<layer<<", wire "<<wire<<", is active "<<myMdcDigiIsActive[i_digi] <<endl;
397
398
399 }
400 getDoca(myHelix_a, wpos, doca_trk, whitPos, vec_zini[i_digi]);
401
402
403
404
405
406 int leftRight = 2;
407 if(doca_trk!=0) {
408 leftRight=int(doca_trk/fabs(doca_trk));
409 }
410
411
412
413
414
415 int signDoca=1;
416 signDoca=leftRight/fabs(leftRight);
417
418
419 if(leftRight==1) leftRight=0;
420 else leftRight=1;
421
422
423 vec_zini[i_digi] = whitPos[2];
424
425
427 double tprop = myMdcCalibFunSvc->
getTprop(layer, vec_zini[i_digi]);
428 double T0Walk = myMdcCalibFunSvc->
getT0(layer,wire) + myMdcCalibFunSvc->
getTimeWalk(layer, charge);
429
430
432 HepPoint3D aNewPivot(whitPos[0],whitPos[1],whitPos[2]);
433
434 aHelix.
pivot(aNewPivot);
435
436 double newPhi0 = aHelix.
phi0();
437
438 double dphi = newPhi0-myHelix->
phi0();
439
440
441
442 if(dphi<-M_PI||dphi>
M_PI) dphi=atan2(
sin(dphi),
cos(dphi));
443 double flightLength = fabs(dphi*myHelix->
radius())*sqrt(1+myHelix->
tanl()*myHelix->
tanl());
444
445 myMapFlylenIdx[flightLength]=i_digi;
446 HepLorentzVector p4_pi = myHelix->
momentum(dphi, 0.13957);
447 double speed = p4_pi.beta()*
CC;
448 double TOF = flightLength/speed*1.e9;
449
450
451 double driftT = rawTime - myEventT0 - TOF - T0Walk - tprop;
452
453
454 double phiWire = atan2(whitPos[1],whitPos[0]);
455 double phiP = p4_pi.phi();
456 double entranceAngle = phiP-phiWire;
457
458
459 if(entranceAngle<-M_PI||entranceAngle>
M_PI) entranceAngle=atan2(
sin(entranceAngle),
cos(entranceAngle));
460
461 double doca_hit = 0.1 * myMdcCalibFunSvc->
driftTimeToDist(driftT,layer,wire,leftRight, entranceAngle);
462
463 double docaErr_hit = 0.1 * myMdcCalibFunSvc->
getSigma(layer, leftRight, doca_hit, entranceAngle, myHelix_a[4], vec_zini[i_digi], charge);
464
465
466
467 doca_hit*=signDoca;
468
469 double delD = doca_hit-doca_trk;
470 double chi = delD/docaErr_hit;
471 if(debug) cout<<"delta_m, err_m, chi = "<<delD<<", "<<docaErr_hit<<", "<<chi<<endl;
472 myChiVecMdcDigi[i_digi]=chi;
473
474 if(myMdcDigiIsActive[i_digi]!=1) continue;
475 if(myUseAxialHitsOnly && myWireFlag[layer]!=0) continue;
476
477 myNFittedHits++;
478 totChi2+=chi*chi;
479 for(int ipar=0; ipar<nPar; ipar++)
480 {
481 double deri;
482
483 getDeriLoc(ipar,myHelix_a, deri, wpos, vec_zini[i_digi]);
484 J(ipar+1,1) = deri;
485
486
487
488 double scale=1;
489 P(ipar+1,1) += J(ipar+1,1)*(doca_hit-doca_trk)/(docaErr_hit*docaErr_hit*scale);
490 for(int ipar2=0; ipar2<=ipar; ipar2++)
491 {
492
493 U(ipar+1,ipar2+1)+=J(ipar+1,1)*J(ipar2+1,1)/(docaErr_hit*docaErr_hit*scale);
494 }
495 }
496
497 }
498 if(debug) cout<<"end of MDC hits loop"<<endl;
499
500
501
502 i_digi=0;
503 vector<const RecCgemCluster*>::iterator iter_cluster = myVecCgemCluster.begin();
504 for(; iter_cluster!=myVecCgemCluster.end(); iter_cluster++, i_digi++)
505 {
506
507 int layer = (*iter_cluster)->getlayerid();
508 int flag = (*iter_cluster)->getflag();
509 if(myUseAxialHitsOnly && flag!=0) continue;
510 if(myUseMdcHitsOnly) continue;
511 int sheet = (*iter_cluster)->getsheetid();
513 if(debug)
514 {
515 cout<<endl<<"layer, sheet, flag = "<<setw(5)<<layer<<setw(5)<<sheet<<setw(5)<<flag<<endl;
516 }
517
518
520 if(fabs(dphi)<1e-10) {
521 myChiVecCgemCluster[i_digi]=-9999;
522
523 continue;
524 }
525 double flightLength = fabs(dphi*myHelix->
radius())*sqrt(1+myHelix->
tanl()*myHelix->
tanl());
526 myMapFlylenIdx[flightLength]=-(i_digi+1);
528 if(debug) cout<<"dphi="<<dphi<<", pos="<<pos<<endl;
529 double phi_trk = pos.phi();
530 double z_trk = pos.z();
532 Hep3Vector p3_trk = myHelix->
momentum(dphi);
533 double phi_p3trk = p3_trk.phi();
534 double incidentPhi = phi_p3trk-phi_trk;
535
536
537 if(incidentPhi<-M_PI||incidentPhi>
M_PI) incidentPhi=atan2(
sin(incidentPhi),
cos(incidentPhi));
538
539
540 double phi_CC(0.0);
541 double X_CC(0.), V_CC(0.);
542 double delta_m, err_m;
543 double Q(0.);
544 double T(100);
545 int mode(2);
546 Q=(*iter_cluster)->getenergydeposit();
547 if(flag==0) {
548 phi_CC = (*iter_cluster)->getrecphi();
549
550 double del_phi = phi_CC-phi_trk;
551
552
553 if(del_phi<-M_PI||del_phi>
M_PI) del_phi=atan2(
sin(del_phi),
cos(del_phi));
554 X_CC=phi_CC*myRmidDGapCgem[layer];
555 if(debug) cout<<"phi_trk, phi_rec = "<<phi_trk<<", "<<phi_CC<<endl;
556
557
558 delta_m=del_phi;
559 err_m=myCgemCalibSvc->
getSigma(layer,flag,mode,incidentPhi,Q,T)/10.;
560 err_m/=myRmidDGapCgem[layer];
561 J_dmdx(1,1)=-1*pos.y()/myR2midDGapCgem[layer];
562 J_dmdx(1,2)=pos.x()/myR2midDGapCgem[layer];
563 J_dmdx(1,3)=0.;
564 }
565 else if(flag==1) {
566 double V_trk = readoutPlane->
getVFromPhiZ(phi_trk,z_trk*10,
false)/10.0;
567 V_CC=(*iter_cluster)->getrecv()/10.;
568
569 if(debug) cout<<"V_trk, V_rec = "<<V_trk<<", "<<V_CC<<endl;
570 delta_m=V_CC-V_trk;
571 if(fabs(delta_m)>5) {
572
573
574
575
576
577
578
580 double delta_m_2=V_CC-V_trk_nearPhiMin;
581 if(fabs(delta_m_2)<fabs(delta_m)) delta_m=delta_m_2;
582 if(debug) cout<<"V_trk_nearPhiMin= "<<V_trk_nearPhiMin<<endl;
583 }
584 err_m=myCgemCalibSvc->
getSigma(layer,flag,mode,incidentPhi,Q,T)/10.;
585 J_dmdx(1,1)=-myRVCgem[layer]*
cos(myAngStereoCgem[layer])*pos.y()/myR2midDGapCgem[layer];
586 J_dmdx(1,2)= myRVCgem[layer]*
cos(myAngStereoCgem[layer])*pos.x()/myR2midDGapCgem[layer];
587 J_dmdx(1,3)= -
sin(myAngStereoCgem[layer]);
588 }
589 else {
590 cout<<"flag ="<<flag<<", DotsHelixFitter::calculateNewHelix() is not ready for it!"<<endl;
591 continue;
592 }
593 JT=J_dmdx*J_dxda;
594 J=JT.T();
595
596
597
598
599
600 double chi = delta_m/err_m;
601 myChiVecCgemCluster[i_digi]=chi;
602 if(debug) cout<<"delta_m, err_m, chi = "<<delta_m<<", "<<err_m<<", "<<chi<<endl;
603 totChi2+=chi*chi;
604 myNFittedHits++;
605 for(int ipar=0; ipar<nPar; ipar++)
606 {
607
608
609 P(ipar+1,1) += J(ipar+1,1)*chi/err_m;
610 for(int ipar2=0; ipar2<=ipar; ipar2++)
611 {
612 U(ipar+1,ipar2+1)+=J(ipar+1,1)*J(ipar2+1,1)/(err_m*err_m);
613 }
614 }
615 if(debug) cout<<"U="<<U<<endl;
616 }
617 if(debug)
618 cout<<"end of CGEM cluster loop"<<endl;
619
620
621
622
623 int ifail=99;
624 U.invert(ifail);
625
626
627
628
629
630
632
633
634
635 for(int ipar=0; ipar<nPar; ipar++)
636 {
637 myHelix_a[ipar]+=da[ipar];
638 if(ipar==1&&(myHelix_a[ipar]>2*
M_PI||myHelix_a[ipar]<0))
639 {
640 double aphi=myHelix_a[ipar];
641 aphi=atan2(
sin(aphi),
cos(aphi));
642 if(aphi<0) aphi+=2*
M_PI;
643 myHelix_a[ipar]=aphi;
644 }
645 myHelix_aVec[ipar]=myHelix_a[ipar];
646 }
647 myHelix->
a(myHelix_aVec);
648 if(debug)
649 {
650 cout<<"aNew = "<<myHelix_aVec
651 <<" chi2 = "<<totChi2
652 <<endl;
653 }
654 myChi2=totChi2;
655
656
657
658 nIterations++;
659 if(debug) cout<<" iteration "<<nIterations<<", chi2="<<totChi2<<endl;
660 if(fabs(lastTotChi2-totChi2)<myDchi2Converge) {
661 if(debug)
662 cout<<"DotsHelixFitter::calculateNewHelix(): converge after "<<nIterations<<" iterations"
663 <<" with lastTotChi2="<<lastTotChi2<<", totChi2="<<totChi2
664 <<endl;
665 if(nPar==5) {
666 myHelix_Ea = U;
668 }
669 return 0;
670
671
672 }
673 else if(totChi2-lastTotChi2>myDchi2Diverge) {
674 n_chi2_increase++;
675 if(n_chi2_increase>myMaxNChi2Increase||totChi2>myChi2Diverge)
676 return 5;
677 }
678 if( nIterations>3 && fabs(secLastTotChi2-totChi2)<(0.1*myDchi2Converge) && fabs(thirdLastTotChi2-lastTotChi2)<(0.1*myDchi2Converge) ) {
679 n_oscillation++;
680
681 if(n_oscillation>0&&totChi2<lastTotChi2) {
682 if(nPar==5) {
683 myHelix_Ea = U;
685 }
686 if(debug) cout<<"DotsHelixFitter::calculateNewHelix(): oscillation happened, thirdLastTotChi2, secLastTotChi2, lastTotChi2 = "<<thirdLastTotChi2<<", "<<secLastTotChi2<<", "<<lastTotChi2<<endl;
687 return 0;
688 }
689 }
690 if(nIterations>myMaxIteration) {
691 if(debug) cout<<"DotsHelixFitter::calculateNewHelix(): "<<nIterations
692 <<" iterations, break with lastTotChi2, totChi2 = "<<lastTotChi2<<", "<<totChi2<<endl;
693 return 4;
694
695 }
696 thirdLastTotChi2=secLastTotChi2;
697 secLastTotChi2=lastTotChi2;
698 lastTotChi2=totChi2;
699 }
700
701
702
703
704
705}
double P(RecMdcKalTrack *trk)
double abs(const EvtComplex &c)
double getVFromPhiZ(double phi, double z, bool checkRange=true) const
double getVFromPhiZ_nearPhiMin(double phi, double z, bool checkRange=true) const
CgemGeoReadoutPlane * getReadoutPlane(int iLayer, int iSheet) const
HepMatrix dxda_cgem(KalmanFit::Helix a, double phi)
const HepSymMatrix & Ea(void) const
returns error matrix.
const HepVector & a(void) const
returns helix parameters.
double getSigma(int layid, int lr, double dist, double entrance=0.0, double tanlam=0.0, double z=0.0, double Q=1000.0) const
double getT0(int layid, int cellid) const
double driftTimeToDist(double drifttime, int layid, int cellid, int lr, double entrance=0.0) const
double getTprop(int lay, double z) const
double getTimeWalk(int layid, double Q) const
static double MdcTime(int timeChannel)
bool getDeriLoc(int ipar, double helix[], double &deri, double wpos[], double zini)