5 #include "ExaTrkXUtils.hpp"
8 #include <boost/graph/adjacency_list.hpp>
9 #include <boost/graph/topological_sort.hpp>
10 #include <boost/graph/connected_components.hpp>
11 #include <boost/graph/graphviz.hpp>
12 #include <boost/property_map/property_map.hpp>
13 #include <boost/graph/graph_utility.hpp>
14 #include <boost/graph/graph_traits.hpp>
19 const std::vector<float>& embedFeatures,
20 std::vector<int64_t>& senders,
21 std::vector<int64_t>& receivers,
22 int64_t numSpacepoints,
37 auto squaredDistance = [&](int64_t
i, int64_t j) {
39 for (
int d = 0;
d < embeddingDim; ++
d) {
40 float diff = embedFeatures[
i * embeddingDim +
d] - embedFeatures[j * embeddingDim +
d];
49 for (int64_t
i = 0;
i < numSpacepoints;
i++) {
51 std::priority_queue<std::pair<float, int64_t>> nearestNeighbors;
53 for (int64_t j =
i + 1; j < numSpacepoints; j++) {
55 float distSquared = squaredDistance(
i, j);
56 if (distSquared <= radiusSquared) {
57 nearestNeighbors.push({distSquared, j});
59 if (nearestNeighbors.size() > (
unsigned long) kVal) {
60 nearestNeighbors.pop();
65 while (!nearestNeighbors.empty()) {
67 receivers.push_back(nearestNeighbors.top().second);
68 nearestNeighbors.pop();
74 vertex_t numSpacepoints,
75 const std::vector<int64_t>& rowIndices,
76 const std::vector<int64_t>& colIndices,
77 const std::vector<weight_t>& edgeWeights,
78 std::vector<std::vector<uint32_t> >& tracks,
79 float ccCut,
float walkMin,
float walkMax
82 std::map<vertex_t, bool> used_hits;
84 for (vertex_t
i = 0;
i < numSpacepoints;
i++) {
88 for(
size_t idx=0;
idx < rowIndices.size(); ++
idx) {
89 add_edge(rowIndices[
idx], colIndices[
idx], edgeWeights[
idx],
G);
95 UndirectedGraph ugraph;
97 for (
auto v : boost::make_iterator_range(vertices(newG))) {
99 add_vertex(
name, ugraph);
102 auto [edge_b, edge_e] = boost::edges(newG);
103 for (
auto it = edge_b;
it != edge_e; ++
it) {
109 std::vector<std::vector<vertex_t>> sub_graphs =
getSimplePath(ugraph);
111 for (
const auto&
track : sub_graphs) {
112 for (
auto hit_id :
track) {
113 used_hits[hit_id] =
true;
117 std::vector<Vertex> topo_order;
118 boost::topological_sort(newG, std::back_inserter(topo_order));
121 auto next_node_fn = [&](
const Graph &
G, vertex_t current_hit) {
126 for(
auto it = topo_order.rbegin();
it != topo_order.rend(); ++
it) {
128 int hit_id =
boost::get(boost::vertex_name, newG, node_id);
129 if (used_hits[hit_id])
continue;
132 auto roads =
buildRoads(newG, node_id, next_node_fn, used_hits);
133 used_hits[node_id] =
true;
139 std::vector<int>& longest_road = *std::max_element(roads.begin(), roads.end(),
140 [](
const std::vector<int> &
a,
const std::vector<int> &
b) {
141 return a.size() < b.size();
144 if (longest_road.size() >= 3) {
145 std::vector<vertex_t>
track;
146 for (
int node_id : longest_road) {
147 auto hit_id =
boost::get(boost::vertex_name, newG, node_id);
148 used_hits[hit_id] =
true;
149 track.push_back(hit_id);
151 sub_graphs.push_back(
track);
157 for (
const auto&
track : sub_graphs) {
158 std::vector<uint32_t> this_track{
track.begin(),
track.end()};
159 tracks.push_back(this_track);
165 std::vector<std::vector<vertex_t>> final_tracks;
167 std::vector<vertex_t> component(num_vertices(
G));
168 size_t num_components = boost::connected_components(
G, &component[0]);
170 std::vector<std::vector<Vertex> > component_groups(num_components);
171 for(
size_t i = 0;
i < component.size(); ++
i) {
172 component_groups[component[
i]].push_back(
i);
176 for(
const auto& sub_graph : component_groups) {
177 if (sub_graph.size() < 3) {
180 bool is_signal_path =
true;
182 for (
int node : sub_graph) {
184 is_signal_path =
false;
190 if (is_signal_path) {
191 std::vector<vertex_t>
track;
192 for (
int node : sub_graph) {
194 track.push_back(hit_id);
196 final_tracks.push_back(
track);
204 vertex_t current_hit,
208 std::vector<vertex_t> next_hits;
209 auto [
begin,
end] = boost::out_edges(current_hit,
G);
211 std::vector<std::pair<vertex_t, double>> neighbors_scores;
216 if (neighbor == current_hit ||
score <= th_min)
continue;
217 neighbors_scores.push_back({neighbor,
score});
220 if (neighbors_scores.empty())
return {};
223 auto best_neighbor = *std::max_element(neighbors_scores.begin(), neighbors_scores.end(),
224 [](
const std::pair<int, double> &
a,
const std::pair<int, double> &
b) {
225 return a.second < b.second;
229 for (
const auto &neighbor : neighbors_scores) {
230 if (neighbor.second > th_add) {
231 next_hits.push_back(neighbor.first);
236 if (next_hits.empty()) {
237 next_hits.push_back(best_neighbor.first);
245 vertex_t starting_node,
246 std::function<std::vector<vertex_t>(
const Graph&, vertex_t)> next_node_fn,
247 std::map<vertex_t, bool>& used_hits
249 std::vector<std::vector<int>>
path = {{starting_node}};
252 std::vector<std::vector<int>> new_path;
253 bool is_all_done =
true;
255 for (
const auto &pp :
path) {
256 vertex_t
start = pp.back();
259 new_path.push_back(pp);
263 auto next_hits = next_node_fn(
G,
start);
265 next_hits.erase(std::remove_if(next_hits.begin(), next_hits.end(),
267 auto hit_id = boost::get(boost::vertex_name, G, node_id);
268 return used_hits[hit_id];
269 }), next_hits.end());
271 if (next_hits.empty()) {
272 new_path.push_back(pp);
275 for (
int nh : next_hits) {
276 std::vector<int> pp_extended = pp;
277 pp_extended.push_back(nh);
278 new_path.push_back(pp_extended);
284 if (is_all_done)
break;
294 std::map<vertex_t, vertex_t> old_vertex_to_new;
295 vertex_t old_vertex_id = 0;
296 vertex_t new_vertex_id = 0;
297 for (
auto v : boost::make_iterator_range(vertices(
G))) {
299 if (in_degree(
v,
G) == 0 && out_degree(
v,
G) == 0) {
303 add_vertex(
name, newG);
304 old_vertex_to_new[old_vertex_id] = new_vertex_id;
309 auto [edge_b, edge_e] = boost::edges(
G);
310 for (
auto it = edge_b;
it != edge_e; ++
it) {
316 if (
weight <= ccCut)
continue;
323 int64_t numSpacepoints,
324 const std::vector<int64_t>& rowIndices,
325 const std::vector<int64_t>& colIndices,
326 std::vector<float>& edgeFeatures
339 int64_t numFeatures = gNodeFeatures.size() / numSpacepoints;
340 edgeFeatures.clear();
341 edgeFeatures.reserve(rowIndices.size() * 6);
342 auto diffPhi = [](
float phi1,
float phi2) {
343 float dphi = (phi1 - phi2) *
M_PI;
346 }
else if (dphi <= -
M_PI) {
351 for (
size_t idx = 0;
idx < rowIndices.size(); ++
idx) {
352 int64_t
src = rowIndices[
idx];
353 int64_t dst = colIndices[
idx];
354 std::vector<float> src_features(gNodeFeatures.begin() +
src * numFeatures,
355 gNodeFeatures.begin() +
src * numFeatures + 4);
356 std::vector<float> dst_features(gNodeFeatures.begin() + dst * numFeatures,
357 gNodeFeatures.begin() + dst * numFeatures + 4);
359 float dr = dst_features[0] - src_features[0];
360 float dphi = diffPhi(dst_features[1], src_features[1]);
361 float dz = dst_features[2] - src_features[2];
362 float deta = dst_features[3] - src_features[3];
363 float phislope = (fabs(
dr) > 1
e-7) ? dphi /
dr : 0.;
364 float rphislope = (fabs(phislope) > 1
e-7) ? (dst_features[0] + src_features[0]) / 2 * phislope : 0.0;
366 edgeFeatures.push_back(
dr);
367 edgeFeatures.push_back(dphi);
368 edgeFeatures.push_back(dz);
369 edgeFeatures.push_back(deta);
370 edgeFeatures.push_back(phislope);
371 edgeFeatures.push_back(rphislope);