34 ActsPlugins::ModuleMapCuda::Config gcCfg;
39 gcCfg.gpuBlocks = 512;
40 auto gc = std::make_shared<ActsPlugins::ModuleMapCuda>(
41 gcCfg,
m_logger->cloneWithSuffix(
"ModuleMap"));
46 std::shared_ptr<ActsPlugins::EdgeClassificationBase> gnn;
47 if (
m_gnnPath.value().find(
".onnx") != std::string::npos) {
48#ifdef ACTS_GNN_ONNX_BACKEND
49 ActsPlugins::OnnxEdgeClassifier::Config gnnCfg;
52 gnn = std::make_shared<ActsPlugins::OnnxEdgeClassifier>(
53 gnnCfg,
m_logger->cloneWithSuffix(
"GNN"));
56 ATH_MSG_FATAL(
"Not compiled with ONNX, cannot interpret *.onnx files");
57 return StatusCode::FAILURE;
59 }
else if (
m_gnnPath.value().find(
".pt") != std::string::npos) {
60#ifdef ACTS_GNN_TORCH_BACKEND
61 ActsPlugins::TorchEdgeClassifier::Config gnnCfg;
64 gnn = std::make_shared<ActsPlugins::TorchEdgeClassifier>(
65 gnnCfg,
m_logger->cloneWithSuffix(
"GNN"));
68 ATH_MSG_FATAL(
"Not compiled with Torch, cannot interpret *.pt files");
69 return StatusCode::FAILURE;
71 }
else if (
m_gnnPath.value().find(
".engine") != std::string::npos) {
72#ifdef ACTS_GNN_WITH_TENSORRT
73 ActsPlugins::TensorRTEdgeClassifier::Config gnnCfg;
77 gnn = std::make_shared<ActsPlugins::TensorRTEdgeClassifier>(
78 gnnCfg,
m_logger->cloneWithSuffix(
"GNN"));
80 ATH_MSG_FATAL(
"Not compiled with TensorRT, cannot interpret *.engine files");
81 return StatusCode::FAILURE;
85 return StatusCode::FAILURE;
89 std::shared_ptr<ActsPlugins::TrackBuildingBase> tb;
90 ATH_MSG_INFO(
"Configure CC&JunctionRemoval as graph segmentation algorithm");
92 ActsPlugins::EdgeLayerConnector::Config tbCfg;
94 tbCfg.blockSize = 512;
96 tb = std::make_shared<ActsPlugins::EdgeLayerConnector>(
97 tbCfg,
m_logger->cloneWithSuffix(
"ELC"));
99 ActsPlugins::CudaTrackBuilding::Config tbCfg;
100 tbCfg.doJunctionRemoval =
true;
101 tb = std::make_shared<ActsPlugins::CudaTrackBuilding>(
102 tbCfg,
m_logger->cloneWithSuffix(
"CC&JR"));
107 gc, std::vector{std::move(gnn)}, tb,
m_logger->cloneWithSuffix(
"Pipeline"));
109 return StatusCode::SUCCESS;
113 const std::vector<const Trk::SpacePoint*>& spacepoints,
114 std::vector<std::vector<uint32_t>>& tracks,
115 std::unordered_map<
int, std::unordered_map<int, float>>* edgeMap)
const {
117 const std::size_t nSP = spacepoints.size();
122 std::vector<std::size_t> sortIdx(nSP);
123 std::iota(sortIdx.begin(), sortIdx.end(), 0);
124 std::ranges::sort(sortIdx, std::less{}, [&](std::size_t i) {
125 return spacepoints[i]->clusterList().first->detectorElement()->identify().get_compact();
130 std::vector<std::uint64_t> moduleIds(nSP);
131 std::vector<int> ids(nSP);
133 for (std::size_t k = 0; k < nSP; ++k) {
134 const std::size_t origIdx = sortIdx[k];
137 moduleIds[k] = spacepoints[origIdx]->clusterList().first->detectorElement()->identify().get_compact();
138 ids[k] =
static_cast<int>(k);
145 auto candidates = [&] {
146 std::unique_lock<std::mutex>
lock;
147 if (m_runMutex)
lock = std::unique_lock<std::mutex>(*m_runMutex);
149 if (edgeMap !=
nullptr) {
151 auto result =
m_gnnPipeline->run(features, moduleIds, ids, ActsPlugins::Device::Cuda(0), hook);
155 const std::vector<std::int64_t>& edgeIndex = hook.
getEdgeIndex();
156 const std::size_t nEdges = edgeScores.size();
159 for (std::size_t i = 0; i < nEdges; ++i) {
160 std::int64_t src = edgeIndex[i];
161 std::int64_t dst = edgeIndex[nEdges + i];
162 (*edgeMap)[sortIdx[src]][sortIdx[dst]] = edgeScores[i];
167 return m_gnnPipeline->run(features, moduleIds, ids, ActsPlugins::Device::Cuda(0));;
170 ATH_MSG_DEBUG(
"GNN pipeline returned " << candidates.size() <<
" candidates");
174 tracks.reserve(candidates.size());
176 for (
const auto& candidate : candidates) {
182 std::vector<uint32_t> track;
183 track.reserve(candidate.size());
184 for (
int sortedIdx : candidate) {
185 track.push_back(
static_cast<uint32_t
>(sortIdx[sortedIdx]));
187 tracks.push_back(std::move(track));
190 ATH_MSG_DEBUG(
"Returning " << tracks.size() <<
" track candidates after filtering (>= "
193 return StatusCode::SUCCESS;