File indexing completed on 2025-12-17 09:19:58
0001 #include "PhotonClusterBuilder.h"
0002
0003 #include <calobase/PhotonClusterv1.h>
0004 #include <calobase/RawCluster.h>
0005 #include <calobase/RawClusterContainer.h>
0006 #include <calobase/RawClusterUtility.h>
0007 #include <calobase/RawTowerGeomContainer.h>
0008 #include <calobase/TowerInfoContainer.h>
0009 #include <calobase/TowerInfoDefs.h>
0010
0011
0012 #include <calobase/RawTowerGeom.h>
0013 #include <calobase/TowerInfo.h>
0014
0015
0016 #include <globalvertex/GlobalVertex.h>
0017 #include <globalvertex/GlobalVertexMap.h>
0018 #include <globalvertex/MbdVertex.h>
0019 #include <globalvertex/MbdVertexMap.h>
0020
0021 #include <phool/PHCompositeNode.h>
0022 #include <phool/PHIODataNode.h>
0023 #include <phool/PHNodeIterator.h>
0024 #include <phool/PHObject.h>
0025 #include <phool/getClass.h>
0026
0027 #include <fun4all/Fun4AllReturnCodes.h>
0028
0029 #include <TMVA/RBDT.hxx>
0030
0031 #include <algorithm>
0032 #include <cmath>
0033 #include <iostream>
0034 #include <set>
0035 #include <stdexcept>
0036
0037 namespace
0038 {
0039
0040 void shift_tower_index(int& ieta, int& iphi, int etadiv, int phidiv)
0041 {
0042 while (iphi < 0)
0043 {
0044 iphi += phidiv;
0045 }
0046 while (iphi >= phidiv)
0047 {
0048 iphi -= phidiv;
0049 }
0050 if (ieta < 0 || ieta >= etadiv)
0051 {
0052 ieta = -1;
0053 }
0054 }
0055 }
0056
0057 PhotonClusterBuilder::PhotonClusterBuilder(const std::string& name)
0058 : SubsysReco(name)
0059 {
0060 }
0061
0062 int PhotonClusterBuilder::InitRun(PHCompositeNode* topNode)
0063 {
0064
0065 if (m_do_bdt)
0066 {
0067 m_bdt = std::make_unique<TMVA::Experimental::RBDT>("myBDT", m_bdt_model_file);
0068 }
0069
0070
0071 m_rawclusters = findNode::getClass<RawClusterContainer>(topNode, m_input_cluster_node);
0072 if (!m_rawclusters)
0073 {
0074 std::cerr << Name() << ": could not find RawClusterContainer node '" << m_input_cluster_node << "'" << std::endl;
0075 return Fun4AllReturnCodes::ABORTRUN;
0076 }
0077
0078 m_emc_tower_container = findNode::getClass<TowerInfoContainer>(topNode, "TOWERINFO_CALIB_CEMC");
0079 if (!m_emc_tower_container)
0080 {
0081 std::cerr << Name() << ": could not find TowerInfoContainer node 'TOWERINFO_CALIB_CEMC'" << std::endl;
0082 return Fun4AllReturnCodes::ABORTRUN;
0083 }
0084
0085 m_geomEM = findNode::getClass<RawTowerGeomContainer>(topNode, "TOWERGEOM_CEMC");
0086 if (!m_geomEM)
0087 {
0088 std::cerr << Name() << ": could not find RawTowerGeomContainer node 'TOWERGEOM_CEMC'" << std::endl;
0089 return Fun4AllReturnCodes::ABORTRUN;
0090 }
0091
0092 m_ihcal_tower_container = findNode::getClass<TowerInfoContainer>(topNode, "TOWERINFO_CALIB_HCALIN");
0093 if (!m_ihcal_tower_container)
0094 {
0095 std::cerr << Name() << ": could not find TowerInfoContainer node 'TOWERINFO_CALIB_HCALIN'" << std::endl;
0096 return Fun4AllReturnCodes::ABORTRUN;
0097 }
0098
0099 m_geomIH = findNode::getClass<RawTowerGeomContainer>(topNode, "TOWERGEOM_HCALIN");
0100 if (!m_geomIH)
0101 {
0102 std::cerr << Name() << ": could not find RawTowerGeomContainer node 'TOWERGEOM_HCALIN'" << std::endl;
0103 return Fun4AllReturnCodes::ABORTRUN;
0104 }
0105
0106 m_ohcal_tower_container = findNode::getClass<TowerInfoContainer>(topNode, "TOWERINFO_CALIB_HCALOUT");
0107 if (!m_ohcal_tower_container)
0108 {
0109 std::cerr << Name() << ": could not find TowerInfoContainer node 'TOWERINFO_CALIB_HCALOUT'" << std::endl;
0110 return Fun4AllReturnCodes::ABORTRUN;
0111 }
0112
0113 m_geomOH = findNode::getClass<RawTowerGeomContainer>(topNode, "TOWERGEOM_HCALOUT");
0114 if (!m_geomOH)
0115 {
0116 std::cerr << Name() << ": could not find RawTowerGeomContainer node 'TOWERGEOM_HCALOUT'" << std::endl;
0117 return Fun4AllReturnCodes::ABORTRUN;
0118 }
0119
0120 CreateNodes(topNode);
0121 return Fun4AllReturnCodes::EVENT_OK;
0122 }
0123
0124 void PhotonClusterBuilder::CreateNodes(PHCompositeNode* topNode)
0125 {
0126 PHNodeIterator iter(topNode);
0127 PHCompositeNode* dstNode = dynamic_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
0128 if (!dstNode)
0129 {
0130 throw std::runtime_error("PhotonClusterBuilder: DST node not found");
0131 }
0132 m_photon_container = findNode::getClass<RawClusterContainer>(dstNode, m_output_photon_node);
0133 if (!m_photon_container)
0134 {
0135 m_photon_container = new RawClusterContainer();
0136 auto* photonNode = new PHIODataNode<PHObject>(m_photon_container, m_output_photon_node, "PHObject");
0137 dstNode->addNode(photonNode);
0138 }
0139 }
0140
0141 int PhotonClusterBuilder::process_event(PHCompositeNode* topNode)
0142 {
0143 if (!m_rawclusters)
0144 {
0145 m_rawclusters = findNode::getClass<RawClusterContainer>(topNode, m_input_cluster_node);
0146 if (!m_rawclusters)
0147 {
0148 std::cerr << Name() << ": missing RawClusterContainer '" << m_input_cluster_node << "'" << std::endl;
0149 return Fun4AllReturnCodes::ABORTEVENT;
0150 }
0151 }
0152
0153
0154 m_vertex = std::numeric_limits<float>::quiet_NaN();
0155
0156
0157 MbdVertexMap* vertexmap = findNode::getClass<MbdVertexMap>(topNode, "MbdVertexMap");
0158
0159 if (!vertexmap)
0160 {
0161 std::cout << "GlobalVertexMap node is missing" << std::endl;
0162 return Fun4AllReturnCodes::EVENT_OK;
0163 }
0164 if (vertexmap && !vertexmap->empty())
0165 {
0166 MbdVertex* vtx = vertexmap->begin()->second;
0167 if (vtx)
0168 {
0169 m_vertex = vtx->get_z();
0170
0171 if (m_vertex != m_vertex)
0172 {
0173 return Fun4AllReturnCodes::EVENT_OK;
0174 }
0175 }
0176 else
0177 {
0178 return Fun4AllReturnCodes::EVENT_OK;
0179 }
0180 }
0181 else
0182 {
0183 return Fun4AllReturnCodes::EVENT_OK;
0184 }
0185
0186
0187 const auto& rcmap = m_rawclusters->getClustersMap();
0188 for (const auto& kv : rcmap)
0189 {
0190 RawCluster* rc = kv.second;
0191 if (!rc)
0192 {
0193 continue;
0194 }
0195
0196 CLHEP::Hep3Vector vertex_vec(0, 0, m_vertex);
0197
0198
0199
0200 float eta = RawClusterUtility::GetPseudorapidity(*rc, vertex_vec);
0201 float phi = RawClusterUtility::GetAzimuthAngle(*rc, vertex_vec);
0202 float E = rc->get_energy();
0203 float ET = E / std::cosh(eta);
0204 if (ET < m_min_cluster_et)
0205 {
0206 continue;
0207 }
0208
0209 PhotonClusterv1* photon = new PhotonClusterv1(*rc);
0210
0211 calculate_shower_shapes(rc, photon, eta, phi);
0212
0213
0214 if (m_do_bdt)
0215 {
0216 calculate_bdt_score(photon);
0217 }
0218
0219 m_photon_container->AddCluster(photon);
0220 }
0221 return Fun4AllReturnCodes::EVENT_OK;
0222 }
0223
0224 void PhotonClusterBuilder::calculate_bdt_score(PhotonClusterv1* photon)
0225 {
0226 if (!m_bdt)
0227 {
0228 return;
0229 }
0230
0231 std::vector<float> x;
0232 for (const auto& feature : m_bdt_feature_list)
0233 {
0234 if (feature == "e11_over_e33")
0235 {
0236 float e11 = photon->get_shower_shape_parameter("e11");
0237 float e33 = photon->get_shower_shape_parameter("e33");
0238 x.push_back((e33 > 0) ? e11 / e33 : 0);
0239 }
0240 else if (feature == "e32_over_e35")
0241 {
0242 float e32 = photon->get_shower_shape_parameter("e32");
0243 float e35 = photon->get_shower_shape_parameter("e35");
0244 x.push_back((e35 > 0) ? e32 / e35 : 0);
0245 }
0246 else if (feature == "vertex_z")
0247 {
0248 x.push_back(m_vertex);
0249 }
0250 else if (feature == "ET")
0251 {
0252 float E = photon->get_energy();
0253 float ET = E / std::cosh(photon->get_shower_shape_parameter("cluster_eta"));
0254 x.push_back(ET);
0255 }
0256 else
0257 {
0258 x.push_back(photon->get_shower_shape_parameter(feature));
0259 }
0260 }
0261
0262 float bdt_score = -1;
0263
0264 bdt_score = m_bdt->Compute(x)[0];
0265
0266 photon->set_shower_shape_parameter("bdt_score", bdt_score);
0267 }
0268
0269 void PhotonClusterBuilder::calculate_shower_shapes(RawCluster* rc, PhotonClusterv1* photon, float cluster_eta, float cluster_phi)
0270 {
0271 std::vector<float> showershape = rc->get_shower_shapes(m_shape_min_tower_E);
0272 if (showershape.empty())
0273 {
0274 return;
0275 }
0276
0277 std::pair<int, int> leadtowerindex = rc->get_lead_tower();
0278 int lead_ieta = leadtowerindex.first;
0279 int lead_iphi = leadtowerindex.second;
0280
0281 float avg_eta = showershape[4] + 0.5F;
0282 float avg_phi = showershape[5] + 0.5F;
0283
0284
0285 int maxieta = std::floor(avg_eta);
0286 int maxiphi = std::floor(avg_phi);
0287
0288
0289
0290
0291
0292
0293
0294 int detamax = 0;
0295 int dphimax = 0;
0296 int nsaturated = 0;
0297 float clusteravgtime = 0;
0298 float cluster_total_e = 0;
0299 const RawCluster::TowerMap& tower_map = rc->get_towermap();
0300 std::set<unsigned int> towers_in_cluster;
0301 for (auto tower_iter : tower_map)
0302 {
0303 RawTowerDefs::keytype tower_key = tower_iter.first;
0304 int ieta = RawTowerDefs::decode_index1(tower_key);
0305 int iphi = RawTowerDefs::decode_index2(tower_key);
0306
0307
0308 unsigned int towerinfokey = TowerInfoDefs::encode_emcal(ieta, iphi);
0309 towers_in_cluster.insert(towerinfokey);
0310 TowerInfo* towerinfo = m_emc_tower_container->get_tower_at_key(towerinfokey);
0311 if (towerinfo)
0312 {
0313 clusteravgtime += towerinfo->get_time() * towerinfo->get_energy();
0314 cluster_total_e += towerinfo->get_energy();
0315 if (towerinfo->get_isSaturated())
0316 {
0317 nsaturated++;
0318 }
0319 }
0320
0321 int totalphibins = 256;
0322 auto dphiwrap = [totalphibins](int towerphi, int maxiphi_arg)
0323 {
0324 int idphi = towerphi - maxiphi_arg;
0325 if (idphi > totalphibins / 2)
0326 {
0327 idphi -= totalphibins;
0328 }
0329 if (idphi < -totalphibins / 2)
0330 {
0331 idphi += totalphibins;
0332 }
0333 return idphi;
0334 };
0335
0336 int deta = ieta - lead_ieta;
0337 int dphi_val = dphiwrap(iphi, lead_iphi);
0338
0339 detamax = std::max(std::abs(deta), detamax);
0340 dphimax = std::max(std::abs(dphi_val), dphimax);
0341 }
0342
0343 if (cluster_total_e > 0)
0344 {
0345 clusteravgtime /= cluster_total_e;
0346 }
0347 else
0348 {
0349 std::cout << "cluster_total_e is 0(this should not happen!!!), setting clusteravgtime to NaN" << std::endl;
0350 clusteravgtime = std::numeric_limits<float>::quiet_NaN();
0351 }
0352
0353 float E77[7][7] = {{0.0F}};
0354 int E77_ownership[7][7] = {{0}};
0355
0356 for (int ieta = maxieta - 3; ieta < maxieta + 4; ieta++)
0357 {
0358 for (int iphi = maxiphi - 3; iphi < maxiphi + 4; iphi++)
0359 {
0360
0361
0362 if (ieta < 0 || ieta > 95)
0363 {
0364 E77[ieta - maxieta + 3][iphi - maxiphi + 3] = 0.0F;
0365 E77_ownership[ieta - maxieta + 3][iphi - maxiphi + 3] = 0;
0366 continue;
0367 }
0368
0369 int temp_ieta = ieta;
0370 int temp_iphi = iphi;
0371 shift_tower_index(temp_ieta, temp_iphi, 96, 256);
0372 if (temp_ieta < 0)
0373 {
0374 continue;
0375 }
0376
0377 unsigned int towerinfokey = TowerInfoDefs::encode_emcal(temp_ieta, temp_iphi);
0378
0379 if (towers_in_cluster.contains(towerinfokey))
0380 {
0381 E77_ownership[ieta - maxieta + 3][iphi - maxiphi + 3] = 1;
0382 }
0383
0384 TowerInfo* towerinfo = m_emc_tower_container->get_tower_at_key(towerinfokey);
0385 if (towerinfo && towerinfo->get_isGood())
0386 {
0387 float energy = towerinfo->get_energy();
0388 if (energy > m_shape_min_tower_E)
0389 {
0390 E77[ieta - maxieta + 3][iphi - maxiphi + 3] = energy;
0391 }
0392 }
0393 }
0394 }
0395
0396 float e11 = E77[3][3];
0397 float e33 = 0;
0398 float e55 = 0;
0399 float e77 = 0;
0400 float e13 = 0;
0401 float e15 = 0;
0402 float e17 = 0;
0403 float e31 = 0;
0404 float e51 = 0;
0405 float e71 = 0;
0406 float e35 = 0;
0407 float e37 = 0;
0408 float e53 = 0;
0409 float e73 = 0;
0410 float e57 = 0;
0411 float e75 = 0;
0412 float weta = 0;
0413 float wphi = 0;
0414 float weta_cog = 0;
0415 float wphi_cog = 0;
0416 float weta_cogx = 0;
0417 float wphi_cogx = 0;
0418 float Eetaphi = 0;
0419 float shift_eta = avg_eta - std::floor(avg_eta) - 0.5;
0420 float shift_phi = avg_phi - std::floor(avg_phi) - 0.5;
0421 float cog_eta = 3 + shift_eta;
0422 float cog_phi = 3 + shift_phi;
0423
0424 float w32 = 0;
0425 float e32 = 0;
0426 float w52 = 0;
0427 float e52 = 0;
0428 float w72 = 0;
0429 float e72 = 0;
0430 float detacog = std::abs(maxieta - avg_eta);
0431 float dphicog = std::abs(maxiphi - avg_phi);
0432 float drad = std::sqrt(dphicog*dphicog + detacog*detacog);
0433
0434
0435 int signphi = (avg_phi - std::floor(avg_phi)) > 0.5 ? 1 : -1;
0436
0437 for (int i = 0; i < 7; i++)
0438 {
0439 for (int j = 0; j < 7; j++)
0440 {
0441 int di = std::abs(i - 3);
0442 int dj = std::abs(j - 3);
0443 float di_float = i - cog_eta;
0444 float dj_float = j - cog_phi;
0445
0446 if (E77_ownership[i][j] == 1)
0447 {
0448 weta += E77[i][j] * di * di;
0449 wphi += E77[i][j] * dj * dj;
0450 weta_cog += E77[i][j] * di_float * di_float;
0451 wphi_cog += E77[i][j] * dj_float * dj_float;
0452 Eetaphi += E77[i][j];
0453 if (i != 3 || j != 3)
0454 {
0455 weta_cogx += E77[i][j] * di_float * di_float;
0456 wphi_cogx += E77[i][j] * dj_float * dj_float;
0457 }
0458 }
0459
0460 e77 += E77[i][j];
0461 if (di <= 1 && (dj == 0 || j == (3 + signphi)))
0462 {
0463 w32 += E77[i][j] * (i - 3) * (i - 3);
0464 e32 += E77[i][j];
0465 }
0466 if (di <= 2 && (dj == 0 || j == (3 + signphi)))
0467 {
0468 w52 += E77[i][j] * (i - 3) * (i - 3);
0469 e52 += E77[i][j];
0470 }
0471 if (di <= 3 && (dj == 0 || j == (3 + signphi)))
0472 {
0473 w72 += E77[i][j] * (i - 3) * (i - 3);
0474 e72 += E77[i][j];
0475 }
0476
0477 if (di <= 0 && dj <= 1)
0478 {
0479 e13 += E77[i][j];
0480 }
0481 if (di <= 0 && dj <= 2)
0482 {
0483 e15 += E77[i][j];
0484 }
0485 if (di <= 0 && dj <= 3)
0486 {
0487 e17 += E77[i][j];
0488 }
0489 if (di <= 1 && dj <= 0)
0490 {
0491 e31 += E77[i][j];
0492 }
0493 if (di <= 2 && dj <= 0)
0494 {
0495 e51 += E77[i][j];
0496 }
0497 if (di <= 3 && dj <= 0)
0498 {
0499 e71 += E77[i][j];
0500 }
0501 if (di <= 1 && dj <= 1)
0502 {
0503 e33 += E77[i][j];
0504 }
0505 if (di <= 1 && dj <= 2)
0506 {
0507 e35 += E77[i][j];
0508 }
0509 if (di <= 1 && dj <= 3)
0510 {
0511 e37 += E77[i][j];
0512 }
0513 if (di <= 2 && dj <= 1)
0514 {
0515 e53 += E77[i][j];
0516 }
0517 if (di <= 3 && dj <= 1)
0518 {
0519 e73 += E77[i][j];
0520 }
0521 if (di <= 2 && dj <= 2)
0522 {
0523 e55 += E77[i][j];
0524 }
0525 if (di <= 2 && dj <= 3)
0526 {
0527 e57 += E77[i][j];
0528 }
0529 if (di <= 3 && dj <= 2)
0530 {
0531 e75 += E77[i][j];
0532 }
0533 }
0534 }
0535
0536 if (Eetaphi > 0)
0537 {
0538 weta /= Eetaphi;
0539 wphi /= Eetaphi;
0540 weta_cog /= Eetaphi;
0541 wphi_cog /= Eetaphi;
0542 weta_cogx /= Eetaphi;
0543 wphi_cogx /= Eetaphi;
0544 }
0545 if (e32 > 0)
0546 {
0547 w32 /= e32;
0548 }
0549 if (e52 > 0)
0550 {
0551 w52 /= e52;
0552 }
0553 if (e72 > 0)
0554 {
0555 w72 /= e72;
0556 }
0557
0558 photon->set_shower_shape_parameter("et1", showershape[0]);
0559 photon->set_shower_shape_parameter("et2", showershape[1]);
0560 photon->set_shower_shape_parameter("et3", showershape[2]);
0561 photon->set_shower_shape_parameter("et4", showershape[3]);
0562 photon->set_shower_shape_parameter("e11", e11);
0563 photon->set_shower_shape_parameter("e33", e33);
0564 photon->set_shower_shape_parameter("e55", e55);
0565 photon->set_shower_shape_parameter("e77", e77);
0566 photon->set_shower_shape_parameter("e13", e13);
0567 photon->set_shower_shape_parameter("e15", e15);
0568 photon->set_shower_shape_parameter("e17", e17);
0569 photon->set_shower_shape_parameter("e31", e31);
0570 photon->set_shower_shape_parameter("e51", e51);
0571 photon->set_shower_shape_parameter("e71", e71);
0572 photon->set_shower_shape_parameter("e35", e35);
0573 photon->set_shower_shape_parameter("e37", e37);
0574 photon->set_shower_shape_parameter("e53", e53);
0575 photon->set_shower_shape_parameter("e73", e73);
0576 photon->set_shower_shape_parameter("e57", e57);
0577 photon->set_shower_shape_parameter("e75", e75);
0578 photon->set_shower_shape_parameter("weta", weta);
0579 photon->set_shower_shape_parameter("wphi", wphi);
0580 photon->set_shower_shape_parameter("weta_cog", weta_cog);
0581 photon->set_shower_shape_parameter("wphi_cog", wphi_cog);
0582 photon->set_shower_shape_parameter("weta_cogx", weta_cogx);
0583 photon->set_shower_shape_parameter("wphi_cogx", wphi_cogx);
0584 photon->set_shower_shape_parameter("detamax", detamax);
0585 photon->set_shower_shape_parameter("dphimax", dphimax);
0586 photon->set_shower_shape_parameter("nsaturated", nsaturated);
0587 photon->set_shower_shape_parameter("e32", e32);
0588 photon->set_shower_shape_parameter("e52", e52);
0589 photon->set_shower_shape_parameter("e72", e72);
0590 photon->set_shower_shape_parameter("w32", w32);
0591 photon->set_shower_shape_parameter("w52", w52);
0592 photon->set_shower_shape_parameter("w72", w72);
0593 photon->set_shower_shape_parameter("cluster_eta", cluster_eta);
0594 photon->set_shower_shape_parameter("cluster_phi", cluster_phi);
0595 photon->set_shower_shape_parameter("mean_time", clusteravgtime);
0596 photon->set_shower_shape_parameter("detacog", detacog);
0597 photon->set_shower_shape_parameter("dphicog", dphicog);
0598 photon->set_shower_shape_parameter("drad", drad);
0599
0600
0601 std::vector<int> ihcal_tower = find_closest_hcal_tower(cluster_eta, cluster_phi, m_geomIH, m_ihcal_tower_container, 0.0, true);
0602 std::vector<int> ohcal_tower = find_closest_hcal_tower(cluster_eta, cluster_phi, m_geomOH, m_ohcal_tower_container, 0.0, false);
0603
0604 float ihcal_et = 0;
0605 float ohcal_et = 0;
0606 float ihcal_et22 = 0;
0607 float ohcal_et22 = 0;
0608 float ihcal_et33 = 0;
0609 float ohcal_et33 = 0;
0610
0611 int ihcal_ieta = ihcal_tower[0];
0612 int ihcal_iphi = ihcal_tower[1];
0613 float ihcalEt33[3][3] = {{0.0F}};
0614
0615 int ohcal_ieta = ohcal_tower[0];
0616 int ohcal_iphi = ohcal_tower[1];
0617 float ohcalEt33[3][3] = {{0.0F}};
0618
0619 for (int ieta_h = ihcal_ieta - 1; ieta_h <= ihcal_ieta + 1; ieta_h++)
0620 {
0621 for (int iphi_h = ihcal_iphi - 1; iphi_h <= ihcal_iphi + 1; iphi_h++)
0622 {
0623 int temp_ieta = ieta_h;
0624 int temp_iphi = iphi_h;
0625 shift_tower_index(temp_ieta, temp_iphi, 24, 64);
0626 if (temp_ieta < 0)
0627 {
0628 continue;
0629 }
0630
0631 unsigned int towerinfokey = TowerInfoDefs::encode_hcal(temp_ieta, temp_iphi);
0632 TowerInfo* towerinfo = m_ihcal_tower_container->get_tower_at_key(towerinfokey);
0633 if (towerinfo && towerinfo->get_isGood())
0634 {
0635 const RawTowerDefs::keytype key = RawTowerDefs::encode_towerid(RawTowerDefs::CalorimeterId::HCALIN, temp_ieta, temp_iphi);
0636 RawTowerGeom* tower_geom = m_geomIH->get_tower_geometry(key);
0637 if (tower_geom)
0638 {
0639 float energy = towerinfo->get_energy();
0640 float eta = getTowerEta(tower_geom, 0, 0, 0);
0641 float sintheta = 1.0 / std::cosh(eta);
0642 float Et = energy * sintheta;
0643 ihcalEt33[ieta_h - ihcal_ieta + 1][iphi_h - ihcal_iphi + 1] = Et;
0644 }
0645 }
0646 }
0647 }
0648
0649 for (int ieta_h = ohcal_ieta - 1; ieta_h <= ohcal_ieta + 1; ieta_h++)
0650 {
0651 for (int iphi_h = ohcal_iphi - 1; iphi_h <= ohcal_iphi + 1; iphi_h++)
0652 {
0653 int temp_ieta = ieta_h;
0654 int temp_iphi = iphi_h;
0655 shift_tower_index(temp_ieta, temp_iphi, 24, 64);
0656 if (temp_ieta < 0)
0657 {
0658 continue;
0659 }
0660
0661 unsigned int towerinfokey = TowerInfoDefs::encode_hcal(temp_ieta, temp_iphi);
0662 TowerInfo* towerinfo = m_ohcal_tower_container->get_tower_at_key(towerinfokey);
0663 if (towerinfo && towerinfo->get_isGood())
0664 {
0665 const RawTowerDefs::keytype key = RawTowerDefs::encode_towerid(RawTowerDefs::CalorimeterId::HCALOUT, temp_ieta, temp_iphi);
0666 RawTowerGeom* tower_geom = m_geomOH->get_tower_geometry(key);
0667 if (tower_geom)
0668 {
0669 float energy = towerinfo->get_energy();
0670 float eta = getTowerEta(tower_geom, 0, 0, 0);
0671 float sintheta = 1.0 / std::cosh(eta);
0672 float Et = energy * sintheta;
0673 ohcalEt33[ieta_h - ohcal_ieta + 1][iphi_h - ohcal_iphi + 1] = Et;
0674 }
0675 }
0676 }
0677 }
0678
0679 ihcal_et = ihcalEt33[1][1];
0680 ohcal_et = ohcalEt33[1][1];
0681
0682 for (int i = 0; i < 3; i++)
0683 {
0684 for (int j = 0; j < 3; j++)
0685 {
0686 ihcal_et33 += ihcalEt33[i][j];
0687 ohcal_et33 += ohcalEt33[i][j];
0688 if (i == 1 || j == 1 + ihcal_tower[2])
0689 {
0690 if (j == 1 || i == 1 + ihcal_tower[3])
0691 {
0692 ihcal_et22 += ihcalEt33[i][j];
0693 }
0694 }
0695 if (i == 1 || j == 1 + ohcal_tower[2])
0696 {
0697 if (j == 1 || i == 1 + ohcal_tower[3])
0698 {
0699 ohcal_et22 += ohcalEt33[i][j];
0700 }
0701 }
0702 }
0703 }
0704
0705 photon->set_shower_shape_parameter("ihcal_et", ihcal_et);
0706 photon->set_shower_shape_parameter("ohcal_et", ohcal_et);
0707 photon->set_shower_shape_parameter("ihcal_et22", ihcal_et22);
0708 photon->set_shower_shape_parameter("ohcal_et22", ohcal_et22);
0709 photon->set_shower_shape_parameter("ihcal_et33", ihcal_et33);
0710 photon->set_shower_shape_parameter("ohcal_et33", ohcal_et33);
0711 photon->set_shower_shape_parameter("ihcal_ieta", ihcal_ieta);
0712 photon->set_shower_shape_parameter("ihcal_iphi", ihcal_iphi);
0713 photon->set_shower_shape_parameter("ohcal_ieta", ohcal_ieta);
0714 photon->set_shower_shape_parameter("ohcal_iphi", ohcal_iphi);
0715
0716 float E = photon->get_energy();
0717 float ET = E / std::cosh(cluster_eta);
0718
0719 auto compute_layer_iso = [&](RawTowerDefs::CalorimeterId calo_id, float radius)
0720 {
0721 TowerInfoContainer* container = nullptr;
0722 RawTowerGeomContainer* geom = nullptr;
0723 if (calo_id == RawTowerDefs::CalorimeterId::CEMC)
0724 {
0725 container = m_emc_tower_container;
0726 geom = m_geomEM;
0727 }
0728 else if (calo_id == RawTowerDefs::CalorimeterId::HCALIN)
0729 {
0730 container = m_ihcal_tower_container;
0731 geom = m_geomIH;
0732 }
0733 else
0734 {
0735 container = m_ohcal_tower_container;
0736 geom = m_geomOH;
0737 }
0738 return calculate_layer_et(cluster_eta, cluster_phi, radius, container, geom, calo_id, m_vertex);
0739 };
0740
0741 const float emcal_et_04 = compute_layer_iso(RawTowerDefs::CalorimeterId::CEMC, 0.4);
0742 const float ihcal_et_04 = compute_layer_iso(RawTowerDefs::CalorimeterId::HCALIN, 0.4);
0743 const float ohcal_et_04 = compute_layer_iso(RawTowerDefs::CalorimeterId::HCALOUT, 0.4);
0744
0745 const float emcal_et_03 = compute_layer_iso(RawTowerDefs::CalorimeterId::CEMC, 0.3);
0746 const float ihcal_et_03 = compute_layer_iso(RawTowerDefs::CalorimeterId::HCALIN, 0.3);
0747 const float ohcal_et_03 = compute_layer_iso(RawTowerDefs::CalorimeterId::HCALOUT, 0.3);
0748
0749 const float emcal_et_02 = compute_layer_iso(RawTowerDefs::CalorimeterId::CEMC, 0.2);
0750 const float emcal_et_01 = compute_layer_iso(RawTowerDefs::CalorimeterId::CEMC, 0.1);
0751 const float emcal_et_005 = compute_layer_iso(RawTowerDefs::CalorimeterId::CEMC, 0.05);
0752
0753 photon->set_shower_shape_parameter("iso_04_emcal", emcal_et_04 - ET);
0754 photon->set_shower_shape_parameter("iso_04_hcalin", ihcal_et_04);
0755 photon->set_shower_shape_parameter("iso_04_hcalout", ohcal_et_04);
0756
0757 photon->set_shower_shape_parameter("iso_03_emcal", emcal_et_03 - ET);
0758 photon->set_shower_shape_parameter("iso_03_hcalin", ihcal_et_03);
0759 photon->set_shower_shape_parameter("iso_03_hcalout", ohcal_et_03);
0760 photon->set_shower_shape_parameter("iso_02_emcal", emcal_et_02 - ET);
0761 photon->set_shower_shape_parameter("iso_01_emcal", emcal_et_01 - ET);
0762 photon->set_shower_shape_parameter("iso_005_emcal", emcal_et_005 - ET);
0763 }
0764
0765 double PhotonClusterBuilder::getTowerEta(RawTowerGeom* tower_geom, double vx, double vy, double vz)
0766 {
0767 if (!tower_geom)
0768 {
0769 return -9999;
0770 }
0771 if (vx == 0 && vy == 0 && vz == 0)
0772 {
0773 return tower_geom->get_eta();
0774 }
0775
0776 double radius = sqrt((tower_geom->get_center_x() - vx) * (tower_geom->get_center_x() - vx) + (tower_geom->get_center_y() - vy) * (tower_geom->get_center_y() - vy));
0777 double theta = atan2(radius, tower_geom->get_center_z() - vz);
0778 return -log(tan(theta / 2.));
0779 }
0780
0781 std::vector<int> PhotonClusterBuilder::find_closest_hcal_tower(float eta, float phi, RawTowerGeomContainer* geom, TowerInfoContainer* towerContainer, float vertex_z, bool isihcal)
0782 {
0783 int matchedieta = -1;
0784 int matchediphi = -1;
0785 double matchedeta = -999;
0786 double matchedphi = -999;
0787
0788 if (!geom || !towerContainer)
0789 {
0790 return {-1, -1, 0, 0};
0791 }
0792
0793 unsigned int ntowers = towerContainer->size();
0794 float minR = 999;
0795
0796 for (unsigned int channel = 0; channel < ntowers; channel++)
0797 {
0798 TowerInfo* tower = towerContainer->get_tower_at_channel(channel);
0799 if (!tower)
0800 {
0801 continue;
0802 }
0803
0804 unsigned int towerkey = towerContainer->encode_key(channel);
0805 int ieta = towerContainer->getTowerEtaBin(towerkey);
0806 int iphi = towerContainer->getTowerPhiBin(towerkey);
0807
0808 RawTowerDefs::keytype key = RawTowerDefs::encode_towerid(isihcal ? RawTowerDefs::CalorimeterId::HCALIN : RawTowerDefs::CalorimeterId::HCALOUT, ieta, iphi);
0809 RawTowerGeom* tower_geom = geom->get_tower_geometry(key);
0810 if (!tower_geom)
0811 {
0812 continue;
0813 }
0814
0815 double this_phi = tower_geom->get_phi();
0816 double this_eta = getTowerEta(tower_geom, 0, 0, vertex_z);
0817 double dR_val = deltaR(eta, phi, this_eta, this_phi);
0818 if (dR_val < minR)
0819 {
0820 minR = dR_val;
0821 matchedieta = ieta;
0822 matchediphi = iphi;
0823 matchedeta = this_eta;
0824 matchedphi = this_phi;
0825 }
0826 }
0827
0828 float deta = eta - matchedeta;
0829 float dphi_val = phi - matchedphi;
0830 if (dphi_val > M_PI)
0831 {
0832 dphi_val -= 2 * M_PI;
0833 }
0834 if (dphi_val < -M_PI)
0835 {
0836 dphi_val += 2 * M_PI;
0837 }
0838
0839 int dphisign = (dphi_val > 0) ? 1 : -1;
0840 int detasign = (deta > 0) ? 1 : -1;
0841
0842 return {matchedieta, matchediphi, detasign, dphisign};
0843 }
0844
0845 float PhotonClusterBuilder::calculate_layer_et(float seed_eta, float seed_phi, float radius, TowerInfoContainer* towerContainer, RawTowerGeomContainer* geomContainer, RawTowerDefs::CalorimeterId calo_id, float vertex_z)
0846 {
0847 if (!towerContainer || !geomContainer)
0848 {
0849 return std::numeric_limits<float>::quiet_NaN();
0850 }
0851
0852 float layer_et = 0.0;
0853 const unsigned int ntowers = towerContainer->size();
0854 for (unsigned int channel = 0; channel < ntowers; ++channel)
0855 {
0856 TowerInfo* tower = towerContainer->get_tower_at_channel(channel);
0857 if (!tower || !tower->get_isGood())
0858 {
0859 continue;
0860 }
0861
0862 unsigned int towerkey = towerContainer->encode_key(channel);
0863 int ieta = towerContainer->getTowerEtaBin(towerkey);
0864 int iphi = towerContainer->getTowerPhiBin(towerkey);
0865
0866 RawTowerDefs::keytype geom_key = RawTowerDefs::encode_towerid(calo_id, ieta, iphi);
0867 RawTowerGeom* tower_geom = geomContainer->get_tower_geometry(geom_key);
0868 if (!tower_geom)
0869 {
0870 continue;
0871 }
0872
0873 double tower_eta = getTowerEta(tower_geom, 0, 0, vertex_z);
0874 double tower_phi = tower_geom->get_phi();
0875
0876 if (deltaR(seed_eta, seed_phi, tower_eta, tower_phi) >= radius)
0877 {
0878 continue;
0879 }
0880
0881 float energy = tower->get_energy();
0882 if (energy <= m_shape_min_tower_E)
0883 {
0884 continue;
0885 }
0886
0887 float et = energy / std::cosh(tower_eta);
0888 layer_et += et;
0889 }
0890
0891 return layer_et;
0892 }
0893
0894 double PhotonClusterBuilder::deltaR(double eta1, double phi1, double eta2, double phi2)
0895 {
0896 double dphi = phi1 - phi2;
0897 while (dphi > M_PI)
0898 {
0899 dphi -= 2 * M_PI;
0900 }
0901 while (dphi <= -M_PI)
0902 {
0903 dphi += 2 * M_PI;
0904 }
0905 return sqrt(pow(eta1 - eta2, 2) + pow(dphi, 2));
0906 }