00001
00008 #include "CbmRichRingFinderHoughImpl.h"
00009 #include "CbmRichRingLight.h"
00010 #include "CbmRichRingFitterCOP.h"
00011
00012 #include <iostream>
00013 #include <cmath>
00014 #include <set>
00015 #include <algorithm>
00016 #include <iostream>
00017
00018 using std::cout;
00019 using std::endl;
00020 using std::vector;
00021 using std::set;
00022 using std::sort;
00023
00024 CbmRichRingFinderHoughImpl::CbmRichRingFinderHoughImpl():
00025 fNofParts(0),
00026
00027 fMaxDistance(0.f),
00028 fMinDistance(0.f),
00029 fMinDistanceSq(0.f),
00030 fMaxDistanceSq(0.f),
00031
00032 fMinRadius(0.f),
00033 fMaxRadius(0.f),
00034
00035 fDx(0.f),
00036 fDy(0.f),
00037 fDr(0.f),
00038 fNofBinsX(0),
00039 fNofBinsY(0),
00040 fNofBinsXY(0),
00041
00042 fHTCut(0),
00043
00044 fNofBinsR(0),
00045 fHTCutR(0),
00046
00047 fMinNofHitsInArea(0),
00048
00049 fRmsCoeffCOP(0.f),
00050 fMaxCutCOP(0.f),
00051
00052 fCurMinX(0.f),
00053 fCurMinY(0.f),
00054
00055 fData(),
00056 fHist(),
00057 fHistR(),
00058 fHitInd(),
00059 fFoundRings(),
00060 fFitCOP(NULL)
00061 {
00062 SetParameters();
00063
00064 fHist.resize(fNofBinsXY);
00065 fHistR.resize(fNofBinsR);
00066 fHitInd.resize(fNofParts);
00067
00068 fFitCOP = new CbmRichRingFitterCOP();
00069 }
00070
00071 CbmRichRingFinderHoughImpl::~CbmRichRingFinderHoughImpl()
00072 {
00073 if (NULL != fFitCOP) delete fFitCOP;
00074 }
00075
00076 void CbmRichRingFinderHoughImpl::DoFind(
00077 const vector<CbmRichHitLight>& hits)
00078 {
00079 for (int i = 0 ; i < fFoundRings.size(); i++){
00080 if (fFoundRings[i] != NULL) delete fFoundRings[i];
00081 }
00082 fFoundRings.clear();
00083 fData.clear();
00084
00085 if (hits.size() < 1) return;
00086
00087 if (fData.size() > MAX_NOF_HITS) {
00088 cout << endl << endl << "-E- CbmRichRingFinderHoughImpl::DoFind"
00089 << ". Number of hits is more than " << MAX_NOF_HITS << endl << endl;
00090 return;
00091 }
00092
00093 for (int iH = 0; iH < hits.size(); iH++){
00094 CbmRichHoughHit tempPoint;
00095 tempPoint.fHit.fX = hits[iH].fX;
00096 tempPoint.fHit.fY = hits[iH].fY;
00097 tempPoint.fX2plusY2 = hits[iH].fX * hits[iH].fX + hits[iH].fY * hits[iH].fY;
00098 tempPoint.fId = iH;
00099 tempPoint.fIsUsed = false;
00100 fData.push_back(tempPoint);
00101 }
00102
00103
00104 std::sort(fData.begin(), fData.end(), CbmRichHoughHitCmpUp());
00105 HoughTransformReconstruction();
00106 fData.clear();
00107 }
00108
00109 void CbmRichRingFinderHoughImpl::SetParameters()
00110 {
00111 fMaxDistance = 115.;
00112 fMinDistance = 10.;
00113 fMinDistanceSq = fMinDistance*fMinDistance;
00114 fMaxDistanceSq = fMaxDistance*fMaxDistance;
00115
00116 fMinRadius = 20.;
00117 fMaxRadius = 65.;
00118
00119 fHTCut = 7;
00120 fHTCutR = 5;
00121 fMinNofHitsInArea = 4;
00122
00123 fNofBinsX = 25;
00124 fNofBinsY = 25;
00125 fNofBinsR = 32;
00126
00127 fRmsCoeffCOP = 3.;
00128 fMaxCutCOP = 10.;
00129
00130 fNofParts = 1;
00131 fDx = 2.f * fMaxDistance / (float)fNofBinsX;
00132 fDy = 2.f * fMaxDistance / (float)fNofBinsY;
00133 fDr = fMaxRadius / (float)fNofBinsR;
00134 fNofBinsXY = fNofBinsX * fNofBinsY;
00135 }
00136
00137 void CbmRichRingFinderHoughImpl::HoughTransformReconstruction()
00138 {
00139 int indmin, indmax;
00140 unsigned int size = fData.size();
00141
00142 fCurMinX = fData[0].fHit.fX - fMaxDistance;
00143 fCurMinY = fData[0].fHit.fY - fMaxDistance;
00144
00145 DefineLocalAreaAndHits(fData[0].fHit.fX, fData[0].fHit.fY , &indmin, &indmax);
00146 HoughTransform(indmin, indmax);
00147 FindPeak(indmin, indmax);
00148
00149 DefineLocalAreaAndHits(fData[0].fHit.fX, fData[0].fHit.fY , &indmin, &indmax);
00150 HoughTransform(indmin, indmax);
00151 FindPeak(indmin, indmax);
00152 }
00153
00154 void CbmRichRingFinderHoughImpl::DefineLocalAreaAndHits(
00155 float x0,
00156 float y0,
00157 int *indmin,
00158 int *indmax)
00159 {
00160 CbmRichHoughHit mpnt;
00161 vector<CbmRichHoughHit>::iterator itmin, itmax;
00162
00163
00164 mpnt.fHit.fX = x0 - fMaxDistance;
00165 itmin = std::lower_bound(fData.begin(), fData.end(), mpnt, CbmRichHoughHitCmpUp());
00166
00167 mpnt.fHit.fX = x0 + fMaxDistance;
00168 itmax = std::lower_bound(fData.begin(), fData.end(), mpnt, CbmRichHoughHitCmpUp()) - 1;
00169
00170 *indmin = itmin - fData.begin();
00171 *indmax = itmax - fData.begin();
00172
00173 int arSize = *indmax - *indmin + 1;
00174 if (arSize <= fMinNofHitsInArea) return;
00175
00176 for (unsigned short i = 0; i < fNofParts; i++){
00177 fHitInd[i].clear();
00178 fHitInd[i].reserve( (*indmax-*indmin) / fNofParts);
00179 }
00180
00181 unsigned short indmin1 = (unsigned short)(*indmin);
00182 unsigned short indmax1 = (unsigned short)(*indmax);
00183
00184 for (unsigned short i = indmin1; i <= indmax1; i++) {
00185 if (fData[i].fIsUsed == true) continue;
00186 float ry = y0 - fData[i].fHit.fY;
00187 if (fabs(ry) > fMaxDistance) continue;
00188 float rx = x0 - fData[i].fHit.fX;
00189 float d = rx * rx + ry * ry;
00190 if (d > fMaxDistanceSq) continue;
00191 fHitInd[i % fNofParts].push_back(i);
00192 }
00193
00194 for (unsigned short j = 0; j < fNofBinsXY; j++){
00195 fHist[j] = 0;
00196 }
00197
00198 for (unsigned short k = 0; k < fNofBinsR; k++) {
00199 fHistR[k] = 0;
00200 }
00201 }
00202
00203 void CbmRichRingFinderHoughImpl::HoughTransform(
00204 unsigned short int indmin,
00205 unsigned short int indmax)
00206 {
00207 for (int iPart = 0; iPart < fNofParts; iPart++){
00208 HoughTransformGroup(indmin, indmax, iPart);
00209 }
00210 }
00211
00212 void CbmRichRingFinderHoughImpl::HoughTransformGroup(
00213 unsigned short int indmin,
00214 unsigned short int indmax,
00215 int iPart)
00216 {
00217 unsigned short nofHits = fHitInd[iPart].size();
00218 float xcs, ycs;
00219 float dx = 1.0f/fDx, dy = 1.0f/fDy, dr = 1.0f/fDr;
00220
00221 vector<CbmRichHoughHit> data;
00222 data.resize(nofHits);
00223 for (int i = 0; i < nofHits; i++){
00224 data[i] = fData[ fHitInd[iPart][i] ];
00225 }
00226
00227 typedef vector<CbmRichHoughHit>::iterator iH;
00228
00229 for (iH iHit1 = data.begin(); iHit1 != data.end(); iHit1++) {
00230 float iH1X = iHit1->fHit.fX;
00231 float iH1Y = iHit1->fHit.fY;
00232
00233 for (iH iHit2 = iHit1 + 1; iHit2 != data.end(); iHit2++) {
00234 float iH2X = iHit2->fHit.fX;
00235 float iH2Y = iHit2->fHit.fY;
00236
00237 float rx0 = iH1X - iH2X;
00238 float ry0 = iH1Y- iH2Y;
00239 float r12 = rx0 * rx0 + ry0 * ry0;
00240 if (r12 < fMinDistanceSq || r12 > fMaxDistanceSq) continue;
00241
00242 float t10 = iHit1->fX2plusY2 - iHit2->fX2plusY2;
00243 for (iH iHit3 = iHit2 + 1; iHit3 != data.end(); iHit3++) {
00244 float iH3X = iHit3->fHit.fX;
00245 float iH3Y = iHit3->fHit.fY;
00246
00247 float rx1 = iH1X - iH3X;
00248 float ry1 = iH1Y - iH3Y;
00249 float r13 = rx1 * rx1 + ry1 * ry1;
00250 if (r13 < fMinDistanceSq || r13 > fMaxDistanceSq)continue;
00251
00252 float rx2 = iH2X - iH3X;
00253 float ry2 = iH2Y - iH3Y;
00254 float r23 = rx2 * rx2 + ry2 * ry2;
00255 if (r23 < fMinDistanceSq || r23 > fMaxDistanceSq)continue;
00256
00257 float det = rx2*ry0 - rx0*ry2;
00258 if (det == 0.0f) continue;
00259 float t19 = 0.5f / det;
00260 float t5 = iHit2->fX2plusY2 - iHit3->fX2plusY2;
00261
00262 float xc = (t5 * ry0 - t10 * ry2) * t19;
00263 xcs = xc - fCurMinX;
00264 int intX = int( xcs *dx);
00265 if (intX < 0 || intX >= fNofBinsX ) continue;
00266
00267 float yc = (t10 * rx2 - t5 * rx0) * t19;
00268 ycs = yc - fCurMinY;
00269 int intY = int( ycs *dy);
00270 if (intY < 0 || intY >= fNofBinsY ) continue;
00271
00272
00273 float t6 = iH1X - xc;
00274 float t7 = iH1Y - yc;
00275
00276 float r = sqrt(t6 * t6 + t7 * t7);
00277
00278 int intR = int(r *dr);
00279 if (intR < 0 || intR >= fNofBinsR) continue;
00280
00281 fHist[intX * fNofBinsX + intY]++;
00282 fHistR[intR]++;
00283 }
00284 }
00285 }
00286
00287 }
00288
00289 void CbmRichRingFinderHoughImpl::FindPeak(
00290 int indmin,
00291 int indmax)
00292 {
00293
00294 int maxBinR = -1, maxR = -1;
00295 unsigned int size = fHistR.size();
00296 for (unsigned int k = 0; k < size; k++){
00297 if (fHistR[k] > maxBinR){
00298 maxBinR = fHistR[k];
00299 maxR = k;
00300 }
00301 }
00302 if (maxBinR < fHTCutR) return;
00303
00304
00305 int maxBinXY = -1, maxXY = -1;
00306 size = fHist.size();
00307 for (unsigned int k = 0; k < size; k++){
00308 if (fHist[k] > maxBinXY){
00309 maxBinXY = fHist[k];
00310 maxXY = k;
00311 }
00312 }
00313 if (maxBinXY < fHTCut) return;
00314
00315 CbmRichRingLight* ring1 = new CbmRichRingLight();
00316
00317
00318 float xc, yc, r;
00319 float rx, ry, dr;
00320 xc = (maxXY / fNofBinsX + 0.5f)* fDx + fCurMinX;
00321 yc = (maxXY % fNofBinsX + 0.5f)* fDy + fCurMinY;
00322 r = (maxR + 0.5f) * fDr;
00323 for (int j = indmin; j < indmax + 1; j++) {
00324 rx = fData[j].fHit.fX - xc;
00325 ry = fData[j].fHit.fY - yc;
00326
00327 dr = fabs(sqrt(rx * rx + ry * ry) - r);
00328 if (dr > 6.) continue;
00329 ring1->AddHit(fData[j].fHit, fData[j].fId);
00330 }
00331
00332 if (ring1->GetNofHits() < 5) {
00333 delete ring1;
00334 return;
00335 }
00336
00337 fFitCOP->DoFit(ring1);
00338 float drCOPCut = fRmsCoeffCOP * sqrt(ring1->GetChi2() / ring1->GetNofHits());
00339 if (drCOPCut > fMaxCutCOP) drCOPCut = fMaxCutCOP;
00340
00341 xc = ring1->GetCenterX();
00342 yc = ring1->GetCenterY();
00343 r = ring1->GetRadius();
00344
00345 delete ring1;
00346
00347 CbmRichRingLight* ring2 = new CbmRichRingLight();
00348 for (int j = indmin; j < indmax + 1; j++) {
00349 rx = fData[j].fHit.fX - xc;
00350 ry = fData[j].fHit.fY - yc;
00351
00352 dr = fabs(sqrt(rx * rx + ry * ry) - r);
00353 if (dr > drCOPCut) continue;
00354 fData[j].fIsUsed = true;
00355 ring2->AddHit(fData[j].fHit, fData[j].fId);
00356 }
00357 if (ring2->GetNofHits() < 5) {
00358 delete ring2;
00359 return;
00360 }
00361
00362 fFitCOP->DoFit(ring2);
00363 fFoundRings.push_back(ring2);
00364 ring2=NULL;
00365 delete ring2;
00366 }