@@ -30,10 +30,14 @@ def __init__(self):
30
30
# 2. Selector for a distance layer.
31
31
self .dist_selector_name1 = "Distances to Structure"
32
32
self .dist_selector_widget1 = self ._create_layer_selector (self .dist_selector_name1 , layer_type = "Shapes" )
33
+ # 3. Selector for a second distance layer (optional).
34
+ self .dist_selector_name2 = "Distances to Structure 2"
35
+ self .dist_selector_widget2 = self ._create_layer_selector (self .dist_selector_name2 , layer_type = "Shapes" )
33
36
34
37
# Add the selector widgets to the layout.
35
38
layout .addWidget (self .vesicle_selector_widget )
36
39
layout .addWidget (self .dist_selector_widget1 )
40
+ layout .addWidget (self .dist_selector_widget2 )
37
41
38
42
# Create the UI elements for defining the vesicle pools:
39
43
# The name of the output name, the name of the vesicle pool, and the criterion for the pool.
@@ -68,6 +72,11 @@ def on_pool_vesicles(self):
68
72
69
73
distance_layer = self ._get_layer_selector_layer (self .dist_selector_name1 )
70
74
distances = None if distance_layer is None else distance_layer .properties
75
+ distance_layer2 = self ._get_layer_selector_layer (self .dist_selector_name2 )
76
+ # Check if the second distance is the same as the first.
77
+ if distance_layer2 .name == distance_layer .name :
78
+ distance_layer2 = None
79
+ distances2 = None if distance_layer2 is None else distance_layer2 .properties
71
80
72
81
if segmentation is None :
73
82
show_info ("INFO: Please choose a segmentation." )
@@ -87,7 +96,9 @@ def on_pool_vesicles(self):
87
96
pool_name = self .pool_name_param .text ()
88
97
89
98
pool_color = self .pool_color_param .text ()
90
- self ._compute_vesicle_pool (segmentation , distances , morphology , pool_layer_name , pool_name , query , pool_color )
99
+ self ._compute_vesicle_pool (
100
+ segmentation , distances , morphology , pool_layer_name , pool_name , query , pool_color , distances2
101
+ )
91
102
92
103
def _update_pool_colors (self , pool_name , pool_color ):
93
104
if pool_color == "" :
@@ -107,6 +118,7 @@ def _compute_vesicle_pool(
107
118
pool_name : str ,
108
119
query : str ,
109
120
pool_color : str ,
121
+ distances2 : Dict = None
110
122
):
111
123
"""Compute a vesicle pool based on the provided query parameters.
112
124
@@ -118,6 +130,7 @@ def _compute_vesicle_pool(
118
130
pool_name: Name for the pooled group to be assigned.
119
131
query: Query parameters.
120
132
pool_color: Optional color for the vesicle pool.
133
+ distances2: Properties from the second distances layer (optional).
121
134
"""
122
135
# Check which of the properties are present and construct the combined properties based on this.
123
136
if distances is None and morphology is None : # No properties were given -> we can't do anything.
@@ -140,7 +153,14 @@ def _compute_vesicle_pool(
140
153
distances = pd .DataFrame (distances ).drop (columns = ["index" ])
141
154
morphology = pd .DataFrame (morphology ).drop (columns = ["index" ])
142
155
merged_df = morphology .merge (distances , left_on = "label" , right_on = "label" , suffixes = ("_morph" , "_dist" ))
143
-
156
+ # Add distances2 if present.
157
+ if distances2 is not None :
158
+ distance_ids = distances2 .get ("label" , [])
159
+ if set (distance_ids ) != set (merged_df .label ):
160
+ show_info ("ERROR: The IDs in distances2 and morphology are not identical." )
161
+ return
162
+ distances2 = pd .DataFrame (distances2 ).drop (columns = ["index" ])
163
+ merged_df = merged_df .merge (distances2 , left_on = "label" , right_on = "label" , suffixes = ("" , "2" ))
144
164
# Assign the vesicles to the current pool by filtering the mergeddataframe based on the query.
145
165
filtered_df = self ._parse_query (query , merged_df )
146
166
if len (filtered_df ) == 0 :
@@ -167,6 +187,12 @@ def _compute_vesicle_pool(
167
187
# Combine the vesicle ids corresponding to the previous assignment with the
168
188
# assignment for the new / current pool.
169
189
old_pool_ids = pool_properties .label .values .tolist ()
190
+
191
+ # Overwrite the intersection of the two pool assignments with the new pool.
192
+ pool_intersections = np .intersect1d (pool_vesicle_ids , old_pool_ids )
193
+ old_pool_ids = [item for item in old_pool_ids if item not in pool_intersections ]
194
+ pool_properties = pool_properties [~ pool_properties ['label' ].isin (pool_intersections )]
195
+
170
196
pool_assignments = sorted (pool_vesicle_ids + old_pool_ids )
171
197
172
198
# Get a map for each vesicle id to its pool.
0 commit comments