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];
47 float radiusSquared = rVal * rVal;
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))) {
98 auto name = boost::get(boost::vertex_name, newG, v);
99 add_vertex(name, ugraph);
102 auto [edge_b, edge_e] = boost::edges(newG);
103 for (
auto it = edge_b; it != edge_e; ++it) {
104 int source = boost::source(*it, newG);
105 int target = boost::target(*it, newG);
106 add_edge(source, target, ugraph);
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(std::move(track));
157 for (
const auto& track : sub_graphs) {
158 std::vector<uint32_t> this_track{track.begin(), track.end()};
159 tracks.push_back(std::move(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) {
183 if (degree(
node,
G) > 2) {
184 is_signal_path =
false;
190 if (is_signal_path) {
191 std::vector<vertex_t> track;
192 for (
int node : sub_graph) {
193 vertex_t hit_id = boost::get(boost::vertex_name,
G,
node);
194 track.push_back(hit_id);
196 final_tracks.push_back(std::move(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;
212 for (
auto it = begin; it != end; ++it) {
213 vertex_t neighbor = target(*it,
G);
214 auto score = boost::get(boost::edge_weight,
G, *it);
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(std::move(pp_extended));
283 path = std::move(new_path);
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))) {
298 auto name = boost::get(boost::vertex_name,
G, v);
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) {
311 auto source = boost::source(*it,
G);
312 auto target = boost::target(*it,
G);
313 source = old_vertex_to_new[source];
314 target = old_vertex_to_new[target];
315 auto weight = boost::get(boost::edge_weight,
G, *it);
316 if (weight <= ccCut)
continue;
317 add_edge(source, target, weight, newG);
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) > 1e-7) ? dphi / dr : 0.;
364 float rphislope = (fabs(phislope) > 1e-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);