File indexing completed on 2026-08-31 08:14:23
0001 #include "SiliconSeedGeoAcceptance.h"
0002
0003 #include <fun4all/Fun4AllReturnCodes.h>
0004
0005 #include <phool/getClass.h>
0006
0007 #include <trackbase/ActsGeometry.h>
0008 #include <trackbase/TrkrDefs.h>
0009
0010 #include <Acts/Definitions/Algebra.hpp>
0011 #include <Acts/Definitions/Units.hpp>
0012 #include <Acts/Surfaces/Surface.hpp>
0013
0014 #include <TFile.h>
0015 #include <TH2D.h>
0016 #include <TRandom3.h>
0017
0018 #include <algorithm>
0019 #include <array>
0020 #include <cmath>
0021 #include <numeric>
0022 #include <set>
0023 #include <string>
0024 #include <utility>
0025 #include <vector>
0026
0027 namespace
0028 {
0029 constexpr double pi = 3.14159265358979323846;
0030 constexpr double twoPi = 2.0 * pi;
0031 constexpr double surfacePhiWindow = 0.3;
0032 constexpr double parallelTolerance = 1.0e-6;
0033 constexpr double surfaceTolerance = 1.0 * Acts::UnitConstants::mm;
0034 constexpr unsigned int lastMvtxLayer = 2;
0035 }
0036
0037 SiliconSeedGeoAcceptance::SiliconSeedGeoAcceptance(const std::string &name) : SubsysReco(name) {}
0038
0039 int SiliconSeedGeoAcceptance::InitRun(PHCompositeNode *topNode)
0040 {
0041
0042 m_tGeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
0043 const auto &gctx = m_tGeometry->geometry().getGeoContext();
0044
0045 m_outputFile = new TFile(m_outputFilename.c_str(), "RECREATE");
0046 for (int nMvtx = 0; nMvtx < m_nMvtxLayerCounts; ++nMvtx)
0047 {
0048 for (int nIntt = 0; nIntt < m_nInttLayerCounts; ++nIntt)
0049 {
0050 const std::string name = "h_A_" + std::to_string(nMvtx) + "_" + std::to_string(nIntt);
0051 m_hA[nMvtx][nIntt] = new TH2D(name.c_str(), ";#eta;vtx z [cm]", m_etaBins, m_etaLo, m_etaHi, m_vtxZBins, m_vtxZLo, m_vtxZHi);
0052 }
0053 }
0054 m_hN = new TH2D("h_N", ";#eta;vtx z [cm]", m_etaBins, m_etaLo, m_etaHi, m_vtxZBins, m_vtxZLo, m_vtxZHi);
0055
0056
0057 const auto &surfaceMap = m_tGeometry->maps().m_siliconSurfaceMap;
0058 m_surfaceLayers.reserve(surfaceMap.size());
0059 m_surfacePhis.reserve(surfaceMap.size());
0060 m_surfaces.reserve(surfaceMap.size());
0061 for (const auto &[hitsetkey, surface] : surfaceMap)
0062 {
0063 const auto center = surface->center(gctx);
0064
0065 m_surfaceLayers.push_back(TrkrDefs::getLayer(hitsetkey));
0066 m_surfacePhis.push_back(std::atan2(center.y(), center.x()));
0067 m_surfaces.push_back(surface);
0068 }
0069
0070
0071 std::vector<std::size_t> order(m_surfaces.size());
0072 std::iota(order.begin(), order.end(), 0);
0073 std::sort(order.begin(), order.end(), [this](std::size_t lhs, std::size_t rhs) { return m_surfacePhis[lhs] < m_surfacePhis[rhs]; });
0074
0075 std::vector<unsigned int> sortedLayers;
0076 std::vector<double> sortedPhis;
0077 std::vector<std::shared_ptr<const Acts::Surface>> sortedSurfaces;
0078 sortedLayers.reserve(order.size());
0079 sortedPhis.reserve(order.size());
0080 sortedSurfaces.reserve(order.size());
0081 for (const auto index : order)
0082 {
0083 sortedLayers.push_back(m_surfaceLayers[index]);
0084 sortedPhis.push_back(m_surfacePhis[index]);
0085 sortedSurfaces.push_back(m_surfaces[index]);
0086 }
0087 m_surfaceLayers = std::move(sortedLayers);
0088 m_surfacePhis = std::move(sortedPhis);
0089 m_surfaces = std::move(sortedSurfaces);
0090
0091
0092 TRandom3 rng(m_randomSeed);
0093 for (int etaBin = 1; etaBin <= m_etaBins; ++etaBin)
0094 {
0095 const double etaLo = m_hN->GetXaxis()->GetBinLowEdge(etaBin);
0096 const double etaHi = m_hN->GetXaxis()->GetBinUpEdge(etaBin);
0097 for (int vtxZBin = 1; vtxZBin <= m_vtxZBins; ++vtxZBin)
0098 {
0099 const double vtxZLo = m_hN->GetYaxis()->GetBinLowEdge(vtxZBin);
0100 const double vtxZHi = m_hN->GetYaxis()->GetBinUpEdge(vtxZBin);
0101 int count[m_nMvtxLayerCounts][m_nInttLayerCounts] = {};
0102
0103 for (int ray = 0; ray < m_raysPerBin; ++ray)
0104 {
0105
0106 const double eta = rng.Uniform(etaLo, etaHi);
0107 const double vtxZ = rng.Uniform(vtxZLo, vtxZHi);
0108 const double phi = rng.Uniform(-pi, pi);
0109
0110 int nMvtx = 0;
0111 int nIntt = 0;
0112 countLayers(eta, phi, vtxZ, nMvtx, nIntt);
0113 ++count[nMvtx][nIntt];
0114 }
0115
0116 for (int nMvtx = 0; nMvtx < m_nMvtxLayerCounts; ++nMvtx)
0117 {
0118 for (int nIntt = 0; nIntt < m_nInttLayerCounts; ++nIntt)
0119 {
0120 m_hA[nMvtx][nIntt]->SetBinContent(etaBin, vtxZBin, static_cast<double>(count[nMvtx][nIntt]) / m_raysPerBin);
0121 }
0122 }
0123 m_hN->SetBinContent(etaBin, vtxZBin, m_raysPerBin);
0124 }
0125 }
0126
0127 return Fun4AllReturnCodes::EVENT_OK;
0128 }
0129
0130 int SiliconSeedGeoAcceptance::process_event(PHCompositeNode * ) { return Fun4AllReturnCodes::ABORTEVENT; }
0131
0132 int SiliconSeedGeoAcceptance::End(PHCompositeNode * )
0133 {
0134 m_outputFile->Write();
0135 m_outputFile->Close();
0136 delete m_outputFile;
0137 m_outputFile = nullptr;
0138 return Fun4AllReturnCodes::EVENT_OK;
0139 }
0140
0141 void SiliconSeedGeoAcceptance::countLayers(double eta, double phi, double vtxZ, int &nMvtx, int &nIntt) const
0142 {
0143
0144
0145 const double theta = 2.0 * std::atan(std::exp(-eta));
0146 const Acts::Vector3 origin(m_beamSpotX, m_beamSpotY, vtxZ);
0147
0148 const Acts::Vector3 direction(std::sin(theta) * std::cos(phi), std::sin(theta) * std::sin(phi), std::cos(theta));
0149
0150
0151 std::array<std::size_t, 2> firstIndex = {};
0152 std::array<std::size_t, 2> lastIndex = {};
0153 int nRanges = 1;
0154 const double phiLo = phi - surfacePhiWindow;
0155 const double phiHi = phi + surfacePhiWindow;
0156 if (phiLo < -pi)
0157 {
0158 firstIndex[0] = 0;
0159 lastIndex[0] = std::upper_bound(m_surfacePhis.begin(), m_surfacePhis.end(), phiHi) - m_surfacePhis.begin();
0160 firstIndex[1] = std::lower_bound(m_surfacePhis.begin(), m_surfacePhis.end(), phiLo + twoPi) - m_surfacePhis.begin();
0161 lastIndex[1] = m_surfacePhis.size();
0162 nRanges = 2;
0163 }
0164 else if (phiHi > pi)
0165 {
0166 firstIndex[0] = std::lower_bound(m_surfacePhis.begin(), m_surfacePhis.end(), phiLo) - m_surfacePhis.begin();
0167 lastIndex[0] = m_surfacePhis.size();
0168 firstIndex[1] = 0;
0169 lastIndex[1] = std::upper_bound(m_surfacePhis.begin(), m_surfacePhis.end(), phiHi - twoPi) - m_surfacePhis.begin();
0170 nRanges = 2;
0171 }
0172 else
0173 {
0174 firstIndex[0] = std::lower_bound(m_surfacePhis.begin(), m_surfacePhis.end(), phiLo) - m_surfacePhis.begin();
0175 lastIndex[0] = std::upper_bound(m_surfacePhis.begin(), m_surfacePhis.end(), phiHi) - m_surfacePhis.begin();
0176 }
0177
0178 const auto &gctx = m_tGeometry->geometry().getGeoContext();
0179 std::set<unsigned int> layersHit;
0180 for (int range = 0; range < nRanges; ++range)
0181 {
0182 for (std::size_t index = firstIndex[range]; index < lastIndex[range]; ++index)
0183 {
0184 const auto &surface = m_surfaces[index];
0185 const Acts::Vector3 centerMm = surface->center(gctx);
0186 const Acts::Vector3 center = centerMm / Acts::UnitConstants::cm;
0187 const Acts::Vector3 normal = surface->normal(gctx, centerMm, direction);
0188 const double denominator = normal.dot(direction);
0189 if (std::abs(denominator) < parallelTolerance)
0190 {
0191 continue;
0192 }
0193
0194
0195 const double pathLength = normal.dot(center - origin) / denominator;
0196 if (pathLength <= 0.0)
0197 {
0198 continue;
0199 }
0200
0201 const Acts::Vector3 intersection = origin + pathLength * direction;
0202
0203
0204
0205 const auto local = surface->globalToLocal(gctx, intersection * Acts::UnitConstants::cm, direction, surfaceTolerance);
0206 if (!local.ok() || !surface->bounds().inside(local.value()))
0207 {
0208 continue;
0209 }
0210
0211 layersHit.insert(m_surfaceLayers[index]);
0212 }
0213 }
0214
0215 nMvtx = 0;
0216 nIntt = 0;
0217 for (const auto layer : layersHit)
0218 {
0219 if (layer <= lastMvtxLayer)
0220 {
0221 ++nMvtx;
0222 }
0223 else
0224 {
0225 ++nIntt;
0226 }
0227 }
0228 }