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