9#include "arich/modules/arichReconstruction/ARICHReconstruction.h"
10#include "arich/dbobjects/ARICHGeometryConfig.h"
11#include "arich/modules/arichReconstruction/Utility.h"
12#include "arich/dataobjects/ARICHHit.h"
13#include "arich/dataobjects/ARICHTrack.h"
14#include "arich/dataobjects/ARICHPhoton.h"
17#include <framework/datastore/StoreArray.h>
20#include <framework/logging/Logger.h>
21#include <framework/gearbox/Const.h>
22#include <framework/geometry/VectorUtil.h>
25#include <Math/Vector3D.h>
36 using namespace arich;
45 m_storePhot(storePhot)
54 m_anorm[i] = ROOT::Math::XYZVector();
63 p_mass[part.getIndex()] = part.getMass();
70 m_anorm[i] = ROOT::Math::XYZVector(0, 0, 1);
92 for (
unsigned i = 1; i <
m_arichgp->getMirrors().getNMirrors() + 1; i++) {
100 for (
int iTile = 1; iTile < 125; iTile++) {
111 if (copyno == -1)
return 0;
112 ROOT::Math::XYVector origin;
113 origin.SetXY(
m_arichgp->getDetectorPlane().getSlotR(copyno) * std::cos(
m_arichgp->getDetectorPlane().getSlotPhi(copyno)),
114 m_arichgp->getDetectorPlane().getSlotR(copyno) * std::sin(
m_arichgp->getDetectorPlane().getSlotPhi(copyno)));
115 ROOT::Math::XYVector a2(a);
116 double phi =
m_arichgp->getDetectorPlane().getSlotPhi(copyno);
117 ROOT::Math::XYVector diff = a2 - origin;
119 const double size =
m_arichgp->getHAPDGeometry().getAPDSizeX();
120 if (fabs(diff.X()) < size / 2. && fabs(diff.Y()) < size / 2.) {
122 m_arichgp->getHAPDGeometry().getXYChannel(diff.X(), diff.Y(), chX, chY);
123 if (chX < 0 || chY < 0)
return 0;
126 if (asicChannel < 0 || !m_chnMask->isActive(copyno,
asicChannel))
return 0;
137 ROOT::Math::XYZVector dirf(a, b,
sqrt(1 - a * a - b * b));
140 ROOT::Math::XYZVector mod(dx, dy, 0);
141 ROOT::Math::XYZVector rpoint = arichTrack.
getPosition() + mod;
144 ROOT::Math::XYZVector rdir = TransformFromFixed(odir) * dirf;
145 double rmomentum = omomentum;
152 double* refractiveInd,
double* z,
int n,
int opt)
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 ROOT::Math::XYZVector();
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.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.R() == 0)
return ROOT::Math::XYZVector();
188 path = (z[a] - r.Z()) / dirf.Z();
189 ROOT::Math::XYZVector r0 = r;
190 if (a == n && opt == 1) {
191 if (
m_arichgp->getAerogelPlane().getAerogelTileID(r.X(), r.Y()) != tileID)
return ROOT::Math::XYZVector();
194 ROOT::Math::XYVector rxy(r);
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;
209 ROOT::Math::XYZVector mirnorm =
m_mirrorNorms[section[k] - 1];
210 double s = dirf.Dot(mirnorm);
211 double s1 = (mirpoint - r0).Dot(mirnorm);
212 r = r0 + s1 / s * dirf;
213 dirf = dirf - 2 * (dirf.Dot(mirnorm)) * mirnorm;
214 path = (z[a] - r.Z()) / dirf.Z();
222 if (!reflok && refl)
return ROOT::Math::XYZVector();
229 if (mirrorID == 0)
return hitpos;
232 return hitpos - 2 * ((hitpos - mirpoint).Dot(mirnorm)) * mirnorm;
241 ROOT::Math::Rotation3D rot = TransformToFixed(mirnorm);
242 ROOT::Math::XYZVector dirTr = rot * dir;
243 if (dirTr.Z() < 0)
return 0;
244 ROOT::Math::XYZVector posTr = rot * (pos - mirpoint);
245 ROOT::Math::XYZVector 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 ROOT::Math::XYZVector& rf, ROOT::Math::XYZVector& dirf,
255 double* refractiveInd,
double* z,
int n,
int mirrorID)
274 static ROOT::Math::XYZVector 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;
283 ROOT::Math::XYZVector dirw;
284 ROOT::Math::XYZVector rh1 = rh - dwin * norm;
286 std::vector <ROOT::Math::XYZVector > rf0(n + 2);
290 std::vector <ROOT::Math::XYZVector > 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.Dot(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];
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 ROOT::Math::XYZVector 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 ROOT::Math::XYZVector adirf = setThetaPhi(thetaCh[iHyp][iAerogel], fi);
432 adirf = TransformFromFixed(edir) * adirf;
433 int ifi = int (fi * 20 / 2. / M_PI);
437 if (dposition.R() > 1.0) {nSig_wo_acc[iHyp][iAerogel][ifi] += 1; nSig_wo_accInt[iHyp][iAerogel] += 1;}
439 unsigned copyno =
m_arichgp->getDetectorPlane().pointSlotID(dposition.X(), dposition.Y());
440 if (!copyno)
continue;
442 if (
InsideDetector(dposition, copyno)) nSig_w_acc[iHyp][iAerogel] += 1;
447 for (
int ik = 0; ik < 20; ik++) {
448 nSig_wo_acc[iHyp][iAerogel][ik] /= nphot_scaling;
450 nSig_w_acc[iHyp][iAerogel] /= nphot_scaling;
451 nSig_wo_accInt[iHyp][iAerogel] /= nphot_scaling;
459 for (
int ik = 0; ik < 20; ik++) {
465 std::vector<double> bkgPars = {momentum /
sqrt(
p_mass[iHyp]*
p_mass[iHyp] + momentum * momentum), double(arichTrack.
hitsWindow())};
466 nBgr[iHyp] =
m_recPars->getExpectedBackgroundHits(bkgPars);
480 if (track_at_detector.Rho() > 85.0) {
481 double trackang = track_at_detector.Phi() - angmir;
482 if (trackang < 0) trackang += 2 * M_PI;
483 if (trackang > 2 * M_PI) trackang -= 2 * M_PI;
484 int section1 = int(trackang * nMirSeg / 2. / M_PI) + 1;
485 int section2 = section1 + 1;
486 if (section1 == nMirSeg) section2 = 1;
487 mirrors[1] = section1; mirrors[2] = section2;
493 for (
unsigned int iPhoton = 0; iPhoton < nPhotonHits; iPhoton++) {
496 int modID = h->getModule();
497 int channel = h->getChannel();
498 ROOT::Math::XYZVector hitpos =
m_arichgp->getMasterVolume().pointToLocal(h->getPosition());
499 bool bkgAdded =
false;
500 int nfoo = nDetPhotons;
501 for (
int iHyp = 0; iHyp <
c_noOfHypotheses; iHyp++) { esigi[iHyp] = 0; ebgri[iHyp] = 0;}
506 for (
int mirr = 0; mirr < refl; mirr++) {
515 if ((track_at_detector - virthitpos).
R() > 25.0)
continue;
524 double fi_cer_trk = 0.;
531 ROOT::Math::XYZVector edirr = arichTrack.
getDirection();
532 ROOT::Math::XYZVector photonDirection;
537 ROOT::Math::XYZVector dirch = TransformToFixed(edirr) * photonDirection;
538 double fi_cer = dirch.Phi();
539 double th_cer = dirch.Theta();
542 th_cer_all[iAerogel] = th_cer;
543 fi_cer_all[iAerogel] = fi_cer;
544 auto deltaPhi = dirch.Phi() - edir.Phi();
546 deltaPhi -= 2 * M_PI;
547 if (deltaPhi < -M_PI)
548 deltaPhi += 2 * M_PI;
549 fi_cer_trk = deltaPhi;
551 if (mirr == 0 && th_cer < 0.1) reflOK =
false;
553 if (th_cer > 0.5 || th_cer < 0.1)
continue;
556 if (nfoo == nDetPhotons) nDetPhotons++;
558 if (fi_cer < 0) fi_cer += 2 * M_PI;
562 fii = 2 * fi_mir - fi_cer - M_PI;
570 ROOT::Math::XYZVector photonDirection1 = setThetaPhi(thetaCh[iHyp][iAerogel], fi_cer);
571 photonDirection1 = TransformFromFixed(edirr) * photonDirection1;
572 int ifi = int (fi_cer * 20 / 2. / M_PI);
573 ROOT::Math::XYZVector detector_position;
578 ROOT::Math::XYZVector meanr = detector_position - epoint;
579 double path = meanr.R();
580 meanr = meanr.Unit();
582 double meanpath = (
m_recPars->getParameters())[2];
583 if (iAerogel == 1) meanpath = meanpath -
m_thickness[iAerogel];
585 double detector_sigma = thcResolution * meanpath / meanr.Z();
586 double wide_sigma = wideGaussSigma * path / meanr.Z();
588 double modphi =
m_arichgp->getDetectorPlane().getSlotPhi(modID);
590 double pad_fi = fii - modphi;
591 double dx = (detector_position - hitpos).
R();
592 double dr = (track_at_detector - detector_position).
R();
595 double normalizacija = nSig_wo_acc[iHyp][iAerogel][ifi] * padSize / (0.1 * M_PI * dr * meanr.Z());
596 weight[iHyp][iAerogel] = normalizacija;
597 weight_sum[iHyp] += weight[iHyp][iAerogel];
598 double integralMain = SquareInt(padSize, pad_fi, dx, detector_sigma) /
sqrt(2.);
599 double integralWide = SquareInt(padSize, pad_fi, dx, wide_sigma) /
sqrt(2.);
601 double exp = normalizacija * ((1 - wideGaussFract) * integralMain + wideGaussFract * integralWide);
603 sigExpArr[iHyp] += exp;
614 std::vector<double> pars = {momentum /
sqrt(
p_mass[iHyp]*
p_mass[iHyp] + momentum * momentum), double(arichTrack.
hitsWindow())};
615 ebgri[iHyp] +=
m_recPars->getBackgroundPerPad(th_cer_all[1], pars);
621 if (
m_storePhot && th_cer_all[1] > 0 && th_cer_all[1] < 0.6) {
625 if (weight_sum[iHyp] > 0) {
627 double emission_prob = weight[iHyp][iAerogel] / weight_sum[iHyp];
628 n_cos_theta_ch[iHyp] += emission_prob *
m_refractiveInd[iAerogel] * cos(th_cer_all[iAerogel]);
629 phi_ch[iHyp] += emission_prob * fi_cer_all[iAerogel];
633 n_cos_theta_ch[iHyp] = -99999.;
634 phi_ch[iHyp] = -99999.;
637 ARICHPhoton phot(iPhoton, th_cer_all[1], fi_cer_all[1], mirrors[mirr]);
643 phot.
setXY(hitpos.X(), hitpos.Y());
657 double expected = esigi[iHyp] + ebgri[iHyp];
658 if (bkgAdded) logL[iHyp] += expected + log(1 - exp(-expected));
668 exppho[iHyp] = nSig_w_acc[iHyp][
m_nAerogelLayers] * (1 - wideGaussFract) + wideGaussFract * 0.7 *
670 logL[iHyp] -= exppho[iHyp];
671 if (isnan(logL[iHyp]) || isinf(logL[iHyp])) {
672 B2WARNING(
"ARICHReconstruction: log likelihood value infinite! Flat background hit probability is " << ebgri[iHyp] <<
"!");
682 if ((thetaCh[0][0] > 0 || thetaCh[0][1] > 0) && nSig_w_acc[0][
m_nAerogelLayers] == 0) flag = 0;
685 arichLikelihood.
setValues(flag, logL, nDetPhotons, exppho);
703 ROOT::Math::XYZVector dir = track.getDirection();
704 if (dir.Z() == 0)
return ROOT::Math::XYZVector();
706 double dmean = 1 - d / expm1(d);
715 ROOT::Math::XYZVector dir = track.getDirection();
716 ROOT::Math::XYZVector pos = track.getPosition();
717 if (dir.Z() == 0)
return ROOT::Math::XYZVector(0, 0, 0);
718 double path = (zout - pos.Z()) / dir.Z();
719 return pos + dir * path;
725 ROOT::Math::XYZVector locPos =
m_arichgp->getMasterVolume().pointToLocal(arichTrack.
getPosition());
726 ROOT::Math::XYZVector locDir =
m_arichgp->getMasterVolume().momentumToLocal(arichTrack.
getDirection());
731 locPos =
m_alignp->pointToLocal(locPos);
732 locDir =
m_alignp->momentumToLocal(locDir);
745 ROOT::Math::XYZVector mirpoint =
m_arichgp->getMirrors().getPoint(mirrorID);
755 ROOT::Math::XYZVector mirnorm =
m_arichgp->getMirrors().getNormVector(mirrorID);
757 VectorUtil::setMagThetaPhi(mirnorm,
759 mirnorm.Theta() +
m_mirrAlign->getAlignmentElement(mirrorID).getAlpha(),
760 mirnorm.Phi() +
m_mirrAlign->getAlignmentElement(mirrorID).getBeta());
765 return m_arichgp->getMirrors().getNormVector(mirrorID);
Datastore class that holds photon hits. Input to the reconstruction.
This is a class to store ARICH likelihoods in the datastore.
void setValues(int flag, const double *logL, int detPhot, const double *expPhot)
Set values.
Struct for ARICH reconstructed photon (hit related to track) information.
void setXY(float x, float y)
Set X-Y position of hit.
void setBkgExp(const double *bkgExp)
Set expected background contribution.
void setChannel(int chn)
set channel (asic) of hit
void setNCosThetaCh(const double *n_cos_theta_ch)
Set n cos(theta_ch)
void setModuleID(int modID)
Set id of hit module.
void setPhiCh(const double *phi_ch)
Set phi_ch.
void setPhiCerTrk(float phi)
Set hit phi angle in track coordinates.
void setSigExp(const double *sigExp)
Set expected signal contribution.
DBObjPtr< ARICHReconstructionPar > m_recPars
reconstruction parameters from the DB
std::vector< ROOT::Math::XYZVector > m_mirrorPoints
vector of points on all mirror plates
double m_zaero[c_noOfAerogels]
z-positions of aerogel layers
double p_mass[c_noOfHypotheses]
particle masses
double m_n0[c_noOfAerogels]
number of emitted photons per unit length
DBObjPtr< ARICHMirrorAlignment > m_mirrAlign
global alignment parameters from the DB
double m_transmissionLen[c_noOfAerogels]
transmission lengths of aerogel layers
bool m_alignMirrors
if set to true mirror alignment constants from DB are used
DBObjPtr< ARICHGeometryConfig > m_arichgp
geometry configuration parameters from the DB
std::vector< ROOT::Math::XYZVector > m_mirrorNorms
vector of normal vectors of all mirror plates
OptionalDBObjPtr< ARICHAeroTilesAlignment > m_tileAlign
alignment of aerogel tiles from DB
double m_trackAngRes
track direction resolution (from tracking)
ROOT::Math::XYZVector m_anorm[c_noOfAerogels]
normal vector of the aerogel plane
double m_refractiveInd[c_noOfAerogels]
refractive indices of aerogel layers
DBObjPtr< ARICHGlobalAlignment > m_alignp
global alignment parameters from the DB
unsigned int m_nAerogelLayers
number of aerogel layers
static const int c_noOfAerogels
Maximal number of aerogel layers to loop over.
double m_trackPosRes
track position resolution (from tracking)
static const int c_noOfHypotheses
Number of hypotheses to loop over.
DBObjPtr< ARICHChannelMapping > m_chnMap
map x,y channels to asic channels from the DB
int m_storePhot
set to 1 to store individual reconstructed photon information
double m_tilePars[124][2]
array of tile parameters
double m_thickness[c_noOfAerogels]
thicknesses of aerogel layers
Datastore class that holds position and momentum information of tracks that hit ARICH.
void setReconstructedValues(ROOT::Math::XYZVector r, ROOT::Math::XYZVector dir, double p)
Sets the reconstructed value of track parameters.
bool hitsWindow() const
Returns true if track hits HAPD window.
ROOT::Math::XYZVector getDirection() const
returns track direction vector
void addPhoton(ARICHPhoton photon)
Add ARICHPhoton to collection of photons.
ROOT::Math::XYZVector getPosition() const
returns track position vector
double getMomentum() const
returns track momentum
static const ParticleSet chargedStableSet
set of charged stable particles
Accessor to arrays stored in the data store.
void setTrackPositionResolution(double pRes)
Sets track position resolution (from tracking).
ROOT::Math::XYZVector FastTracking(ROOT::Math::XYZVector dirf, ROOT::Math::XYZVector r, double *refind, double *z, int n, int opt)
Calculates the intersection of the Cherenkov photon emitted from point "r" in "dirf" direction with t...
int CherenkovPhoton(ROOT::Math::XYZVector r, ROOT::Math::XYZVector rh, ROOT::Math::XYZVector &rf, ROOT::Math::XYZVector &dirf, double *refind, double *z, int n, int mirrorID=0)
Calculates the direction of photon emission.
int likelihood2(ARICHTrack &arichTrack, const StoreArray< ARICHHit > &arichHits, ARICHLikelihood &arichLikelihood)
Computes the value of identity likelihood function for different particle hypotheses.
void initialize()
Read geometry parameters from xml and initialize class members.
ROOT::Math::XYZVector HitVirtualPosition(const ROOT::Math::XYZVector &hitpos, int mirrorID)
Returns the hit virtual position, assuming that it was reflected from mirror.
void correctEmissionPoint(int tileID, double r)
Correct mean emission point z position.
ROOT::Math::XYZVector getMirrorNorm(int mirrorID)
Returns normal vector of the mirror plate with id mirrorID.
void setTrackAngleResolution(double aRes)
Sets track direction resolution (from tracking).
int InsideDetector(ROOT::Math::XYZVector a, int copyno)
Returns 1 if vector "a" lies on "copyno"-th detector active surface of detector and 0 else.
void transformTrackToLocal(ARICHTrack &arichTrack, bool align)
Transforms track parameters from global Belle2 to ARICH local frame.
bool HitsMirror(const ROOT::Math::XYZVector &pos, const ROOT::Math::XYZVector &dir, int mirrorID)
Returns true if photon at position pos with direction dir hits mirror plate with ID mirrorID.
ROOT::Math::XYZVector getTrackMeanEmissionPosition(const ARICHTrack &track, int iAero)
Returns mean emission position of Cherenkov photons from i-th aerogel layer.
ROOT::Math::XYZVector getMirrorPoint(int mirrorID)
Returns point on the mirror plate with id mirrorID.
ROOT::Math::XYZVector getTrackPositionAtZ(const ARICHTrack &track, double zout)
Returns track direction at point with z coordinate "zout" (assumes straight track).
ARICHReconstruction(int storePhotons=0)
Constructor.
int smearTrack(ARICHTrack &arichTrack)
Smears track parameters ("simulate" the uncertainties of tracking).
double sqrt(double a)
sqrt for double
Abstract base class for different kinds of events.
record to be used to store ASIC info