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>
27 using namespace boost;
35 using namespace arich;
37 ARICHReconstruction::ARICHReconstruction(
int storePhot):
44 m_storePhot(storePhot)
62 p_mass[part.getIndex()] = part.getMass();
91 for (
unsigned i = 1; i <
m_arichgp->getMirrors().getNMirrors() + 1; i++) {
99 for (
int iTile = 1; iTile < 125; iTile++) {
100 m_tilePars[iTile - 1][0] =
m_tileAlign->getAlignmentElement(iTile).getAlpha();
101 m_tilePars[iTile - 1][1] =
m_tileAlign->getAlignmentElement(iTile).getBeta();
110 if (copyno == -1)
return 0;
112 origin.SetMagPhi(
m_arichgp->getDetectorPlane().getSlotR(copyno),
m_arichgp->getDetectorPlane().getSlotPhi(copyno));
113 TVector2 a2(a.X(), a.Y());
114 double phi =
m_arichgp->getDetectorPlane().getSlotPhi(copyno);
115 TVector2 diff = a2 - origin;
116 diff = diff.Rotate(-phi);
117 const double size =
m_arichgp->getHAPDGeometry().getAPDSizeX();
118 if (fabs(diff.X()) < size / 2. && fabs(diff.Y()) < size / 2.) {
120 m_arichgp->getHAPDGeometry().getXYChannel(diff.X(), diff.Y(), chX, chY);
121 if (chX < 0 || chY < 0)
return 0;
135 TVector3 dirf(a, b,
sqrt(1 - a * a - b * b));
138 TVector3 mod = TVector3(dx, dy, 0);
142 TVector3 rdir = TransformFromFixed(odir) * dirf;
143 double rmomentum = omomentum;
160 double angmir = 0;
int section[2] = {0, 0};
162 unsigned tileID =
m_arichgp->getAerogelPlane().getAerogelTileID(r.X(), r.Y());
164 if (tileID == 0 && opt == 1)
return TVector3();
166 int nmir =
m_arichgp->getMirrors().getNMirrors();
168 double dangle = 2 * M_PI / nmir;
169 angmir =
m_arichgp->getMirrors().getStartAngle() - dangle / 2.;
171 double trkangle = r.XYvector().Phi() - angmir;
172 if (trkangle < 0) trkangle += 2 * M_PI;
173 if (trkangle > 2 * M_PI) trkangle -= 2 * M_PI;
175 section[1] = int(trkangle / dangle) + 1;
178 bool reflok =
false;
bool refl =
false;
179 double path = (z[0] - r.Z()) / dirf.Z();
181 for (
int a = 1; a <= n + 1 ; a++) {
182 double rind = refractiveInd[a] / refractiveInd[a - 1];
183 dirf = Refraction(dirf, rind);
184 if (dirf.Mag() == 0)
return TVector3();
185 path = (z[a] - r.Z()) / dirf.Z();
187 if (a == n && opt == 1) {
188 if (
m_arichgp->getAerogelPlane().getAerogelTileID(r.X(), r.Y()) != tileID)
return TVector3();
191 TVector2 rxy = r.XYvector();
193 if (a != n || nmir == 0)
continue;
194 double angle = rxy.Phi() - angmir;
195 if (angle < 0) angle += 2 * M_PI;
196 if (angle > 2 * M_PI) angle -= 2 * M_PI;
197 double dangle = 2 * M_PI / nmir;
198 section[0] = int(angle / dangle) + 1;
202 if (section[0] == section[1]) nrefl = 1;
203 for (
int k = 0; k < nrefl; k++) {
204 if (!
HitsMirror(r0, dirf, section[k]))
continue;
207 double s = dirf * mirnorm;
208 double s1 = (mirpoint - r0) * mirnorm;
209 r = r0 + s1 / s * dirf;
210 dirf = dirf - 2 * (dirf * mirnorm) * mirnorm;
211 path = (z[a] - r.Z()) / dirf.Z();
219 if (!reflok && refl)
return TVector3();
226 if (mirrorID == 0)
return hitpos;
229 return hitpos - 2 * ((hitpos - mirpoint) * mirnorm) * mirnorm;
238 TRotation rot = TransformToFixed(mirnorm);
239 TVector3 dirTr = rot * dir;
240 if (dirTr.Z() < 0)
return 0;
241 TVector3 posTr = rot * (pos - mirpoint);
242 TVector3 pointOnMirr = posTr - (posTr.Z() / dirTr.Z()) * dirTr;
243 if (fabs(pointOnMirr.Y()) <
m_arichgp->getMirrors().getPlateLength() / 2.
244 && fabs(pointOnMirr.X()) <
m_arichgp->getMirrors().getPlateWidth() / 2.)
return 1;
251 TVector3& rf, TVector3& dirf,
252 double* refractiveInd,
double* z,
int n,
int mirrorID)
271 static TVector3 norm(0, 0, 1);
273 double dwin =
m_arichgp->getHAPDGeometry().getWinThickness();
274 double refractiveInd0 =
m_arichgp->getHAPDGeometry().getWinRefIndex();
278 const double dmin = 0.0000001;
279 const int niter = 100;
281 TVector3 rh1 = rh - dwin * norm;
283 std::vector <TVector3> rf0(n + 2);
287 std::vector <TVector3> dirf0(n + 2);
300 for (
int iter = 0; iter < niter; iter++) {
304 if (iter == 0) dirf0[n] = (rh1 - rf0[1]).
Unit();
305 else dirf0[n] = (rh1 - rf0[n]).
Unit();
309 for (
int a = n - 1; a >= 0 ; a--) {
310 double rind = refractiveInd[a] / refractiveInd[a + 1];
311 dirf0[a] = Refraction(dirf0[a + 1], rind);
314 double path = (z[0] - r.Z()) / dirf0[0].Z();
315 double x1 = rf0[1].X();
316 double y1 = rf0[1].Y();
317 for (
int a = 0; a < n ; a++) {
318 rf0[a + 1] = rf0[a] + dirf0[a] * path;
319 path = (z[a + 1] - rf0[a + 1].Z()) / dirf0[a + 1].Z();
322 Refraction(dirf0[n], norm, refractiveInd0, dirw);
326 path = dwin / (dirw * norm);
327 rh1 = rh - dirw * path;
329 double d2 = (rf0[1].X() - x1) * (rf0[1].X() - x1) + (rf0[1].Y() - y1) * (rf0[1].Y() - y1);
331 if ((d2 < dmin) && (iter)) {
335 if (!
HitsMirror(rf0[n], dirf0[n], mirrorID))
return -1;
350 const unsigned int nPhotonHits = arichHits.getEntries();
363 double padSize =
m_arichgp->getHAPDGeometry().getPadSize();
364 int nMirSeg =
m_arichgp->getMirrors().getNMirrors();
365 double angmir =
m_arichgp->getMirrors().getStartAngle();
375 if (edir.Z() < 0)
return 0;
378 double thcResolution =
m_recPars->getThcResolution(momentum);
379 if (thcResolution < 0) thcResolution = 0.01;
381 double wideGaussFract = (
m_recPars->getParameters())[0];
382 double wideGaussSigma = (
m_recPars->getParameters())[1];
385 double r = arichTrack.
getPosition().XYvector().Mod();
392 float nphot_scaling = 20.;
404 thetaCh[iHyp][iAerogel] = ExpectedCherenkovAngle(momentum,
410 if (pathLengthRadiator) pathLengthRadiator =
m_thickness[iAerogel] / pathLengthRadiator;
413 double dxx = pathLengthRadiator / double(nStep);
415 double nPhot =
m_n0[iAerogel] * sin(thetaCh[iHyp][iAerogel]) * sin(thetaCh[iHyp][iAerogel]) * dxx * nphot_scaling;
419 for (
int iepoint = 0; iepoint < nStep; iepoint++) {
421 TVector3 epoint = exit_point - (0.5 + iepoint) * dxx * edir;
423 unsigned int genPhot = nPhot * abs;
426 for (
unsigned int iPhoton = 0; iPhoton < genPhot; iPhoton++) {
427 double fi = 2 * M_PI * iPhoton / float(genPhot);
428 TVector3 adirf = setThetaPhi(thetaCh[iHyp][iAerogel], fi);
429 adirf = TransformFromFixed(edir) * adirf;
430 int ifi = int (fi * 20 / 2. / M_PI);
433 if (dposition.Mag() > 1.0) {nSig_wo_acc[iHyp][iAerogel][ifi] += 1; nSig_wo_accInt[iHyp][iAerogel] += 1;}
435 unsigned copyno =
m_arichgp->getDetectorPlane().pointSlotID(dposition.X(), dposition.Y());
436 if (!copyno)
continue;
438 if (
InsideDetector(dposition, copyno)) nSig_w_acc[iHyp][iAerogel] += 1;
443 for (
int ik = 0; ik < 20; ik++) {
444 nSig_wo_acc[iHyp][iAerogel][ik] /= nphot_scaling;
446 nSig_w_acc[iHyp][iAerogel] /= nphot_scaling;
447 nSig_wo_accInt[iHyp][iAerogel] /= nphot_scaling;
455 for (
int ik = 0; ik < 20; ik++) {
461 std::vector<double> bkgPars = {momentum /
sqrt(
p_mass[iHyp]*
p_mass[iHyp] + momentum * momentum), double(arichTrack.
hitsWindow())};
462 nBgr[iHyp] =
m_recPars->getExpectedBackgroundHits(bkgPars);
476 if (track_at_detector.XYvector().Mod() > 85.0) {
477 double trackang = track_at_detector.Phi() - angmir;
478 if (trackang < 0) trackang += 2 * M_PI;
479 if (trackang > 2 * M_PI) trackang -= 2 * M_PI;
480 int section1 = int(trackang * nMirSeg / 2. / M_PI) + 1;
481 int section2 = section1 + 1;
482 if (section1 == nMirSeg) section2 = 1;
483 mirrors[1] = section1; mirrors[2] = section2;
489 for (
unsigned int iPhoton = 0; iPhoton < nPhotonHits; iPhoton++) {
492 int modID = h->getModule();
493 int channel = h->getChannel();
494 TVector3 hitpos =
m_arichgp->getMasterVolume().pointToLocal(h->getPosition());
495 bool bkgAdded =
false;
496 int nfoo = nDetPhotons;
497 for (
int iHyp = 0; iHyp <
c_noOfHypotheses; iHyp++) { esigi[iHyp] = 0; ebgri[iHyp] = 0;}
502 for (
int mirr = 0; mirr < refl; mirr++) {
511 if ((track_at_detector - virthitpos).Mag() > 25.0)
continue;
520 double fi_cer_trk = 0.;
528 TVector3 photonDirection;
533 TVector3 dirch = TransformToFixed(edirr) * photonDirection;
534 double fi_cer = dirch.Phi();
535 double th_cer = dirch.Theta();
538 th_cer_all[iAerogel] = th_cer;
539 fi_cer_all[iAerogel] = fi_cer;
540 fi_cer_trk = dirch.XYvector().DeltaPhi(edirr.XYvector());
542 if (mirr == 0 && th_cer < 0.1) reflOK =
false;
544 if (th_cer > 0.5 || th_cer < 0.1)
continue;
547 if (nfoo == nDetPhotons) nDetPhotons++;
549 if (fi_cer < 0) fi_cer += 2 * M_PI;
552 double fi_mir =
m_mirrorNorms[mirrors[mirr] - 1].XYvector().Phi();
553 fii = 2 * fi_mir - fi_cer - M_PI;
561 TVector3 photonDirection1 = setThetaPhi(thetaCh[iHyp][iAerogel], fi_cer);
562 photonDirection1 = TransformFromFixed(edirr) * photonDirection1;
563 int ifi = int (fi_cer * 20 / 2. / M_PI);
564 TVector3 photonAtAerogelExit = photonDirection1 * (
m_thickness[iAerogel] / photonDirection1.Z());
565 TVector3 trackAtAerogelExit = edirr * (
m_thickness[iAerogel] / edirr.Z());
566 TVector3 dtrackphoton = photonAtAerogelExit - trackAtAerogelExit;
567 TVector3 detector_position;
572 TVector3 meanr = detector_position - epoint;
573 double path = meanr.Mag();
574 meanr = meanr.Unit();
576 double meanpath = (
m_recPars->getParameters())[2];
577 if (iAerogel == 1) meanpath = meanpath -
m_thickness[iAerogel];
579 double detector_sigma = thcResolution * meanpath / 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 * meanr.Z());
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;
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.
double sqrt(double a)
sqrt for double
Abstract base class for different kinds of events.
record to be used to store ASIC info