-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add path pruning, __array__ method, and longest shortest branch detec…
…tion to Skeleton (#117)
- Loading branch information
1 parent
97a217d
commit ac04540
Showing
6 changed files
with
191 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import networkx as nx | ||
import numpy as np | ||
from pandas import DataFrame | ||
import toolz as tz | ||
|
||
|
||
def find_main_branches(summary: DataFrame) -> np.ndarray: | ||
"""Predict the extent of branching. | ||
Parameters | ||
---------- | ||
summary : pd.DataFrame | ||
The summary table of the skeleton to analyze. | ||
This must contain: ['node-id-src', 'node-id-dst', 'branch-distance'] | ||
Returns | ||
------- | ||
is_main: array | ||
True if the index-matched path is the longest shortest path of the | ||
skeleton | ||
""" | ||
is_main = np.zeros(summary.shape[0], dtype=bool) | ||
us = summary['node-id-src'] | ||
vs = summary['node-id-dst'] | ||
ws = summary['branch-distance'] | ||
|
||
edge2idx = { | ||
(u, v): i | ||
for i, (u, v) in enumerate(zip(us, vs)) | ||
} | ||
|
||
edge2idx.update({ | ||
(v, u): i | ||
for i, (u, v) in enumerate(zip(us, vs)) | ||
}) | ||
|
||
g = nx.Graph() | ||
|
||
g.add_weighted_edges_from( | ||
zip(us, vs, ws) | ||
) | ||
|
||
for conn in nx.connected_components(g): | ||
curr_val = 0 | ||
curr_pair = None | ||
h = g.subgraph(conn) | ||
p = dict(nx.all_pairs_dijkstra_path_length(h)) | ||
for src in p: | ||
for dst in p[src]: | ||
val = p[src][dst] | ||
if (val is not None | ||
and np.isfinite(val) | ||
and val > curr_val): | ||
curr_val = val | ||
curr_pair = (src, dst) | ||
for i, j in tz.sliding_window( | ||
2, | ||
nx.shortest_path( | ||
h, source=curr_pair[0], target=curr_pair[1], weight='weight' | ||
) | ||
): | ||
is_main[edge2idx[(i, j)]] = 1 | ||
|
||
return is_main |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import pytest | ||
|
||
from skan._testdata import skeleton0 | ||
from skan import Skeleton | ||
|
||
|
||
@pytest.mark.parametrize('branch_num', [0]) | ||
def test_pruning(branch_num): | ||
skeleton = Skeleton(skeleton0) | ||
pruned = skeleton.prune_paths([branch_num]) | ||
print(pruned.skeleton_image.astype(int)) | ||
assert pruned.n_paths == 1 | ||
|
||
|
||
@pytest.mark.xfail | ||
@pytest.mark.parametrize('branch_num', [0, 1, 2]) | ||
def test_pruning_comprehensive(branch_num): | ||
skeleton = Skeleton(skeleton0) | ||
pruned = skeleton.prune_paths([branch_num]) | ||
print(pruned.skeleton_image.astype(int)) | ||
assert pruned.n_paths == 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import numpy as np | ||
|
||
from skan._testdata import skeleton1 | ||
from skan import Skeleton, summarize | ||
|
||
def test_find_main(): | ||
skeleton = Skeleton(skeleton1) | ||
summary_df = summarize(skeleton) | ||
|
||
non_main_edge_start = [2, 1] | ||
non_main_edge_finish = [3, 3] | ||
|
||
non_main_df = summary_df.loc[summary_df['main'] == False] | ||
assert non_main_df.shape[0] == 1 | ||
coords = non_main_df[['coord-src-0', 'coord-src-1', 'coord-dst-0', 'coord-dst-1']].to_numpy() | ||
assert ( | ||
np.all(coords == non_main_edge_start + non_main_edge_finish) | ||
or np.all(coords == non_main_edge_finish + non_main_edge_start) | ||
) |