6
6
from skimage .measure import regionprops
7
7
from skimage .segmentation import find_boundaries
8
8
9
- from synapse_net .file_utils import read_mrc
10
- from synapse_net .sample_data import get_sample_data
11
9
from synapse_net .distance_measurements import measure_segmentation_to_object_distances
10
+ from synapse_net .file_utils import read_mrc
11
+ from synapse_net .imod .to_imod import convert_segmentation_to_spheres
12
12
from synapse_net .inference import compute_scale_from_voxel_size , get_model , run_segmentation
13
+ from synapse_net .sample_data import get_sample_data
13
14
14
15
15
16
def segment_structures (tomogram , voxel_size ):
@@ -72,15 +73,23 @@ def postprocess_segmentation(segmentations):
72
73
73
74
74
75
def measure_distances (segmentations , voxel_size ):
76
+ # Here, we measure the distances from each vesicle to the active zone.
77
+ # We use the function 'measure_segmentation_to_object_distances' for this,
78
+ # which uses an euclidean distance transform scaled with the voxel size
79
+ # to determine distances.
75
80
vesicles , active_zone = segmentations ["vesicles" ], segmentations ["active_zone" ]
76
81
voxel_size = tuple (voxel_size [ax ] for ax in "zyx" )
77
82
distances , _ , _ , vesicle_ids = measure_segmentation_to_object_distances (
78
83
vesicles , active_zone , resolution = voxel_size
79
84
)
85
+ # We convert the result to a pandas data frame.
80
86
return pd .DataFrame ({"vesicle_id" : vesicle_ids , "distance" : distances })
81
87
82
88
83
89
def assign_vesicle_pools (vesicle_attributes ):
90
+ # We assign the vesicles to their respective pool, 'docked' and 'non-attached',
91
+ # based on the criterion of being within 2 nm from the active zone.
92
+ # We add the pool assignment as a new column to the dataframe with vesicle attributes.
84
93
docked_vesicle_distance = 2 # nm
85
94
vesicle_attributes ["pool" ] = vesicle_attributes ["distance" ].apply (
86
95
lambda x : "docked" if x < docked_vesicle_distance else "non-attached"
@@ -89,6 +98,7 @@ def assign_vesicle_pools(vesicle_attributes):
89
98
90
99
91
100
def visualize_results (tomogram , segmentations , vesicle_attributes ):
101
+ # Here, we visualize the segmentation and pool assignment result in napari.
92
102
93
103
# Create a segmentation to visualize the vesicle pools.
94
104
docked_ids = vesicle_attributes [vesicle_attributes .pool == "docked" ].vesicle_id
@@ -97,6 +107,7 @@ def visualize_results(tomogram, segmentations, vesicle_attributes):
97
107
vesicle_pools = np .isin (vesicles , docked_ids ).astype ("uint8" )
98
108
vesicle_pools [np .isin (vesicles , non_attached_ids )] = 2
99
109
110
+ # Create a napari viewer, add the tomogram data and the segmentation results.
100
111
viewer = napari .Viewer ()
101
112
viewer .add_image (tomogram )
102
113
for name , segmentation in segmentations .items ():
@@ -105,9 +116,16 @@ def visualize_results(tomogram, segmentations, vesicle_attributes):
105
116
napari .run ()
106
117
107
118
108
- # TODO compute the vesicle radii and other features and then save the attributes.
109
119
def save_analysis (segmentations , vesicle_attributes , save_path ):
110
- pass
120
+ # Here, we compute the radii and centroid positions of the vesicles,
121
+ # add them to the vesicle attributes and then save all vesicle attributes to
122
+ # an excel table. You can use this table for evaluation of the analysis.
123
+ vesicles = segmentations ["vesicles" ]
124
+ coordinates , radii = convert_segmentation_to_spheres (vesicles , radius_factor = 0.7 )
125
+ vesicle_attributes ["radius" ] = radii
126
+ for ax_id , ax_name in enumerate ("zyx" ):
127
+ vesicle_attributes [f"center-{ ax_name } " ] = coordinates [:, ax_id ]
128
+ vesicle_attributes .to_excel (save_path , index = False )
111
129
112
130
113
131
def main ():
@@ -119,16 +137,7 @@ def main():
119
137
tomogram , voxel_size = read_mrc (mrc_path )
120
138
121
139
# Segment synaptic vesicles, the active zone, and the synaptic compartment.
122
- # segmentations = segment_structures(tomogram, voxel_size)
123
-
124
- # Load saved segmentations for development.
125
- import h5py
126
- segmentations = {}
127
- with h5py .File ("seg.h5" , "r" ) as f :
128
- for name , ds in f .items ():
129
- # f.create_dataset(name, data=seg, compression="gzip")
130
- seg = ds [:]
131
- segmentations [name ] = seg
140
+ segmentations = segment_structures (tomogram , voxel_size )
132
141
133
142
# Post-process the segmentations, to find the presynaptic terminal,
134
143
# filter out vesicles not in the terminal, and to 'snape' the AZ to the presynaptic boundary.
0 commit comments