File indexing completed on 2026-05-14 07:45:07
0001
0002
0003
0004
0005
0006
0007 #include <DD4hep/Alignments.h>
0008 #include <DD4hep/DetElement.h>
0009 #include <DD4hep/Objects.h>
0010 #include <DD4hep/VolumeManager.h>
0011 #include <Evaluator/DD4hepUnits.h>
0012 #include <Math/GenVector/Cartesian3D.h>
0013 #include <Math/GenVector/DisplacementVector3D.h>
0014 #include <edm4hep/Vector3f.h>
0015 #include <algorithm>
0016 #include <cmath>
0017 #include <cstdlib>
0018 #include <numbers>
0019 #include <tuple>
0020 #include <vector>
0021
0022 #include "HEXPLIT.h"
0023 #include "algorithms/calorimetry/HEXPLITConfig.h"
0024
0025 namespace eicrecon {
0026
0027
0028 const std::vector<double> HEXPLIT::neighbor_offsets_x_H4 = []() {
0029 std::vector<double> x;
0030 double rs[2] = {1.5, std::numbers::sqrt3 / 2.};
0031 double offsets[2] = {0, M_PI / 2};
0032 for (int i = 0; i < 2; i++) {
0033 for (int j = 0; j < 6; j += 1) {
0034 x.push_back(rs[i] * cos(j * M_PI / 3 + offsets[i]));
0035 }
0036 }
0037 return x;
0038 }();
0039
0040 const std::vector<double> HEXPLIT::neighbor_offsets_y_H4 = []() {
0041 std::vector<double> y;
0042 double rs[2] = {1.5, std::numbers::sqrt3 / 2.};
0043 double offsets[2] = {0, M_PI / 2};
0044 for (int i = 0; i < 2; i++) {
0045 for (int j = 0; j < 6; j += 1) {
0046 y.push_back(rs[i] * sin(j * M_PI / 3 + offsets[i]));
0047 }
0048 }
0049 return y;
0050 }();
0051
0052
0053 const std::vector<std::vector<int>> HEXPLIT::neighbor_indices_H4 = {
0054 {0, 11, 10}, {1, 6, 11}, {2, 7, 6}, {3, 8, 7}, {4, 9, 8}, {5, 10, 9},
0055 {6, 11, 7}, {7, 6, 8}, {8, 7, 9}, {9, 8, 10}, {10, 9, 11}, {11, 10, 6}};
0056
0057
0058 const std::vector<double> HEXPLIT::subcell_offsets_x_H4 = []() {
0059 std::vector<double> x;
0060 double rs[2] = {0.75, std::numbers::sqrt3 / 4.};
0061 double offsets[2] = {0, M_PI / 2};
0062 for (int i = 0; i < 2; i++) {
0063 for (int j = 0; j < 6; j += 1) {
0064 x.push_back(rs[i] * cos(j * M_PI / 3 + offsets[i]));
0065 }
0066 }
0067 return x;
0068 }();
0069
0070 const std::vector<double> HEXPLIT::subcell_offsets_y_H4 = []() {
0071 std::vector<double> y;
0072 double rs[2] = {0.75, std::numbers::sqrt3 / 4.};
0073 double offsets[2] = {0, M_PI / 2};
0074 for (int i = 0; i < 2; i++) {
0075 for (int j = 0; j < 6; j += 1) {
0076 y.push_back(rs[i] * sin(j * M_PI / 3 + offsets[i]));
0077 }
0078 }
0079 return y;
0080 }();
0081
0082 const std::vector<double> HEXPLIT::neighbor_offsets_x_S2 = {1, -1, -1, 1};
0083 const std::vector<double> HEXPLIT::neighbor_offsets_y_S2 = {1, 1, -1, -1};
0084
0085 const std::vector<std::vector<int>> HEXPLIT::neighbor_indices_S2 = {{0}, {1}, {2}, {3}};
0086
0087 const std::vector<double> HEXPLIT::subcell_offsets_x_S2 = {0.5, -0.5, -0.5, 0.5};
0088 const std::vector<double> HEXPLIT::subcell_offsets_y_S2 = {0.5, 0.5, -0.5, -0.5};
0089
0090 void HEXPLIT::init() {
0091 if (m_cfg.stag_type == HEXPLITConfig::StaggerType::H4) {
0092 stag = stag_H4;
0093 } else if (m_cfg.stag_type == HEXPLITConfig::StaggerType::S2) {
0094 stag = stag_S2;
0095 } else if (m_cfg.stag_type == HEXPLITConfig::StaggerType::H3) {
0096 error("H3 staggering not implemented yet in EICrecon");
0097 }
0098 }
0099
0100 void HEXPLIT::process(const HEXPLIT::Input& input, const HEXPLIT::Output& output) const {
0101
0102 const auto [hits] = input;
0103 auto [subcellHits] = output;
0104
0105 double MIP = m_cfg.MIP / dd4hep::GeV;
0106 double delta = m_cfg.delta_in_MIPs * MIP;
0107 double Emin = m_cfg.Emin_in_MIPs * MIP;
0108 double tmax = m_cfg.tmax / dd4hep::ns;
0109
0110 auto volman = m_detector->volumeManager();
0111
0112 for (const auto& hit : *hits) {
0113
0114 if (hit.getEnergy() < Emin || hit.getTime() > tmax) {
0115 continue;
0116 }
0117
0118
0119 std::vector<double> Eneighbors(stag.NEIGHBORS, 0.0);
0120
0121 double sl = hit.getDimension().x / 2.;
0122 for (const auto& other_hit : *hits) {
0123
0124
0125
0126 double tol = 0.1;
0127
0128
0129 int dz = std::abs(hit.getLayer() - other_hit.getLayer());
0130 if (dz > 2 || dz == 0) {
0131 continue;
0132 }
0133 if (other_hit.getEnergy() < Emin || other_hit.getTime() > tmax) {
0134 continue;
0135 }
0136
0137 double dx = (other_hit.getLocal().x - hit.getLocal().x) / sl;
0138 double dy = (other_hit.getLocal().y - hit.getLocal().y) / sl;
0139 if (std::abs(dx) > 2 || std::abs(dy) > std::numbers::sqrt3) {
0140 continue;
0141 }
0142
0143
0144
0145 for (int k = 0; k < stag.NEIGHBORS; k++) {
0146 if (std::abs(dx - stag.neighbor_offsets_x[k]) < tol &&
0147 std::abs(dy - stag.neighbor_offsets_y[k]) < tol) {
0148 Eneighbors[k] += other_hit.getEnergy();
0149 break;
0150 }
0151 }
0152 }
0153
0154 double weights[12];
0155 for (int k = 0; k < stag.NEIGHBORS; k++) {
0156 Eneighbors[k] = std::max(Eneighbors[k], delta);
0157 }
0158 double sum_weights = 0;
0159 if (m_cfg.stag_type == HEXPLITConfig::StaggerType::H4)
0160 for (int k = 0; k < stag.SUBCELLS; k++) {
0161 weights[k] = Eneighbors[stag.neighbor_indices[k][0]] *
0162 Eneighbors[stag.neighbor_indices[k][1]] *
0163 Eneighbors[stag.neighbor_indices[k][2]];
0164 sum_weights += weights[k];
0165 }
0166 else if (m_cfg.stag_type == HEXPLITConfig::StaggerType::S2) {
0167 for (int k = 0; k < stag.SUBCELLS; k++) {
0168 weights[k] = Eneighbors[stag.neighbor_indices[k][0]];
0169 sum_weights += weights[k];
0170 }
0171 } else if (m_cfg.stag_type == HEXPLITConfig::StaggerType::H3) {
0172 for (int k = 0; k < stag.SUBCELLS; k++) {
0173 weights[k] =
0174 Eneighbors[stag.neighbor_indices[k][0]] * Eneighbors[stag.neighbor_indices[k][1]];
0175 sum_weights += weights[k];
0176 }
0177 }
0178 for (int k = 0; k < stag.SUBCELLS; k++) {
0179
0180
0181 const decltype(edm4eic::CalorimeterHitData::local) local(
0182 hit.getLocal().x + stag.subcell_offsets_x[k] * sl,
0183 hit.getLocal().y + stag.subcell_offsets_y[k] * sl, hit.getLocal().z);
0184
0185
0186 dd4hep::Position local_position;
0187 local_position.SetX(local.x * dd4hep::mm);
0188 local_position.SetY(local.y * dd4hep::mm);
0189 local_position.SetZ(local.z * dd4hep::mm);
0190
0191 dd4hep::Position global_position;
0192 try {
0193
0194
0195 auto alignment = volman.lookupDetElement(hit.getCellID()).nominal();
0196
0197 global_position = alignment.localToWorld(local_position);
0198
0199 } catch (...) {
0200
0201 warning("Cannot find transformation from local to global coordinates.");
0202 global_position = local_position;
0203 }
0204
0205
0206 const decltype(edm4eic::CalorimeterHitData::position) position = {
0207 static_cast<float>(global_position.X() / dd4hep::mm),
0208 static_cast<float>(global_position.Y() / dd4hep::mm),
0209 static_cast<float>(global_position.Z() / dd4hep::mm)};
0210
0211
0212 int orientation = static_cast<int>(k % 3 == 0);
0213 const decltype(edm4eic::CalorimeterHitData::dimension) dimension(
0214 sl * (orientation != 0 ? 1 : 1.5),
0215 sl * std::numbers::sqrt3 / 2. * (orientation != 0 ? 2 : 1), hit.getDimension()[2]);
0216
0217 subcellHits->create(hit.getCellID(), hit.getEnergy() * weights[k] / sum_weights, 0,
0218 hit.getTime(), 0, position, dimension, hit.getSector(), hit.getLayer(),
0219 local);
0220 }
0221 }
0222 }
0223
0224 }