@@ -21,7 +21,6 @@ def get_ids_that_ends_with_split(
2121 counts = counts [parents > 0 ]
2222 parents = parents [parents > 0 ]
2323 ends_with_split = parents [counts > 1 ]
24- print ("ends_with_split:" , ends_with_split )
2524 return ends_with_split
2625
2726
@@ -54,8 +53,10 @@ def is_matching(
5453 mapped_comp : list ,
5554 ref_children : np .ndarray ,
5655 comp_children : np .ndarray ,
57- tr : int ,
58- tc : int
56+ t_parent_end_ref : int ,
57+ t_parent_end_comp : int ,
58+ t_child_start_ref : list ,
59+ t_child_start_comp : list ,
5960):
6061 """
6162 Checks if the reference and the computed track match.
@@ -67,8 +68,10 @@ def is_matching(
6768 mapped_comp: The matched labels of the result masks.
6869 ref_children: The children ids of the reference track.
6970 comp_children: The children ids of the computed track.
70- tr: The frame of the reference track end.
71- tc: The frame of the computed track end.
71+ t_parent_end_ref: The frame of the reference track end.
72+ t_parent_end_comp: The frame of the computed track end.
73+ t_child_start_ref: The frame of the reference track start.
74+ t_child_start_comp: The frame of the computed track start.
7275
7376 Returns:
7477 True if the reference and the computed track match, False otherwise.
@@ -77,21 +80,33 @@ def is_matching(
7780 if len (ref_children ) != len (comp_children ):
7881 return False
7982 # Compare parents
80- t1 , _ = min (tr , tc ), max ( tr , tc )
81- mr , mc = mapped_ref [t1 ], mapped_comp [t1 ]
83+ t_start = min (t_parent_end_ref , t_parent_end_comp )
84+ mr , mc = mapped_ref [t_start ], mapped_comp [t_start ]
8285 if np .sum (mc == id_comp ) < 1 or np .sum (mr == id_ref ) != 1 :
8386 return False
8487 ind = np .argwhere (mr == id_ref ).squeeze ()
8588 if mc [ind ] != id_comp :
8689 return False
87- # # Compare children ### WHAT IS A CORRECT DETECTED MITOSIS?
88- # mr, mc = np.concatenate(mapped_ref[t2 + 1]), np.concatenate(mapped_comp[t2 + 1])
89- # if not np.all(np.isin(comp_children, mc)):
90- # return False
91- # if not np.all(np.isin(mr[np.isin(mc, comp_children)], ref_children)):
92- # return False
90+ # Compare children
91+ # Iterate over all GT ids and check if the first detection is matched to the correct reference children
92+ matched_children = []
93+ for i , t_ref in zip (ref_children , t_child_start_ref ):
94+ for j , t_comp in zip (comp_children , t_child_start_comp ):
95+ t_max = max (t_ref , t_comp )
96+ if i in mapped_ref [t_max ] and j in mapped_comp [t_max ]:
97+ ind = mapped_ref [t_max ].index (i )
98+ if mapped_comp [t_max ][ind ] == j :
99+ # There is a match!
100+ if j not in matched_children :
101+ matched_children .append (j )
102+ break
103+
104+ if len (matched_children ) != len (ref_children ):
105+ return False
106+
93107 return True
94108
109+
95110def raw_division_metrics (
96111 comp_tracks : np .ndarray ,
97112 ref_tracks : np .ndarray ,
@@ -101,7 +116,7 @@ def raw_division_metrics(
101116):
102117 """
103118 Computes number of true positives, false positives, and false negatives for divisions.
104-
119+
105120 Args:
106121 comp_tracks: The result tracks. A (n,4) numpy ndarray with columns:
107122 - label
@@ -137,36 +152,49 @@ def raw_division_metrics(
137152 ends_with_split_comp = get_ids_that_ends_with_split (comp_tracks )
138153 t_comp = np .asarray ([comp_tracks [comp_tracks [:, 0 ] == comp ][0 , 2 ]
139154 for comp in ends_with_split_comp ])
140-
141- # If there are no divisions in the reference
155+
156+ # If there are no divisions in the reference
142157 if len (ends_with_split_ref ) == 0 :
143158 return (0 , len (ends_with_split_comp ), 0 )
144-
159+
145160 # If there are no divisions in the computed result
146161 if len (ends_with_split_comp ) == 0 :
147162 return (0 , 0 , len (ends_with_split_ref ))
148-
163+
149164 # Find all matches between reference and computed branching events (mitosis)
150165 matches = []
151- for comp , tc in zip (ends_with_split_comp , t_comp ):
166+ for comp , t_parent_end_start in zip (ends_with_split_comp , t_comp ):
152167 # Find potential matches
153- pot_matches = np .abs (t_ref - tc ) <= i
168+ pot_matches = np .abs (t_ref - t_parent_end_start ) <= i
154169 if len (pot_matches ) == 0 :
155170 continue
156171 comp_children = comp_tracks [comp_tracks [:, 3 ] == comp ][:, 0 ]
172+ t_child_start_comp = []
173+ for j in comp_children :
174+ t = comp_tracks [comp_tracks [:, 0 ] == j ][0 , 1 ]
175+ t_child_start_comp .append (t )
157176 # Evaluate potential matches
158- for ref , tr in zip (
177+ for ref , t_parent_end_ref in zip (
159178 ends_with_split_ref [pot_matches ],
160179 t_ref [pot_matches ]
161180 ):
162181 ref_children = ref_tracks [ref_tracks [:, 3 ] == ref ][:, 0 ]
182+ t_child_start_ref = []
183+ for j in ref_children :
184+ t = ref_tracks [ref_tracks [:, 0 ] == j ][0 , 1 ]
185+ t_child_start_ref .append (t )
163186 if is_matching (
164- comp , ref , mapped_ref , mapped_comp , ref_children ,
165- comp_children , tr , tc
187+ comp , ref ,
188+ mapped_ref , mapped_comp ,
189+ ref_children , comp_children ,
190+ t_parent_end_ref , t_parent_end_start ,
191+ t_child_start_ref ,
192+ t_child_start_comp ,
166193 ):
167194 matches .append ((ref , comp ))
168195 return (len (matches ), len (ends_with_split_comp ) - len (matches ), len (ends_with_split_ref ) - len (matches ))
169196
197+
170198def bc (
171199 tp : int ,
172200 fp : int ,
0 commit comments