CbmRoot
Loading...
Searching...
No Matches
CbmRichRingFinderHoughImpl.cxx
Go to the documentation of this file.
1/* Copyright (C) 2008-2021 UGiessen/JINR-LIT, Giessen/Dubna
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Andrey Lebedev, Semen Lebedev [committer] */
4
13
14#include "../../littrack/std/utils/CbmLitMemoryManagment.h"
16#include "CbmRichRingLight.h"
18#include "TSystem.h"
19
20#include <algorithm>
21#include <cmath>
22#include <iostream>
23#include <set>
24
25using std::cout;
26using std::endl;
27using std::set;
28using std::sort;
29using std::vector;
30
32 : fNofParts(0)
33 ,
34
35 fMaxDistance(0.f)
36 , fMinDistance(0.f)
37 , fMinDistanceSq(0.f)
38 , fMaxDistanceSq(0.f)
39 ,
40
41 fMinRadius(0.f)
42 , fMaxRadius(0.f)
43 ,
44
45 fDx(0.f)
46 , fDy(0.f)
47 , fDr(0.f)
48 , fNofBinsX(0)
49 , fNofBinsY(0)
50 , fNofBinsXY(0)
51 ,
52
53 fHTCut(0)
54 ,
55
56 fNofBinsR(0)
57 , fHTCutR(0)
58 ,
59
60 fMinNofHitsInArea(0)
61 ,
62
63 fRmsCoeffEl(0.f)
64 , fMaxCutEl(0.f)
65 , fRmsCoeffCOP(0.f)
66 , fMaxCutCOP(0.f)
67 ,
68
69 fAnnCut(0.f)
70 , fUsedHitsAllCut(0.f)
71 ,
72
73 fTimeCut(0.)
74 ,
75
76 fCurMinX(0.f)
77 , fCurMinY(0.f)
78 ,
79
80 fUseAnnSelect(true)
81 ,
82
83 fData()
84 , fHist()
85 , fHistR()
86 , fHitInd()
87 , fFoundRings()
88 , fFitCOP(NULL)
89 , fANNSelect(NULL)
90 ,
91
92 fCurTime(0.)
93
94{
95}
96
98{
99 if (NULL != fFitCOP) delete fFitCOP;
100 if (NULL != fANNSelect) delete fANNSelect;
101}
102
104{
106
107 fHist.resize(fNofBinsXY);
108 fHistR.resize(fNofBinsR);
109 fHitInd.resize(fNofParts);
110
112 if (fUseAnnSelect) {
114 fANNSelect->Init();
115 }
116}
117
119{
120 // if (fData.size() > MAX_NOF_HITS) {
121 // cout << endl << endl << "-E- CbmRichRingFinderHoughImpl::DoFind" << ". Number of hits is more than " << MAX_NOF_HITS << endl << endl;
122 // return;
123 // }
124
125 for_each(fFoundRings.begin(), fFoundRings.end(), DeleteObject());
126 fFoundRings.clear();
127 fFoundRings.reserve(100);
128
129 std::sort(fData.begin(), fData.end(),
130 [](const CbmRichHoughHit& m1, const CbmRichHoughHit& m2) { return m1.fHit.fX < m2.fHit.fX; });
133 fData.clear();
134}
135
137{
138 fMaxDistance = 11.5;
139 fMinDistance = 2.5;
142
143 fMinRadius = 3.5;
144 fMaxRadius = 5.7;
145
146 fHTCut = 20;
147 fHTCutR = 12;
149
150 fNofBinsX = 25;
151 fNofBinsY = 25;
152 fNofBinsR = 32;
153
154 fAnnCut = 0.6;
155 fUsedHitsAllCut = 0.4;
156
157 fRmsCoeffEl = 2.5;
158 fMaxCutEl = 1.0;
159 fRmsCoeffCOP = 3.;
160 fMaxCutCOP = 1.0;
161
162 fTimeCut = 3.;
163
164 fNofParts = 1;
165 fDx = 2.f * fMaxDistance / (float) fNofBinsX;
166 fDy = 2.f * fMaxDistance / (float) fNofBinsY;
167 fDr = fMaxRadius / (float) fNofBinsR;
169}
170
172{
173 int indmin, indmax;
174 unsigned int size = fData.size();
175 for (unsigned int iHit = 0; iHit < size; iHit++) {
176 if (fData[iHit].fIsUsed == true) continue;
177
178 fCurMinX = fData[iHit].fHit.fX - fMaxDistance;
179 fCurMinY = fData[iHit].fHit.fY - fMaxDistance;
180 fCurTime = fData[iHit].fTime;
181
182 DefineLocalAreaAndHits(fData[iHit].fHit.fX, fData[iHit].fHit.fY, &indmin, &indmax);
183 HoughTransform(indmin, indmax);
184 FindPeak(indmin, indmax);
185 }
186}
187
188void CbmRichRingFinderHoughImpl::DefineLocalAreaAndHits(float x0, float y0, int* indmin, int* indmax)
189{
190 CbmRichHoughHit mpnt;
191 vector<CbmRichHoughHit>::iterator itmin, itmax;
192
193 //find all hits which are in the corridor
194 mpnt.fHit.fX = x0 - fMaxDistance;
195 itmin = std::lower_bound(fData.begin(), fData.end(), mpnt, [](const CbmRichHoughHit& m1, const CbmRichHoughHit& m2) {
196 return m1.fHit.fX < m2.fHit.fX;
197 });
198
199 mpnt.fHit.fX = x0 + fMaxDistance;
200 itmax = std::lower_bound(fData.begin(), fData.end(), mpnt,
201 [](const CbmRichHoughHit& m1, const CbmRichHoughHit& m2) { return m1.fHit.fX < m2.fHit.fX; })
202 - 1;
203
204 *indmin = itmin - fData.begin();
205 *indmax = itmax - fData.begin();
206
207 int arSize = *indmax - *indmin + 1;
208 if (arSize <= fMinNofHitsInArea) return;
209
210 for (unsigned short i = 0; i < fNofParts; i++) {
211 fHitInd[i].clear();
212 fHitInd[i].reserve((*indmax - *indmin) / fNofParts);
213 }
214
215 for (int i = *indmin; i <= *indmax; i++) {
216 if (fData[i].fIsUsed == true) continue;
217 float ry = y0 - fData[i].fHit.fY;
218 if (fabs(ry) > fMaxDistance) continue;
219 float rx = x0 - fData[i].fHit.fX;
220 float d = rx * rx + ry * ry;
221 if (d > fMaxDistanceSq) continue;
222 if (std::fabs(fCurTime - fData[i].fTime) > fTimeCut) continue;
223
224 fHitInd[i % fNofParts].push_back(i);
225 }
226
227 for (unsigned short j = 0; j < fNofBinsXY; j++) {
228 fHist[j] = 0;
229 }
230
231 for (unsigned short k = 0; k < fNofBinsR; k++) {
232 fHistR[k] = 0;
233 }
234}
235
236void CbmRichRingFinderHoughImpl::HoughTransform(unsigned int indmin, unsigned int indmax)
237{
238 for (int iPart = 0; iPart < fNofParts; iPart++) {
239 HoughTransformGroup(indmin, indmax, iPart);
240 } //iPart
241}
242
243void CbmRichRingFinderHoughImpl::HoughTransformGroup(unsigned int /*indmin*/, unsigned int /*indmax*/, int iPart)
244{
245 unsigned int nofHits = fHitInd[iPart].size();
246 float xcs, ycs; // xcs = xc - fCurMinX
247 float dx = 1.0f / fDx, dy = 1.0f / fDy, dr = 1.0f / fDr;
248
249 vector<CbmRichHoughHit> data;
250 data.resize(nofHits);
251 for (unsigned int i = 0; i < nofHits; i++) {
252 data[i] = fData[fHitInd[iPart][i]];
253 }
254
255 typedef vector<CbmRichHoughHit>::iterator iH;
256
257 for (iH iHit1 = data.begin(); iHit1 != data.end(); iHit1++) {
258 float iH1X = iHit1->fHit.fX;
259 float iH1Y = iHit1->fHit.fY;
260 double time1 = iHit1->fTime;
261
262 for (iH iHit2 = iHit1 + 1; iHit2 != data.end(); iHit2++) {
263 float iH2X = iHit2->fHit.fX;
264 float iH2Y = iHit2->fHit.fY;
265 double time2 = iHit2->fTime;
266 if (std::fabs(time1 - time2) > fTimeCut) continue;
267
268 float rx0 = iH1X - iH2X; //rx12
269 float ry0 = iH1Y - iH2Y; //ry12
270 float r12 = rx0 * rx0 + ry0 * ry0;
271
272 if (r12 < fMinDistanceSq || r12 > fMaxDistanceSq) continue;
273
274 float t10 = iHit1->fX2plusY2 - iHit2->fX2plusY2;
275 for (iH iHit3 = iHit2 + 1; iHit3 != data.end(); iHit3++) {
276 float iH3X = iHit3->fHit.fX;
277 float iH3Y = iHit3->fHit.fY;
278 double time3 = iHit3->fTime;
279
280 if (std::fabs(time1 - time3) > fTimeCut) continue;
281 if (std::fabs(time2 - time3) > fTimeCut) continue;
282
283 float rx1 = iH1X - iH3X; //rx13
284 float ry1 = iH1Y - iH3Y; //ry13
285 float r13 = rx1 * rx1 + ry1 * ry1;
286 if (r13 < fMinDistanceSq || r13 > fMaxDistanceSq) continue;
287
288 float rx2 = iH2X - iH3X; //rx23
289 float ry2 = iH2Y - iH3Y; //ry23
290 float r23 = rx2 * rx2 + ry2 * ry2;
291 if (r23 < fMinDistanceSq || r23 > fMaxDistanceSq) continue;
292
293 float det = rx2 * ry0 - rx0 * ry2;
294 if (det == 0.0f) continue;
295 float t19 = 0.5f / det;
296 float t5 = iHit2->fX2plusY2 - iHit3->fX2plusY2;
297
298 float xc = (t5 * ry0 - t10 * ry2) * t19;
299 xcs = xc - fCurMinX;
300 int intX = int(xcs * dx);
301 if (intX < 0 || intX >= fNofBinsX) continue;
302
303 float yc = (t10 * rx2 - t5 * rx0) * t19;
304 ycs = yc - fCurMinY;
305 int intY = int(ycs * dy);
306 if (intY < 0 || intY >= fNofBinsY) continue;
307
308 //radius calculation
309 float t6 = iH1X - xc;
310 float t7 = iH1Y - yc;
311 //if (t6 > fMaxRadius || t7 > fMaxRadius) continue;
312 float r = sqrt(t6 * t6 + t7 * t7);
313 //if (r < fMinRadius) continue;
314 int intR = int(r * dr);
315 if (intR < 0 || intR >= fNofBinsR) continue;
316
317 fHist[intX * fNofBinsX + intY]++;
318 fHistR[intR]++;
319 } // iHit1
320 } // iHit2
321 } // iHit3
322 //hitIndPart.clear();
323}
324
325void CbmRichRingFinderHoughImpl::FindPeak(int indmin, int indmax)
326{
327 // Find MAX bin R and compare it with CUT
328 int maxBinR = -1, maxR = -1;
329 unsigned int size = fHistR.size();
330 for (unsigned int k = 0; k < size; k++) {
331 if (fHistR[k] > maxBinR) {
332 maxBinR = fHistR[k];
333 maxR = k;
334 }
335 }
336 //cout << "maxBinR:" << maxBinR << endl;
337 if (maxBinR < fHTCutR) return;
338
339 // Find MAX bin XY and compare it with CUT
340 int maxBinXY = -1, maxXY = -1;
341 size = fHist.size();
342 for (unsigned int k = 0; k < size; k++) {
343 if (fHist[k] > maxBinXY) {
344 maxBinXY = fHist[k];
345 maxXY = k;
346 }
347 }
348 //cout << "maxBinXY:" << maxBinXY << endl;
349 if (maxBinXY < fHTCut) return;
350
351 CbmRichRingLight* ring1 = new CbmRichRingLight();
352
353 // Find Preliminary Xc, Yc, R
354 float xc, yc, r;
355 float rx, ry, dr;
356 xc = (maxXY / fNofBinsX + 0.5f) * fDx + fCurMinX;
357 yc = (maxXY % fNofBinsX + 0.5f) * fDy + fCurMinY;
358 r = (maxR + 0.5f) * fDr;
359 for (int j = indmin; j < indmax + 1; j++) {
360 if (std::fabs(fCurTime - fData[j].fTime) > fTimeCut) continue;
361 rx = fData[j].fHit.fX - xc;
362 ry = fData[j].fHit.fY - yc;
363
364 dr = fabs(sqrt(rx * rx + ry * ry) - r);
365 if (dr > 0.9f) continue;
366 ring1->AddHit(fData[j].fHit);
367 }
368
369 if (ring1->GetNofHits() < 7) {
370 delete ring1;
371 return;
372 }
373
374 fFitCOP->DoFit(ring1);
375 float drCOPCut = fRmsCoeffCOP * sqrt(ring1->GetChi2() / ring1->GetNofHits());
376 if (drCOPCut > fMaxCutCOP) drCOPCut = fMaxCutCOP;
377
378 xc = ring1->GetCenterX();
379 yc = ring1->GetCenterY();
380 r = ring1->GetRadius();
381
382 delete ring1;
383
384 CbmRichRingLight* ring2 = new CbmRichRingLight();
385 for (int j = indmin; j < indmax + 1; j++) {
386 if (std::fabs(fCurTime - fData[j].fTime) > fTimeCut) continue;
387
388 rx = fData[j].fHit.fX - xc;
389 ry = fData[j].fHit.fY - yc;
390
391
392 dr = fabs(sqrt(rx * rx + ry * ry) - r);
393 if (dr > drCOPCut) continue;
394 //fData[j+indmin].fIsUsed = true;
395 ring2->AddHit(fData[j].fHit);
396 }
397
398 if (ring2->GetNofHits() < 7) {
399 delete ring2;
400 return;
401 }
402
403 fFitCOP->DoFit(ring2);
404
405 if (fUseAnnSelect) fANNSelect->DoSelect(ring2);
406 float select = (fUseAnnSelect) ? ring2->GetSelectionNN() : 1.;
407 // cout << select << endl;
408
409 // Remove found hits only for good quality rings
410 if (select > fAnnCut) {
411 RemoveHitsAroundRing(indmin, indmax, ring2);
412 }
413
414 if (select > -0.7) {
415 fFoundRings.push_back(ring2);
416 ring2 = NULL;
417 }
418 delete ring2;
419}
420
422{
423 float rms = sqrt(ring->GetChi2() / ring->GetNofHits());
424 float dCut = fRmsCoeffEl * rms;
425 if (dCut > fMaxCutEl) dCut = fMaxCutEl;
426
427 for (int j = indmin; j < indmax + 1; j++) {
428 if (std::fabs(fCurTime - fData[j].fTime) > fTimeCut) continue;
429 float rx = fData[j].fHit.fX - ring->GetCenterX();
430 float ry = fData[j].fHit.fY - ring->GetCenterY();
431
432 float dr = fabs(sqrt(rx * rx + ry * ry) - ring->GetRadius());
433 if (dr < dCut) {
434 fData[j].fIsUsed = true;
435 }
436 }
437}
438
440{
441 int nofRings = fFoundRings.size();
442 sort(fFoundRings.begin(), fFoundRings.end(), [](const CbmRichRingLight* ring1, const CbmRichRingLight* ring2) {
443 return ring1->GetSelectionNN() > ring2->GetSelectionNN();
444 });
445 set<unsigned int> usedHitsAll;
446 vector<unsigned int> goodRingIndex;
447 goodRingIndex.reserve(nofRings);
448 // CbmRichRingLight* ring2;
449
450 for (int iRing = 0; iRing < nofRings; iRing++) {
451 CbmRichRingLight* ring = fFoundRings[iRing];
452 ring->SetRecFlag(-1);
453 int nofHits = ring->GetNofHits();
454 bool isGoodRingAll = true;
455 int nofUsedHitsAll = 0;
456 for (int iHit = 0; iHit < nofHits; iHit++) {
457 set<unsigned int>::iterator it = usedHitsAll.find(ring->GetHitId(iHit));
458 if (it != usedHitsAll.end()) {
459 nofUsedHitsAll++;
460 }
461 }
462 if ((float) nofUsedHitsAll / (float) nofHits > fUsedHitsAllCut) {
463 isGoodRingAll = false;
464 }
465
466 if (isGoodRingAll) {
467 fFoundRings[iRing]->SetRecFlag(1);
468 for (unsigned int iRSet = 0; iRSet < goodRingIndex.size(); iRSet++) {
469 ReAssignSharedHits(goodRingIndex[iRSet], iRing);
470 }
471 goodRingIndex.push_back(iRing);
472 for (int iHit = 0; iHit < nofHits; iHit++) {
473 usedHitsAll.insert(ring->GetHitId(iHit));
474 }
475 } // isGoodRing
476 } // iRing
477
478 // usedHits.clear();
479 usedHitsAll.clear();
480 goodRingIndex.clear();
481}
482
484{
485 CbmRichRingLight* ring1 = fFoundRings[ringInd1];
486 CbmRichRingLight* ring2 = fFoundRings[ringInd2];
487 int nofHits1 = ring1->GetNofHits();
488 int nofHits2 = ring2->GetNofHits();
489
490 for (int iHit1 = 0; iHit1 < nofHits1; iHit1++) {
491 unsigned int hitId1 = ring1->GetHitId(iHit1);
492 for (int iHit2 = 0; iHit2 < nofHits2; iHit2++) {
493 unsigned int hitId2 = ring2->GetHitId(iHit2);
494 if (hitId1 != hitId2) continue;
495 int hitIndData = GetHitIndexById(hitId1);
496 float hitX = fData[hitIndData].fHit.fX;
497 float hitY = fData[hitIndData].fHit.fY;
498 float rx1 = hitX - ring1->GetCenterX();
499 float ry1 = hitY - ring1->GetCenterY();
500 float dr1 = fabs(sqrt(rx1 * rx1 + ry1 * ry1) - ring1->GetRadius());
501
502 float rx2 = hitX - ring2->GetCenterX();
503 float ry2 = hitY - ring2->GetCenterY();
504 float dr2 = fabs(sqrt(rx2 * rx2 + ry2 * ry2) - ring2->GetRadius());
505
506 if (dr1 > dr2) {
507 ring1->RemoveHit(hitId1);
508 }
509 else {
510 ring2->RemoveHit(hitId2);
511 }
512 } //iHit2
513 } //iHit1
514}
515
517{
518 unsigned int size = fData.size();
519 for (unsigned int i = 0; i < size; i++) {
520 if (fData[i].fHit.fId == hitId) return i;
521 }
522 return -1;
523}
524
525void CbmRichRingFinderHoughImpl::CalculateRingParameters(float x[], float y[], float* xc, float* yc, float* r)
526{
527 float t1, t2, t3, t4, t5, t6, t8, t9, t10, t11, t14, t16, t19, t21, t41;
528
529 t1 = x[1] * x[1];
530 t2 = x[2] * x[2];
531 t3 = y[1] * y[1];
532 t4 = y[2] * y[2];
533 t5 = t1 - t2 + t3 - t4;
534 t6 = y[0] - y[1];
535 t8 = x[0] * x[0];
536 t9 = y[0] * y[0];
537 t10 = t8 - t1 + t9 - t3;
538 t11 = y[1] - y[2];
539 t14 = x[1] - x[2];
540 t16 = x[0] - x[1];
541 t19 = 1.0f / (t14 * t6 - t16 * t11);
542
543 *xc = 0.5e0 * (t5 * t6 - t10 * t11) * t19;
544 *yc = 0.5e0 * (t10 * t14 - t5 * t16) * t19;
545
546 t21 = (x[0] - *xc) * (x[0] - *xc);
547 t41 = (y[0] - *yc) * (y[0] - *yc);
548 *r = sqrt(t21 + t41);
549}
static TFile * fHist
Ring finder implementation based on Hough Transform method.
Here the ring is fitted with the COP algorithm from A. Ayriyan/G. Ososkov.
Implementation for concrete RICH ring selection algorithm: reject rings using a trained neural net (i...
friend fvec sqrt(const fvec &a)
static constexpr size_t size()
Definition KfSimdPseudo.h:2
Implementation of RICH hit for ring finder algorithm.
void RemoveHitsAroundRing(int indmin, int indmax, CbmRichRingLight *ring)
Set fIsUsed flag to true for hits attached to the ring.
int GetHitIndexById(unsigned int hitId)
Return hit indez in the internal Array.
vector< vector< unsigned int > > fHitInd
void CalculateRingParameters(float x[], float y[], float *xc, float *yc, float *r)
Calculate circle center and radius.
void SetParameters()
Set parameters of the algorithm.
virtual void HoughTransformGroup(unsigned int indmin, unsigned int indmax, int iPart)
void DoFind()
Start point to run algorithm.
void RingSelection()
Ring selection procedure.
vector< CbmRichRingLight * > fFoundRings
void FindPeak(int indmin, int indmax)
CbmRichRingFinderHoughImpl()
Standard constructor.
virtual void HoughTransform(unsigned int indmin, unsigned int indmax)
Run HoughTransformGroup for each group of hits.
virtual void HoughTransformReconstruction()
Run HT for each hit.
virtual void DefineLocalAreaAndHits(float x0, float y0, int *indmin, int *indmax)
Find hits in a local area.
void ReAssignSharedHits(int ringInd1, int ringInd2)
Reassign shared hits from two rings to only one of the rings.
virtual ~CbmRichRingFinderHoughImpl()
Distructor.
Here the ring is fitted with the COP algorithm from A. Ayriyan/G. Ososkov.
virtual void DoFit(CbmRichRingLight *ring)
Inherited from CbmRichRingFitterBase.
float GetCenterX() const
float GetSelectionNN() const
float GetRadius() const
float GetCenterY() const
int GetNofHits() const
Return number of hits in ring.
float GetChi2() const
unsigned int GetHitId(int ind)
Return hit index in TClonesArray.
bool RemoveHit(int hitId)
Remove hit from the ring.
void AddHit(CbmRichHitLight hit)
Add new hit to the ring.
Implementation for concrete RICH ring selection algorithm: reject rings using a trained neural net (i...
void DoSelect(CbmRichRingLight *ring)
virtual void Init()
Initialize ANN.