File indexing completed on 2025-12-17 09:19:56
0001 #include "BEmcRecCEMC.h"
0002
0003 #include "BEmcCluster.h"
0004 #include "BEmcProfile.h"
0005
0006 #include <cmath>
0007 #include <iostream>
0008 #include <Math/Vector3D.h> // for TVector3 used in calculateIncidence
0009 #include <algorithm> // for std::max
0010 using ROOT::Math::XYZVector;
0011
0012 BEmcRecCEMC::BEmcRecCEMC()
0013 {
0014 Name("BEmcRecCEMC");
0015 SetCylindricalGeometry();
0016 }
0017
0018 void BEmcRecCEMC::LoadProfile(const std::string& fname)
0019 {
0020
0021 _emcprof = new BEmcProfile(fname);
0022 }
0023
0024 void BEmcRecCEMC::GetImpactThetaPhi(float xg, float yg, float zg, float& theta, float& phi)
0025 {
0026 theta = 0;
0027 phi = 0;
0028
0029
0030 float rg = std::sqrt((xg * xg) + (yg * yg));
0031 float theta_twr;
0032 if (std::fabs(zg) <= 15)
0033 {
0034 theta_twr = 0;
0035 }
0036 else if (zg > 15)
0037 {
0038 theta_twr = std::atan2(zg - 15, rg);
0039 }
0040 else
0041 {
0042 theta_twr = std::atan2(zg + 15, rg);
0043 }
0044 float theta_tr = std::atan2(zg - fVz, rg);
0045 theta = std::fabs(theta_tr - theta_twr);
0046
0047 }
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240 bool BEmcRecCEMC::calculateIncidence(float x, float y,
0241 float& a_phi_sgn, float& a_eta_sgn)
0242 {
0243
0244
0245
0246 const int ix = EmcCluster::lowint(x + 0.5F);
0247 const int iy = EmcCluster::lowint(y + 0.5F);
0248
0249 TowerGeom g{};
0250 if (!GetTowerGeometry(ix, iy, g))
0251 {
0252 return false;
0253 }
0254
0255
0256 const float dx = x - ix;
0257 const float dy = y - iy;
0258
0259
0260
0261
0262
0263 const XYZVector C(g.Xcenter, g.Ycenter, g.Zcenter);
0264 const XYZVector ephi_geom(g.dX[0], g.dY[0], g.dZ[0]);
0265 const XYZVector eeta_geom(g.dX[1], g.dY[1], g.dZ[1]);
0266
0267 if (std::sqrt(ephi_geom.Mag2()) < 1e-9 || std::sqrt(eeta_geom.Mag2()) < 1e-9)
0268 {
0269 return false;
0270 }
0271
0272 const XYZVector F = C + dx * ephi_geom + dy * eeta_geom;
0273
0274
0275
0276
0277 const XYZVector V(0., 0., fVz);
0278 XYZVector pF = F - V;
0279 const double pFmag = std::sqrt(pF.Mag2());
0280 if (!(pFmag > 0.0))
0281 {
0282 return false;
0283 }
0284 pF *= (1.0 / pFmag);
0285
0286
0287
0288 auto basis_to_incidence =
0289 [&](const XYZVector& un_b, const XYZVector& uphi_b, const XYZVector& ueta_b,
0290 double& pn_b, double& pph_b, double& pet_b,
0291 double& aphi_b, double& aeta_b) -> bool
0292 {
0293 pn_b = pF.Dot(un_b);
0294 pph_b = pF.Dot(uphi_b);
0295 pet_b = pF.Dot(ueta_b);
0296
0297 const double apn_b = std::max(1e-12, std::fabs(pn_b));
0298 const double aphi_mag_b = std::atan2(std::fabs(pph_b), apn_b);
0299 const double aeta_mag_b = std::atan2(std::fabs(pet_b), apn_b);
0300
0301 const double sgn_phi_b = (pph_b >= 0.0) ? +1.0 : -1.0;
0302 const double sgn_eta_b = (pet_b >= 0.0) ? +1.0 : -1.0;
0303
0304 aphi_b = sgn_phi_b * aphi_mag_b;
0305 aeta_b = sgn_eta_b * aeta_mag_b;
0306
0307 return (std::isfinite(aphi_b) && std::isfinite(aeta_b));
0308 };
0309
0310
0311
0312
0313 XYZVector un_mech;
0314 XYZVector uphi_mech;
0315 XYZVector ueta_mech;
0316 {
0317 const double rx = g.rotX;
0318 const double ry = g.rotY;
0319 const double rz = g.rotZ;
0320
0321 const double cx = std::cos(rx);
0322 const double sx = std::sin(rx);
0323 const double cy = std::cos(ry);
0324 const double sy = std::sin(ry);
0325 const double cz = std::cos(rz);
0326 const double sz = std::sin(rz);
0327
0328 auto applyRot = [&](const XYZVector& v) -> XYZVector
0329 {
0330
0331 double vx = v.X();
0332 double vy = v.Y();
0333 double vz = v.Z();
0334
0335
0336 const double vx1 = vx;
0337 const double vy1 = cx * vy - sx * vz;
0338 const double vz1 = sx * vy + cx * vz;
0339
0340
0341 const double vx2 = cy * vx1 + sy * vz1;
0342 const double vy2 = vy1;
0343 const double vz2 = -sy * vx1 + cy * vz1;
0344
0345
0346 const double vx3 = cz * vx2 - sz * vy2;
0347 const double vy3 = sz * vx2 + cz * vy2;
0348 const double vz3 = vz2;
0349
0350 return XYZVector(vx3, vy3, vz3);
0351 };
0352
0353
0354 XYZVector u_axis = applyRot(XYZVector(0., 0., 1.));
0355 const XYZVector u_x = applyRot(XYZVector(1., 0., 0.));
0356 const XYZVector u_y = applyRot(XYZVector(0., 1., 0.));
0357
0358
0359 const double amag = std::sqrt(u_axis.Mag2());
0360 if (!(amag > 0.0))
0361 {
0362 return false;
0363 }
0364
0365 u_axis *= (1.0 / amag);
0366 if (u_axis.Dot(C) < 0.0)
0367 {
0368 u_axis = -u_axis;
0369 }
0370
0371 un_mech = u_axis;
0372
0373
0374 uphi_mech = u_x - un_mech * u_x.Dot(un_mech);
0375 const double uphim = std::sqrt(uphi_mech.Mag2());
0376 if (!(uphim > 0.0))
0377 {
0378 return false;
0379 }
0380 uphi_mech *= (1.0 / uphim);
0381
0382
0383 ueta_mech = u_y
0384 - un_mech * u_y.Dot(un_mech)
0385 - uphi_mech * u_y.Dot(uphi_mech);
0386 const double uetam = std::sqrt(ueta_mech.Mag2());
0387 if (!(uetam > 0.0))
0388 {
0389 return false;
0390 }
0391 ueta_mech *= (1.0 / uetam);
0392
0393
0394 if (un_mech.Cross(uphi_mech).Dot(ueta_mech) < 0.0)
0395 {
0396 ueta_mech = -ueta_mech;
0397 }
0398
0399
0400 XYZVector uphi_ref = ephi_geom;
0401 const double refMag = std::sqrt(uphi_ref.Mag2());
0402 if (refMag > 0.0)
0403 {
0404 uphi_ref *= (1.0 / refMag);
0405 if (uphi_mech.Dot(uphi_ref) < 0.0)
0406 {
0407 uphi_mech = -uphi_mech;
0408 ueta_mech = -ueta_mech;
0409 }
0410 }
0411 }
0412
0413
0414
0415
0416 double pn = 0.0;
0417 double pph = 0.0;
0418 double pet = 0.0;
0419 double aphi = 0.0;
0420 double aeta = 0.0;
0421
0422 if (!basis_to_incidence(un_mech, uphi_mech, ueta_mech,
0423 pn, pph, pet,
0424 aphi, aeta))
0425 {
0426 return false;
0427 }
0428
0429 a_phi_sgn = static_cast<float>(aphi);
0430 a_eta_sgn = static_cast<float>(aeta);
0431
0432 m_lastAlphaPhiSigned = a_phi_sgn;
0433 m_lastAlphaEtaSigned = a_eta_sgn;
0434
0435 const bool ok =
0436 (std::isfinite(a_phi_sgn) && std::isfinite(a_eta_sgn));
0437
0438 return ok;
0439 }
0440
0441 void BEmcRecCEMC::CorrectShowerDepth(int ix, int iy, float E, float xA, float yA, float zA, float& xC, float& yC, float& zC)
0442 {
0443 if (!m_UseCorrectShowerDepth)
0444 {
0445 xC = xA;
0446 yC = yA;
0447 zC = zA;
0448 return;
0449 }
0450
0451 float logE = log(0.1);
0452 if (E > 0.1)
0453 {
0454 logE = std::log(E);
0455 }
0456
0457 float phi = 0;
0458
0459
0460 if (m_UseDetailedGeometry)
0461 {
0462 phi = 0.0033 - 0.0010 * logE;
0463 }
0464 else
0465 {
0466 phi = 0.0016 - 0.0010 * logE;
0467 }
0468 xC = xA * std::cos(phi) - yA * std::sin(phi);
0469 yC = xA * std::sin(phi) + yA * std::cos(phi);
0470
0471
0472 float rA = std::sqrt((xA * xA) + (yA * yA));
0473 float theta_twr;
0474 if (m_UseDetailedGeometry)
0475 {
0476
0477 TowerGeom geom0;
0478 GetTowerGeometry(ix, iy, geom0);
0479 theta_twr = M_PI / 2 + geom0.rotX;
0480 }
0481 else
0482 {
0483
0484 theta_twr = M_PI / 2 - angles[iy];
0485 }
0486
0487 float theta_tr = std::atan2(zA - fVz, rA);
0488
0489
0490
0491 float L = 0;
0492 if (m_UseDetailedGeometry)
0493 {
0494 L = -2.67787 + 0.924138 * logE;
0495 }
0496 else
0497 {
0498 L = -1.79968 + 0.837322 * logE;
0499 }
0500 float dz = L * std::sin(theta_tr - theta_twr) / std::cos(theta_twr);
0501
0502 if (!m_UseDetailedGeometry)
0503 {
0504
0505
0506
0507 dz -= fVz * 0.10;
0508 }
0509
0510 zC = zA - dz;
0511
0512
0513
0514
0515 if (m_UseDetailedGeometry && std::abs(fVz) > 20)
0516 {
0517 float eta = std::asinh((zC - fVz) / rA);
0518 if (fVz > 0)
0519 {
0520 eta -= slopes_[iy] * (fVz - 20);
0521 }
0522 else
0523 {
0524 eta -= slopes_[fNy - iy - 1] * (fVz + 20);
0525 }
0526 zC = fVz + rA * std::sinh(eta);
0527 }
0528
0529 return;
0530 }
0531
0532 void BEmcRecCEMC::CorrectEnergy(float Energy, float , float ,
0533 float& Ecorr)
0534 {
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555 Ecorr = Energy;
0556 }
0557
0558 void BEmcRecCEMC::CorrectECore(float Ecore, float , float , float& Ecorr)
0559 {
0560
0561
0562
0563
0564
0565 const float c0 = 0.950;
0566 Ecorr = Ecore / c0;
0567 }
0568
0569 void BEmcRecCEMC::CorrectPosition(float Energy, float x, float y,
0570 float& xc, float& yc)
0571 {
0572
0573
0574
0575
0576
0577
0578 float bx;
0579 float by;
0580 float x0;
0581 float y0;
0582 int ix0;
0583 int iy0;
0584
0585 if (!m_UseCorrectPosition)
0586 {
0587 xc = x;
0588 yc = y;
0589 return;
0590 }
0591
0592 if (Energy < 0.01)
0593 {
0594 return;
0595 }
0596
0597 bx = 0.15;
0598 by = 0.15;
0599
0600 x0 = x;
0601 ix0 = EmcCluster::lowint(x0 + 0.5);
0602
0603 if (std::abs(x0 - ix0) <= 0.5)
0604 {
0605 x0 = ix0 + bx * asinh(2. * (x0 - ix0) * sinh(0.5 / bx));
0606 }
0607 else
0608 {
0609 x0 = x;
0610 std::cout << "????? Something wrong in BEmcRecCEMC::CorrectPosition: x = "
0611 << x << " dx = " << x0 - ix0 << std::endl;
0612 }
0613
0614
0615
0616 int ix8 = int(x + 0.5) / 8;
0617 float x8 = x + 0.5 - (ix8 * 8) - 4;
0618 float dx = 0;
0619 if (m_UseDetailedGeometry)
0620 {
0621
0622
0623
0624 int local_ix8 = int(x+0.5) - ix8 * 8;
0625 dx = factor_[local_ix8] * x8 / 4.;
0626 }
0627 else
0628 {
0629 dx = 0.10 * x8 / 4.;
0630 if (std::fabs(x8) > 3.3)
0631 {
0632 dx = 0;
0633 }
0634 }
0635
0636 xc = x0 - dx;
0637 while (xc < -0.5)
0638 {
0639 xc += float(fNx);
0640 }
0641 while (xc >= fNx - 0.5)
0642 {
0643 xc -= float(fNx);
0644 }
0645
0646 y0 = y;
0647 iy0 = EmcCluster::lowint(y0 + 0.5);
0648
0649 if (std::abs(y0 - iy0) <= 0.5)
0650 {
0651 y0 = iy0 + by * std::asinh(2. * (y0 - iy0) * sinh(0.5 / by));
0652 }
0653 else
0654 {
0655 y0 = y;
0656 std::cout << "????? Something wrong in BEmcRecCEMC::CorrectPosition: y = "
0657 << y << "dy = " << y0 - iy0 << std::endl;
0658 }
0659 yc = y0;
0660 }