-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
anna-grim
committed
Jun 25, 2024
1 parent
dd5fece
commit 2784743
Showing
5 changed files
with
219 additions
and
94 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
""" | ||
Created on Sat June 25 9:00:00 2024 | ||
@author: Anna Grim | ||
@email: [email protected] | ||
Module that removes doubled fragments from a NeuroGraph. | ||
""" | ||
|
||
from deep_neurographs import utils | ||
import networkx as nx | ||
|
||
|
||
def run(neurograph, max_size, node_spacing): | ||
""" | ||
Removes connected components from "neurgraph" that are likely to be a | ||
double. | ||
Parameters | ||
---------- | ||
neurograph : NeuroGraph | ||
Graph to be searched for doubles. | ||
max_size : int | ||
Maximum size of connected components to be searched. | ||
node_spacing : int | ||
Expected distance in microns between nodes in "neurograph". | ||
Returns | ||
------- | ||
NeuroGraph | ||
Graph with doubles removed. | ||
""" | ||
# Assign processes | ||
doubles_cnt = 0 | ||
neurograph.init_kdtree() | ||
not_doubles = set() | ||
for nodes in list(nx.connected_components(neurograph)): | ||
# Determine whether to inspect fragment | ||
swc_id = get_swc_id(neurograph, nodes) | ||
if swc_id not in not_doubles: | ||
xyz_arr = inspect_component(neurograph, nodes) | ||
if len(xyz_arr) > 0 and len(xyz_arr) * node_spacing < max_size: | ||
not_double_id = is_double(neurograph, xyz_arr, swc_id) | ||
if not_double_id: | ||
doubles_cnt += 1 | ||
neurograph = remove_component(neurograph, nodes, swc_id) | ||
not_doubles.add(not_double_id) | ||
print("# Doubles detected:", doubles_cnt) | ||
|
||
|
||
def is_double(neurograph, xyz_arr, swc_id_i): | ||
""" | ||
Determines whether the connected component corresponding to "root" is a | ||
double of another connected component. | ||
Paramters | ||
--------- | ||
neurograph : NeuroGraph | ||
Graph to be searched for doubles. | ||
xyz_arr : numpy.ndarray | ||
Array containing xyz coordinates corresponding to some fragment (i.e. | ||
connected component in neurograph). | ||
swc_id_i : str | ||
swc id corresponding to fragment. | ||
Returns | ||
------- | ||
str or None | ||
Indication of whether connected component is a double. If True, the | ||
swc_id of the main fragment (i.e. non doubles) is returned. Otherwise, | ||
the value None is returned to indicate that query fragment is not a | ||
double. | ||
""" | ||
# Compute projections | ||
hits = dict() | ||
for xyz_i in xyz_arr: | ||
for xyz_j in neurograph.query_kdtree(xyz_i, 6): | ||
try: | ||
swc_id_j = neurograph.xyz_to_swc(xyz_j) | ||
if swc_id_i != swc_id_j: | ||
hits = utils.append_dict_value(hits, swc_id_j, 1) | ||
except: | ||
pass | ||
|
||
# Check criteria | ||
if len(hits) > 0: | ||
swc_id_j = utils.find_best(hits) | ||
percent_hit = len(hits[swc_id_j]) / len(xyz_arr) | ||
else: | ||
percent_hit = 0 | ||
return swc_id_j if swc_id_j is not None and percent_hit > 0.5 else None | ||
|
||
|
||
# --- utils --- | ||
def get_swc_id(neurograph, nodes): | ||
""" | ||
Gets the swc id corresponding to "nodes". | ||
Parameters | ||
---------- | ||
neurograph : NeuroGraph | ||
Graph containing "nodes". | ||
nodes : list[int] | ||
Nodes to be checked. | ||
Returns | ||
------- | ||
str | ||
swc id of "nodes". | ||
""" | ||
i = utils.sample_singleton(nodes) | ||
return neurograph.nodes[i]["swc_id"] | ||
|
||
|
||
def inspect_component(neurograph, nodes): | ||
""" | ||
Determines whether to inspect component for doubles. | ||
Parameters | ||
---------- | ||
neurograph : NeuroGraph | ||
Graph to be searched. | ||
nodes : iterable | ||
Nodes that comprise a connected component. | ||
Returns | ||
------- | ||
numpy.ndarray or list | ||
Array containing xyz coordinates of nodes. | ||
""" | ||
if len(nodes) == 2: | ||
i, j = tuple(nodes) | ||
return neurograph.edges[i, j]["xyz"] | ||
else: | ||
return [] | ||
|
||
|
||
def remove_component(neurograph, nodes, swc_id): | ||
""" | ||
Removes "nodes" from "neurograph". | ||
Parameters | ||
---------- | ||
neurograph : NeuroGraph | ||
Graph that contains "nodes". | ||
nodes : list[int] | ||
Nodes to be removed. | ||
swc_id : str | ||
swc id corresponding to nodes which comprise a connected component in | ||
"neurograph". | ||
Returns | ||
------- | ||
NeuroGraph | ||
Graph with nodes removed. | ||
""" | ||
i, j = tuple(nodes) | ||
neurograph = remove_xyz_entries(neurograph, i, j) | ||
neurograph.remove_nodes_from([i, j]) | ||
neurograph.leafs.remove(i) | ||
neurograph.leafs.remove(j) | ||
neurograph.swc_ids.remove(swc_id) | ||
return neurograph | ||
|
||
|
||
def remove_xyz_entries(neurograph, i, j): | ||
""" | ||
Removes dictionary entries from "neurograph.xyz_to_edge" corresponding to | ||
the edge {i, j}. | ||
Parameters | ||
---------- | ||
neurograph : NeuroGraph | ||
Graph to be updated. | ||
i : int | ||
Node in "neurograph". | ||
j : int | ||
Node in "neurograph". | ||
Returns | ||
------- | ||
NeuroGraph | ||
Updated graph. | ||
""" | ||
for xyz in neurograph.edges[i, j]["xyz"]: | ||
del neurograph.xyz_to_edge[tuple(xyz)] | ||
return neurograph |
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
Oops, something went wrong.