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>
24 #include <TRotation.h>
28 using namespace boost;
36 using namespace arich;
38 ARICHReconstruction::ARICHReconstruction(
int storePhot):
45 m_storePhot(storePhot)
63 p_mass[part.getIndex()] = part.getMass();
92 for (
unsigned i = 1; i <
m_arichgp->getMirrors().getNMirrors() + 1; i++) {
100 for (
int iTile = 1; iTile < 125; iTile++) {
101 m_tilePars[iTile - 1][0] =
m_tileAlign->getAlignmentElement(iTile).getAlpha();
102 m_tilePars[iTile - 1][1] =
m_tileAlign->getAlignmentElement(iTile).getBeta();
111 if (copyno == -1)
return 0;
113 origin.SetMagPhi(
m_arichgp->getDetectorPlane().getSlotR(copyno),
m_arichgp->getDetectorPlane().getSlotPhi(copyno));
114 TVector2 a2(a.X(), a.Y());
115 double phi =
m_arichgp->getDetectorPlane().getSlotPhi(copyno);
116 TVector2 diff = a2 - origin;
117 diff = diff.Rotate(-phi);
118 const double size =
m_arichgp->getHAPDGeometry().getAPDSizeX();
119 if (fabs(diff.X()) < size / 2. && fabs(diff.Y()) < size / 2.) {
121 m_arichgp->getHAPDGeometry().getXYChannel(diff.X(), diff.Y(), chX, chY);
122 if (chX < 0 || chY < 0)
return 0;
136 TVector3 dirf(a, b, sqrt(1 - a * a - b * b));
139 TVector3 mod = TVector3(dx, dy, 0);
143 TVector3 rdir = TransformFromFixed(odir) * dirf;
144 double rmomentum = omomentum;
161 double angmir = 0;
int section[2] = {0, 0};
163 unsigned tileID =
m_arichgp->getAerogelPlane().getAerogelTileID(r.X(), r.Y());
165 if (tileID == 0 && opt == 1)
return TVector3();
167 int nmir =
m_arichgp->getMirrors().getNMirrors();
169 double dangle = 2 * M_PI / nmir;
170 angmir =
m_arichgp->getMirrors().getStartAngle() - dangle / 2.;
172 double trkangle = r.XYvector().Phi() - angmir;
173 if (trkangle < 0) trkangle += 2 * M_PI;
174 if (trkangle > 2 * M_PI) trkangle -= 2 * M_PI;
176 section[1] = int(trkangle / dangle) + 1;
179 bool reflok =
false;
bool refl =
false;
180 double path = (z[0] - r.z()) / dirf.z();
182 for (
int a = 1; a <= n + 1 ; a++) {
183 double rind = refractiveInd[a] / refractiveInd[a - 1];
184 dirf = Refraction(dirf, rind);
185 if (dirf.Mag() == 0)
return TVector3();
186 path = (z[a] - r.z()) / dirf.z();
188 if (a == n && opt == 1) {
189 if (
m_arichgp->getAerogelPlane().getAerogelTileID(r.X(), r.Y()) != tileID)
return TVector3();
192 TVector2 rxy = r.XYvector();
194 if (a != n || nmir == 0)
continue;
195 double angle = rxy.Phi() - angmir;
196 if (angle < 0) angle += 2 * M_PI;
197 if (angle > 2 * M_PI) angle -= 2 * M_PI;
198 double dangle = 2 * M_PI / nmir;
199 section[0] = int(angle / dangle) + 1;
203 if (section[0] == section[1]) nrefl = 1;
204 for (
int k = 0; k < nrefl; k++) {
205 if (!
HitsMirror(r0, dirf, section[k]))
continue;
208 double s = dirf * mirnorm;
209 double s1 = (mirpoint - r0) * mirnorm;
210 r = r0 + s1 / s * dirf;
211 dirf = dirf - 2 * (dirf * mirnorm) * mirnorm;
212 path = (z[a] - r.z()) / dirf.z();
220 if (!reflok && refl)
return TVector3();
227 if (mirrorID == 0)
return hitpos;
230 return hitpos - 2 * ((hitpos - mirpoint) * mirnorm) * mirnorm;
239 TRotation rot = TransformToFixed(mirnorm);
240 TVector3 dirTr = rot * dir;
241 if (dirTr.Z() < 0)
return 0;
242 TVector3 posTr = rot * (pos - mirpoint);
243 TVector3 pointOnMirr = posTr - (posTr.Z() / dirTr.Z()) * dirTr;
244 if (fabs(pointOnMirr.Y()) <
m_arichgp->getMirrors().getPlateLength() / 2.
245 && fabs(pointOnMirr.X()) <
m_arichgp->getMirrors().getPlateWidth() / 2.)
return 1;
252 TVector3& rf, TVector3& dirf,
253 double* refractiveInd,
double* z,
int n,
int mirrorID)
272 static TVector3 norm(0, 0, 1);
274 double dwin =
m_arichgp->getHAPDGeometry().getWinThickness();
275 double refractiveInd0 =
m_arichgp->getHAPDGeometry().getWinRefIndex();
279 const double dmin = 0.0000001;
280 const int niter = 100;
282 TVector3 rh1 = rh - dwin * norm;
284 std::vector <TVector3> rf0(n + 2);
288 std::vector <TVector3> dirf0(n + 2);
301 for (
int iter = 0; iter < niter; iter++) {
305 if (iter == 0) dirf0[n] = (rh1 - rf0[1]).
Unit();
306 else dirf0[n] = (rh1 - rf0[n]).
Unit();
310 for (
int a = n - 1; a >= 0 ; a--) {
311 double rind = refractiveInd[a] / refractiveInd[a + 1];
312 dirf0[a] = Refraction(dirf0[a + 1], rind);
315 double path = (z[0] - r.z()) / dirf0[0].z();
316 double x1 = rf0[1].x();
317 double y1 = rf0[1].y();
318 for (
int a = 0; a < n ; a++) {
319 rf0[a + 1] = rf0[a] + dirf0[a] * path;
320 path = (z[a + 1] - rf0[a + 1].z()) / dirf0[a + 1].z();
323 Refraction(dirf0[n], norm, refractiveInd0, dirw);
327 path = dwin / (dirw * norm);
328 rh1 = rh - dirw * path;
330 double d2 = (rf0[1].x() - x1) * (rf0[1].x() - x1) + (rf0[1].y() - y1) * (rf0[1].y() - y1);
332 if ((d2 < dmin) && (iter)) {
336 if (!
HitsMirror(rf0[n], dirf0[n], mirrorID))
return -1;
351 const unsigned int nPhotonHits = arichHits.getEntries();
364 double padSize =
m_arichgp->getHAPDGeometry().getPadSize();
365 int nMirSeg =
m_arichgp->getMirrors().getNMirrors();
366 double angmir =
m_arichgp->getMirrors().getStartAngle();
376 if (edir.z() < 0)
return 0;
379 double thcResolution =
m_recPars->getThcResolution(momentum);
380 if (thcResolution < 0) thcResolution = 0.01;
382 double wideGaussFract = (
m_recPars->getParameters())[0];
383 double wideGaussSigma = (
m_recPars->getParameters())[1];
386 double r = arichTrack.
getPosition().XYvector().Mod();
393 float nphot_scaling = 20.;
405 thetaCh[iHyp][iAerogel] = ExpectedCherenkovAngle(momentum,
411 if (pathLengthRadiator) pathLengthRadiator =
m_thickness[iAerogel] / pathLengthRadiator;
414 double dxx = pathLengthRadiator / double(nStep);
416 double nPhot =
m_n0[iAerogel] * sin(thetaCh[iHyp][iAerogel]) * sin(thetaCh[iHyp][iAerogel]) * dxx * nphot_scaling;
420 for (
int iepoint = 0; iepoint < nStep; iepoint++) {
422 TVector3 epoint = exit_point - (0.5 + iepoint) * dxx * edir;
424 unsigned int genPhot = nPhot * abs;
427 for (
unsigned int iPhoton = 0; iPhoton < genPhot; iPhoton++) {
428 double fi = 2 * M_PI * iPhoton / float(genPhot);
429 TVector3 adirf = setThetaPhi(thetaCh[iHyp][iAerogel], fi);
430 adirf = TransformFromFixed(edir) * adirf;
431 int ifi = int (fi * 20 / 2. / M_PI);
434 if (dposition.Mag() > 1.0) {nSig_wo_acc[iHyp][iAerogel][ifi] += 1; nSig_wo_accInt[iHyp][iAerogel] += 1;}
436 unsigned copyno =
m_arichgp->getDetectorPlane().pointSlotID(dposition.X(), dposition.Y());
437 if (!copyno)
continue;
439 if (
InsideDetector(dposition, copyno)) nSig_w_acc[iHyp][iAerogel] += 1;
444 for (
int ik = 0; ik < 20; ik++) {
445 nSig_wo_acc[iHyp][iAerogel][ik] /= nphot_scaling;
447 nSig_w_acc[iHyp][iAerogel] /= nphot_scaling;
448 nSig_wo_accInt[iHyp][iAerogel] /= nphot_scaling;
456 for (
int ik = 0; ik < 20; ik++) {
462 std::vector<double> bkgPars = {momentum / sqrt(
p_mass[iHyp]*
p_mass[iHyp] + momentum * momentum), double(arichTrack.
hitsWindow())};
463 nBgr[iHyp] =
m_recPars->getExpectedBackgroundHits(bkgPars);
477 if (track_at_detector.XYvector().Mod() > 85.0) {
478 double trackang = track_at_detector.Phi() - angmir;
479 if (trackang < 0) trackang += 2 * M_PI;
480 if (trackang > 2 * M_PI) trackang -= 2 * M_PI;
481 int section1 = int(trackang * nMirSeg / 2. / M_PI) + 1;
482 int section2 = section1 + 1;
483 if (section1 == nMirSeg) section2 = 1;
484 mirrors[1] = section1; mirrors[2] = section2;
490 for (
unsigned int iPhoton = 0; iPhoton < nPhotonHits; iPhoton++) {
493 int modID = h->getModule();
494 int channel = h->getChannel();
495 TVector3 hitpos =
m_arichgp->getMasterVolume().pointToLocal(h->getPosition());
496 bool bkgAdded =
false;
497 int nfoo = nDetPhotons;
498 for (
int iHyp = 0; iHyp <
c_noOfHypotheses; iHyp++) { esigi[iHyp] = 0; ebgri[iHyp] = 0;}
503 for (
int mirr = 0; mirr < refl; mirr++) {
512 if ((track_at_detector - virthitpos).Mag() > 25.0)
continue;
521 double fi_cer_trk = 0.;
529 TVector3 photonDirection;
534 TVector3 dirch = TransformToFixed(edirr) * photonDirection;
535 double fi_cer = dirch.Phi();
536 double th_cer = dirch.Theta();
539 th_cer_all[iAerogel] = th_cer;
540 fi_cer_all[iAerogel] = fi_cer;
541 fi_cer_trk = dirch.XYvector().DeltaPhi(edirr.XYvector());
543 if (mirr == 0 && th_cer < 0.1) reflOK =
false;
545 if (th_cer > 0.5 || th_cer < 0.1)
continue;
548 if (nfoo == nDetPhotons) nDetPhotons++;
550 if (fi_cer < 0) fi_cer += 2 * M_PI;
553 double fi_mir =
m_mirrorNorms[mirrors[mirr] - 1].XYvector().Phi();
554 fii = 2 * fi_mir - fi_cer - M_PI;
562 TVector3 photonDirection1 = setThetaPhi(thetaCh[iHyp][iAerogel], fi_cer);
563 photonDirection1 = TransformFromFixed(edirr) * photonDirection1;
564 int ifi = int (fi_cer * 20 / 2. / M_PI);
565 TVector3 photonAtAerogelExit = photonDirection1 * (
m_thickness[iAerogel] / photonDirection1.z());
566 TVector3 trackAtAerogelExit = edirr * (
m_thickness[iAerogel] / edirr.z());
567 TVector3 dtrackphoton = photonAtAerogelExit - trackAtAerogelExit;
568 TVector3 detector_position;
573 TVector3 meanr = detector_position - epoint;
574 double path = meanr.Mag();
575 meanr = meanr.Unit();
577 double detector_sigma = thcResolution * path / meanr.z();
578 double wide_sigma = wideGaussSigma * path / meanr.z();
580 double modphi =
m_arichgp->getDetectorPlane().getSlotPhi(modID);
582 double pad_fi = fii - modphi;
583 double dx = (detector_position - hitpos).Mag();
584 double dr = (track_at_detector - detector_position).Mag();
587 double normalizacija = nSig_wo_acc[iHyp][iAerogel][ifi] * padSize / (0.1 * M_PI * dr);
588 weight[iHyp][iAerogel] = normalizacija;
589 weight_sum[iHyp] += weight[iHyp][iAerogel];
590 double integralMain = SquareInt(padSize, pad_fi, dx, detector_sigma) / sqrt(2.);
591 double integralWide = SquareInt(padSize, pad_fi, dx, wide_sigma) / sqrt(2.);
593 double exp = normalizacija * ((1 - wideGaussFract) * integralMain + wideGaussFract * integralWide);
595 sigExpArr[iHyp] += exp;
606 std::vector<double> pars = {momentum / sqrt(
p_mass[iHyp]*
p_mass[iHyp] + momentum * momentum), double(arichTrack.
hitsWindow())};
607 ebgri[iHyp] +=
m_recPars->getBackgroundPerPad(th_cer_all[1], pars);
613 if (
m_storePhot && th_cer_all[1] > 0 && th_cer_all[1] < 0.6) {
617 if (weight_sum[iHyp] > 0) {
619 double emission_prob = weight[iHyp][iAerogel] / weight_sum[iHyp];
620 n_cos_theta_ch[iHyp] += emission_prob *
m_refractiveInd[iAerogel] * cos(th_cer_all[iAerogel]);
621 phi_ch[iHyp] += emission_prob * fi_cer_all[iAerogel];
625 n_cos_theta_ch[iHyp] = -99999.;
626 phi_ch[iHyp] = -99999.;
629 ARICHPhoton phot(iPhoton, th_cer_all[1], fi_cer_all[1], mirrors[mirr]);
635 phot.
setXY(hitpos.X(), hitpos.Y());
649 double expected = esigi[iHyp] + ebgri[iHyp];
650 if (bkgAdded) logL[iHyp] += expected + log(1 - exp(-expected));
660 exppho[iHyp] = nSig_w_acc[iHyp][
m_nAerogelLayers] * (1 - wideGaussFract) + wideGaussFract * 0.7 *
662 logL[iHyp] -= exppho[iHyp];
663 if (isnan(logL[iHyp]) || isinf(logL[iHyp])) {
664 B2WARNING(
"ARICHReconstruction: log likelihood value infinite! Flat background hit probability is " << ebgri[iHyp] <<
"!");
674 if ((thetaCh[0][0] > 0 || thetaCh[0][1] > 0) && nSig_w_acc[0][
m_nAerogelLayers] == 0) flag = 0;
677 arichLikelihood.
setValues(flag, logL, nDetPhotons, exppho);
695 TVector3 dir = track.getDirection();
696 if (dir.Z() == 0)
return TVector3();
698 double dmean = 1 - d / expm1(d);
707 TVector3 dir = track.getDirection();
708 TVector3 pos = track.getPosition();
709 if (dir.Z() == 0)
return TVector3(0, 0, 0);
710 double path = (zout - pos.Z()) / dir.Z();
711 return pos + dir * path;
723 locPos =
m_alignp->pointToLocal(locPos);
724 locDir =
m_alignp->momentumToLocal(locDir);
737 TVector3 mirpoint =
m_arichgp->getMirrors().getPoint(mirrorID);
747 TVector3 mirnorm =
m_arichgp->getMirrors().getNormVector(mirrorID);
748 mirnorm.SetTheta(mirnorm.Theta() +
m_mirrAlign->getAlignmentElement(mirrorID).getAlpha());
749 mirnorm.SetPhi(mirnorm.Phi() +
m_mirrAlign->getAlignmentElement(mirrorID).getBeta());
753 return m_arichgp->getMirrors().getNormVector(mirrorID);
759 double ang = m_tilePars[tileID - 1][0] + m_tilePars[tileID - 1][1] * r;
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< TVector3 > m_mirrorNorms
vector of nomal vectors of 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 emmited 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
OptionalDBObjPtr< ARICHAeroTilesAlignment > m_tileAlign
alignment of aerogel tiles from DB
double m_trackAngRes
track direction resolution (from tracking)
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
TVector3 m_anorm[c_noOfAerogels]
normal vector of the aerogle plane
std::vector< TVector3 > m_mirrorPoints
vector of points on all mirror plates
double m_thickness[c_noOfAerogels]
thicknesses of areogel layers
Datastore class that holds position and momentum information of tracks that hit ARICH.
void setReconstructedValues(TVector3 r, TVector3 dir, double p)
Sets the reconstructed value of track parameters.
bool hitsWindow() const
Returns true if track hits HAPD window.
TVector3 getPosition() const
returns track position vector
void addPhoton(ARICHPhoton photon)
Add ARICHPhoton to collection of photons.
TVector3 getDirection() const
returns track direction 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)
TVector3 getMirrorNorm(int mirrorID)
Returns normal vector of the mirror plate with id mirrorID.
int likelihood2(ARICHTrack &arichTrack, const StoreArray< ARICHHit > &arichHits, ARICHLikelihood &arichLikelihood)
Computes the value of identity likelihood function for different particle hypotheses.
void initialize()
read geomerty parameters from xml and initialize class memebers
TVector3 getMirrorPoint(int mirrorID)
Returns point on the mirror plate with id mirrorID.
void correctEmissionPoint(int tileID, double r)
correct mean emission point z position
int InsideDetector(TVector3 a, int copyno)
Returns 1 if vector "a" lies on "copyno"-th detector active surface of detector and 0 else.
void setTrackAngleResolution(double aRes)
Sets track direction resolution (from tracking)
int CherenkovPhoton(TVector3 r, TVector3 rh, TVector3 &rf, TVector3 &dirf, double *refind, double *z, int n, int mirrorID=0)
Calculates the direction of photon emission.
TVector3 FastTracking(TVector3 dirf, TVector3 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...
TVector3 HitVirtualPosition(const TVector3 &hitpos, int mirrorID)
Returns the hit virtual position, assuming that it was reflected from mirror.
void transformTrackToLocal(ARICHTrack &arichTrack, bool align)
Transforms track parameters from global Belle2 to ARICH local frame.
bool HitsMirror(const TVector3 &pos, const TVector3 &dir, int mirrorID)
returns true if photon at position pos with direction dir hits mirror plate with ID mirrorID
TVector3 getTrackPositionAtZ(const ARICHTrack &track, double zout)
Returns track direction at point with z coordinate "zout" (assumes straight track).
int smearTrack(ARICHTrack &arichTrack)
Smeares track parameters ("simulate" the uncertainties of tracking).
TVector3 getTrackMeanEmissionPosition(const ARICHTrack &track, int iAero)
Returns mean emission position of Cherenkov photons from i-th aerogel layer.
Abstract base class for different kinds of events.
record to be used to store ASIC info