From a6bef6e9a15c4f76539b42726e38781880c84019 Mon Sep 17 00:00:00 2001 From: Yves Biener Date: Thu, 9 Apr 2026 10:48:07 +0200 Subject: [PATCH] mod: node vs edge centrality based euklidian distance calculation --- comparison.py | 1 + distance_types.py | 28 ++++++++++++------------ src/plot.py | 55 ++++++++++++++++++++++++++++++++++++----------- 3 files changed, 57 insertions(+), 27 deletions(-) diff --git a/comparison.py b/comparison.py index 2d58203..130b59d 100644 --- a/comparison.py +++ b/comparison.py @@ -43,6 +43,7 @@ def leverage(g, weight): li = 0.0 neighbours = g.get_all_neighbours(v) ki = len(neighbours) + # mibitof has an isolated node, why? should that not be possible with the triangulation? if ki == 0: continue # sum diff --git a/distance_types.py b/distance_types.py index c4b8081..2e46ffb 100644 --- a/distance_types.py +++ b/distance_types.py @@ -38,18 +38,18 @@ def spatial_graph(adata): def apply(g, seed, weight, convex_hull, ax, ax2, method): # calculate centrality values - vp, ep = method(g, weight=weight) - ep.a = np.nan_to_num(ep.a) # correct floating point values - min_val, max_val = ep.a.min(), ep.a.max() - ep.a = (ep.a - min_val) / (max_val - min_val) + vp = method(g, weight=weight) + vp.a = np.nan_to_num(vp.a) # correct floating point values + min_val, max_val = vp.a.min(), vp.a.max() + vp.a = (vp.a - min_val) / (max_val - min_val) # euklidian distance - quantification = plot.quantification_data(g, ep, convex_hull) + quantification = plot.quantification_data(g, vp, convex_hull) plot.quantification_plot(ax, quantification, None, None, "Euklidian Distance", None) # generate model based on convex hull and associated centrality values - # path distance - quantification = plot.quantification_data_path_distance(g, weight, ep, convex_hull) + # path distance (node based centrality) + quantification = plot.quantification_data_node_path_distance(g, weight, vp, convex_hull) plot.quantification_plot(ax2, quantification, None, None, "Shortest Path Distance", None) @@ -63,13 +63,13 @@ fig = plt.figure(figsize=(21, 5)) ax1, ax2, ax3 = fig.subplots(1, 3) # plot graph with convex_hull -vp, ep = betweenness(g, weight=weight) -ep.a = np.nan_to_num(ep.a) # correct floating point values -min_val, max_val = ep.a.min(), ep.a.max() -ep.a = (ep.a - min_val) / (max_val - min_val) +vp = closeness(g, weight=weight) +vp.a = np.nan_to_num(vp.a) # correct floating point values +min_val, max_val = vp.a.min(), vp.a.max() +vp.a = (vp.a - min_val) / (max_val - min_val) -plot.graph_plot(fig, ax1, g, ep, convex_hull, f"Pointcloud (seed: {seed})", True) +plot.graph_plot(fig, ax1, g, vp, convex_hull, f"Pointcloud (seed: {seed})", False) -apply(g, seed, weight, convex_hull, ax2, ax3, betweenness) +apply(g, seed, weight, convex_hull, ax2, ax3, closeness) -fig.savefig(f"Distance_5000_betweenness_edge_euklidian.svg", format='svg') +fig.savefig(f"Distance_5000_node_closeness.svg", format='svg') diff --git a/src/plot.py b/src/plot.py index 49cab6f..092e600 100644 --- a/src/plot.py +++ b/src/plot.py @@ -162,6 +162,39 @@ def quantification_data(G, measures, convex_hull): return np.array(quantification) +def quantification_data_node_path_distance(G, weights, measures, convex_hull): + quantification = [] + pos = G.vp["pos"] + x = [] + y = [] + convex_hull_verticies = [] + for v in G.vertices(): + ver = pos[v] + for n in convex_hull: + if np.equal(n, np.array([ver[0], ver[1]])).all(): + convex_hull_verticies.append(v) + + measures = measures.a + keys = iter(measures) + + points = np.stack((np.array(x), np.array(y)), axis=-1) + for v in G.vertices(): + min_distance = math.inf + key = next(keys) + + for h in convex_hull_verticies: + vertices, edges = graph_tool.topology.shortest_path(G, v, h, weights=weights) + # TODO calculate the total distance + path_length = sum([weights[edge] for edge in edges]) + if path_length < min_distance: + min_distance = path_length + quantification.append([min_distance, key]) + + # sort by distance + quantification.sort(key=lambda entry: entry[0]) + return np.array(quantification) + + def quantification_data_edges(G, measures, convex_hull): # calculate distance based on the median of the distances of the two verticies an edge connects quantification = [] @@ -181,22 +214,18 @@ def quantification_data_edges(G, measures, convex_hull): min_distance_source = math.inf min_distance_target = math.inf key = next(keys) - for point in convex_hull: - # TODO isn't there the dot product missing? - # -> such that there might be a shorter path? - # -> for each `point` take its each of its two neighbours (idx - 1 & idx + 1) - # and create another vector on which you project the verticies too? - vector = Vector.vec(pos[e.source()], point) - distance = Vector.vec_len(vector) + for idx, point in enumerate(convex_hull): + hull_line = Vector.vec(convex_hull[idx - 1], point) + a = point + b = convex_hull[idx - 1] + distance = abs((a[1] - b[1]) * pos[e.source()][0] - (a[0] - b[0]) * pos[e.source()][1] + a[1]*b[0] - b[1]*a[0])/Vector.vec_len(hull_line) if distance < min_distance_source: min_distance_source = distance for point in convex_hull: - # TODO isn't there the dot product missing? - # -> such that there might be a shorter path? - # -> for each `point` take its each of its two neighbours (idx - 1 & idx + 1) - # and create another vector on which you project the verticies too? - vector = Vector.vec(pos[e.target()], point) - distance = Vector.vec_len(vector) + hull_line = Vector.vec(convex_hull[idx - 1], point) + a = point + b = convex_hull[idx - 1] + distance = abs((a[1] - b[1]) * pos[e.target()][0] - (a[0] - b[0]) * pos[e.target()][1] + a[1]*b[0] - b[1]*a[0])/Vector.vec_len(hull_line) if distance < min_distance_target: min_distance_target = distance quantification.append([(min_distance_target + min_distance_source) / 2, key])