Project
Loading...
Searching...
No Matches
Recon.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#include "HMPIDBase/Param.h"
13#include "HMPIDReconstruction/Recon.h" //class header
14// #include "ReconstructionDataFormats/MatchInfoHMP.h"
15
16#include <TRotation.h> //TracePhot()
17#include <TH1D.h> //HoughResponse()
18#include <TRandom.h> //HoughResponse()
19
22
24
25using namespace o2::hmpid;
26// ClassImp(Recon);
28//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
30{
31 //..
32 // Init some variables
33 //..
34 if (n <= 0) {
35 return;
36 }
37
38 // ef : changed to smart-pointer Array
39 // fPhotFlag = new int[n];
40 fPhotFlag = std::unique_ptr<int[]>(new int[n]);
41 fPhotClusIndex = std::unique_ptr<int[]>(new int[n]);
42
43 fPhotCkov = std::unique_ptr<double[]>(new double[n]);
44 fPhotPhi = std::unique_ptr<double[]>(new double[n]);
45 fPhotWei = std::unique_ptr<double[]>(new double[n]);
46 //
47}
48//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
49void Recon::ckovAngle(o2::dataformats::MatchInfoHMP* match, const std::vector<o2::hmpid::Cluster> clusters, int index, double nmean, float xRa, float yRa)
50{
51 // Pattern recognition method based on Hough transform
52 // Arguments: pTrk - track for which Ckov angle is to be found
53 // pCluLst - list of clusters for this chamber
54 // Returns: - track ckov angle, [rad],
55
56 const int nMinPhotAcc = 3; // Minimum number of photons required to perform the pattern recognition
57
58 int nClusTot = clusters.size();
59
60 initVars(nClusTot);
61
62 float xPc, yPc, th, ph;
63
64 match->getHMPIDtrk(xPc, yPc, th, ph); // initialize this track: th and ph angles at middle of RAD
65
66 setTrack(xRa, yRa, th, ph);
67
68 fParam->setRefIdx(nmean);
69
70 float mipQ = -1, mipX = -1, mipY = -1;
71 int chId = -1, sizeClu = -1;
72
73 fPhotCnt = 0;
74
75 int nPads = 0;
76
77 for (int iClu = 0; iClu < clusters.size(); iClu++) { // clusters loop
78
79 o2::hmpid::Cluster cluster = clusters.at(iClu);
80 nPads += cluster.size();
81 if (iClu == index) { // this is the MIP! not a photon candidate: just store mip info
82 mipX = cluster.x();
83 mipY = cluster.y();
84 mipQ = cluster.q();
85 sizeClu = cluster.size();
86 continue;
87 }
88
89 chId = cluster.ch();
90 if (cluster.q() > 2 * fParam->qCut() || cluster.size() > 4) {
91 continue;
92 }
93 double thetaCer, phiCer;
94 if (findPhotCkov(cluster.x(), cluster.y(), thetaCer, phiCer)) { // find ckov angle for this photon candidate
95 fPhotCkov[fPhotCnt] = thetaCer; // actual theta Cerenkov (in TRS)
96 fPhotPhi[fPhotCnt] = phiCer;
97 fPhotClusIndex[fPhotCnt] = iClu; // actual phi Cerenkov (in TRS): -pi to come back to "unusual" ref system (X,Y,-Z)
98 fPhotCnt++; // increment counter of photon candidates
99 }
100 } // clusters loop
101
102 match->setHMPIDmip(mipX, mipY, mipQ, fPhotCnt); // store mip info in any case
103 match->setIdxHMPClus(chId, index + 1000 * sizeClu); // set index of cluster
104 match->setMipClusSize(sizeClu);
105
106 if (fPhotCnt < nMinPhotAcc) { // no reconstruction with <=3 photon candidates
107 match->setHMPsignal(kNoPhotAccept); // set the appropriate flag
108 return;
109 }
110
111 fMipPos.Set(mipX, mipY);
112
113 // PATTERN RECOGNITION STARTED:
114 if (fPhotCnt > fParam->multCut()) {
115 fIsWEIGHT = kTRUE;
116 } // offset to take into account bkg in reconstruction
117 else {
118 fIsWEIGHT = kFALSE;
119 }
120
121 float photCharge[10] = {0x0};
122
123 int iNrec = flagPhot(houghResponse(), clusters, photCharge); // flag photons according to individual theta ckov with respect to most probable
124 // int iNrec = flagPhot(houghResponse(), clusters); // flag photons according to individual theta ckov with respect to most probable
125
126 match->setPhotCharge(photCharge);
127 match->setHMPIDmip(mipX, mipY, mipQ, iNrec); // store mip info
128
129 if (iNrec < nMinPhotAcc) {
130 match->setHMPsignal(kNoPhotAccept); // no photon candidates are accepted
131 return;
132 }
133
134 int occupancy = (int)(1000 * (nPads / (6. * 80. * 48.)));
135
136 double thetaC = findRingCkov(clusters.size()); // find the best reconstructed theta Cherenkov
137 findRingGeom(thetaC, 2);
138
139 match->setHMPsignal(thetaC + occupancy); // store theta Cherenkov and chmaber occupancy
140 // match->SetHMPIDchi2(fCkovSigma2); //store experimental ring angular resolution squared
141
142 // deleteVars(); ef : in case of smart-pointers, should not be necessary?
143} // CkovAngle()
144//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
145bool Recon::findPhotCkov(double cluX, double cluY, double& thetaCer, double& phiCer)
146{
147 // Finds Cerenkov angle for this photon candidate
148 // Arguments: cluX,cluY - position of cadidate's cluster
149 // Returns: Cerenkov angle
150
151 TVector3 dirCkov;
152
153 double zRad = -0.5 * fParam->radThick() - 0.5 * fParam->winThick(); // z position of middle of RAD
154 TVector3 rad(fTrkPos.X(), fTrkPos.Y(), zRad); // impact point at middle of RAD
155 TVector3 pc(cluX, cluY, 0.5 * fParam->winThick() + fParam->gapThick()); // mip at PC
156 double cluR = TMath::Sqrt((cluX - fPc.X()) * (cluX - fPc.X()) +
157 (cluY - fPc.Y()) * (cluY - fPc.Y())); // ref. distance impact RAD-CLUSTER
158 double phi = (pc - rad).Phi(); // phi of photon
159
160 double ckov1 = 0;
161 double ckov2 = 0.75 + fTrkDir.Theta(); // start to find theta cerenkov in DRS
162 const double kTol = 0.01;
163 Int_t iIterCnt = 0;
164 while (1) {
165 if (iIterCnt >= 50) {
166 return kFALSE;
167 }
168 double ckov = 0.5 * (ckov1 + ckov2);
169 dirCkov.SetMagThetaPhi(1, ckov, phi);
170 TVector2 posC = traceForward(dirCkov); // trace photon with actual angles
171 double dist = cluR - (posC - fPc).Mod(); // get distance between trial point and cluster position
172 if (posC.X() == -999) {
173 dist = -999;
174 } // total reflection problem
175 iIterCnt++; // counter step
176 if (dist > kTol) {
177 ckov1 = ckov;
178 } // cluster @ larger ckov
179 else if (dist < -kTol) {
180 ckov2 = ckov;
181 } // cluster @ smaller ckov
182 else { // precision achived: ckov in DRS found
183 dirCkov.SetMagThetaPhi(1, ckov, phi); //
184 lors2Trs(dirCkov, thetaCer, phiCer); // find ckov (in TRS:the effective Cherenkov angle!)
185 return kTRUE;
186 }
187 }
188} // FindPhotTheta()
189//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
190bool Recon::findPhotCkov2(double cluX, double cluY, double& thetaCer, double& phiCer)
191{
192
193 // TVector3 emissionV;
195 // emissionV.SetXYZ(xEm, yEm, zEm);
196
197 // TVector3 directionV;
199 // directionV.SetXYZ(trkPx, trkPy, trkPz);
200
201 double zRad = -0.5 * fParam->radThick() - 0.5 * fParam->winThick(); // z position of middle of RAD
202 TVector3 emissionV(fTrkPos.X(), fTrkPos.Y(), zRad); // impact point at middle of RAD
203
204 TVector3 photonHitV, apparentV, surfaceV;
205 photonHitV.SetXYZ(cluX, cluY, 0.5 * fParam->winThick() + fParam->gapThick());
206 apparentV = photonHitV - emissionV;
207 surfaceV = emissionV;
208 // surfaceV.SetZ(0);
209
210 Double_t n1 = fParam->getRefIdx();
211 Double_t n2 = 1.;
212 Double_t apparentTheta = apparentV.Theta();
213 Double_t correctedTheta = asin(n2 / n1 * sin(apparentTheta));
214 Double_t deltaTheta = apparentTheta - correctedTheta;
215
216 TVector3 perpV = apparentV.Cross(surfaceV);
217 TVector3 cherenkovV = apparentV;
218 // cherenkovV.Rotate(deltaTheta, perpV);
219
220 lors2Trs(cherenkovV, thetaCer, phiCer);
221
222 // thetaCer = cherenkovV.Angle(fTrkDir);
223 // phiCer = cherenkovV.Phi();
224
225 return kTRUE;
226}
227//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
228TVector2 Recon::traceForward(TVector3 dirCkov) const
229{
230 // Trace forward a photon from (x,y) up to PC
231 // Arguments: dirCkov photon vector in LORS
232 // Returns: pos of traced photon at PC
233
234 TVector2 pos(-999, -999);
235 double thetaCer = dirCkov.Theta();
236 if (thetaCer > TMath::ASin(1. / fParam->getRefIdx())) {
237 return pos;
238 } // total refraction on WIN-GAP boundary
239 double zRad = -0.5 * fParam->radThick() - 0.5 * fParam->winThick(); // z position of middle of RAD
240 TVector3 posCkov(fTrkPos.X(), fTrkPos.Y(), zRad); // RAD: photon position is track position @ middle of RAD
241 propagate(dirCkov, posCkov, -0.5 * fParam->winThick()); // go to RAD-WIN boundary
242 refract(dirCkov, fParam->getRefIdx(), fParam->winIdx()); // RAD-WIN refraction
243 propagate(dirCkov, posCkov, 0.5 * fParam->winThick()); // go to WIN-GAP boundary
244 refract(dirCkov, fParam->winIdx(), fParam->gapIdx()); // WIN-GAP refraction
245 propagate(dirCkov, posCkov, 0.5 * fParam->winThick() + fParam->gapThick()); // go to PC
246 pos.Set(posCkov.X(), posCkov.Y());
247 return pos;
248
249} // TraceForward()
250
251//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
252void Recon::lors2Trs(TVector3 dirCkov, double& thetaCer, double& phiCer) const
253{
254 // Theta Cerenkov reconstruction
255 // Arguments: dirCkov photon vector in LORS
256 // Returns: thetaCer of photon in TRS
257 // phiCer of photon in TRS
258 // TVector3 dirTrk;
259 // dirTrk.SetMagThetaPhi(1,fTrkDir.Theta(),fTrkDir.Phi()); -> dirTrk.SetCoordinates(1,fTrkDir.Theta(),fTrkDir.Phi())
260 // double thetaCer = TMath::ACos(dirCkov*dirTrk);
261
262 TRotation mtheta;
263 mtheta.RotateY(-fTrkDir.Theta());
264
265 TRotation mphi;
266 mphi.RotateZ(-fTrkDir.Phi());
267
268 TRotation mrot = mtheta * mphi;
269
270 TVector3 dirCkovTRS;
271 dirCkovTRS = mrot * dirCkov;
272 phiCer = dirCkovTRS.Phi(); // actual value of the phi of the photon
273 thetaCer = dirCkovTRS.Theta(); // actual value of thetaCerenkov of the photon
274}
275//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
276void Recon::trs2Lors(TVector3 dirCkov, double& thetaCer, double& phiCer) const
277{
278 // Theta Cerenkov reconstruction
279 // Arguments: dirCkov photon vector in TRS
280 // Returns: thetaCer of photon in LORS
281 // phiCer of photon in LORS
282
283 // TRotation mtheta;
284 // mtheta.RotateY(fTrkDir.Theta()); ef : changed to :
285
286 TRotation mtheta;
287 mtheta.RotateY(fTrkDir.Theta());
288
289 TRotation mphi;
290 mphi.RotateZ(fTrkDir.Phi());
291
292 TRotation mrot = mphi * mtheta;
293
294 TVector3 dirCkovLORS;
295 dirCkovLORS = mrot * dirCkov;
296
297 phiCer = dirCkovLORS.Phi(); // actual value of the phi of the photon
298 thetaCer = dirCkovLORS.Theta(); // actual value of thetaCerenkov of the photon
299}
300//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
301void Recon::findRingGeom(double ckovAng, int level)
302{
303 // Find area covered in the PC acceptance
304 // Arguments: ckovAng - cerenkov angle
305 // level - precision in finding area and portion of ring accepted (multiple of 50)
306 // Returns: area of the ring in cm^2 for given theta ckov
307
308 Int_t kN = 50 * level;
309 Int_t nPoints = 0;
310 Double_t area = 0;
311
312 Bool_t first = kFALSE;
313 TVector2 pos1;
314
315 for (Int_t i = 0; i < kN; i++) {
316 if (!first) {
317 pos1 = tracePhot(ckovAng, Double_t(TMath::TwoPi() * (i + 1) / kN)); // find a good trace for the first photon
318 if (pos1.X() == -999) {
319 continue;
320 } // no area: open ring
321 if (!fParam->isInside(pos1.X(), pos1.Y(), 0)) {
322 pos1 = intWithEdge(fMipPos, pos1); // find the very first intersection...
323 } else {
324 if (!fParam->isInDead(pos1.X(), pos1.Y())) {
325 nPoints++;
326 } // photon is accepted if not in dead zone
327 }
328 first = kTRUE;
329 continue;
330 }
331 TVector2 pos2 = tracePhot(ckovAng, Double_t(TMath::TwoPi() * (i + 1) / kN)); // trace the next photon
332 if (pos2.X() == -999) {
333 {
334 continue;
335 }
336 } // no area: open ring
337 if (!fParam->isInside(pos2.X(), pos2.Y(), 0)) {
338 pos2 = intWithEdge(fMipPos, pos2);
339 } else {
340 if (!fParam->isInDead(pos2.X(), pos2.Y())) {
341 nPoints++;
342 } // photon is accepted if not in dead zone
343 }
344 area += TMath::Abs((pos1 - fMipPos).X() * (pos2 - fMipPos).Y() - (pos1 - fMipPos).Y() * (pos2 - fMipPos).X()); // add area of the triangle...
345 pos1 = pos2;
346 }
347 //--- find area and length of the ring;
348 fRingAcc = (Double_t)nPoints / (Double_t)kN;
349 area *= 0.5;
350 fRingArea = area;
351
352} // FindRingGeom()
353//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
354const TVector2 Recon::intWithEdge(TVector2 p1, TVector2 p2)
355{
356 // It finds the intersection of the line for 2 points traced as photons
357 // and the edge of a given PC
358 // Arguments: 2 points obtained tracing the photons
359 // Returns: intersection point with detector (PC) edges
360
361 double xmin = (p1.X() < p2.X()) ? p1.X() : p2.X();
362 double xmax = (p1.X() < p2.X()) ? p2.X() : p1.X();
363 double ymin = (p1.Y() < p2.Y()) ? p1.Y() : p2.Y();
364 double ymax = (p1.Y() < p2.Y()) ? p2.Y() : p1.Y();
365
366 double m = TMath::Tan((p2 - p1).Phi());
367 TVector2 pint;
368 // intersection with low X
369 pint.Set((double)(p1.X() + (0 - p1.Y()) / m), 0.);
370 if (pint.X() >= 0 && pint.X() <= fParam->sizeAllX() &&
371 pint.X() >= xmin && pint.X() <= xmax &&
372 pint.Y() >= ymin && pint.Y() <= ymax) {
373 return pint;
374 }
375 // intersection with high X
376 pint.Set((double)(p1.X() + (fParam->sizeAllY() - p1.Y()) / m), (double)(fParam->sizeAllY()));
377 if (pint.X() >= 0 && pint.X() <= fParam->sizeAllX() &&
378 pint.X() >= xmin && pint.X() <= xmax &&
379 pint.Y() >= ymin && pint.Y() <= ymax) {
380 return pint;
381 }
382 // intersection with left Y
383 pint.Set(0., (double)(p1.Y() + m * (0 - p1.X())));
384 if (pint.Y() >= 0 && pint.Y() <= fParam->sizeAllY() &&
385 pint.Y() >= ymin && pint.Y() <= ymax &&
386 pint.X() >= xmin && pint.X() <= xmax) {
387 return pint;
388 }
389 // intersection with righ Y
390 pint.Set((double)(fParam->sizeAllX()), (double)(p1.Y() + m * (fParam->sizeAllX() - p1.X()))); // ef: Set->SetCoordinates
391 if (pint.Y() >= 0 && pint.Y() <= fParam->sizeAllY() &&
392 pint.Y() >= ymin && pint.Y() <= ymax &&
393 pint.X() >= xmin && pint.X() <= xmax) {
394 return pint;
395 }
396 return p1;
397} // IntWithEdge()
398//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
400{
401 // Loops on all Ckov candidates and estimates the best Theta Ckov for a ring formed by those candidates. Also estimates an error for that Theat Ckov
402 // collecting errors for all single Ckov candidates thetas. (Assuming they are independent)
403 // Arguments: iNclus- total number of clusters in chamber for background estimation
404 // Return: best estimation of track Theta ckov
405
406 Double_t wei = 0.;
407 Double_t weightThetaCerenkov = 0.;
408
409 Double_t ckovMin = 9999., ckovMax = 0.;
410 Double_t sigma2 = 0; // to collect error squared for this ring
411
412 for (Int_t i = 0; i < fPhotCnt; i++) { // candidates loop
413 if (fPhotFlag[i] == 2) {
414 if (fPhotCkov[i] < ckovMin) {
415 ckovMin = fPhotCkov[i];
416 } // find max and min Theta ckov from all candidates within probable window
417 if (fPhotCkov[i] > ckovMax) {
418 ckovMax = fPhotCkov[i];
419 }
420 weightThetaCerenkov += fPhotCkov[i] * fPhotWei[i];
421 wei += fPhotWei[i]; // collect weight as sum of all candidate weghts
422
423 sigma2 += 1. / fParam->sigma2(fTrkDir.Theta(), fTrkDir.Phi(), fPhotCkov[i], fPhotPhi[i]);
424 }
425 } // candidates loop
426
427 if (sigma2 > 0) {
428 fCkovSigma2 = 1. / sigma2;
429 } else {
430 fCkovSigma2 = 1e10;
431 }
432
433 if (wei != 0.) {
434 weightThetaCerenkov /= wei;
435 } else {
436 weightThetaCerenkov = 0.;
437 }
438 return weightThetaCerenkov;
439
440} // FindCkovRing()
441//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
442int Recon::flagPhot(double ckov, const std::vector<o2::hmpid::Cluster> clusters, float* photChargeVec)
443// int Recon::flagPhot(double ckov, const std::vector<o2::hmpid::Cluster> clusters)
444{
445 // Flag photon candidates if their individual ckov angle is inside the window around ckov angle returned by HoughResponse()
446 // Arguments: ckov- value of most probable ckov angle for track as returned by HoughResponse()
447 // Returns: number of photon candidates happened to be inside the window
448
449 // Photon Flag: Flag = 0 initial set;
450 // Flag = 1 good candidate (charge compatible with photon);
451 // Flag = 2 photon used for the ring;
452
453 Int_t steps = (Int_t)((ckov) / fDTheta); // how many times we need to have fDTheta to fill the distance between 0 and thetaCkovHough
454
455 Double_t tmin = (Double_t)(steps - 1) * fDTheta;
456 Double_t tmax = (Double_t)(steps)*fDTheta;
457 Double_t tavg = 0.5 * (tmin + tmax);
458
459 tmin = tavg - 0.5 * fWindowWidth;
460 tmax = tavg + 0.5 * fWindowWidth;
461
462 Int_t iInsideCnt = 0; // count photons which Theta ckov inside the window
463 for (Int_t i = 0; i < fPhotCnt; i++) { // photon candidates loop
464 fPhotFlag[i] = 0;
465 if (fPhotCkov[i] >= tmin && fPhotCkov[i] <= tmax) {
466 fPhotFlag[i] = 2;
468 float charge = cluster.q();
469 if (iInsideCnt < 10) {
470 photChargeVec[iInsideCnt] = charge;
471 } // AddObjectToFriends(pCluLst,i,pTrk);
472 iInsideCnt++;
473 }
474 }
475
476 return iInsideCnt;
477
478} // FlagPhot()
479//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
480TVector2 Recon::tracePhot(double ckovThe, double ckovPhi) const
481{
482 // Trace a single Ckov photon from emission point somewhere in radiator up to photocathode taking into account ref indexes of materials it travereses
483 // Arguments: ckovThe,ckovPhi- photon ckov angles in TRS, [rad]
484 // Returns: distance between photon point on PC and track projection
485
486 double theta, phi;
487 TVector3 dirTRS, dirLORS;
488 dirTRS.SetMagThetaPhi(1, ckovThe, ckovPhi); // photon in TRS
489 trs2Lors(dirTRS, theta, phi);
490 dirLORS.SetMagThetaPhi(1, theta, phi); // photon in LORS
491 return traceForward(dirLORS); // now foward tracing
492
493} // tracePhot()
494//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
495void Recon::propagate(const TVector3 dir, TVector3& pos, double z) const
496{
497 // Finds an intersection point between a line and XY plane shifted along Z.
498 // Arguments: dir,pos - vector along the line and any point of the line
499 // z - z coordinate of plain
500 // Returns: none
501 // On exit: pos is the position if this intesection if any
502 static TVector3 nrm(0, 0, 1);
503 TVector3 pnt(0, 0, z);
504
505 TVector3 diff = pnt - pos;
506 double sint = (nrm * diff) / (nrm * dir);
507 pos += sint * dir;
508} // Propagate()
509//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
510void Recon::refract(TVector3& dir, double n1, double n2) const
511{
512 // Refract direction vector according to Snell law
513 // Arguments:
514 // n1 - ref idx of first substance
515 // n2 - ref idx of second substance
516 // Returns: none
517 // On exit: dir is new direction
518
519 double sinref = (n1 / n2) * TMath::Sin(dir.Theta());
520 if (TMath::Abs(sinref) > 1.) {
521 dir.SetXYZ(-999, -999, -999);
522 } else {
523 dir.SetTheta(TMath::ASin(sinref));
524 }
525}
526//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
528{
529 // fIdxMip = mipId;
530
531 Double_t kThetaMax = 0.75;
532 Int_t nChannels = (Int_t)(kThetaMax / fDTheta + 0.5);
533 TH1D* phots = new TH1D("Rphot", "phots", nChannels, 0, kThetaMax);
534 TH1D* photsw = new TH1D("RphotWeighted", "photsw", nChannels, 0, kThetaMax);
535 TH1D* resultw = new TH1D("resultw", "resultw", nChannels, 0, kThetaMax);
536 Int_t nBin = (Int_t)(kThetaMax / fDTheta);
537 Int_t nCorrBand = (Int_t)(fWindowWidth / (2 * fDTheta));
538
539 for (Int_t i = 0; i < fPhotCnt; i++) { // photon cadidates loop
540 Double_t angle = fPhotCkov[i];
541 if (angle < 0 || angle > kThetaMax) {
542 continue;
543 }
544 phots->Fill(angle);
545 Int_t bin = (Int_t)(0.5 + angle / (fDTheta));
546 Double_t weight = 1.;
547 if (fIsWEIGHT) {
548 Double_t lowerlimit = ((Double_t)bin) * fDTheta - 0.5 * fDTheta;
549 Double_t upperlimit = ((Double_t)bin) * fDTheta + 0.5 * fDTheta;
550 findRingGeom(lowerlimit);
551 Double_t areaLow = getRingArea();
552 findRingGeom(upperlimit);
553 Double_t areaHigh = getRingArea();
554 Double_t diffArea = areaHigh - areaLow;
555 if (diffArea > 0) {
556 weight = 1. / diffArea;
557 }
558 }
559 photsw->Fill(angle, weight);
560 fPhotWei[i] = weight;
561 } // photon candidates loop
562
563 for (Int_t i = 1; i <= nBin; i++) {
564 Int_t bin1 = i - nCorrBand;
565 Int_t bin2 = i + nCorrBand;
566 if (bin1 < 1) {
567 bin1 = 1;
568 }
569 if (bin2 > nBin) {
570 bin2 = nBin;
571 }
572 Double_t sumPhots = phots->Integral(bin1, bin2);
573 if (sumPhots < 3) {
574 continue;
575 } // if less then 3 photons don't trust to this ring
576 Double_t sumPhotsw = photsw->Integral(bin1, bin2);
577 if ((Double_t)((i + 0.5) * fDTheta) > 0.7) {
578 continue;
579 }
580 resultw->Fill((Double_t)((i + 0.5) * fDTheta), sumPhotsw);
581 }
582 // evaluate the "BEST" theta ckov as the maximum value of histogramm
583 Double_t* pVec = resultw->GetArray();
584 Int_t locMax = TMath::LocMax(nBin, pVec);
585 delete phots;
586 delete photsw;
587 delete resultw; // Reset and delete objects
588
589 return (Double_t)(locMax * fDTheta + 0.5 * fDTheta); // final most probable track theta ckov
590
591} // HoughResponse()
592//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
593double Recon::findRingExt(double ckov, Int_t ch, double xPc, double yPc, double thRa, double phRa)
594{
595 // To find the acceptance of the ring even from external inputs.
596 //
597 //
598 double xRa = xPc - (fParam->radThick() + fParam->winThick() + fParam->gapThick()) * TMath::Cos(phRa) * TMath::Tan(thRa); // just linear extrapolation back to RAD
599 double yRa = yPc - (fParam->radThick() + fParam->winThick() + fParam->gapThick()) * TMath::Sin(phRa) * TMath::Tan(thRa);
600
601 int nStep = 500;
602 int nPhi = 0;
603
604 Int_t ipc, ipadx, ipady;
605
606 if (ckov > 0) {
607 setTrack(xRa, yRa, thRa, phRa);
608 for (int j = 0; j < nStep; j++) {
609 TVector2 pos;
610 pos = tracePhot(ckov, j * TMath::TwoPi() / (double)(nStep - 1));
611 if (Param::isInDead(pos.X(), pos.Y())) {
612 continue;
613 }
614 fParam->lors2Pad(pos.X(), pos.Y(), ipc, ipadx, ipady);
615 ipadx += (ipc % 2) * fParam->kPadPcX;
616 ipady += (ipc / 2) * fParam->kPadPcY;
617 if (ipadx < 0 || ipady > 160 || ipady < 0 || ipady > 144 || ch < 0 || ch > 6) {
618 continue;
619 }
620 if (Param::isDeadPad(ipadx, ipady, ch)) {
621 continue;
622 }
623 nPhi++;
624 } // point loop
625 return ((double)nPhi / (double)nStep);
626 } // if
627 return -1;
628}
Base track model for the Barrel, params only, w/o covariance.
int16_t charge
Definition RawEventData.h:5
int32_t i
constexpr int p2()
constexpr int p1()
constexpr to accelerate the coordinates changing
Class to store the output of the matching to HMPID.
uint16_t pos
Definition RawData.h:3
uint32_t j
Definition RawData.h:0
ClassImp(o2::hmpid::Recon)
HMPID cluster implementation.
Definition Cluster.h:27
static float sizeAllX()
Definition Param.h:82
static bool isDeadPad(Int_t padx, Int_t pady, Int_t ch)
Definition Param.cxx:475
double winThick() const
Definition Param.h:167
static bool isInDead(float x, float y)
Definition Param.cxx:461
void setRefIdx(double refRadIdx)
Definition Param.h:231
double getRefIdx() const
Definition Param.h:157
static float sizeAllY()
Definition Param.h:83
float qCut() const
Definition Param.h:163
static void lors2Pad(float x, float y, Int_t &pc, Int_t &px, Int_t &py)
Definition Param.cxx:488
double radThick() const
Definition Param.h:166
double winIdx() const
Definition Param.h:169
static bool isInside(float x, float y, float d=0)
Definition Param.h:132
double gapIdx() const
Definition Param.h:170
double gapThick() const
Definition Param.h:168
double sigma2(double trkTheta, double trkPhi, double ckovTh, double ckovPh)
Definition Param.cxx:283
float multCut() const
Definition Param.h:164
double fCkovSigma2
Definition Recon.h:168
void ckovAngle(o2::dataformats::MatchInfoHMP *match, const std::vector< o2::hmpid::Cluster > clusters, int index, double nmean, float xRa, float yRa)
Definition Recon.cxx:49
o2::hmpid::Param * fParam
Definition Recon.h:183
std::unique_ptr< int[]> fPhotClusIndex
Definition Recon.h:161
TVector3 fTrkDir
Definition Recon.h:177
double fRingArea
Definition Recon.h:174
void setTrack(double xRad, double yRad, double theta, double phi)
Definition Recon.h:134
std::unique_ptr< double[]> fPhotPhi
Definition Recon.h:163
bool findPhotCkov2(double cluX, double cluY, double &thetaCer, double &phiCer)
Definition Recon.cxx:190
TVector2 traceForward(TVector3 dirCkov) const
Definition Recon.cxx:228
bool findPhotCkov(double cluX, double cluY, double &thetaCer, double &phiCer)
Definition Recon.cxx:145
double getRingArea() const
Definition Recon.h:123
double findRingCkov(int iNclus)
Definition Recon.cxx:399
double findRingExt(double ckov, int ch, double xPc, double yPc, double thRa, double phRa)
Definition Recon.cxx:593
void initVars(int n)
Definition Recon.cxx:29
std::unique_ptr< double[]> fPhotWei
Definition Recon.h:164
float fDTheta
Definition Recon.h:171
double fRingAcc
Definition Recon.h:175
void lors2Trs(TVector3 dirCkov, double &thetaCer, double &phiCer) const
Definition Recon.cxx:252
std::unique_ptr< int[]> fPhotFlag
Definition Recon.h:160
std::unique_ptr< double[]> fPhotCkov
Definition Recon.h:162
void refract(TVector3 &dir, double n1, double n2) const
Definition Recon.cxx:510
void propagate(const TVector3 dir, TVector3 &pos, double z) const
Definition Recon.cxx:495
TVector2 fTrkPos
Definition Recon.h:179
TVector2 tracePhot(double ckovTh, double ckovPh) const
Definition Recon.cxx:480
TVector2 fMipPos
Definition Recon.h:180
void trs2Lors(TVector3 dirCkov, double &thetaCer, double &phiCer) const
Definition Recon.cxx:276
TVector2 fPc
Definition Recon.h:181
const TVector2 intWithEdge(TVector2 p1, TVector2 p2)
Definition Recon.cxx:354
float fWindowWidth
Definition Recon.h:172
double houghResponse()
Definition Recon.cxx:527
int flagPhot(double ckov, const std::vector< o2::hmpid::Cluster > clusters, float *photChargeVec)
Definition Recon.cxx:442
void findRingGeom(double ckovAng, int level=1)
Definition Recon.cxx:301
bool match(const std::vector< std::string > &queries, const char *pattern)
Definition dcs-ccdb.cxx:229
GLdouble n
Definition glcorearb.h:1982
const GLfloat * m
Definition glcorearb.h:4066
GLuint index
Definition glcorearb.h:781
GLuint GLuint GLfloat weight
Definition glcorearb.h:5477
GLfloat angle
Definition glcorearb.h:4071
GLint level
Definition glcorearb.h:275
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
constexpr size_t nChannels
std::vector< Cluster > clusters