File indexing completed on 2025-01-18 09:11:35
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/Digitization/DigitizationConfigurator.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Surfaces/AnnulusBounds.hpp"
0013 #include "Acts/Surfaces/DiscTrapezoidBounds.hpp"
0014 #include "Acts/Surfaces/RadialBounds.hpp"
0015 #include "Acts/Surfaces/RectangleBounds.hpp"
0016 #include "Acts/Surfaces/Surface.hpp"
0017 #include "Acts/Surfaces/SurfaceBounds.hpp"
0018 #include "Acts/Surfaces/TrapezoidBounds.hpp"
0019 #include "Acts/Utilities/BinUtility.hpp"
0020 #include "Acts/Utilities/BinningType.hpp"
0021 #include "Acts/Utilities/Zip.hpp"
0022 #include "ActsExamples/Digitization/SmearingConfig.hpp"
0023 #include "ActsFatras/Digitization/UncorrelatedHitSmearer.hpp"
0024
0025 #include <algorithm>
0026 #include <cmath>
0027
0028 namespace {
0029
0030
0031
0032
0033 bool digiConfigMaybeEqual(ActsExamples::DigiComponentsConfig &a,
0034 ActsExamples::DigiComponentsConfig &b) {
0035
0036 for (const auto &[as, bs] :
0037 Acts::zip(a.smearingDigiConfig, b.smearingDigiConfig)) {
0038 if (as.index != bs.index) {
0039 return false;
0040 }
0041 }
0042
0043 const auto &ag = a.geometricDigiConfig;
0044 const auto &bg = b.geometricDigiConfig;
0045 return (ag.indices == bg.indices && ag.segmentation == bg.segmentation &&
0046 ag.thickness == bg.thickness && ag.threshold == bg.threshold &&
0047 ag.digital == bg.digital);
0048 }
0049
0050 }
0051
0052 void ActsExamples::DigitizationConfigurator::operator()(
0053 const Acts::Surface *surface) {
0054 if (surface->associatedDetectorElement() != nullptr) {
0055 Acts::GeometryIdentifier geoId = surface->geometryId();
0056 auto dInputConfig = inputDigiComponents.find((geoId));
0057 if (dInputConfig != inputDigiComponents.end()) {
0058
0059 DigiComponentsConfig dOutputConfig;
0060 dOutputConfig.smearingDigiConfig = dInputConfig->smearingDigiConfig;
0061
0062 if (!dInputConfig->geometricDigiConfig.indices.empty()) {
0063
0064 dOutputConfig.geometricDigiConfig.indices =
0065 dInputConfig->geometricDigiConfig.indices;
0066 dOutputConfig.geometricDigiConfig.thickness =
0067 dInputConfig->geometricDigiConfig.thickness;
0068 dOutputConfig.geometricDigiConfig.chargeSmearer =
0069 dInputConfig->geometricDigiConfig.chargeSmearer;
0070 dOutputConfig.geometricDigiConfig.digital =
0071 dInputConfig->geometricDigiConfig.digital;
0072
0073 const Acts::SurfaceBounds &sBounds = surface->bounds();
0074 auto boundValues = sBounds.values();
0075
0076 const auto &inputSegmentation =
0077 dInputConfig->geometricDigiConfig.segmentation;
0078 Acts::BinUtility outputSegmentation;
0079
0080 switch (sBounds.type()) {
0081
0082 case Acts::SurfaceBounds::eRectangle: {
0083 if (inputSegmentation.binningData()[0].binvalue ==
0084 Acts::AxisDirection::AxisX) {
0085 double minX = boundValues[Acts::RectangleBounds::eMinX];
0086 double maxX = boundValues[Acts::RectangleBounds::eMaxX];
0087 unsigned int nBins = static_cast<unsigned int>(std::round(
0088 (maxX - minX) / inputSegmentation.binningData()[0].step));
0089 outputSegmentation += Acts::BinUtility(
0090 nBins, static_cast<float>(minX), static_cast<float>(maxX),
0091 Acts::open, Acts::AxisDirection::AxisX);
0092 }
0093 if (inputSegmentation.binningData()[0].binvalue ==
0094 Acts::AxisDirection::AxisY ||
0095 inputSegmentation.dimensions() == 2) {
0096 unsigned int accessBin =
0097 inputSegmentation.dimensions() == 2 ? 1 : 0;
0098 double minY = boundValues[Acts::RectangleBounds::eMinY];
0099 double maxY = boundValues[Acts::RectangleBounds::eMaxY];
0100 unsigned int nBins = static_cast<unsigned int>(
0101 std::round((maxY - minY) /
0102 inputSegmentation.binningData()[accessBin].step));
0103 outputSegmentation += Acts::BinUtility(
0104 nBins, static_cast<float>(minY), static_cast<float>(maxY),
0105 Acts::open, Acts::AxisDirection::AxisY);
0106 }
0107 } break;
0108
0109
0110 case Acts::SurfaceBounds::eTrapezoid: {
0111 if (inputSegmentation.binningData()[0].binvalue ==
0112 Acts::AxisDirection::AxisX) {
0113 double maxX = std::max(
0114 boundValues[Acts::TrapezoidBounds::eHalfLengthXnegY],
0115 boundValues[Acts::TrapezoidBounds::eHalfLengthXposY]);
0116 unsigned int nBins = static_cast<unsigned int>(std::round(
0117 2 * maxX / inputSegmentation.binningData()[0].step));
0118 outputSegmentation += Acts::BinUtility(
0119 nBins, -static_cast<float>(maxX), static_cast<float>(maxX),
0120 Acts::open, Acts::AxisDirection::AxisX);
0121 }
0122 if (inputSegmentation.binningData()[0].binvalue ==
0123 Acts::AxisDirection::AxisY ||
0124 inputSegmentation.dimensions() == 2) {
0125 unsigned int accessBin =
0126 inputSegmentation.dimensions() == 2 ? 1 : 0;
0127 double maxY = boundValues[Acts::TrapezoidBounds::eHalfLengthY];
0128 unsigned int nBins = static_cast<unsigned int>(
0129 std::round((2 * maxY) /
0130 inputSegmentation.binningData()[accessBin].step));
0131 outputSegmentation += Acts::BinUtility(
0132 nBins, -static_cast<float>(maxY), static_cast<float>(maxY),
0133 Acts::open, Acts::AxisDirection::AxisY);
0134 }
0135 } break;
0136
0137
0138 case Acts::SurfaceBounds::eAnnulus: {
0139 if (inputSegmentation.binningData()[0].binvalue ==
0140 Acts::AxisDirection::AxisR) {
0141 double minR = boundValues[Acts::AnnulusBounds::eMinR];
0142 double maxR = boundValues[Acts::AnnulusBounds::eMaxR];
0143 unsigned int nBins = static_cast<unsigned int>(std::round(
0144 (maxR - minR) / inputSegmentation.binningData()[0].step));
0145 outputSegmentation += Acts::BinUtility(
0146 nBins, static_cast<float>(minR), static_cast<float>(maxR),
0147 Acts::open, Acts::AxisDirection::AxisR);
0148 }
0149 if (inputSegmentation.binningData()[0].binvalue ==
0150 Acts::AxisDirection::AxisPhi ||
0151 inputSegmentation.dimensions() == 2) {
0152 unsigned int accessBin =
0153 inputSegmentation.dimensions() == 2 ? 1 : 0;
0154 double averagePhi = boundValues[Acts::AnnulusBounds::eAveragePhi];
0155 double minPhi =
0156 averagePhi - boundValues[Acts::AnnulusBounds::eMinPhiRel];
0157 double maxPhi =
0158 averagePhi + boundValues[Acts::AnnulusBounds::eMaxPhiRel];
0159 unsigned int nBins = static_cast<unsigned int>(
0160 std::round((maxPhi - minPhi) /
0161 inputSegmentation.binningData()[accessBin].step));
0162 outputSegmentation += Acts::BinUtility(
0163 nBins, static_cast<float>(minPhi), static_cast<float>(maxPhi),
0164 Acts::open, Acts::AxisDirection::AxisPhi);
0165 }
0166
0167 } break;
0168
0169
0170 case Acts::SurfaceBounds::eDiscTrapezoid: {
0171 double minR = boundValues[Acts::DiscTrapezoidBounds::eMinR];
0172 double maxR = boundValues[Acts::DiscTrapezoidBounds::eMaxR];
0173
0174 if (inputSegmentation.binningData()[0].binvalue ==
0175 Acts::AxisDirection::AxisR) {
0176 unsigned int nBins = static_cast<unsigned int>(std::round(
0177 (maxR - minR) / inputSegmentation.binningData()[0].step));
0178 outputSegmentation += Acts::BinUtility(
0179 nBins, static_cast<float>(minR), static_cast<float>(maxR),
0180 Acts::open, Acts::AxisDirection::AxisR);
0181 }
0182 if (inputSegmentation.binningData()[0].binvalue ==
0183 Acts::AxisDirection::AxisPhi ||
0184 inputSegmentation.dimensions() == 2) {
0185 unsigned int accessBin =
0186 inputSegmentation.dimensions() == 2 ? 1 : 0;
0187 double hxMinR =
0188 boundValues[Acts::DiscTrapezoidBounds::eHalfLengthXminR];
0189 double hxMaxR =
0190 boundValues[Acts::DiscTrapezoidBounds::eHalfLengthXmaxR];
0191
0192 double averagePhi =
0193 boundValues[Acts::DiscTrapezoidBounds::eAveragePhi];
0194 double alphaMinR = std::atan2(minR, hxMinR);
0195 double alphaMaxR = std::atan2(maxR, hxMaxR);
0196 double alpha = std::max(alphaMinR, alphaMaxR);
0197 unsigned int nBins = static_cast<unsigned int>(std::round(
0198 2 * alpha / inputSegmentation.binningData()[accessBin].step));
0199 outputSegmentation += Acts::BinUtility(
0200 nBins, static_cast<float>(averagePhi - alpha),
0201 static_cast<float>(averagePhi + alpha), Acts::open,
0202 Acts::AxisDirection::AxisPhi);
0203 }
0204
0205 } break;
0206
0207 case Acts::SurfaceBounds::eDisc: {
0208 if (inputSegmentation.binningData()[0].binvalue ==
0209 Acts::AxisDirection::AxisR) {
0210 double minR = boundValues[Acts::RadialBounds::eMinR];
0211 double maxR = boundValues[Acts::RadialBounds::eMaxR];
0212 unsigned int nBins = static_cast<unsigned int>(std::round(
0213 (maxR - minR) / inputSegmentation.binningData()[0].step));
0214 outputSegmentation += Acts::BinUtility(
0215 nBins, static_cast<float>(minR), static_cast<float>(maxR),
0216 Acts::open, Acts::AxisDirection::AxisR);
0217 }
0218 if (inputSegmentation.binningData()[0].binvalue ==
0219 Acts::AxisDirection::AxisPhi ||
0220 inputSegmentation.dimensions() == 2) {
0221 unsigned int accessBin =
0222 inputSegmentation.dimensions() == 2 ? 1 : 0;
0223
0224 double averagePhi = boundValues[Acts::RadialBounds::eAveragePhi];
0225 double halfPhiSector =
0226 boundValues[Acts::RadialBounds::eHalfPhiSector];
0227 double minPhi = averagePhi - halfPhiSector;
0228 double maxPhi = averagePhi + halfPhiSector;
0229
0230 unsigned int nBins = static_cast<unsigned int>(
0231 std::round((maxPhi - minPhi) /
0232 inputSegmentation.binningData()[accessBin].step));
0233 outputSegmentation += Acts::BinUtility(
0234 nBins, static_cast<float>(minPhi), static_cast<float>(maxPhi),
0235 Acts::open, Acts::AxisDirection::AxisPhi);
0236 }
0237
0238 } break;
0239
0240 default:
0241 break;
0242 }
0243
0244 dOutputConfig.geometricDigiConfig.segmentation = outputSegmentation;
0245 }
0246
0247
0248 if (compactify) {
0249
0250
0251 Acts::GeometryIdentifier volGeoId =
0252 Acts::GeometryIdentifier().setVolume(geoId.volume());
0253
0254 auto volRep = volumeLayerComponents.find(volGeoId);
0255 if (volRep != volumeLayerComponents.end() &&
0256 digiConfigMaybeEqual(dOutputConfig, volRep->second)) {
0257
0258 return;
0259 } else {
0260 volumeLayerComponents[volGeoId] = dOutputConfig;
0261 outputDigiComponents.push_back({volGeoId, dOutputConfig});
0262 }
0263
0264
0265 Acts::GeometryIdentifier volLayGeoId =
0266 Acts::GeometryIdentifier(volGeoId).setLayer(geoId.layer());
0267 auto volLayRep = volumeLayerComponents.find(volLayGeoId);
0268
0269 if (volLayRep != volumeLayerComponents.end() &&
0270 digiConfigMaybeEqual(dOutputConfig, volLayRep->second)) {
0271 return;
0272 } else {
0273 volumeLayerComponents[volLayGeoId] = dOutputConfig;
0274 outputDigiComponents.push_back({volLayGeoId, dOutputConfig});
0275 }
0276 }
0277
0278
0279 outputDigiComponents.push_back({geoId, dOutputConfig});
0280 }
0281 }
0282 }