EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CbmRichRingFinderHoughImpl.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CbmRichRingFinderHoughImpl.cxx
1 
2 // --------------------------------------------------------------------------------------
3 // CbmRichRingFinderHoughBase source file
4 // Base class for ring finders based on on HT method
5 // Implementation: Semen Lebedev (s.lebedev@gsi.de)
6 
8 #include "CbmRichRingLight.h"
10 
11 
12 #include <iostream>
13 #include <cmath>
14 #include <set>
15 #include <algorithm>
16 #include <iostream>
17 
18 
19 using std::cout;
20 using std::endl;
21 using std::vector;
22 
23 // ----- Standard constructor ------------------------------------------
25 {
26 
27 }
28 
30 {
31  SetParameters();
32  fHist.resize(fNofBinsXY);
33  fHistR.resize(fNofBinsR);
34  fHitInd.resize(fNofParts);
35 
37 
39  fANNSelect->Init();
40 
41 }
42 
43 // ----- Destructor ----------------------------------------------------
45 {
46  delete fFitCOP;
47  delete fANNSelect;
48 }
49 
51 {
52  if (fData.size() > kMAX_NOF_HITS) {
53  cout<< "-E- CbmRichRingFinderHoughImpl::DoFind: Number of hits is more than "<< kMAX_NOF_HITS << endl;
54  return ;
55  }
56 
57  for_each(fFoundRings.begin(), fFoundRings.end(), DeleteObject());
58  fFoundRings.clear();
59  fFoundRings.reserve(100);
60 
61  std::sort(fData.begin(), fData.end(), CbmRichHoughHitCmpUp());
63  RingSelection();
64  fData.clear();
65 }
66 
68 {
69  fMaxDistance = 11.5;
70  fMinDistance = 3.;
73 
74  fMinRadius = 3.3;
75  fMaxRadius = 5.7;
76 
77  fHTCut = 5;
78  fHitCut = 2;
79  fHTCutR = 5;
80  fHitCutR = 2;
82 
83  fNofBinsX = 17;
84  fNofBinsY = 25;
85  fNofBinsR = 32;
86 
87  fAnnCut = -0.6;
88  fUsedHitsCut = 0.4;
89  fUsedHitsAllCut = 0.4;
90 
91  fRmsCoeffEl = 2.5;
92  fMaxCutEl = 1.2;
93  fRmsCoeffCOP = 3.;
94  fMaxCutCOP = 1.2;
95 
96  fDx = 1.36 * fMaxDistance / (float) fNofBinsX;
97  fDy = 2. * fMaxDistance / (float) fNofBinsY;
98  fDr = fMaxRadius / (float) fNofBinsR;
100 }
101 
103 {
104  int indmin, indmax;
105  for (unsigned int iHit = 0; iHit < fData.size(); iHit++)
106  {
107  if (fData[iHit].fIsUsed == true) continue;
108 
109  fCurMinX = fData[iHit].fHit.fX - 0.36f*fMaxDistance;
110  fCurMinY = fData[iHit].fHit.fY - fMaxDistance;
111 
112  DefineLocalAreaAndHits(fData[iHit].fHit.fX, fData[iHit].fHit.fY , &indmin, &indmax);
113  HoughTransform(indmin, indmax);
114  FindPeak(indmin, indmax);
115  }//main loop over hits
116 }
117 
119  int *indmin, int *indmax)
120 {
121  CbmRichHoughHit mpnt;
122  std::vector<CbmRichHoughHit>::iterator itmin, itmax;
123 
124  //find all hits which are in the corridor
125  mpnt.fHit.fX = x0 - 0.36f*fMaxDistance;
126  itmin = std::lower_bound(fData.begin(), fData.end(), mpnt, CbmRichHoughHitCmpUp());
127 
128  mpnt.fHit.fX = x0 + fMaxDistance;
129  itmax = std::lower_bound(fData.begin(), fData.end(), mpnt, CbmRichHoughHitCmpUp()) - 1;
130 
131  *indmin = itmin - fData.begin();
132  *indmax = itmax - fData.begin();
133 
134  int arSize = *indmax - *indmin + 1;
135  if (arSize <= fMinNofHitsInArea) return;
136 
137 // for (int i = 0; i < fNofParts; i++){
138 // fHitInd[i].clear();
139 // fHitInd[i].reserve( (*indmax-*indmin) / fNofParts);
140 // }
141 
142  fDataPart1.clear();
143  fDataPart1.reserve( (*indmax-*indmin) / fNofParts);
144  fDataPart2.clear();
145  fDataPart2.reserve( (*indmax-*indmin) / fNofParts);
146 
147  register int indmin1=*indmin;
148  register int indmax1=*indmax;
149  register float maxDistance08 = 0.8f*fMaxDistance;
150 
151  if (fNofParts == 2){
152  for (int i = indmin1; i <= indmax1; i+=2) {
153  if (fData[i].fIsUsed == true) continue;
154  register float ry = y0 - fData[i].fHit.fY;
155  if (fabs(ry) > maxDistance08) continue;
156  register float rx = x0 - fData[i].fHit.fX;
157  register float d = rx * rx +ry * ry;
158  if (d > fMaxDistanceSq) continue;
159 // fHitInd[0].push_back(i);
160  fDataPart1.push_back(fData[i]);
161  }
162  for (int i = indmin1+1; i <= indmax1; i+=2) {
163  if (fData[i].fIsUsed == true) continue;
164  register float ry = y0 - fData[i].fHit.fY;
165  if (fabs(ry) > maxDistance08) continue;
166  register float rx = x0 - fData[i].fHit.fX;
167  register float d = rx * rx +ry * ry;
168  if (d > fMaxDistanceSq) continue;
169 // fHitInd[1].push_back(i);
170  fDataPart2.push_back(fData[i]);
171  }
172  }else { //fNofParts!=2
173 // for (int i = indmin1; i <= indmax1; i++) {
174 // if (fData[i]->fIsUsed == true) continue;
175 // ry = y0 - fData[i]->fY;
176 // if (fabs(ry) > maxDistance08) continue;
177 // rx = x0 - fData[i]->fX;
178 // float d = rx * rx +ry * ry;
179 // if (d > fMaxDistanceSq) continue;
180 //
181 // fHitInd[i % fNofParts].push_back(i);
182 // }
183  }
184 
185  for (register unsigned short j = 0; j < fNofBinsXY; j++){
186  fHist[j] = 0;
187  }
188 
189  //InitHist();
190 
191  for (register unsigned short k = 0; k < fNofBinsR; k++) {
192  fHistR[k] = 0;
193  }
194 }
195 
196 void CbmRichRingFinderHoughImpl::HoughTransform(unsigned short int indmin, unsigned short int indmax)
197 {
198  for (int iPart = 0; iPart < fNofParts; iPart++){
199 // int nofHits = fHitInd[iPart].size();
200 // if (nofHits <= fMinNofHitsInArea) continue;
201  HoughTransformGroup(indmin, indmax, iPart);
202  }//iPart
203 }
204 
205 void CbmRichRingFinderHoughImpl::HoughTransformGroup(unsigned short int indmin,
206  unsigned short int indmax, int iPart)
207 {
208  register unsigned short nofHits;// = fHitInd[iPart].size();
209  register float xcs, ycs; // xcs = xc - fCurMinX
210  register float dx = 1.0f/fDx, dy = 1.0f/fDy, dr = 1.0f/fDr;
211 
212  register vector<CbmRichHoughHit> data;
213  if (iPart == 0){
214  data = fDataPart1;
215  nofHits = fDataPart1.size();
216  } else if (iPart == 1) {
217  data = fDataPart2;
218  nofHits = fDataPart2.size();
219  }
220  typedef vector<CbmRichHoughHit>::iterator iH;
221 
222  for (iH iHit1 = data.begin(); iHit1 != data.end(); iHit1++) {
223  register float iH1X = iHit1->fHit.fX;
224  register float iH1Y = iHit1->fHit.fY;
225 
226  for (iH iHit2 = iHit1 + 1; iHit2 != data.end(); iHit2++) {
227  register float iH2X = iHit2->fHit.fX;
228  register float iH2Y = iHit2->fHit.fY;
229 
230  register float rx0 = iH1X - iH2X;//rx12
231  register float ry0 = iH1Y- iH2Y;//ry12
232  register float r12 = rx0 * rx0 + ry0 * ry0;
233  if (r12 < fMinDistanceSq || r12 > fMaxDistanceSq) continue;
234 
235  register float t10 = iHit1->fX2plusY2 - iHit2->fX2plusY2;
236  for (iH iHit3 = iHit2 + 1; iHit3 != data.end(); iHit3++) {
237  register float iH3X = iHit3->fHit.fX;
238  register float iH3Y = iHit3->fHit.fY;
239 
240  register float rx1 = iH1X - iH3X;//rx13
241  register float ry1 = iH1Y - iH3Y;//ry13
242  register float r13 = rx1 * rx1 + ry1 * ry1;
243  if (r13 < fMinDistanceSq || r13 > fMaxDistanceSq)continue;
244 
245  register float rx2 = iH2X - iH3X;//rx23
246  register float ry2 = iH2Y - iH3Y;//ry23
247  register float r23 = rx2 * rx2 + ry2 * ry2;
248  if (r23 < fMinDistanceSq || r23 > fMaxDistanceSq)continue;
249 
250  register float det = rx2*ry0 - rx0*ry2;
251  if (det == 0.0f) continue;
252  register float t19 = 0.5f / det;
253  register float t5 = iHit2->fX2plusY2 - iHit3->fX2plusY2;
254 
255  register float xc = (t5 * ry0 - t10 * ry2) * t19;
256  xcs = xc - fCurMinX;
257  register int intX = int( xcs *dx);
258  if (intX < 0 || intX >= fNofBinsX ) continue;
259 
260  register float yc = (t10 * rx2 - t5 * rx0) * t19;
261  ycs = yc - fCurMinY;
262  register int intY = int( ycs *dy);
263  if (intY < 0 || intY >= fNofBinsY ) continue;
264 
265  //radius calculation
266  register float t6 = iH1X - xc;
267  register float t7 = iH1Y - yc;
268  //if (t6 > fMaxRadius || t7 > fMaxRadius) continue;
269  register float r = sqrt(t6 * t6 + t7 * t7);
270  //if (r < fMinRadius) continue;
271  register int intR = int(r *dr);
272  if (intR < 0 || intR >= fNofBinsR) continue;
273 
274  fHist[intX * fNofBinsX + intY]++;
275  fHistR[intR]++;
276  }//iHit1
277  }//iHit2
278  }//iHit3
279  //hitIndPart.clear();
280 }
281 
282 void CbmRichRingFinderHoughImpl::FindPeak(int indmin, int indmax)
283 {
284 //Find MAX bin R and compare it with CUT
285  int maxBinR = -1, maxR = -1;
286  register unsigned int size = fHistR.size();
287  for (unsigned int k = 0; k < size; k++){
288  if (fHistR[k] > maxBinR){
289  maxBinR = fHistR[k];
290  maxR = k;
291  }
292  }
293  if (maxBinR < fHTCutR) return;
294 
295 //Find MAX bin XY and compare it with CUT
296  int maxBinXY = -1, maxXY = -1;
297  size = fHist.size();
298  for (unsigned int k = 0; k < size; k++){
299  if (fHist[k] > maxBinXY){
300  maxBinXY = fHist[k];
301  maxXY = k;
302  }
303  }
304  if (maxBinXY < fHTCut) return;
305 
306  CbmRichRingLight* ring1 = new CbmRichRingLight();
307 
308 //Find Preliminary Xc, Yc, R
309  register float xc, yc, r;
310  register float rx, ry, dr;
311  xc = (maxXY/fNofBinsX + 0.5f)* fDx + fCurMinX;
312  yc = (maxXY%fNofBinsX + 0.5f)* fDy + fCurMinY;
313  r = (maxR + 0.5f)* fDr;
314  for (int j = indmin; j < indmax + 1; j++) {
315  rx = fData[j].fHit.fX - xc;
316  ry = fData[j].fHit.fY - yc;
317 
318  dr = fabs(sqrt(rx * rx + ry * ry) - r);
319  if (dr > 0.6f) continue;
320  ring1->AddHit(fData[j].fHit, fData[j].fId);
321  }
322 
323  if (ring1->GetNofHits() < 7) return;
324 
325  fFitCOP->DoFit(ring1);
326  float drCOPCut = fRmsCoeffCOP*sqrt(ring1->GetChi2()/ring1->GetNofHits());
327  if (drCOPCut > fMaxCutCOP) drCOPCut = fMaxCutCOP;
328 
329  xc = ring1->GetCenterX();
330  yc = ring1->GetCenterY();
331  r = ring1->GetRadius();
332 
333  delete ring1;
334 
335  CbmRichRingLight* ring2 = new CbmRichRingLight();
336  for (int j = indmin; j < indmax + 1; j++) {
337  rx = fData[j].fHit.fX - xc;
338  ry = fData[j].fHit.fY - yc;
339 
340  dr = fabs(sqrt(rx * rx + ry * ry) - r);
341  if (dr > drCOPCut) continue;
342  //fData[j+indmin].fIsUsed = true;
343  ring2->AddHit(fData[j].fHit, fData[j].fId);
344  }
345 
346  if (ring2->GetNofHits() < 7) return;
347 
348  fFitCOP->DoFit(ring2);
349 
350  fANNSelect->DoSelect(ring2);
351  float select = ring2->GetSelectionNN();
352  //cout << ring2->GetRadius() << " " << ring2->GetSelectionNN() << endl;
353  //remove found hits only for good quality rings
354  if (select > fAnnCut) {
355 
356  RemoveHitsAroundRing(indmin, indmax, ring2);
357  //RemoveHitsAroundEllipse(indmin, indmax, ring2);
358 
359  //fFoundRings.push_back(ring2);
360  }
361 
362  if (select > -0.7) {
363  fFoundRings.push_back(ring2);
364  }
365  //fFoundRings.push_back(ring2);
366 }
367 
368 void CbmRichRingFinderHoughImpl::RemoveHitsAroundRing(int indmin, int indmax,
369  CbmRichRingLight* ring)
370 {
371  float rms = sqrt(ring->GetChi2()/ring->GetNofHits());
372  float dCut = fRmsCoeffEl * rms;
373  if (dCut > fMaxCutEl) dCut = fMaxCutEl;
374 
375  for (int j = indmin; j < indmax + 1; j++) {
376  float rx = fData[j].fHit.fX - ring->GetCenterX();
377  float ry = fData[j].fHit.fY - ring->GetCenterY();
378 
379  float dr = fabs(sqrt(rx * rx + ry * ry) - ring->GetRadius());
380  if (dr < dCut) {
381  fData[j].fIsUsed = true;
382  }
383  }
384 }
385 
387 {
388  int nofRings = fFoundRings.size();
389  std::sort(fFoundRings.begin(), fFoundRings.end(), CbmRichRingComparatorMore());
390 
391  std::set<unsigned short> usedHitsAll;
392  std::vector<unsigned short> goodRingIndex;
393  goodRingIndex.reserve(nofRings);
394  CbmRichRingLight* ring2;
395 
396  for (int iRing = 0; iRing < nofRings; iRing++){
397  CbmRichRingLight* ring = fFoundRings[iRing];
398  ring->SetRecFlag(-1);
399  int nofHits = ring->GetNofHits();
400 
401  bool isGoodRingAll = true;
402  int nofUsedHitsAll = 0;
403  for(int iHit = 0; iHit < nofHits; iHit++){
404  std::set<unsigned short>::iterator it = usedHitsAll.find(ring->GetHitId(iHit));
405  if(it != usedHitsAll.end()){
406  nofUsedHitsAll++;
407  }
408  }
409  if ((float)nofUsedHitsAll/(float)nofHits > fUsedHitsAllCut){
410  isGoodRingAll = false;
411  }
412 
413  if (isGoodRingAll){
414  fFoundRings[iRing]->SetRecFlag(1);
415  for (int iRSet = 0; iRSet < goodRingIndex.size(); iRSet++){
416  ReAssingSharedHits(goodRingIndex[iRSet] ,iRing);
417  }
418  goodRingIndex.push_back(iRing);
419 
420  for(int iHit = 0; iHit < nofHits; iHit++){
421 
422  usedHitsAll.insert(ring->GetHitId(iHit));
423  }
424  }// isGoodRing
425  }// iRing
426 
427  usedHitsAll.clear();
428  goodRingIndex.clear();
429 
430 }
431 
432 void CbmRichRingFinderHoughImpl::ReAssingSharedHits(int ringInd1, int ringInd2)
433 {
434  CbmRichRingLight* ring1 = fFoundRings[ringInd1];
435  CbmRichRingLight* ring2 = fFoundRings[ringInd2];
436  int nofHits1 = ring1->GetNofHits();
437  int nofHits2 = ring2->GetNofHits();
438 
439  for(int iHit1 = 0; iHit1 < nofHits1; iHit1++){
440  unsigned short hitInd1 = ring1->GetHitId(iHit1);
441  for(int iHit2 = 0; iHit2 < nofHits2; iHit2++){
442  unsigned short hitInd2 = ring2->GetHitId(iHit2);
443  if(hitInd1 != hitInd2) continue;
444  int hitIndData = GetHitIndex(hitInd1);
445  float hitX = fData[hitIndData].fHit.fX;
446  float hitY = fData[hitIndData].fHit.fY;
447  float rx1 = hitX - ring1->GetCenterX();
448  float ry1 = hitY - ring1->GetCenterY();
449  float dr1 = fabs(sqrt(rx1 * rx1 + ry1 * ry1) - ring1->GetRadius());
450 
451  float rx2 = hitX - ring2->GetCenterX();
452  float ry2 = hitY - ring2->GetCenterY();
453  float dr2 = fabs(sqrt(rx2 * rx2 + ry2 * ry2) - ring2->GetRadius());
454 
455  if (dr1 > dr2){
456  ring1->RemoveHit(hitInd1);
457  } else {
458  ring2->RemoveHit(hitInd2);
459  }
460 
461  }//iHit2
462  }//iHit1
463 }
464 int CbmRichRingFinderHoughImpl::GetHitIndex(unsigned short hitInd)
465 {
466  unsigned int size = fData.size();
467  for (register unsigned int i = 0; i < size; i++){
468  if (fData[i].fId == hitInd) return i;
469  }
470 
471 }