25 #include "TClonesArray.h"
26 #include "TStopwatch.h"
42 : fRecoTime(0), fNEvents(0) {
50 "Ring finding: Prepare data",
51 "Ring finding: Init of param",
52 "Ring finding: Hit selection",
53 "Ring finding: Final fit",
54 "Ring finding: Store ring",
64 #endif // PRINT_TIMING
74 TClonesArray* RingArray) {
75 if (!RingArray || !HitArray)
return 0;
82 #endif // PRINT_TIMING
86 #endif // PRINT_TIMING
87 vector<ENNRingHit> Up;
88 vector<ENNRingHit> Down;
90 const Int_t nhits = HitArray->GetEntriesFast();
92 for (
register Int_t
i = 0;
i < nhits; ++
i) {
93 CbmRichHit* hit = L1_DYNAMIC_CAST<CbmRichHit*>(HitArray->At(
i));
110 #endif // PRINT_TIMING
114 #endif // PRINT_TIMING
119 vector<Int_t> outIndicesUp;
120 vector<Int_t> outIndicesDown;
121 outIndicesUp.resize(Up.size());
122 outIndicesDown.resize(Down.size());
123 for (
THitIndex k = 0; k < Up.size(); k++) {
124 Up[k].localIndex = k;
125 outIndicesUp[k] = Up[k].outIndex;
127 for (
THitIndex k = 0; k < Down.size(); k++) {
128 Down[k].localIndex = k;
129 outIndicesDown[k] = Down[k].outIndex;
134 #endif // PRINT_TIMING
138 #endif // PRINT_TIMING
145 for (
THitIndex k = 0; k < Up.size(); k++) {
148 hits.CopyHit(Up[k], k_4);
150 for (
THitIndex k = 0; k < Down.size(); k++) {
153 hits.CopyHit(Down[k], k_4);
158 #endif // PRINT_TIMING
169 ENNRingFinder(Up.size(), UpV, R, HitSize, MinRingHits, RMin, RMax);
170 ENNRingFinder(Down.size(), DownV, R, HitSize, MinRingHits, RMin, RMax);
176 #endif // PRINT_TIMING
178 for (vector<ENNRing>::iterator
i = R.begin();
i != R.end(); ++
i) {
179 if (!
i->on)
continue;
181 CbmRichRing* ring = L1_DYNAMIC_CAST<CbmRichRing*>(RingArray->At(NRings));
190 ring->
AddHit(outIndicesUp[
i->localIHits[j]]);
192 ring->
AddHit(outIndicesDown[
i->localIHits[j]]);
197 #endif // PRINT_TIMING
201 cout.setf(ios::fixed);
202 cout.setf(ios::showpoint);
205 <<
"/" << timer.RealTime() * 1000. << endl;
208 static float timeStat[
NTimers];
209 static bool firstCall = 1;
218 cout <<
"Timing statEvents / curEvent[ms] | statEvents[%] : " << endl;
219 cout.flags(ios::left | ios::oct | ios::showpoint | ios::fixed);
225 <<
" / " <<
fTimers[
i].RealTime() * 1000. <<
" | "
226 << timeStat[
i] / timeStat[1] * 100 << endl;
228 #endif // PRINT_TIMING
236 vector<ENNRing>& Rings,
243 #endif // PRINT_TIMING
246 const fvec MinRingHits_v = MinRingHits;
247 const fvec Rejection = .5;
248 const float ShadowSize = HitSize / 4;
249 const int StartHitMaxQuality = 15;
250 const int SearchHitMaxQuality = 100;
252 const fvec R2MinCut = 3. * 3., R2MaxCut = 7. * 7.;
254 const fvec HitSize2 = 2 * HitSize;
256 const fvec HitSizeSq_v = HitSize * HitSize;
257 const float HitSizeSq = HitSizeSq_v[0];
259 const float AreaSize = 2 * RMax[0] + HitSize;
260 const float AreaSize2 = AreaSize * AreaSize;
270 #endif // PRINT_TIMING
273 const int MaxAreaHits = 200;
276 PickUpArea.resize(MaxAreaHits);
281 rings_tmp.resize(100);
286 int ileft = 0, iright = ileft;
299 for (
THitIndex ii_main = 0; ii_main < NHits;) {
302 GetTimer(
"Ring finding: Prepare data").Start(0);
303 #endif // PRINT_TIMING
306 fvec S0, S1, S2, S3, S4, S5, S6, S7;
307 fvec X = 0, Y = 0, R = 0, R2 = 0;
311 fvec SearchAreaSize = 0;
312 fvec PickUpAreaSize = 0;
314 for (
int i_4 = 0; (i_4 <
fvecLen) && (ii_main < NHits); ii_main++) {
315 const THitIndex i_main = i_main_array[ii_main];
316 const int i_main_4 = i_main %
fvecLen, i_main_V = i_main /
fvecLen;
318 if (
i->quality[i_main_4] >= StartHitMaxQuality)
321 i_mains[i_4] = i_main;
323 float left =
i->x[i_main_4] - AreaSize;
324 float right =
i->x[i_main_4] + AreaSize;
331 while ((iright < NHits)
335 for (
int j = ileft; j < iright; ++j) {
338 sHit.
CopyHit(HitsV[j_V], j_4, i_4);
340 sHit.
ly[i_4] = sHit.
y[i_4] -
i->y[i_main_4];
342 sHit.
lx[i_4] = sHit.
x[i_4] -
i->x[i_main_4];
343 sHit.
S0 = sHit.
lx * sHit.
lx;
344 sHit.
S1 = sHit.
ly * sHit.
ly;
347 if (sHit.
lr2[i_4] > AreaSize2)
continue;
351 >= SearchHitMaxQuality) {
352 PickUpArea[
static_cast<int>(PickUpAreaSize[i_4]++)].CopyHit(
353 HitsV[j_V], j_4, i_4);
357 SearchAreaSize[i_4]++;
361 if (SearchAreaSize[i_4] < MinRingHits - 1)
continue;
366 int MaxSearchAreaSize = 0;
367 int MaxPickUpAreaSize = 0;
368 for (
int i_4 = 0; i_4 <
fvecLen; i_4++) {
370 MaxSearchAreaSize = (MaxSearchAreaSize < SearchAreaSize[i_4])
371 ?
int(SearchAreaSize[i_4])
373 MaxPickUpAreaSize = (MaxPickUpAreaSize < PickUpAreaSize[i_4])
374 ?
int(PickUpAreaSize[i_4])
378 GetTimer(
"Ring finding: Prepare data").Stop();
380 #endif // PRINT_TIMING
383 GetTimer(
"Ring finding: Init of param").Start(0);
384 #endif // PRINT_TIMING
385 for (
int isa = 0; isa < MaxSearchAreaSize;
388 const fvec validHit = (
fvec(isa) < SearchAreaSize) & validRing;
389 sHit.
lx =
if3(validHit, sHit.
lx, 0);
390 sHit.
ly =
if3(validHit, sHit.
ly, 0);
396 S0 = S1 = S2 = S3 = S4 = 0.;
397 for (
int ih = 0; ih < MaxSearchAreaSize; ih++) {
399 const fvec validHit = (
fvec(ih) < SearchAreaSize) & validRing;
403 Dmax =
if3((lr > Dmax) & validHit, lr, Dmax);
405 sHit.
S2 = sHit.
lx * sHit.
ly;
406 sHit.
S3 = sHit.
lx * lr2;
407 sHit.
S4 = sHit.
ly * lr2;
410 const fvec w =
if3(validHit,
if3(lr >
fvec(1.E-4), 1. / lr, 1), 0);
411 const fvec w2 = w * w;
412 sHit.
Cx = w * sHit.
lx;
413 sHit.
Cy = w * sHit.
ly;
423 GetTimer(
"Ring finding: Init of param").Stop();
425 #endif // PRINT_TIMING
429 GetTimer(
"Ring finding: Hit selection").Start(0);
430 #endif // PRINT_TIMING
433 fvec tmp = S0 * S1 - S2 * S2;
437 X = (S3 * S1 - S4 * S2) * tmp;
438 Y = (S4 * S0 - S3 * S2) * tmp;
442 const fvec Dcut = Dmax * Rejection;
444 S0 = S1 = S2 = S3 = S4 = 0.0;
447 for (
THitIndex ih = 0; ih < MaxSearchAreaSize; ih++) {
448 const fvec validHit = (
fvec(ih) < SearchAreaSize) & validRing;
451 const fvec dx = sHit.
lx - X;
452 const fvec dy = sHit.
ly - Y;
455 sHit.
on_ring = (
d <= HitSize) & validHit;
458 Dmax =
if3(((dp <= Dcut) & (dp > Dmax)), dp, Dmax);
461 1. / (HitSizeSq_v +
fabs(dSq)),
462 1. / (1.e-5 +
fabs(dSq)));
463 w =
if3((dp <= Dcut) & validHit, w, 0);
475 GetTimer(
"Ring finding: Hit selection").Stop();
478 GetTimer(
"Ring finding: Final fit").Start(0);
479 #endif // PRINT_TIMING
483 S0 = S1 = S2 = S3 = S4 = S5 = S6 = S7 = 0.0;
484 for (
THitIndex ih = 0; ih < MaxSearchAreaSize; ih++) {
497 const fvec s0 = S6 * S0 - S2 * S5;
498 const fvec s1 = S0 * S1 - S2 * S2;
499 const fvec s2 = S0 * S4 - S2 * S3;
501 const fvec tmp = s1 * (S5 * S5 - NRingHits * S0) + s0 * s0;
502 const fvec A = ((S0 * S7 - S3 * S5) * s1 - s2 * s0) / tmp;
503 Y = (s2 + s0 * A) / s1 * 0.5;
504 X = (S3 + S5 * A - S2 * Y * 2) / S0 * 0.5;
505 R2 = X * X + Y * Y - A;
510 validRing = !((NRingHits < MinRingHits_v) | (R2 > R2MaxCut)
514 GetTimer(
"Ring finding: Final fit").Stop();
515 #endif // PRINT_TIMING
519 GetTimer(
"Ring finding: Store ring").Start(0);
520 #endif // PRINT_TIMING
526 ENNRingV &ringV = rings_tmp[nRings_tmp++];
529 ringV.
x = iHit.
x + X;
530 ringV.
y = iHit.
y + Y;
538 for(
THitIndex ih = 0; ih < MaxSearchAreaSize; ih++){
539 fvec validHit = ih < SearchAreaSize;
542 const fvec dx = sHit.
x - ringV.
x;
543 const fvec dy = sHit.
y - ringV.
y;
545 validHit = validHit & (
d <= HitSize );
549 validHit = validHit & (
d <= ShadowSize );
550 if (
Empty (validHit) )
continue;
553 for(
int ipu = 0; ipu < MaxPickUpAreaSize; ipu++ ) {
554 fvec validHit = ipu < PickUpAreaSize;
556 ENNHitV &puHit = PickUpArea[ipu];
557 const fvec dx = puHit.
x - ringV.
x;
558 const fvec dy = puHit.
y - ringV.
y;
560 validHit = validHit & (
d <= HitSize );
561 if (
Empty (validHit) )
continue;
565 validHit = validHit & (
d <= ShadowSize );
566 if (
Empty (validHit) )
continue;
579 for(
int i_4 = 0; (i_4 <
fvecLen); i_4++) {
580 const int NShadow = Shadow.size();
581 for(
int is = 0; is < NShadow; is++ ) {
582 cout << i_4 << Shadow[is] << endl;
583 float ih_f = (Shadow[is])[i_4]-200;
584 if (ih_f == -1)
continue;
585 int ih =
static_cast<int>(ih_f);
586 float ih_f2 =
static_cast<float>(ih);
587 cout << ih_f <<
" " << ih <<
" " << ih_f2 <<
" " << ih%
fvecLen <<
" " << ih/
fvecLen << endl;
600 for (
int i_4 = 0; (i_4 <
fvecLen); i_4++) {
603 if ( (!validRing[i_4]))
continue;
606 Rings.push_back(voidRing);
609 ring.
x = iHit.
x[i_4] + X[i_4];
610 ring.
y = iHit.
y[i_4] + Y[i_4];
619 for (
THitIndex ih = 0; ih < SearchAreaSize[i_4]; ih++) {
621 const float dx = sHit.
x[i_4] - ring.
x;
622 const float dy = sHit.
y[i_4] - ring.
y;
623 const float d =
fabs(
sqrt(dx * dx + dy * dy) - R[i_4]);
632 for (
int ipu = 0; ipu < PickUpAreaSize[i_4]; ipu++) {
633 ENNHitV& puHit = PickUpArea[ipu];
634 const float dx = puHit.
x[i_4] - ring.
x;
635 const float dy = puHit.
y[i_4] - ring.
y;
636 const float d =
fabs(
sqrt(dx * dx + dy * dy) - ring.
r);
651 int quality = ring.
NHits;
658 const int NShadow = Shadow.size();
659 for (
int is = 0; is < NShadow; is++) {
672 GetTimer(
"Ring finding: Store ring").Stop();
673 #endif // PRINT_TIMING
680 #endif // PRINT_TIMING
681 typedef vector<ENNRing>::iterator iR;
682 iR Rbeg = Rings.begin() + NInRings;
683 iR Rend = Rings.end();
686 #ifdef NEW_SELECTION // TODO optimize. at the moment just creates additional ghosts
690 const int NHitsV = HitsV.size();
691 for (
int ih = 0; ih < NHitsV; ih++)
692 HitsV[ih].quality = 0.;
694 for (iR ir = Rbeg; ir != Rend; ++ir) {
696 ir->NOwn = ir->NHits;
699 for (iR
i = Rbeg;
i != Rend; ++
i) {
700 if (
i->skip)
continue;
701 for (iR j =
i + 1; j != Rend; ++j) {
702 if (j->skip)
continue;
704 float dist = j->r +
i->r + HitSize2[0];
706 sqrt((j->x -
i->x) * (j->x -
i->x) + (j->y -
i->y) * (j->y -
i->y));
707 if (distCentr > dist)
continue;
708 Int_t NOverlaped = 0;
711 const THitIndex maxJ = j->localIHits.size();
714 if (
i->localIHits[n] == j->localIHits[
m]) NOverlaped++;
716 if (NOverlaped > 0.7 * maxI) BigRing = &(*i);
717 if (NOverlaped > 0.7 * maxJ) BigRing = &(*j);
719 std::vector<THitIndex> newIndices;
723 if (
i->localIHits[n] == j->localIHits[
m]) IsNew = 0;
724 if (IsNew) newIndices.push_back(
i->localIHits[n]);
731 const THitIndex newISize = newIndices.size();
732 for (
THitIndex in = 0; in < newISize; in++)
733 j->localIHits.push_back(newIndices[in]);
743 for (iR
i = Rbeg;
i != Rend; ++
i) {
746 float S0, S1, S2, S3, S4, S5, S6, S7, X, Y, R;
747 S0 = S1 = S2 = S3 = S4 = S5 = S6 = S7 = 0.0;
752 const int firstIh_4 = firstIh %
fvecLen;
755 vector<ENNSearchHitV> shits;
757 for (
THitIndex iih = 0; iih < maxI; iih++) {
763 shit.
ly[0] = hit.
y[ih_4] - firstHit.
y[firstIh_4];
764 shit.
lx[0] = hit.
x[ih_4] - firstHit.
x[firstIh_4];
765 shit.
S0[0] = shit.
lx[0] * shit.
lx[0];
766 shit.
S1[0] = shit.
ly[0] * shit.
ly[0];
767 shit.
lr2[0] = shit.
S0[0] + shit.
S1[0];
768 float lr2 = shit.
lr2[0];
769 float lr =
sqrt(lr2);
770 shit.
S2[0] = shit.
lx[0] * shit.
ly[0];
771 shit.
S3[0] = shit.
lx[0] * lr2;
772 shit.
S4[0] = shit.
ly[0] * lr2;
773 shit.
C[0] = -lr * 0.5;
779 shit.
Cx[0] = w * shit.
lx[0];
780 shit.
Cy[0] = w * shit.
ly[0];
784 X =
i->x - firstHit.
x[firstIh_4];
785 Y =
i->y - firstHit.
y[firstIh_4];
789 float Dcut = Dmax * Rejection[0];
791 S0 = S1 = S2 = S3 = S4 = S5 = S6 = S7 = 0.0;
793 for (
THitIndex ih = 0; ih < maxI; ih++) {
796 float dx = shit.
lx[0] - X;
797 float dy = shit.
ly[0] - Y;
798 float d =
fabs(
sqrt(dx * dx + dy * dy) - R);
799 shit.
on_ring[0] = (
d <= HitSize2[0]);
805 float dp =
fabs(shit.
C[0] + shit.
Cx[0] * X + shit.
Cy[0] * Y);
806 if (dp > Dcut)
continue;
807 if (dp > Dmax) Dmax = dp;
809 w = 10. / (1.e-5 +
fabs(
d *
d));
812 S0 += w * shit.
S0[0];
813 S1 += w * shit.
S1[0];
814 S2 += w * shit.
S2[0];
815 S3 += w * shit.
S3[0];
816 S4 += w * shit.
S4[0];
817 S5 += w * shit.
lx[0];
818 S6 += w * shit.
ly[0];
819 S7 += w * shit.
lr2[0];
822 float s0 = S6 * S0 - S2 * S5;
823 float s1 = S0 * S1 - S2 * S2;
824 float s2 = S0 * S4 - S2 * S3;
826 if (
fabs(s0) < 1.E-6 ||
fabs(s1) < 1.E-6)
continue;
827 float tmp = s1 * (S5 * S5 - n * S0) + s0 * s0;
828 float A = ((S0 * S7 - S3 * S5) * s1 - s2 * s0) / tmp;
829 Y = (s2 + s0 * A) / s1 / 2;
830 X = (S3 + S5 * A - S2 * Y * 2) / S0 / 2;
831 float R2 = X * X + Y * Y - A;
833 if (R2 < 0)
continue;
835 if (Dmax <= 0) search_stop++;
836 }
while (search_stop < 2.);
839 i->x = X + firstHit.
x[firstIh_4];
840 i->y = Y + firstHit.
y[firstIh_4];
842 if (R < 2.5 || R > 7.5) {
848 std::vector<THitIndex> newHits;
851 for (
THitIndex iih = 0; iih < maxI; iih++) {
857 float dx = hit.
x[ih_4] -
i->x;
858 float dy = hit.
y[ih_4] -
i->y;
859 float d =
fabs(
sqrt(dx * dx + dy * dy) -
i->r);
860 shit.
on_ring[ih_4] = (
d <= HitSize);
862 newHits.push_back(ih);
867 i->localIHits.clear();
868 i->localIHits = newHits;
869 i->NHits =
i->localIHits.size();
872 if (
i->localIHits.size() < MinRingHits) {
878 i->chi2 / ((
i->localIHits.size() - 3) * HitSize * HitSize);
884 for (iR
i = Rbeg;
i != Rend; ++
i) {
886 if (
i->skip)
continue;
896 for (iR j =
i + 1; j != Rend; ++j) {
897 if (
i->skip)
continue;
898 float dist = j->r + best->r + HitSize2[0];
899 if (
fabs(j->x - best->x) > dist ||
fabs(j->y - best->y) > dist)
902 const THitIndex maxJ = j->localIHits.size();
914 #else // NEW_SELECTION
916 const int NHitsV = HitsV.size();
917 for (
int ih = 0; ih < NHitsV; ih++)
918 HitsV[ih].quality = 0.;
919 for (iR ir = Rbeg; ir != Rend; ++ir) {
921 ir->NOwn = ir->NHits;
922 ir->skip = ((ir->NHits < MinRingHits) || (ir->NHits <= 6 && ir->chi2 > .3));
928 float bestChi2 = 1.E20;
929 for (iR ir = Rbeg; ir != Rend; ++ir) {
933 if (ir->skip)
continue;
934 const bool skip = ((ir->NOwn < 1.0 * MinRingHits)
935 || (ir->NHits < 10 && ir->NOwn < 1.00 * ir->NHits)
936 || (ir->NOwn < .60 * ir->NHits));
938 const bool isBetter =
940 & ((ir->NOwn > 1.2 * bestOwn)
941 || (ir->NOwn >= 1. * bestOwn && ir->chi2 < bestChi2));
942 bestOwn = (isBetter) ? ir->NOwn : bestOwn;
943 bestChi2 = (isBetter) ? ir->chi2 : bestChi2;
944 best = (isBetter) ? ir : best;
946 if (best == Rend)
break;
949 const THitIndex NHitsBest = best->localIHits.size();
950 for (
THitIndex iih = 0; iih < NHitsBest; iih++) {
951 const THitIndex ih = best->localIHits[iih];
954 for (iR ir = Rbeg; ir != Rend; ++ir) {
955 if (ir->skip)
continue;
956 float dist = ir->r + best->r + HitSize2[0];
957 if (
fabs(ir->x - best->x) > dist ||
fabs(ir->y - best->y) > dist)
960 const THitIndex NHitsCur = ir->localIHits.size();
961 for (
THitIndex iih = 0; iih < NHitsCur; iih++) {
962 const THitIndex ih = ir->localIHits[iih];
967 #endif // else NEW_SELECTION
972 #endif // PRINT_TIMING