Skip to content

Commit 4fa5a0c

Browse files
committed
symmetric > ensure_symmetry
1 parent 2e31539 commit 4fa5a0c

3 files changed

Lines changed: 73 additions & 42 deletions

File tree

src/spikeinterface/comparison/comparisontools.py

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,36 @@ def compute_matching_matrix(
132132
num_units_train2,
133133
delta_frames,
134134
):
135+
"""
136+
Internal function used by `make_match_count_matrix()`.
137+
This function is for one segment only.
138+
The llop over segment is done in `make_match_count_matrix()`
139+
140+
Parameters
141+
----------
142+
spike_frames_train1 : ndarray
143+
An array of integer frame numbers corresponding to spike times for the first train. Must be in ascending order.
144+
spike_frames_train2 : ndarray
145+
An array of integer frame numbers corresponding to spike times for the second train. Must be in ascending order.
146+
unit_indices1 : ndarray
147+
An array of integers where `unit_indices1[i]` gives the unit index associated with the spike at `spike_frames_train1[i]`.
148+
unit_indices2 : ndarray
149+
An array of integers where `unit_indices2[i]` gives the unit index associated with the spike at `spike_frames_train2[i]`.
150+
num_units_train1 : int
151+
The total count of unique units in the first spike train.
152+
num_units_train2 : int
153+
The total count of unique units in the second spike train.
154+
delta_frames : int
155+
The inclusive upper limit on the frame difference for which two spikes are considered matching. That is
156+
if `abs(spike_frames_train1[i] - spike_frames_train2[j]) <= delta_frames` then the spikes at `spike_frames_train1[i]`
157+
and `spike_frames_train2[j]` are considered matching.
158+
159+
Returns
160+
-------
161+
matching_matrix : ndarray
162+
A 2D numpy array of shape `(num_units_train1, num_units_train2)`
163+
164+
"""
135165
matching_matrix = np.zeros((num_units_train1, num_units_train2), dtype=np.uint16)
136166

