Skip to content

Commit 0a3cfed

Browse files
authored
Merge branch 'main' into add-mitov3
2 parents 11e30e5 + 3c31509 commit 0a3cfed

File tree

5 files changed

+66
-11
lines changed

5 files changed

+66
-11
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
SynapseNet is a tool for segmentation and analysis of synapses in electron microscopy.
44

55
To learn how to use SynapseNet, check out [the documentation](https://computational-cell-analytics.github.io/synapse-net/) and [the tutorial video](https://youtu.be/7n8Oq1uAByE).
6-
To learn more about how it works, check out [our preprint](https://www.biorxiv.org/content/10.1101/2024.12.02.626387v1).
6+
To learn more about how it works, check out [our publication](https://www.molbiolcell.org/doi/full/10.1091/mbc.E24-11-0519).
77

88
See an example reconstruction of a mossy fibre synapse with SynapseNet.
99
Automatic segmentation of synaptic vesicles are rendered in orange, active zones in blue and two mitochondria in red and cyan.

synapse_net/inference/inference.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ def get_model_training_resolution(model_type: str) -> Dict[str, float]:
114114
"active_zone": {"x": 1.38, "y": 1.38, "z": 1.38},
115115
"compartments": {"x": 3.47, "y": 3.47, "z": 3.47},
116116
"mitochondria": {"x": 2.07, "y": 2.07, "z": 2.07},
117+
# TODO: this is just copied from the previous mito model, it may be necessary to update this.
118+
"mitochondria2": {"x": 1.45, "y": 1.45, "z": 1.45},
117119
"mitochondria3": {"x": 2.87, "y": 2.87, "z": 2.87},
118120
"cristae": {"x": 1.44, "y": 1.44, "z": 1.44},
119121
"ribbon": {"x": 1.188, "y": 1.188, "z": 1.188},

synapse_net/tools/cli.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,17 +107,23 @@ def pool_visualization_cli():
107107
help="The filepath to the mrc file containing the tomogram data."
108108
)
109109
parser.add_argument(
110-
"--vesicle_path", "-v", required=True, help="The filepath to the tif file containing the vesicle segmentation."
110+
"--vesicle_paths", "-v", required=True, nargs="+",
111+
help="The filepath(s) to the tif file(s) containing the vesicle segmentation."
111112
)
112113
parser.add_argument(
113114
"--table_paths", "-t", required=True, nargs="+",
114-
help="The filepath to the table with the vesicle pool assignments."
115+
help="The filepath(s) to the table(s) with the vesicle pool assignments."
115116
)
116117
parser.add_argument(
117118
"-s", "--segmentation_paths", nargs="+", help="Filepaths for additional segmentations."
118119
)
120+
parser.add_argument(
121+
"--split_pools", action="store_true", help="Whether to split the pools into individual layers.",
122+
)
119123
args = parser.parse_args()
120-
_visualize_vesicle_pools(args.input_path, args.vesicle_path, args.table_paths, args.segmentation_paths)
124+
_visualize_vesicle_pools(
125+
args.input_path, args.vesicle_paths, args.table_paths, args.segmentation_paths, args.split_pools
126+
)
121127

122128

123129
# TODO: handle kwargs

synapse_net/tools/pool_visualization.py

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,34 @@
22

33
import imageio.v3 as imageio
44
import napari
5+
import numpy as np
56
import pandas as pd
67

8+
from elf.parallel import isin
79
from ..file_utils import read_mrc
810

911

10-
def _create_pools(vesicles, table):
12+
def _create_pools(vesicles, table, split_pools):
1113
label_ids, pool_colors = table.label.values, table.color.values
1214

1315
pools = vesicles
1416
colormap = {label_id: color for label_id, color in zip(label_ids, pool_colors)}
1517
colormap[None] = [0, 0, 0, 0]
1618

17-
return pools, colormap
19+
if split_pools:
20+
unique_colors = np.unique(pool_colors)
21+
pool_ret = {}
22+
for this_color in unique_colors:
23+
this_pool = pools.copy()
24+
this_ids = [label_id for label_id, color in colormap.items() if color == this_color]
25+
pool_mask = np.zeros(this_pool.shape, dtype="bool")
26+
pool_mask = isin(this_pool, this_ids, out=pool_mask, block_shape=(32, 128, 128))
27+
this_pool[~pool_mask] = 0
28+
pool_ret[this_color] = this_pool
29+
else:
30+
pool_ret = {"pools": pools}
31+
32+
return pool_ret, colormap
1833

1934

2035
def _parse_tables(table_paths):
@@ -39,25 +54,36 @@ def load_table(path):
3954
return table
4055

4156

42-
def _visualize_vesicle_pools(input_path, vesicle_path, table_paths, segmentation_paths):
57+
def _visualize_vesicle_pools(input_path, vesicle_paths, table_paths, segmentation_paths, split_pools):
4358
# Load the tomogram data, including scale information.
4459
data, voxel_size = read_mrc(input_path)
4560
axes = "zyx" if data.ndim == 3 else "yx"
4661
scale = tuple(float(voxel_size[ax]) for ax in axes)
4762
print("Loading data with scale", scale, "nanometer")
4863

49-
# Load the vesicle layer.
50-
vesicles = imageio.imread(vesicle_path)
64+
# Load the vesicle layer, either from a single file with
65+
if len(vesicle_paths) == 1:
66+
vesicles = imageio.imread(vesicle_paths)
67+
else:
68+
vesicles = None
69+
for path in vesicle_paths:
70+
this_vesicles = imageio.imread(path)
71+
if vesicles is None:
72+
vesicles = this_vesicles.copy()
73+
else:
74+
ves_mask = this_vesicles != 0
75+
vesicles[ves_mask] = this_vesicles[ves_mask]
5176

5277
# Load the tables with the pool assignments.
5378
# Create and add the pool layer.
5479
table = _parse_tables(table_paths)
55-
pools, colormap = _create_pools(vesicles, table)
80+
pools, colormap = _create_pools(vesicles, table, split_pools)
5681

5782
viewer = napari.Viewer()
5883
viewer.add_image(data, scale=scale)
5984
viewer.add_labels(vesicles, scale=scale)
60-
viewer.add_labels(pools, scale=scale, name="pools", colormap=colormap)
85+
for pool_name, pool in pools.items():
86+
viewer.add_labels(pool, scale=scale, name=pool_name, colormap=colormap)
6187

6288
# Add the additional segmentations.
6389
if segmentation_paths is not None:

test/test_inference.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from shutil import rmtree
55

66
import imageio.v3 as imageio
7+
import requests
78
from synapse_net.file_utils import read_mrc
89
from synapse_net.sample_data import get_sample_data
910

@@ -23,6 +24,26 @@ def tearDown(self):
2324
except OSError:
2425
pass
2526

27+
# Test that all models can be accessed by pooch and have the necessary resolution information.
28+
def test_models(self):
29+
from synapse_net.inference.inference import _get_model_registry, get_model_training_resolution
30+
31+
def check_url(url):
32+
try:
33+
# Make a HEAD request to the URL, which fetches HTTP headers but no content.
34+
response = requests.head(url, allow_redirects=True)
35+
# Check if the HTTP status code is one that indicates availability (200 <= code < 400).
36+
return response.status_code < 400
37+
except requests.RequestException:
38+
# Handle connection exceptions
39+
return False
40+
41+
registry = _get_model_registry()
42+
for name in registry.registry.keys():
43+
url_exists = check_url(registry.get_url(name))
44+
self.assertTrue(url_exists)
45+
get_model_training_resolution(name)
46+
2647
def test_run_segmentation(self):
2748
from synapse_net.inference import run_segmentation, get_model
2849

0 commit comments

Comments
 (0)