File indexing completed on 2025-08-06 08:17:31
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "BEmcRec.h"
0010 #include "BEmcCluster.h"
0011 #include "BEmcProfile.h"
0012
0013 #include <TMath.h>
0014
0015 #include <cmath>
0016 #include <cstdlib>
0017 #include <fstream>
0018 #include <iostream>
0019 #include <utility>
0020
0021
0022
0023
0024 BEmcRec::BEmcRec() : fModules(new std::vector<EmcModule>), fClusters(new std::vector<EmcCluster>)
0025 {
0026 fTowerGeom.clear();
0027
0028
0029 }
0030
0031
0032
0033 BEmcRec::~BEmcRec()
0034 {
0035 if (fModules)
0036 {
0037 fModules->clear();
0038 delete fModules;
0039 }
0040
0041 if (fClusters)
0042 {
0043 fClusters->clear();
0044 delete fClusters;
0045 }
0046
0047 delete _emcprof;
0048 }
0049
0050
0051
0052 void BEmcRec::LoadProfile(const std::string& )
0053 {
0054 std::cout << "Warning from BEmcRec::LoadProfile(): No acton defined for shower profile evaluation; should be defined in a detector specific module " << Name() << std::endl;
0055 }
0056
0057 void BEmcRec::PrintTowerGeometry(const std::string& fname)
0058 {
0059 std::ofstream outfile(fname);
0060 if (!outfile.is_open())
0061 {
0062 std::cout << "Error in BEmcRec::PrintTowerGeometry(): Failed to open file "
0063 << fname << std::endl;
0064 return;
0065 }
0066 outfile << "Number of bins:" << std::endl;
0067 outfile << fNx << " " << fNy << std::endl;
0068 outfile << "ix iy x y z dx0 dy0 dz0 dx1 dy1 dz1" << std::endl;
0069 int ich;
0070 TowerGeom geom;
0071 std::map<int, TowerGeom>::iterator it;
0072 for (int iy = 0; iy < fNy; iy++)
0073 {
0074 for (int ix = 0; ix < fNx; ix++)
0075 {
0076 ich = iy * fNx + ix;
0077 it = fTowerGeom.find(ich);
0078 if (it != fTowerGeom.end())
0079 {
0080 geom = it->second;
0081 outfile << ix << " " << iy << " " << geom.Xcenter << " "
0082 << geom.Ycenter << " " << geom.Zcenter << " " << geom.dX[0] << " "
0083 << geom.dY[0] << " " << geom.dZ[0] << " " << geom.dX[1] << " "
0084 << geom.dY[1] << " " << geom.dZ[1] << std::endl;
0085
0086 }
0087 }
0088 }
0089 }
0090
0091 void BEmcRec::PrintTowerGeometryDetailed(const std::string& fname)
0092 {
0093 std::ofstream outfile(fname);
0094 if (!outfile.is_open())
0095 {
0096 std::cout << "Error in BEmcRec::PrintTowerGeometry(): Failed to open file "
0097 << fname << std::endl;
0098 return;
0099 }
0100 outfile << "Number of bins:" << std::endl;
0101 outfile << fNx << " " << fNy << std::endl;
0102 outfile << "ieta iphi vtx_1_x vtx_1_y vtx_1_z vtx_2_x vtx_2_y vtx_2_z vtx_3_x vtx_3_y vtx_3_z vtx_4_x vtx_4_y vtx_4_z vtx_5_x vtx_5_y vtx_5_z vtx_6_x vtx_6_y vtx_6_z vtx_7_x vtx_7_y vtx_7_z vtx_8_x vtx_8_y vtx_8_z\n";
0103 int ich;
0104 RawTowerGeom *geom;
0105 std::map<int, RawTowerGeom*>::iterator it;
0106 for (int iy = 0; iy < fNy; iy++)
0107 {
0108 for (int ix = 0; ix < fNx; ix++)
0109 {
0110 ich = iy * fNx + ix;
0111 it = fTowerGeomDetailed.find(ich);
0112 if (it != fTowerGeomDetailed.end())
0113 {
0114 geom = it->second;
0115 outfile << ix << " " << iy << " ";
0116 for (int ivtx = 0; ivtx < 8; ivtx++) {
0117 outfile << geom->get_vertex_x(ivtx) << " " << geom->get_vertex_y(ivtx) << " " << geom->get_vertex_z(ivtx) << " ";
0118 }
0119 outfile << "\n";
0120 }
0121 }
0122 }
0123 }
0124
0125 bool BEmcRec::GetTowerGeometry(int ix, int iy, TowerGeom& geom)
0126 {
0127 if (ix < 0 || ix >= fNx || iy < 0 || iy >= fNy)
0128 {
0129 return false;
0130 }
0131
0132 int ich = (iy * fNx) + ix;
0133 std::map<int, TowerGeom>::iterator it = fTowerGeom.find(ich);
0134 if (it == fTowerGeom.end())
0135 {
0136 return false;
0137 }
0138
0139 geom = it->second;
0140 return true;
0141 }
0142
0143 bool BEmcRec::SetTowerGeometry(int ix, int iy, const RawTowerGeom& raw_geom0)
0144 {
0145 if (ix < 0 || ix >= fNx || iy < 0 || iy >= fNy)
0146 {
0147 return false;
0148 }
0149
0150 TowerGeom geom;
0151 geom.Xcenter = raw_geom0.get_center_x();
0152 geom.Ycenter = raw_geom0.get_center_y();
0153 geom.Zcenter = raw_geom0.get_center_z();
0154
0155 if (m_UseDetailedGeometry)
0156 {
0157 geom.rotX = raw_geom0.get_rotx();
0158 geom.rotY = raw_geom0.get_roty();
0159 geom.rotZ = raw_geom0.get_rotz();
0160
0161
0162 geom.dX[0] = raw_geom0.get_center_high_phi_x() - raw_geom0.get_center_low_phi_x();
0163 geom.dY[0] = raw_geom0.get_center_high_phi_y() - raw_geom0.get_center_low_phi_y();
0164 geom.dZ[0] = raw_geom0.get_center_high_phi_z() - raw_geom0.get_center_low_phi_z();
0165 geom.dX[1] = raw_geom0.get_center_high_eta_x() - raw_geom0.get_center_low_eta_x();
0166 geom.dY[1] = raw_geom0.get_center_high_eta_y() - raw_geom0.get_center_low_eta_y();
0167 geom.dZ[1] = raw_geom0.get_center_high_eta_z() - raw_geom0.get_center_low_eta_z();
0168 }
0169 else
0170 {
0171
0172 geom.rotX = 0;
0173 geom.rotY = 0;
0174 geom.rotZ = 0;
0175
0176
0177
0178 geom.dX[0] = geom.dX[1] = 0;
0179 geom.dY[0] = geom.dY[1] = 0;
0180 geom.dZ[0] = geom.dZ[1] = 0;
0181 }
0182
0183 int ich = (iy * fNx) + ix;
0184 fTowerGeom[ich] = geom;
0185
0186 if (m_UseDetailedGeometry)
0187 {
0188
0189 RawTowerGeomv5 *geom_detailed = new RawTowerGeomv5(raw_geom0);
0190 fTowerGeomDetailed[ich] = geom_detailed;
0191 }
0192
0193 return true;
0194 }
0195
0196 bool BEmcRec::CompleteTowerGeometry()
0197
0198 {
0199 if (fTowerGeom.empty() || fNx <= 0)
0200 {
0201 std::cout << "Error in BEmcRec::CalculateTowerSize(): Tower geometry not well setup (NX = "
0202 << fNx << ")" << std::endl;
0203 return false;
0204 }
0205
0206 const int nb = 8;
0207 int idx[nb] = {0, 1, 0, -1, -1, 1, 1, -1};
0208 int idy[nb] = {-1, 0, 1, 0, -1, -1, 1, 1};
0209
0210 std::map<int, TowerGeom>::iterator it;
0211
0212 for (it = fTowerGeom.begin(); it != fTowerGeom.end(); ++it)
0213 {
0214 int ich = it->first;
0215 TowerGeom geom0 = it->second;
0216 int ix = ich % fNx;
0217 int iy = ich / fNx;
0218
0219 TowerGeom geomx;
0220 int inx = 0;
0221
0222 while (inx < nb && (idx[inx] == 0 || !GetTowerGeometry(ix + idx[inx], iy + idy[inx], geomx)))
0223 {
0224 inx++;
0225 }
0226 if (inx >= nb)
0227 {
0228 std::cout << "Error in BEmcRec::CompleteTowerGeometry(): Error when locating neighbour for (ix,iy)=("
0229 << ix << "," << iy << ")" << std::endl;
0230 return false;
0231 }
0232
0233 TowerGeom geomy;
0234 int iny = 0;
0235
0236 while (iny < nb && (idy[iny] == 0 || !GetTowerGeometry(ix + idx[iny], iy + idy[iny], geomy)))
0237 {
0238 iny++;
0239 }
0240 if (iny >= nb)
0241 {
0242 std::cout << "Error in BEmcRec::CompleteTowerGeometry(): Error when locating neighbour for (ix,iy)=("
0243 << ix << "," << iy << ")" << std::endl;
0244 return false;
0245 }
0246
0247 geom0.dX[0] = (geomx.Xcenter - geom0.Xcenter) / float(idx[inx]);
0248 geom0.dY[0] = (geomx.Ycenter - geom0.Ycenter) / float(idx[inx]);
0249 geom0.dZ[0] = (geomx.Zcenter - geom0.Zcenter) / float(idx[inx]);
0250 geom0.dX[1] = (geomy.Xcenter - geom0.Xcenter) / float(idy[iny]);
0251 geom0.dY[1] = (geomy.Ycenter - geom0.Ycenter) / float(idy[iny]);
0252 geom0.dZ[1] = (geomy.Zcenter - geom0.Zcenter) / float(idy[iny]);
0253
0254 it->second = geom0;
0255
0256 }
0257
0258 return true;
0259 }
0260
0261 void BEmcRec::Tower2Global(float E, float xC, float yC,
0262 float& xA, float& yA, float& zA)
0263
0264
0265 {
0266
0267
0268 bool flagDoSD = true;
0269 if (xA < -999)
0270 {
0271 flagDoSD = false;
0272 }
0273
0274 xA = 0;
0275 yA = 0;
0276 zA = 0;
0277
0278
0279 int ix = xC + 0.5;
0280 if (ix < 0 || ix >= fNx)
0281 {
0282 std::cout << m_ThisName << " Error in BEmcRec::Tower2Global: wrong input x: " << ix << std::endl;
0283 return;
0284 }
0285
0286
0287 int iy = yC + 0.5;
0288 if (iy < 0 || iy >= fNy)
0289 {
0290 std::cout << "Error in BEmcRec::Tower2Global: wrong input y: " << iy << std::endl;
0291 return;
0292 }
0293
0294
0295 TowerGeom geom0;
0296
0297 if (!GetTowerGeometry(ix, iy, geom0))
0298 {
0299
0300 const int idx[4] = {1, 0, -1, 0};
0301 const int idy[4] = {0, 1, 0, -1};
0302 int ii = 0;
0303 while (ii < 4 && !GetTowerGeometry(ix + idx[ii], iy + idy[ii], geom0))
0304 {
0305 ii++;
0306 }
0307 if (ii >= 4)
0308 {
0309 std::cout << "Error in BEmcRec::Tower2Global: can not identify neighbour for tower ("
0310 << ix << "," << iy << ")" << std::endl;
0311 return;
0312 }
0313 float Xc = geom0.Xcenter - (idx[ii] * geom0.dX[0]) - (idy[ii] * geom0.dX[1]);
0314 float Yc = geom0.Ycenter - (idx[ii] * geom0.dY[0]) - (idy[ii] * geom0.dY[1]);
0315 float Zc = geom0.Zcenter - (idx[ii] * geom0.dZ[0]) - (idy[ii] * geom0.dZ[1]);
0316 geom0.Xcenter = Xc;
0317 geom0.Ycenter = Yc;
0318 geom0.Zcenter = Zc;
0319 }
0320
0321 float xt = geom0.Xcenter + ((xC - ix) * geom0.dX[0]) + ((yC - iy) * geom0.dX[1]);
0322 float yt = geom0.Ycenter + ((xC - ix) * geom0.dY[0]) + ((yC - iy) * geom0.dY[1]);
0323 float zt = geom0.Zcenter + ((xC - ix) * geom0.dZ[0]) + ((yC - iy) * geom0.dZ[1]);
0324
0325 if (flagDoSD)
0326 {
0327 CorrectShowerDepth(ix, iy, E, xt, yt, zt, xA, yA, zA);
0328 }
0329 else
0330 {
0331
0332
0333 float savzt = zt;
0334 CorrectShowerDepth(ix, iy, E, xt, yt, zt, xA, yA, zA);
0335 zA = savzt;
0336 }
0337 }
0338
0339
0340
0341 int BEmcRec::iTowerDist(int ix1, int ix2) const
0342
0343 {
0344 int idist = ix2 - ix1;
0345 if (bCYL)
0346 {
0347 int idistr = fNx - abs(idist);
0348 if (idistr < abs(idist))
0349 {
0350 if (idist < 0)
0351 {
0352 idist = idistr;
0353 }
0354 else
0355 {
0356 idist = -idistr;
0357 }
0358 }
0359 }
0360
0361 return idist;
0362 }
0363
0364 float BEmcRec::fTowerDist(float x1, float x2) const
0365 {
0366 float dist = x2 - x1;
0367 if (bCYL)
0368 {
0369 float distr = fNx - std::fabs(dist);
0370 if (distr < std::abs(dist))
0371 {
0372 if (dist < 0)
0373 {
0374 dist = distr;
0375 }
0376 else
0377 {
0378 dist = -distr;
0379 }
0380 }
0381 }
0382 return dist;
0383 }
0384
0385
0386
0387 int BEmcRec::FindClusters()
0388
0389
0390 {
0391 int nhit;
0392 int nCl;
0393
0394 int* LenCl;
0395 int next;
0396 int ib;
0397 int ie;
0398 int iab;
0399 int iae;
0400 int last;
0401 int LastCl;
0402 int leng;
0403 int ich;
0404 int ia = 0;
0405
0406 EmcModule* vv;
0407 EmcModule *vhit;
0408 EmcModule *vt;
0409 EmcCluster Clt(this);
0410 std::vector<EmcModule>::iterator ph;
0411 std::vector<EmcModule> hl;
0412
0413 (*fClusters).clear();
0414 nhit = (*fModules).size();
0415
0416 if (nhit <= 0)
0417 {
0418 return 0;
0419 }
0420 if (nhit == 1)
0421 {
0422 Clt.ReInitialize((*fModules));
0423 fClusters->push_back(Clt);
0424 return 1;
0425 }
0426
0427 int MaxLen = fgMaxLen;
0428 LenCl = new int[MaxLen];
0429 ZeroVector(LenCl, MaxLen);
0430
0431 vt = new EmcModule[nhit];
0432 vhit = new EmcModule[nhit];
0433
0434 ph = (*fModules).begin();
0435 vv = vhit;
0436 while (ph != (*fModules).end())
0437 {
0438 *vv++ = *ph++;
0439 }
0440
0441 qsort(vhit, nhit, sizeof(EmcModule), HitNCompare);
0442
0443 nCl = 0;
0444 next = 0;
0445 for (ich = 1; ich < nhit + 1; ich++)
0446 {
0447 if (ich < nhit)
0448 {
0449 ia = vhit[ich].ich;
0450 }
0451
0452
0453
0454 if ((ia - vhit[ich - 1].ich > 1)
0455 || (ich >= nhit)
0456 || (ia - ia / fNx * fNx == 0))
0457 {
0458
0459 ib = next;
0460 ie = ich - 1;
0461 next = ich;
0462 if (nCl >= MaxLen)
0463 {
0464
0465
0466
0467 int* LenCltmp = new int[MaxLen];
0468 CopyVector(LenCl, LenCltmp, MaxLen);
0469 delete[] LenCl;
0470
0471 LenCl = new int[MaxLen * 2];
0472 ZeroVector(LenCl, MaxLen * 2);
0473 CopyVector(LenCltmp, LenCl, MaxLen);
0474 delete[] LenCltmp;
0475 MaxLen *= 2;
0476
0477 }
0478 nCl++;
0479 LenCl[nCl - 1] = next - ib;
0480 if (nCl > 1)
0481 {
0482
0483
0484 iab = vhit[ib].ich;
0485 iae = vhit[ie].ich;
0486 last = ib - 1;
0487 LastCl = nCl - 2;
0488 for (int iCl = LastCl; iCl >= 0; iCl--)
0489 {
0490 leng = LenCl[iCl];
0491
0492 if (iab - vhit[last].ich > fNx)
0493 {
0494 goto new_ich;
0495 }
0496 for (int ichc = last; ichc >= last - leng + 1; ichc--)
0497 {
0498
0499
0500
0501
0502 if ((vhit[ichc].ich + fNx <= iae && vhit[ichc].ich + fNx >= iab) || (bCYL && (iae % fNx == fNx - 1) && (iae - vhit[ichc].ich == fNx - 1))
0503 )
0504 {
0505
0506 CopyVector(&vhit[last + 1 - leng], vt, leng);
0507 CopyVector(&vhit[last + 1], &vhit[last + 1 - leng], ib - 1 - last);
0508 CopyVector(vt, &vhit[ib - leng], leng);
0509
0510
0511 for (int i = iCl; i < nCl - 2; i++)
0512 {
0513 LenCl[i] = LenCl[i + 1];
0514 }
0515 ib -= leng;
0516 LenCl[nCl - 2] = LenCl[nCl - 1] + leng;
0517 nCl--;
0518 goto new_icl;
0519 }
0520 }
0521
0522 new_icl:
0523 last = last - leng;
0524 }
0525
0526 }
0527
0528 }
0529
0530 new_ich:
0531 continue;
0532 }
0533
0534 if (nCl > 0)
0535 {
0536 ib = 0;
0537 for (int iCl = 0; iCl < nCl; iCl++)
0538 {
0539 leng = LenCl[iCl];
0540 hl.clear();
0541 for (ich = 0; ich < leng; ich++)
0542 {
0543 hl.push_back(vhit[ib + ich]);
0544 }
0545 Clt.ReInitialize(hl);
0546 ib += LenCl[iCl];
0547 fClusters->push_back(Clt);
0548 }
0549 }
0550 delete[] LenCl;
0551 delete[] vhit;
0552 delete[] vt;
0553
0554 return nCl;
0555 }
0556
0557
0558
0559 void BEmcRec::Momenta(std::vector<EmcModule>* phit, float& pe, float& px,
0560 float& py, float& pxx, float& pyy, float& pyx,
0561 float thresh) const
0562 {
0563
0564
0565 float a;
0566 float x;
0567 float y;
0568 float e;
0569 float xx;
0570 float yy;
0571 float yx;
0572 std::vector<EmcModule>::iterator ph;
0573
0574 pe = 0;
0575 px = 0;
0576 py = 0;
0577 pxx = 0;
0578 pyy = 0;
0579 pyx = 0;
0580 if (phit->empty())
0581 {
0582 return;
0583 }
0584
0585
0586
0587 ph = phit->begin();
0588 float emax = 0;
0589 int ichmax = 0;
0590
0591 while (ph != phit->end())
0592 {
0593 a = ph->amp;
0594 if (a > emax)
0595 {
0596 emax = a;
0597 ichmax = ph->ich;
0598 }
0599 ++ph;
0600 }
0601
0602 if (emax <= 0)
0603 {
0604 return;
0605 }
0606
0607 int iymax = ichmax / fNx;
0608 int ixmax = ichmax - iymax * fNx;
0609
0610
0611
0612 x = 0;
0613 y = 0;
0614 e = 0;
0615 xx = 0;
0616 yy = 0;
0617 yx = 0;
0618 ph = phit->begin();
0619
0620 while (ph != phit->end())
0621 {
0622 a = ph->amp;
0623 if (a > thresh)
0624 {
0625 int iy = ph->ich / fNx;
0626 int ix = ph->ich - (iy * fNx);
0627 int idx = iTowerDist(ixmax, ix);
0628 int idy = iy - iymax;
0629 e += a;
0630 x += idx * a;
0631 y += idy * a;
0632 xx += a * idx * idx;
0633 yy += a * idy * idy;
0634 yx += a * idx * idy;
0635 }
0636 ++ph;
0637 }
0638
0639 pe = e;
0640
0641 if (e > 0)
0642 {
0643 x /= e;
0644 y /= e;
0645 xx = xx / e - x * x;
0646 yy = yy / e - y * y;
0647 yx = yx / e - y * x;
0648
0649 x += ixmax;
0650 y += iymax;
0651
0652 while (x < -0.5)
0653 {
0654 x += float(fNx);
0655 }
0656 while (x >= fNx - 0.5)
0657 {
0658 x -= float(fNx);
0659 }
0660
0661 px = x;
0662 py = y;
0663 pxx = xx;
0664 pyy = yy;
0665 pyx = yx;
0666 }
0667 }
0668
0669
0670
0671 float BEmcRec::PredictEnergy(float en, float xcg, float ycg, int ix, int iy)
0672 {
0673 if (_emcprof != nullptr && bProfileProb)
0674 {
0675 return PredictEnergyProb(en, xcg, ycg, ix, iy);
0676 }
0677
0678 float dx = std::fabs(fTowerDist(float(ix), xcg));
0679 float dy = ycg - iy;
0680 return PredictEnergyParam(en, dx, dy);
0681 }
0682
0683 float BEmcRec::PredictEnergyParam(float , float xc, float yc)
0684 {
0685
0686
0687
0688
0689 float dx;
0690 float dy;
0691 float r1;
0692 float r2;
0693 float r3;
0694 float fPpar1;
0695 float fPpar2;
0696 float fPpar3;
0697 float fPpar4;
0698
0699 float fPshiftx = 0;
0700 float fPshifty = 0;
0701
0702
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712
0713 fPpar1 = 0.549;
0714 fPpar2 = 0.304;
0715 fPpar3 = 0.389;
0716 fPpar4 = 0.326;
0717
0718
0719
0720
0721
0722
0723
0724
0725
0726
0727
0728
0729
0730
0731
0732 dx = std::fabs(xc - fPshiftx);
0733 dy = std::fabs(yc - fPshifty);
0734 r2 = dx * dx + dy * dy;
0735 r1 = std::sqrt(r2);
0736 r3 = r2 * r1;
0737 double e = (fPpar1 * std::exp(-r3 / fPpar2)) + (fPpar3 * std::exp(-r1 / fPpar4));
0738
0739 return e;
0740 }
0741
0742 float BEmcRec::PredictEnergyProb(float en, float xcg, float ycg, int ix, int iy)
0743
0744
0745 {
0746 if (_emcprof == nullptr)
0747 {
0748 return -1;
0749 }
0750
0751 while (xcg < -0.5)
0752 {
0753 xcg += float(fNx);
0754 }
0755 while (xcg >= fNx - 0.5)
0756 {
0757 xcg -= float(fNx);
0758 }
0759
0760
0761 int ixcg = int(xcg + 0.5);
0762
0763 int iycg = int(ycg + 0.5);
0764 float ddx = std::fabs(xcg - ixcg);
0765 float ddy = std::fabs(ycg - iycg);
0766
0767 float xg=0;
0768 float yg=0;
0769 float zg=0;
0770 Tower2Global(en, xcg, ycg, xg, yg, zg);
0771
0772 float theta;
0773 float phi;
0774 GetImpactThetaPhi(xg, yg, zg, theta, phi);
0775
0776 int isx = 1;
0777 if (xcg - ixcg < 0)
0778 {
0779 isx = -1;
0780 }
0781 int isy = 1;
0782 if (ycg - iycg < 0)
0783 {
0784 isy = -1;
0785 }
0786
0787 int idx = iTowerDist(ixcg, ix) * isx;
0788 int idy = (iy - iycg) * isy;
0789
0790 int id = -1;
0791 if (idx == 0 && idy == 0)
0792 {
0793 id = 0;
0794 }
0795 else if (idx == 1 && idy == 0)
0796 {
0797 id = 1;
0798 }
0799 else if (idx == 1 && idy == 1)
0800 {
0801 id = 2;
0802 }
0803 else if (idx == 0 && idy == 1)
0804 {
0805 id = 3;
0806 }
0807
0808 if (id < 0)
0809 {
0810 float dx = std::fabs(fTowerDist(xcg, float(ix)));
0811 float dy = std::fabs(iy - ycg);
0812 float rr = std::sqrt((dx * dx) + (dy * dy));
0813
0814 return _emcprof->PredictEnergyR(en, theta, phi, rr);
0815 }
0816
0817 float ep[4];
0818 float err[4];
0819 for (int ip = 0; ip < 4; ip++)
0820 {
0821 _emcprof->PredictEnergy(ip, en, theta, phi, ddx, ddy, ep[ip], err[ip]);
0822 }
0823
0824 float eout;
0825
0826 if (id == 0)
0827 {
0828 eout = (ep[1] + ep[2]) / 2. + ep[3];
0829 }
0830 else if (id == 1)
0831 {
0832 eout = (ep[0] - ep[2]) / 2. - ep[3];
0833 }
0834 else if (id == 3)
0835 {
0836 eout = (ep[0] - ep[1]) / 2. - ep[3];
0837 }
0838 else
0839 {
0840 eout = ep[3];
0841 }
0842
0843
0844 if (eout < 0)
0845 {
0846 eout = 1e-6;
0847 }
0848
0849 return eout;
0850 }
0851
0852
0853
0854 float BEmcRec::GetTowerEnergy(int iy, int iz, std::vector<EmcModule>* plist) const
0855 {
0856 int nn = plist->size();
0857 if (nn <= 0)
0858 {
0859 return 0;
0860 }
0861
0862 for (int i = 0; i < nn; i++)
0863 {
0864 int ich = (*plist)[i].ich;
0865 int iyt = ich / fNx;
0866 int izt = ich % fNx;
0867 if (iy == iyt && iz == izt)
0868 {
0869 return (*plist)[i].amp;
0870 }
0871 }
0872 return 0;
0873 }
0874
0875
0876 float BEmcRec::GetProb(std::vector<EmcModule> HitList, float en, float xg, float yg, float zg, float& chi2, int& ndf)
0877
0878 {
0879
0880 float enoise = GetProbNoiseParam();
0881
0882 float thresh = GetTowerThreshold();
0883
0884 chi2 = 0;
0885 ndf = 0;
0886 if (_emcprof == nullptr)
0887 {
0888 return -1;
0889 }
0890
0891 if (!(_emcprof->IsLoaded()))
0892 {
0893 return -1;
0894 }
0895
0896 int nn = HitList.size();
0897 if (nn <= 0)
0898 {
0899 return -1;
0900 }
0901
0902 float theta;
0903 float phi;
0904 GetImpactThetaPhi(xg, yg, zg, theta, phi);
0905
0906
0907
0908 float etot;
0909 float zcg;
0910 float ycg;
0911 float zz;
0912 float yy;
0913 float yz;
0914 Momenta(&HitList, etot, zcg, ycg, zz, yy, yz, thresh);
0915
0916
0917 int iz0cg = int(zcg + 0.5);
0918
0919 int iy0cg = int(ycg + 0.5);
0920 float ddz = std::fabs(zcg - iz0cg);
0921 float ddy = std::fabs(ycg - iy0cg);
0922
0923 int isz = 1;
0924 if (zcg - iz0cg < 0)
0925 {
0926 isz = -1;
0927 }
0928 int isy = 1;
0929 if (ycg - iy0cg < 0)
0930 {
0931 isy = -1;
0932 }
0933
0934
0935
0936
0937 float e1;
0938 float e2;
0939 float e3;
0940 float e4;
0941 e1 = GetTowerEnergy(iy0cg, iz0cg, &HitList);
0942 e2 = GetTowerEnergy(iy0cg, iz0cg + isz, &HitList);
0943 e3 = GetTowerEnergy(iy0cg + isy, iz0cg + isz, &HitList);
0944 e4 = GetTowerEnergy(iy0cg + isy, iz0cg, &HitList);
0945
0946 if (e1 < thresh)
0947 {
0948 e1 = 0;
0949 }
0950 if (e2 < thresh)
0951 {
0952 e2 = 0;
0953 }
0954 if (e3 < thresh)
0955 {
0956 e3 = 0;
0957 }
0958 if (e4 < thresh)
0959 {
0960 e4 = 0;
0961 }
0962
0963 float e1t = (e1 + e2 + e3 + e4) / etot;
0964 float e2t = (e1 + e2 - e3 - e4) / etot;
0965 float e3t = (e1 - e2 - e3 + e4) / etot;
0966 float e4t = (e3) / etot;
0967
0968
0969
0970 const int NP = 4;
0971 float ep[NP];
0972 float err[NP];
0973 for (int ip = 0; ip < NP; ip++)
0974 {
0975 _emcprof->PredictEnergy(ip, en, theta, phi, ddz, ddy, ep[ip], err[ip]);
0976 if (ep[ip] < 0)
0977 {
0978 return -1;
0979 }
0980 if (ip < 3)
0981 {
0982 err[ip] = std::sqrt((err[ip] * err[ip]) + (4 * enoise * enoise / etot / etot));
0983 }
0984 else
0985 {
0986 err[ip] = std::sqrt((err[ip] * err[ip]) + (1 * enoise * enoise / etot / etot));
0987 }
0988 }
0989
0990 chi2 = 0.;
0991 chi2 += (ep[0] - e1t) * (ep[0] - e1t) / err[0] / err[0];
0992 chi2 += (ep[1] - e2t) * (ep[1] - e2t) / err[1] / err[1];
0993 chi2 += (ep[2] - e3t) * (ep[2] - e3t) / err[2] / err[2];
0994 chi2 += (ep[3] - e4t) * (ep[3] - e4t) / err[3] / err[3];
0995 ndf = 4;
0996
0997 chi2 /= 1.5;
0998
0999 float prob = TMath::Prob(chi2, ndf);
1000
1001 return prob;
1002 }
1003
1004
1005
1006
1007 int BEmcRec::HitNCompare(const void* h1, const void* h2)
1008 {
1009 return (static_cast<const EmcModule*>(h1)->ich - static_cast<const EmcModule*>(h2)->ich);
1010 }
1011
1012
1013
1014 int BEmcRec::HitACompare(const void* h1, const void* h2)
1015 {
1016 float amp1 = static_cast<const EmcModule*>(h1)->amp;
1017 float amp2 = static_cast<const EmcModule*>(h2)->amp;
1018 return (amp1 < amp2) ? 1 : (amp1 > amp2) ? -1 : 0;
1019 }
1020
1021
1022
1023 void BEmcRec::ZeroVector(int* v, int N)
1024 {
1025 int* p = v;
1026 for (int i = 0; i < N; i++)
1027 {
1028 *p++ = 0;
1029 }
1030 }
1031
1032
1033
1034 void BEmcRec::ZeroVector(float* v, int N)
1035 {
1036 float* p = v;
1037 for (int i = 0; i < N; i++)
1038 {
1039 *p++ = 0;
1040 }
1041 }
1042
1043
1044
1045 void BEmcRec::ZeroVector(EmcModule* v, int N)
1046 {
1047
1048 for (int i = 0; i < N; i++)
1049 {
1050 v[i].ich = 0;
1051 v[i].amp = 0;
1052 v[i].tof = 0;
1053 }
1054 }
1055
1056
1057
1058 void BEmcRec::CopyVector(const int* from, int* to, int N)
1059 {
1060 if (N <= 0)
1061 {
1062 return;
1063 }
1064 for (int i = 0; i < N; i++)
1065 {
1066 to[i] = from[i];
1067 }
1068 }
1069
1070
1071
1072 void BEmcRec::CopyVector(const EmcModule* from, EmcModule* to, int N)
1073 {
1074 if (N <= 0)
1075 {
1076 return;
1077 }
1078 for (int i = 0; i < N; i++)
1079 {
1080 to[i] = from[i];
1081 }
1082 }
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094