137167
# Used to avoid the same spike matching twice
@@ -176,7 +206,7 @@ def compute_matching_matrix(
176206
return compute_matching_matrix
177207

178208

179-
def make_match_count_matrix(sorting1, sorting2, delta_frames, symmetric=False):
209+
def make_match_count_matrix(sorting1, sorting2, delta_frames, ensure_symmetry=False):
180210
"""
181211
Computes a matrix representing the matches between two Sorting objects.
182212
@@ -194,11 +224,11 @@ def make_match_count_matrix(sorting1, sorting2, delta_frames, symmetric=False):
194224
An array of integer frame numbers corresponding to spike times for the second train. Must be in ascending order.
195225
delta_frames : int
196226
The inclusive upper limit on the frame difference for which two spikes are considered matching. That is
197-
if `abs(spike_frames_train1[i] - spike_frames_train2[j]) <= delta_frames` then the spikes at `spike_frames_train1[i]`
198-
and `spike_frames_train2[j]` are considered matching.
199-
symmetric: bool, dfault False
200-
If symmetric, the this the algos is run two times by switching sorting1 and sorting2 the minimum of the two
201-
results is taken.
227+
if `abs(spike_frames_train1[i] - spike_frames_train2[j]) <= delta_frames` then the spikes at
228+
`spike_frames_train1[i]` and `spike_frames_train2[j]` are considered matching.
229+
ensure_symmetry: bool, default False
230+
If ensure_symmetry=True, then the algo is run two times by switching sorting1 and sorting2.
231+
And the minimum of the two results is taken.
202232
Returns
203233
-------
204234
matching_matrix : ndarray
@@ -221,11 +251,12 @@ def make_match_count_matrix(sorting1, sorting2, delta_frames, symmetric=False):
221251
3. Save the index of the first match as the new `second_train_search_start `
222252
3. For each match, find as many matches as possible from the first match onwards.
223253
224-
An important condition is that the same spike is not matched twice. This is managed by keeping track
254+
An important condition here is that the same spike is not matched twice. This is managed by keeping track
225255
of the last matched frame for each unit pair in `last_match_frame1` and `last_match_frame2`
226-
There are corner cases where a spike can be counted twice in the the spiketrain 2 in case of bursting situations
227-
(below delta_frames) in the spiketrain 1. To ensure that the number of match do not exceed the number of spike,
228-
we applied a final clip.
256+
There are corner cases where a spike can be counted twice in the spiketrain 2 if there are bouts of bursting activity
257+
(below delta_frames) in the spiketrain 1. To ensure that the number of matches does not exceed the number of spikes,
258+
we apply a final clip.
259+
229260
230261
For more details on the rationale behind this approach, refer to the documentation of this module and/or
231262
the metrics section in SpikeForest documentation.
@@ -265,7 +296,7 @@ def make_match_count_matrix(sorting1, sorting2, delta_frames, symmetric=False):
265296
delta_frames,
266297
)
267298

268-
if symmetric:
299+
if ensure_symmetry:
269300
matching_matrix_seg_switch = get_optimized_compute_matching_matrix()(
270301
sample_frames2_sorted,
271302
sample_frames1_sorted,
@@ -327,7 +358,7 @@ def make_agreement_scores(sorting1, sorting2, delta_frames):
327358
event_counts1 = pd.Series(ev_counts1, index=unit1_ids)
328359
event_counts2 = pd.Series(ev_counts2, index=unit2_ids)
329360

330-
match_event_count = make_match_count_matrix(sorting1, sorting2, delta_frames)
361+
match_event_count = make_match_count_matrix(sorting1, sorting2, delta_frames, ensure_symmetry=True)
331362

332363
agreement_scores = make_agreement_scores_from_count(match_event_count, event_counts1, event_counts2)
333364

src/spikeinterface/comparison/paircomparisons.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def __init__(
2828
delta_time=0.4,
2929
match_score=0.5,
3030
chance_score=0.1,
31-
symmetric=False,
31+
ensure_symmetry=False,
3232
n_jobs=1,
3333
verbose=False,
3434
):
@@ -56,7 +56,7 @@ def __init__(
5656
self.unit1_ids = self.sorting1.get_unit_ids()
5757
self.unit2_ids = self.sorting2.get_unit_ids()
5858

59-
self.symmetric = symmetric
59+
self.ensure_symmetry = ensure_symmetry
6060

6161
self._do_agreement()
6262
self._do_matching()
@@ -88,7 +88,7 @@ def _do_agreement(self):
8888

8989
# matrix of event match count for each pair
9090
self.match_event_count = make_match_count_matrix(
91-
self.sorting1, self.sorting2, self.delta_frames, symmetric=self.symmetric
91+
self.sorting1, self.sorting2, self.delta_frames, ensure_symmetry=self.ensure_symmetry
9292
)
9393

9494
# agreement matrix score for each pair
@@ -156,7 +156,7 @@ def __init__(
156156
delta_time=delta_time,
157157
match_score=match_score,
158158
chance_score=chance_score,
159-
symmetric=True,
159+
ensure_symmetry=True,
160160
n_jobs=n_jobs,
161161
verbose=verbose,
162162
)
@@ -289,7 +289,7 @@ def __init__(
289289
delta_time=delta_time,
290290
match_score=match_score,
291291
chance_score=chance_score,
292-
symmetric=False,
292+
ensure_symmetry=False,
293293
n_jobs=n_jobs,
294294
verbose=verbose,
295295
)

src/spikeinterface/comparison/tests/test_comparisontools.py

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -154,17 +154,17 @@ def test_make_match_count_matrix_repeated_matching_but_no_double_counting_2():
154154
sorting1, sorting2 = make_sorting(frames_spike_train1, unit_indices1, frames_spike_train2, unit_indices2)
155155

156156
# this is easy because it is sorting2 centric
157-
result = make_match_count_matrix(sorting2, sorting1, delta_frames=delta_frames, symmetric=False)
157+
result = make_match_count_matrix(sorting2, sorting1, delta_frames=delta_frames, ensure_symmetry=False)
158158
expected_result = np.array([[2]])
159159
assert_array_equal(result.to_numpy(), expected_result)
160160

161161
# this work only because we protect by clipping
162-
result = make_match_count_matrix(sorting1, sorting2, delta_frames=delta_frames, symmetric=False)
162+
result = make_match_count_matrix(sorting1, sorting2, delta_frames=delta_frames, ensure_symmetry=False)
163163
expected_result = np.array([[2]])
164164
assert_array_equal(result.to_numpy(), expected_result)
165165

166166

167-
def test_make_match_count_matrix_symmetric():
167+
def test_make_match_count_matrix_ensure_symmetry():
168168
frames_spike_train1 = [
169169
100,
170170
102,
@@ -179,8 +179,8 @@ def test_make_match_count_matrix_symmetric():
179179

180180
sorting1, sorting2 = make_sorting(frames_spike_train1, unit_indices1, frames_spike_train2, unit_indices2)
181181

182-
result = make_match_count_matrix(sorting1, sorting2, delta_frames=delta_frames, symmetric=True)
183-
result_T = make_match_count_matrix(sorting2, sorting1, delta_frames=delta_frames, symmetric=True)
182+
result = make_match_count_matrix(sorting1, sorting2, delta_frames=delta_frames, ensure_symmetry=True)
183+
result_T = make_match_count_matrix(sorting2, sorting1, delta_frames=delta_frames, ensure_symmetry=True)
184184

185185
assert_array_equal(result.T, result_T)
186186

@@ -481,23 +481,23 @@ def test_do_count_score_and_perf():
481481

482482

483483
if __name__ == "__main__":
484-
# test_make_match_count_matrix()
485-
# test_make_match_count_matrix_sorting_with_itself_simple()
486-
# test_make_match_count_matrix_sorting_with_itself_longer()
487-
# test_make_match_count_matrix_with_mismatched_sortings()
488-
# test_make_match_count_matrix_no_double_matching()
489-
# test_make_match_count_matrix_repeated_matching_but_no_double_counting()
490-
# test_make_match_count_matrix_repeated_matching_but_no_double_counting_2()
491-
# test_make_match_count_matrix_test_proper_search_in_the_second_train()
492-
test_make_match_count_matrix_symmetric()
493-
494-
# test_make_agreement_scores()
495-
496-
# test_make_possible_match()
497-
# test_make_best_match()
498-
# test_make_hungarian_match()
499-
500-
# test_do_score_labels()
501-
# test_compare_spike_trains()
502-
# test_do_confusion_matrix()
503-
# test_do_count_score_and_perf()
484+
test_make_match_count_matrix()
485+
test_make_match_count_matrix_sorting_with_itself_simple()
486+
test_make_match_count_matrix_sorting_with_itself_longer()
487+
test_make_match_count_matrix_with_mismatched_sortings()
488+
test_make_match_count_matrix_no_double_matching()
489+
test_make_match_count_matrix_repeated_matching_but_no_double_counting()
490+
test_make_match_count_matrix_repeated_matching_but_no_double_counting_2()
491+
test_make_match_count_matrix_test_proper_search_in_the_second_train()
492+
test_make_match_count_matrix_ensure_symmetry()
493+
494+
test_make_agreement_scores()
495+
496+
test_make_possible_match()
497+
test_make_best_match()
498+
test_make_hungarian_match()
499+
500+
test_do_score_labels()
501+
test_compare_spike_trains()
502+
test_do_confusion_matrix()
503+
test_do_count_score_and_perf()

0 commit comments

Comments
 (0)