242 vector<ENNRing>& Rings,
float HitSize,
THitIndex MinRingHits,
250 const fvec MinRingHits_v = MinRingHits;
251 const fvec Rejection = .5;
252 const float ShadowSize = HitSize / 4;
253 const int StartHitMaxQuality = 15;
254 const int SearchHitMaxQuality = 100;
256 const fvec R2MinCut = 3. * 3., R2MaxCut = 7. * 7.;
258 const fvec HitSize2 = 2 * HitSize;
260 const fvec HitSizeSq_v = HitSize * HitSize;
261 const float HitSizeSq = HitSizeSq_v[0];
263 const float AreaSize = 2 * RMax[0] + HitSize;
264 const float AreaSize2 = AreaSize * AreaSize;
277 const int MaxAreaHits = 200;
280 PickUpArea.
reset(MaxAreaHits);
285 rings_tmp.
reset(100);
290 int ileft = 0, iright = ileft;
302 for (
THitIndex ii_main = 0; ii_main < NHits;) {
305 GetTimer(
"Ring finding: Prepare data").Start(0);
309 fvec S0, S1, S2, S3, S4, S5, S6, S7;
310 fvec X = 0, Y = 0, R = 0, R2 = 0;
312 fmask validRing(fmask::One());
314 fvec SearchAreaSize = 0;
315 fvec PickUpAreaSize = 0;
317 for (
size_t i_4 = 0; (i_4 < fvec::size()) && (ii_main < NHits); ii_main++) {
318 const THitIndex i_main = i_main_array[ii_main];
319 const int i_main_4 = i_main % fvec::size(), i_main_V = i_main / fvec::size();
321 if (i->
quality[i_main_4] >= StartHitMaxQuality)
continue;
323 i_mains[i_4] = i_main;
325 float left = i->
x[i_main_4] - AreaSize;
326 float right = i->
x[i_main_4] + AreaSize;
331 while ((HitsV[ileft / fvec::size()].
x[ileft % fvec::size()] < left))
333 while ((iright < NHits) && (HitsV[iright / fvec::size()].
x[ileft % fvec::size()] < right))
336 for (
int j = ileft; j < iright; ++j) {
337 const int j_4 = j % fvec::size(), j_V = j / fvec::size();
339 sHit.
CopyHit(HitsV[j_V], j_4, i_4);
341 sHit.
ly[i_4] = sHit.
y[i_4] - i->
y[i_main_4];
343 sHit.
lx[i_4] = sHit.
x[i_4] - i->
x[i_main_4];
344 sHit.
S0 = sHit.
lx * sHit.
lx;
345 sHit.
S1 = sHit.
ly * sHit.
ly;
348 if (sHit.
lr2[i_4] > AreaSize2)
continue;
349 if (kf::utils::IsUnlikely(j == i_main))
continue;
351 if (sHit.
quality[i_4] >= SearchHitMaxQuality) {
352 PickUpArea[
static_cast<int>(PickUpAreaSize[i_4]++)].CopyHit(HitsV[j_V], j_4, i_4);
356 SearchAreaSize[i_4]++;
360 if (SearchAreaSize[i_4] < MinRingHits - 1)
continue;
365 int MaxSearchAreaSize = 0;
366 int MaxPickUpAreaSize = 0;
367 for (
size_t i_4 = 0; i_4 < fvec::size(); i_4++) {
368 iHit.
CopyHit(HitsV[i_mains[i_4] / fvec::size()], i_mains[i_4] % fvec::size(), i_4);
369 MaxSearchAreaSize = (MaxSearchAreaSize < SearchAreaSize[i_4]) ?
int(SearchAreaSize[i_4]) : MaxSearchAreaSize;
370 MaxPickUpAreaSize = (MaxPickUpAreaSize < PickUpAreaSize[i_4]) ?
int(PickUpAreaSize[i_4]) : MaxPickUpAreaSize;
373 GetTimer(
"Ring finding: Prepare data").Stop();
378 GetTimer(
"Ring finding: Init of param").Start(0);
380 for (
int isa = 0; isa < MaxSearchAreaSize; isa++) {
382 const fmask validHit = (
fvec(isa) < SearchAreaSize) & validRing;
383 sHit.
lx =
iif(validHit, sHit.
lx, fvec::Zero());
384 sHit.
ly =
iif(validHit, sHit.
ly, fvec::Zero());
385 sHit.
lr2 =
iif(validHit, sHit.
lr2, fvec::Zero());
390 S0 = S1 = S2 = S3 = S4 = 0.;
391 for (
int ih = 0; ih < MaxSearchAreaSize; ih++) {
393 const fmask validHit = (
fvec(ih) < SearchAreaSize) & validRing;
397 Dmax =
iif((lr > Dmax) & validHit, lr, Dmax);
399 sHit.
S2 = sHit.
lx * sHit.
ly;
400 sHit.
S3 = sHit.
lx * lr2;
401 sHit.
S4 = sHit.
ly * lr2;
402 sHit.
C = -lr *
fvec(.5);
404 const fvec w =
iif(validHit,
iif(lr >
fvec(1.E-4),
fvec(1.) / lr, fvec::One()), fvec::Zero());
405 const fvec w2 = w * w;
406 sHit.
Cx = w * sHit.
lx;
407 sHit.
Cy = w * sHit.
ly;
417 GetTimer(
"Ring finding: Init of param").Stop();
423 GetTimer(
"Ring finding: Hit selection").Start(0);
427 fvec tmp = S0 * S1 - S2 * S2;
430 tmp =
fvec(0.5) / tmp;
431 X = (S3 * S1 - S4 * S2) * tmp;
432 Y = (S4 * S0 - S3 * S2) * tmp;
436 const fvec Dcut = Dmax * Rejection;
438 S0 = S1 = S2 = S3 = S4 = fvec::Zero();
441 for (
THitIndex ih = 0; ih < MaxSearchAreaSize; ih++) {
442 const fmask validHit = (
fvec(ih) < SearchAreaSize) & validRing;
445 const fvec dx = sHit.
lx - X;
446 const fvec dy = sHit.
ly - Y;
447 const fvec d = abs(
sqrt(dx * dx + dy * dy) - R);
448 const fvec dSq = d * d;
449 sHit.
on_ring = (d <= HitSize) & validHit;
451 Dmax =
iif(((dp <= Dcut) & (dp > Dmax)), dp, Dmax);
454 w =
iif((dp <= Dcut) & validHit, w, fvec::Zero());
462 }
while ((Dmax >
fvec(0.)).isNotEmpty());
466 GetTimer(
"Ring finding: Hit selection").Stop();
469 GetTimer(
"Ring finding: Final fit").Start(0);
474 S0 = S1 = S2 = S3 = S4 = S5 = S6 = S7 = 0.0;
475 for (
THitIndex ih = 0; ih < MaxSearchAreaSize; ih++) {
477 const fvec w =
iif(SearchArea[ih].on_ring, fvec::One(), fvec::Zero());
488 const fvec s0 = S6 * S0 - S2 * S5;
489 const fvec s1 = S0 * S1 - S2 * S2;
490 const fvec s2 = S0 * S4 - S2 * S3;
492 const fvec tmp = s1 * (S5 * S5 - NRingHits * S0) + s0 * s0;
493 const fvec A = ((S0 * S7 - S3 * S5) * s1 - s2 * s0) / tmp;
494 Y = (s2 + s0 * A) / s1 *
fvec(0.5);
495 X = (S3 + S5 * A - S2 * Y * 2) / S0 *
fvec(0.5);
496 R2 = X * X + Y * Y - A;
502 !((NRingHits < MinRingHits_v) | (R2 > R2MaxCut) | (R2 < R2MinCut));
505 GetTimer(
"Ring finding: Final fit").Stop();
510 GetTimer(
"Ring finding: Store ring").Start(0);
512 if (kf::utils::IsUnlikely(validRing.isEmpty()))
continue;
517 ENNRingV &ringV = rings_tmp[nRings_tmp++];
520 ringV.
x = iHit.
x + X;
521 ringV.
y = iHit.
y + Y;
529 for(
THitIndex ih = 0; ih < MaxSearchAreaSize; ih++){
530 fvec validHit = ih < SearchAreaSize;
533 const fvec dx = sHit.
x - ringV.
x;
534 const fvec dy = sHit.
y - ringV.
y;
535 const fvec d = abs(
sqrt(dx*dx+dy*dy) - ringV.
r );
536 validHit = validHit & ( d <= HitSize );
539 ringV.
NHits +=
iif(validHit, fvec::One(), fvec::Zero());
540 validHit = validHit & ( d <= ShadowSize );
541 if ( validHit.isEmpty() )
continue;
544 for(
int ipu = 0; ipu < MaxPickUpAreaSize; ipu++ ) {
545 fvec validHit = ipu < PickUpAreaSize;
547 ENNHitV &puHit = PickUpArea[ipu];
548 const fvec dx = puHit.
x - ringV.
x;
549 const fvec dy = puHit.
y - ringV.
y;
550 const fvec d = abs(
sqrt(dx*dx+dy*dy) - ringV.
r );
551 validHit = validHit & ( d <= HitSize );
552 if ( validHit.isEmpty() )
continue;
555 ringV.
NHits +=
iif(validHit, fvec::One(), fvec::Zero());
556 validHit = validHit & ( d <= ShadowSize );
557 if ( validHit.isEmpty() )
continue;
570 for(
int i_4 = 0; (i_4 < fvec::size()); i_4++) {
571 const int NShadow = Shadow.size();
572 for(
int is = 0; is < NShadow; is++ ) {
573 cout << i_4 << Shadow[is] << endl;
574 float ih_f = (Shadow[is])[i_4]-200;
575 if (ih_f == -1)
continue;
576 int ih =
static_cast<int>(ih_f);
577 float ih_f2 =
static_cast<float>(ih);
578 cout << ih_f <<
" " << ih <<
" " << ih_f2 <<
" " << ih%fvec::size() <<
" " << ih/fvec::size() << endl;
581 ENNHitV & hitV = HitsV[ih/fvec::size()];
591 for (
size_t i_4 = 0; (i_4 < fvec::size()); i_4++) {
594 if ( (!validRing[i_4]))
continue;
597 Rings.push_back(voidRing);
600 ring.
x = iHit.
x[i_4] + X[i_4];
601 ring.
y = iHit.
y[i_4] + Y[i_4];
606 vector<THitIndex> Shadow;
609 for (
THitIndex ih = 0; ih < SearchAreaSize[i_4]; ih++) {
611 const float dx = sHit.
x[i_4] - ring.
x;
612 const float dy = sHit.
y[i_4] - ring.
y;
613 const float d = fabs(
sqrt(dx * dx + dy * dy) - R[i_4]);
614 if (kf::utils::IsUnlikely(d <= HitSize)) {
621 for (
int ipu = 0; ipu < PickUpAreaSize[i_4]; ipu++) {
622 ENNHitV& puHit = PickUpArea[ipu];
623 const float dx = puHit.
x[i_4] - ring.
x;
624 const float dy = puHit.
y[i_4] - ring.
y;
625 const float d = fabs(
sqrt(dx * dx + dy * dy) - ring.
r);
626 if (kf::utils::IsUnlikely(d <= HitSize)) {
633 if (kf::utils::IsUnlikely(ring.
NHits < MinRingHits)) {
638 int quality = ring.
NHits;
645 const int NShadow = Shadow.size();
646 for (
int is = 0; is < NShadow; is++) {
648 const THitIndex ih_4 = ih % fvec::size();
649 ENNHitV& hitV = HitsV[ih / fvec::size()];
658 GetTimer(
"Ring finding: Store ring").Stop();
667 typedef vector<ENNRing>::iterator iR;
668 iR Rbeg = Rings.begin() + NInRings;
669 iR Rend = Rings.end();
676 const int NHitsV = HitsV.size();
677 for (
int ih = 0; ih < NHitsV; ih++)
678 HitsV[ih].quality = 0.;
680 for (iR ir = Rbeg; ir != Rend; ++ir) {
682 ir->NOwn = ir->NHits;
685 for (iR i = Rbeg; i != Rend; ++i) {
686 if (i->skip)
continue;
687 for (iR j = i + 1; j != Rend; ++j) {
688 if (j->skip)
continue;
690 float dist = j->r + i->r + HitSize2[0];
691 float distCentr =
sqrt((j->x - i->x) * (j->x - i->x) + (j->y - i->y) * (j->y - i->y));
692 if (distCentr > dist)
continue;
693 Int_t NOverlaped = 0;
695 const THitIndex maxI = i->localIHits.size();
696 const THitIndex maxJ = j->localIHits.size();
699 if (i->localIHits[n] == j->localIHits[m]) NOverlaped++;
701 if (NOverlaped > 0.7 * maxI) BigRing = &(*i);
702 if (NOverlaped > 0.7 * maxJ) BigRing = &(*j);
704 std::vector<THitIndex> newIndices;
708 if (i->localIHits[n] == j->localIHits[m]) IsNew = 0;
709 if (IsNew) newIndices.push_back(i->localIHits[n]);
716 const THitIndex newISize = newIndices.size();
717 for (
THitIndex in = 0; in < newISize; in++)
718 j->localIHits.push_back(newIndices[in]);
728 for (iR i = Rbeg; i != Rend; ++i) {
731 float S0, S1, S2, S3, S4, S5, S6, S7, X, Y, R;
732 S0 = S1 = S2 = S3 = S4 = S5 = S6 = S7 = 0.0;
735 const THitIndex firstIh = i->localIHits[0];
736 const ENNHitV& firstHit = HitsV[firstIh / fvec::size()];
737 const int firstIh_4 = firstIh % fvec::size();
738 const THitIndex maxI = i->localIHits.size();
740 vector<ENNSearchHitV> shits;
742 for (
THitIndex iih = 0; iih < maxI; iih++) {
744 const ENNHitV& hit = HitsV[ih / fvec::size()];
745 const int ih_4 = ih % fvec::size();
748 shit.
ly[0] = hit.
y[ih_4] - firstHit.
y[firstIh_4];
749 shit.
lx[0] = hit.
x[ih_4] - firstHit.
x[firstIh_4];
750 shit.
S0[0] = shit.
lx[0] * shit.
lx[0];
751 shit.
S1[0] = shit.
ly[0] * shit.
ly[0];
752 shit.
lr2[0] = shit.
S0[0] + shit.
S1[0];
753 float lr2 = shit.
lr2[0];
754 float lr =
sqrt(lr2);
755 shit.
S2[0] = shit.
lx[0] * shit.
ly[0];
756 shit.
S3[0] = shit.
lx[0] * lr2;
757 shit.
S4[0] = shit.
ly[0] * lr2;
758 shit.
C[0] = -lr * 0.5;
764 shit.
Cx[0] = w * shit.
lx[0];
765 shit.
Cy[0] = w * shit.
ly[0];
769 X = i->x - firstHit.
x[firstIh_4];
770 Y = i->y - firstHit.
y[firstIh_4];
774 float Dcut = Dmax * Rejection[0];
776 S0 = S1 = S2 = S3 = S4 = S5 = S6 = S7 = 0.0;
778 for (
THitIndex ih = 0; ih < maxI; ih++) {
781 float dx = shit.
lx[0] - X;
782 float dy = shit.
ly[0] - Y;
783 float d = fabs(
sqrt(dx * dx + dy * dy) - R);
784 shit.
on_ring[0] = (d <= HitSize2[0]);
791 float dp = fabs(shit.
C[0] + shit.
Cx[0] * X + shit.
Cy[0] * Y);
792 if (dp > Dcut)
continue;
793 if (dp > Dmax) Dmax = dp;
795 w = 10. / (1.e-5 + fabs(d * d));
798 S0 += w * shit.
S0[0];
799 S1 += w * shit.
S1[0];
800 S2 += w * shit.
S2[0];
801 S3 += w * shit.
S3[0];
802 S4 += w * shit.
S4[0];
803 S5 += w * shit.
lx[0];
804 S6 += w * shit.
ly[0];
805 S7 += w * shit.
lr2[0];
808 float s0 = S6 * S0 - S2 * S5;
809 float s1 = S0 * S1 - S2 * S2;
810 float s2 = S0 * S4 - S2 * S3;
812 if (fabs(s0) < 1.E-6 || fabs(s1) < 1.E-6)
continue;
813 float tmp = s1 * (S5 * S5 - n * S0) + s0 * s0;
814 float A = ((S0 * S7 - S3 * S5) * s1 - s2 * s0) / tmp;
815 Y = (s2 + s0 * A) / s1 / 2;
816 X = (S3 + S5 * A - S2 * Y * 2) / S0 / 2;
817 float R2 = X * X + Y * Y - A;
819 if (R2 < 0)
continue;
821 if (Dmax <= 0) search_stop++;
822 }
while (search_stop < 2.);
825 i->x = X + firstHit.
x[firstIh_4];
826 i->y = Y + firstHit.
y[firstIh_4];
828 if (R < 2.5 || R > 7.5) {
834 std::vector<THitIndex> newHits;
837 for (
THitIndex iih = 0; iih < maxI; iih++) {
839 const ENNHitV& hit = HitsV[ih / fvec::size()];
841 const int ih_4 = ih % fvec::size();
843 float dx = hit.
x[ih_4] - i->x;
844 float dy = hit.
y[ih_4] - i->y;
845 float d = fabs(
sqrt(dx * dx + dy * dy) - i->r);
846 shit.
on_ring[ih_4] = (d <= HitSize);
848 newHits.push_back(ih);
853 i->localIHits.clear();
854 i->localIHits = newHits;
855 i->NHits = i->localIHits.size();
858 if (i->localIHits.size() < MinRingHits) {
863 i->chi2 = i->chi2 / ((i->localIHits.size() - 3) * HitSize * HitSize);
869 for (iR i = Rbeg; i != Rend; ++i) {
871 if (i->skip)
continue;
874 const THitIndex maxI = i->localIHits.size();
877 ENNHitV& hit = HitsV[ih / fvec::size()];
878 const int ih_4 = ih % fvec::size();
881 for (iR j = i + 1; j != Rend; ++j) {
882 if (i->skip)
continue;
883 float dist = j->r + best->r + HitSize2[0];
884 if (fabs(j->x - best->x) > dist || fabs(j->y - best->y) > dist)
continue;
886 const THitIndex maxJ = j->localIHits.size();
889 const ENNHitV& hitm = HitsV[ihm / fvec::size()];
890 if (hitm.
quality[ihm % fvec::size()] == 0) j->NOwn++;
901 const int NHitsV = HitsV.size();
902 for (
int ih = 0; ih < NHitsV; ih++)
903 HitsV[ih].quality = 0.;
904 for (iR ir = Rbeg; ir != Rend; ++ir) {
906 ir->NOwn = ir->NHits;
907 ir->skip = ((ir->NHits < MinRingHits) || (ir->NHits <= 6 && ir->chi2 > .3));
913 float bestChi2 = 1.E20;
914 for (iR ir = Rbeg; ir != Rend; ++ir) {
918 if (ir->skip)
continue;
919 const bool skip = ((ir->NOwn < 1.0 * MinRingHits) || (ir->NHits < 10 && ir->NOwn < 1.00 * ir->NHits)
920 || (ir->NOwn < .60 * ir->NHits));
922 const bool isBetter = !skip & ((ir->NOwn > 1.2 * bestOwn) || (ir->NOwn >= 1. * bestOwn && ir->chi2 < bestChi2));
923 bestOwn = (isBetter) ? ir->NOwn : bestOwn;
924 bestChi2 = (isBetter) ? ir->chi2 : bestChi2;
925 best = (isBetter) ? ir : best;
927 if (best == Rend)
break;
930 const THitIndex NHitsBest = best->localIHits.size();
931 for (
THitIndex iih = 0; iih < NHitsBest; iih++) {
932 const THitIndex ih = best->localIHits[iih];
933 HitsV[ih / fvec::size()].quality[ih % fvec::size()] = 1;
935 for (iR ir = Rbeg; ir != Rend; ++ir) {
936 if (ir->skip)
continue;
937 float dist = ir->r + best->r + HitSize2[0];
938 if (fabs(ir->x - best->x) > dist || fabs(ir->y - best->y) > dist)
continue;
940 const THitIndex NHitsCur = ir->localIHits.size();
941 for (
THitIndex iih = 0; iih < NHitsCur; iih++) {
942 const THitIndex ih = ir->localIHits[iih];
943 ir->NOwn += (HitsV[ih / fvec::size()].quality[ih % fvec::size()] == 0);