11 #include "arich/modules/arichReconstruction/ARICHReconstruction.h"
12 #include "arich/dbobjects/ARICHGeometryConfig.h"
13 #include "arich/modules/arichReconstruction/Utility.h"
14 #include "arich/dataobjects/ARICHHit.h"
15 #include "arich/dataobjects/ARICHTrack.h"
16 #include "arich/dataobjects/ARICHPhoton.h"
19 #include <framework/datastore/StoreArray.h>
22 #include <framework/logging/Logger.h>
23 #include <framework/gearbox/Const.h>
26 #include <TRotation.h>
30 using namespace boost;
38 using namespace arich;
40 ARICHReconstruction::ARICHReconstruction(
int storePhot):
47 m_storePhot(storePhot)
65 p_mass[part.getIndex()] = part.getMass();
94 for (
unsigned i = 1; i <
m_arichgp->getMirrors().getNMirrors() + 1; i++) {
102 for (
int iTile = 1; iTile < 125; iTile++) {
103 m_tilePars[iTile - 1][0] =
m_tileAlign->getAlignmentElement(iTile).getAlpha();
104 m_tilePars[iTile - 1][1] =
m_tileAlign->getAlignmentElement(iTile).getBeta();
113 if (copyno == -1)
return 0;
115 origin.SetMagPhi(
m_arichgp->getDetectorPlane().getSlotR(copyno),
m_arichgp->getDetectorPlane().getSlotPhi(copyno));
116 TVector2 a2(a.X(), a.Y());
117 double phi =
m_arichgp->getDetectorPlane().getSlotPhi(copyno);
118 TVector2 diff = a2 - origin;
119 diff = diff.Rotate(-phi);
120 const double size =
m_arichgp->getHAPDGeometry().getAPDSizeX();
121 if (fabs(diff.X()) < size / 2. && fabs(diff.Y()) < size / 2.) {
123 m_arichgp->getHAPDGeometry().getXYChannel(diff.X(), diff.Y(), chX, chY);
124 if (chX < 0 || chY < 0)
return 0;
138 TVector3 dirf(a, b, sqrt(1 - a * a - b * b));
141 TVector3 mod = TVector3(dx, dy, 0);
145 TVector3 rdir = TransformFromFixed(odir) * dirf;
146 double rmomentum = omomentum;
163 double angmir = 0;
int section[2] = {0, 0};
165 unsigned tileID =
m_arichgp->getAerogelPlane().getAerogelTileID(r.X(), r.Y());
167 if (tileID == 0 && opt == 1)
return TVector3();
169 int nmir =
m_arichgp->getMirrors().getNMirrors();
171 double dangle = 2 * M_PI / nmir;
172 angmir =
m_arichgp->getMirrors().getStartAngle() - dangle / 2.;
174 double trkangle = r.XYvector().Phi() - angmir;
175 if (trkangle < 0) trkangle += 2 * M_PI;
176 if (trkangle > 2 * M_PI) trkangle -= 2 * M_PI;
178 section[1] = int(trkangle / dangle) + 1;
181 bool reflok =
false;
bool refl =
false;
182 double path = (z[0] - r.z()) / dirf.z();
184 for (
int a = 1; a <= n + 1 ; a++) {
185 double rind = refractiveInd[a] / refractiveInd[a - 1];
186 dirf = Refraction(dirf, rind);
187 if (dirf.Mag() == 0)
return TVector3();
188 path = (z[a] - r.z()) / dirf.z();
190 if (a == n && opt == 1) {
191 if (
m_arichgp->getAerogelPlane().getAerogelTileID(r.X(), r.Y()) != tileID)
return TVector3();
194 TVector2 rxy = r.XYvector();
196 if (a != n || nmir == 0)
continue;
197 double angle = rxy.Phi() - angmir;
198 if (angle < 0) angle += 2 * M_PI;
199 if (angle > 2 * M_PI) angle -= 2 * M_PI;
200 double dangle = 2 * M_PI / nmir;
201 section[0] = int(angle / dangle) + 1;
205 if (section[0] == section[1]) nrefl = 1;
206 for (
int k = 0; k < nrefl; k++) {
207 if (!
HitsMirror(r0, dirf, section[k]))
continue;
210 double s = dirf * mirnorm;
211 double s1 = (mirpoint - r0) * mirnorm;
212 r = r0 + s1 / s * dirf;
213 dirf = dirf - 2 * (dirf * mirnorm) * mirnorm;
214 path = (z[a] - r.z()) / dirf.z();
222 if (!reflok && refl)
return TVector3();
229 if (mirrorID == 0)
return hitpos;
232 return hitpos - 2 * ((hitpos - mirpoint) * mirnorm) * mirnorm;
241 TRotation rot = TransformToFixed(mirnorm);
242 TVector3 dirTr = rot * dir;
243 if (dirTr.Z() < 0)
return 0;
244 TVector3 posTr = rot * (pos - mirpoint);
245 TVector3 pointOnMirr = posTr - (posTr.Z() / dirTr.Z()) * dirTr;
246 if (fabs(pointOnMirr.Y()) <
m_arichgp->getMirrors().getPlateLength() / 2.
247 && fabs(pointOnMirr.X()) <
m_arichgp->getMirrors().getPlateWidth() / 2.)
return 1;
254 TVector3& rf, TVector3& dirf,
255 double* refractiveInd,
double* z,
int n,
int mirrorID)
274 static TVector3 norm(0, 0, 1);
276 double dwin =
m_arichgp->getHAPDGeometry().getWinThickness();
277 double refractiveInd0 =
m_arichgp->getHAPDGeometry().getWinRefIndex();
281 const double dmin = 0.0000001;
282 const int niter = 100;
284 TVector3 rh1 = rh - dwin * norm;
286 std::vector <TVector3> rf0(n + 2);
290 std::vector <TVector3> dirf0(n + 2);
303 for (
int iter = 0; iter < niter; iter++) {
307 if (iter == 0) dirf0[n] = (rh1 - rf0[1]).
Unit();
308 else dirf0[n] = (rh1 - rf0[n]).
Unit();
312 for (
int a = n - 1; a >= 0 ; a--) {
313 double rind = refractiveInd[a] / refractiveInd[a + 1];
314 dirf0[a] = Refraction(dirf0[a + 1], rind);
317 double path = (z[0] - r.z()) / dirf0[0].z();
318 double x1 = rf0[1].x();
319 double y1 = rf0[1].y();
320 for (
int a = 0; a < n ; a++) {
321 rf0[a + 1] = rf0[a] + dirf0[a] * path;
322 path = (z[a + 1] - rf0[a + 1].z()) / dirf0[a + 1].z();
325 Refraction(dirf0[n], norm, refractiveInd0, dirw);
329 path = dwin / (dirw * norm);
330 rh1 = rh - dirw * path;
332 double d2 = (rf0[1].x() - x1) * (rf0[1].x() - x1) + (rf0[1].y() - y1) * (rf0[1].y() - y1);
334 if ((d2 < dmin) && (iter)) {
338 if (!
HitsMirror(rf0[n], dirf0[n], mirrorID))
return -1;
353 const unsigned int nPhotonHits = arichHits.getEntries();
366 double padSize =
m_arichgp->getHAPDGeometry().getPadSize();
367 int nMirSeg =
m_arichgp->getMirrors().getNMirrors();
368 double angmir =
m_arichgp->getMirrors().getStartAngle();
378 if (edir.z() < 0)
return 0;
381 double thcResolution =
m_recPars->getThcResolution(momentum);
382 if (thcResolution < 0) thcResolution = 0.01;
384 double wideGaussFract = (
m_recPars->getParameters())[0];
385 double wideGaussSigma = (
m_recPars->getParameters())[1];
388 double r = arichTrack.
getPosition().XYvector().Mod();
395 float nphot_scaling = 20.;
407 thetaCh[iHyp][iAerogel] = ExpectedCherenkovAngle(momentum,
413 if (pathLengthRadiator) pathLengthRadiator =
m_thickness[iAerogel] / pathLengthRadiator;
416 double dxx = pathLengthRadiator / double(nStep);
418 double nPhot =
m_n0[iAerogel] * sin(thetaCh[iHyp][iAerogel]) * sin(thetaCh[iHyp][iAerogel]) * dxx * nphot_scaling;
422 for (
int iepoint = 0; iepoint < nStep; iepoint++) {
424 TVector3 epoint = exit_point - (0.5 + iepoint) * dxx * edir;
426 unsigned int genPhot = nPhot * abs;
429 for (
unsigned int iPhoton = 0; iPhoton < genPhot; iPhoton++) {
430 double fi = 2 * M_PI * iPhoton / float(genPhot);
431 TVector3 adirf = setThetaPhi(thetaCh[iHyp][iAerogel], fi);
432 adirf = TransformFromFixed(edir) * adirf;
433 int ifi = int (fi * 20 / 2. / M_PI);
436 if (dposition.Mag() > 1.0) {nSig_wo_acc[iHyp][iAerogel][ifi] += 1; nSig_wo_accInt[iHyp][iAerogel] += 1;}
438 unsigned copyno =
m_arichgp->getDetectorPlane().pointSlotID(dposition.X(), dposition.Y());
439 if (!copyno)
continue;
441 if (
InsideDetector(dposition, copyno)) nSig_w_acc[iHyp][iAerogel] += 1;
446 for (
int ik = 0; ik < 20; ik++) {
447 nSig_wo_acc[iHyp][iAerogel][ik] /= nphot_scaling;
449 nSig_w_acc[iHyp][iAerogel] /= nphot_scaling;
450 nSig_wo_accInt[iHyp][iAerogel] /= nphot_scaling;
458 for (
int ik = 0; ik < 20; ik++) {
464 std::vector<double> bkgPars = {momentum / sqrt(
p_mass[iHyp]*
p_mass[iHyp] + momentum * momentum), double(arichTrack.
hitsWindow())};
465 nBgr[iHyp] =
m_recPars->getExpectedBackgroundHits(bkgPars);
479 if (track_at_detector.XYvector().Mod() > 85.0) {
480 double trackang = track_at_detector.Phi() - angmir;
481 if (trackang < 0) trackang += 2 * M_PI;
482 if (trackang > 2 * M_PI) trackang -= 2 * M_PI;
483 int section1 = int(trackang * nMirSeg / 2. / M_PI) + 1;
484 int section2 = section1 + 1;
485 if (section1 == nMirSeg) section2 = 1;
486 mirrors[1] = section1; mirrors[2] = section2;
492 for (
unsigned int iPhoton = 0; iPhoton < nPhotonHits; iPhoton++) {
495 int modID = h->getModule();
496 int channel = h->getChannel();
497 TVector3 hitpos =
m_arichgp->getMasterVolume().pointToLocal(h->getPosition());
498 bool bkgAdded =
false;
499 int nfoo = nDetPhotons;
500 for (
int iHyp = 0; iHyp <
c_noOfHypotheses; iHyp++) { esigi[iHyp] = 0; ebgri[iHyp] = 0;}
505 for (
int mirr = 0; mirr < refl; mirr++) {
514 if ((track_at_detector - virthitpos).Mag() > 25.0)
continue;
523 double fi_cer_trk = 0.;
531 TVector3 photonDirection;
536 TVector3 dirch = TransformToFixed(edirr) * photonDirection;
537 double fi_cer = dirch.Phi();
538 double th_cer = dirch.Theta();
541 th_cer_all[iAerogel] = th_cer;
542 fi_cer_all[iAerogel] = fi_cer;
543 fi_cer_trk = dirch.XYvector().DeltaPhi(edirr.XYvector());
545 if (mirr == 0 && th_cer < 0.1) reflOK =
false;
547 if (th_cer > 0.5 || th_cer < 0.1)
continue;
550 if (nfoo == nDetPhotons) nDetPhotons++;
552 if (fi_cer < 0) fi_cer += 2 * M_PI;
555 double fi_mir =
m_mirrorNorms[mirrors[mirr] - 1].XYvector().Phi();
556 fii = 2 * fi_mir - fi_cer - M_PI;
564 TVector3 photonDirection1 = setThetaPhi(thetaCh[iHyp][iAerogel], fi_cer);
565 photonDirection1 = TransformFromFixed(edirr) * photonDirection1;
566 int ifi = int (fi_cer * 20 / 2. / M_PI);
567 TVector3 photonAtAerogelExit = photonDirection1 * (
m_thickness[iAerogel] / photonDirection1.z());
568 TVector3 trackAtAerogelExit = edirr * (
m_thickness[iAerogel] / edirr.z());
569 TVector3 dtrackphoton = photonAtAerogelExit - trackAtAerogelExit;
570 TVector3 detector_position;
575 TVector3 meanr = detector_position - epoint;
576 double path = meanr.Mag();
577 meanr = meanr.Unit();
579 double detector_sigma = thcResolution * path / meanr.z();
580 double wide_sigma = wideGaussSigma * path / meanr.z();
582 double modphi =
m_arichgp->getDetectorPlane().getSlotPhi(modID);
584 double pad_fi = fii - modphi;
585 double dx = (detector_position - hitpos).Mag();
586 double dr = (track_at_detector - detector_position).Mag();
589 double normalizacija = nSig_wo_acc[iHyp][iAerogel][ifi] * padSize / (0.1 * M_PI * dr);
590 weight[iHyp][iAerogel] = normalizacija;
591 weight_sum[iHyp] += weight[iHyp][iAerogel];
592 double integralMain = SquareInt(padSize, pad_fi, dx, detector_sigma) / sqrt(2.);
593 double integralWide = SquareInt(padSize, pad_fi, dx, wide_sigma) / sqrt(2.);
595 double exp = normalizacija * ((1 - wideGaussFract) * integralMain + wideGaussFract * integralWide);
597 sigExpArr[iHyp] += exp;
608 std::vector<double> pars = {momentum / sqrt(
p_mass[iHyp]*
p_mass[iHyp] + momentum * momentum), double(arichTrack.
hitsWindow())};
609 ebgri[iHyp] +=
m_recPars->getBackgroundPerPad(th_cer_all[1], pars);
615 if (
m_storePhot && th_cer_all[1] > 0 && th_cer_all[1] < 0.6) {
619 if (weight_sum[iHyp] > 0) {
621 double emission_prob = weight[iHyp][iAerogel] / weight_sum[iHyp];
622 n_cos_theta_ch[iHyp] += emission_prob *
m_refractiveInd[iAerogel] * cos(th_cer_all[iAerogel]);
623 phi_ch[iHyp] += emission_prob * fi_cer_all[iAerogel];
627 n_cos_theta_ch[iHyp] = -99999.;
628 phi_ch[iHyp] = -99999.;
631 ARICHPhoton phot(iPhoton, th_cer_all[1], fi_cer_all[1], mirrors[mirr]);
637 phot.
setXY(hitpos.X(), hitpos.Y());
651 double expected = esigi[iHyp] + ebgri[iHyp];
652 if (bkgAdded) logL[iHyp] += expected + log(1 - exp(-expected));
662 exppho[iHyp] = nSig_w_acc[iHyp][
m_nAerogelLayers] * (1 - wideGaussFract) + wideGaussFract * 0.7 *
664 logL[iHyp] -= exppho[iHyp];
665 if (isnan(logL[iHyp]) || isinf(logL[iHyp])) {
666 B2WARNING(
"ARICHReconstruction: log likelihood value infinite! Flat background hit probability is " << ebgri[iHyp] <<
"!");
676 if ((thetaCh[0][0] > 0 || thetaCh[0][1] > 0) && nSig_w_acc[0][
m_nAerogelLayers] == 0) flag = 0;
679 arichLikelihood.
setValues(flag, logL, nDetPhotons, exppho);
697 TVector3 dir = track.getDirection();
698 if (dir.Z() == 0)
return TVector3();
700 double dmean = 1 - d / expm1(d);
709 TVector3 dir = track.getDirection();
710 TVector3 pos = track.getPosition();
711 if (dir.Z() == 0)
return TVector3(0, 0, 0);
712 double path = (zout - pos.Z()) / dir.Z();
713 return pos + dir * path;
725 locPos =
m_alignp->pointToLocal(locPos);
726 locDir =
m_alignp->momentumToLocal(locDir);
739 TVector3 mirpoint =
m_arichgp->getMirrors().getPoint(mirrorID);
749 TVector3 mirnorm =
m_arichgp->getMirrors().getNormVector(mirrorID);
750 mirnorm.SetTheta(mirnorm.Theta() +
m_mirrAlign->getAlignmentElement(mirrorID).getAlpha());
751 mirnorm.SetPhi(mirnorm.Phi() +
m_mirrAlign->getAlignmentElement(mirrorID).getBeta());
755 return m_arichgp->getMirrors().getNormVector(mirrorID);
761 double ang = m_tilePars[tileID - 1][0] + m_tilePars[tileID - 1][1] * r;