Skip to content

Commit 4b58406

Browse files
committed
Allow for all id strategies
1 parent ed6dba0 commit 4b58406

2 files changed

Lines changed: 57 additions & 32 deletions

File tree

src/spikeinterface/postprocessing/correlograms.py

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,42 @@ def _merge_extension_data(
133133
new_data = dict(ccgs=new_ccgs, bins=new_bins)
134134
else:
135135

136+
# First, we make a transformation matrix, which tells us how unit_indices from the
137+
# old to the new sorter are mapped. The i-th original unit_index gets mapped to the
138+
# j-th new unit_index; where j is the only non-zero element of the matrix. To help
139+
# construct the matrix we first make a dictionary of the form {old_index: new_index}
140+
old_to_new_unit_index_map = {}
141+
for old_unit in self.sorting_analyzer.unit_ids:
142+
unit_involved_in_merge = False
143+
for merge_unit_group, new_unit_id in zip(merge_unit_groups, new_unit_ids):
144+
# check if the old_unit is involved in a merge
145+
if old_unit in merge_unit_group:
146+
# check if it is mapped to itself?
147+
if old_unit == new_unit_id:
148+
old_to_new_unit_index_map[self.sorting_analyzer.sorting.id_to_index(old_unit)] = (
149+
new_sorting_analyzer.sorting.id_to_index(new_unit_id)
150+
)
151+
# or to a unit_id outwith the old ones
152+
elif new_unit_id not in self.sorting_analyzer.unit_ids:
153+
if (
154+
new_sorting_analyzer.sorting.id_to_index(new_unit_id)
155+
not in old_to_new_unit_index_map.values()
156+
):
157+
old_to_new_unit_index_map[self.sorting_analyzer.sorting.id_to_index(old_unit)] = (
158+
new_sorting_analyzer.sorting.id_to_index(new_unit_id)
159+
)
160+
unit_involved_in_merge = True
161+
if unit_involved_in_merge is False:
162+
old_to_new_unit_index_map[self.sorting_analyzer.sorting.id_to_index(old_unit)] = (
163+
new_sorting_analyzer.sorting.id_to_index(old_unit)
164+
)
165+
166+
transformation_matrix = np.zeros(
167+
(len(new_sorting_analyzer.unit_ids), len(self.sorting_analyzer.unit_ids)), dtype="int"
168+
)
169+
for col, row in old_to_new_unit_index_map.items():
170+
transformation_matrix[row][col] = 1
171+
136172
need_to_append = False
137173
delete_from = 1
138174

@@ -145,40 +181,22 @@ def _merge_extension_data(
145181
# Sum unit rows of the correlogram matrix: C_{k,l} = C_{i,l} + C_{j,l}
146182
# and place this sum in the first unit index from the merge group
147183
new_col = np.sum(correlograms[merge_unit_group_indices, :, :], axis=0)
148-
correlograms[merge_unit_group_indices[0], :, :] = new_col
149-
correlograms[merge_unit_group_indices[1:], :, :] = 0
184+
# correlograms[merge_unit_group_indices[0], :, :] = new_col
185+
correlograms[merge_unit_group_indices, :, :] = new_col
186+
# correlograms[merge_unit_group_indices[1:], :, :] = 0
150187

151188
# Sum unit columns of the correlogram matrix: C_{l,k} = C_{l,i} + C_{l,j}
152189
# and put this sum in the first unit index from the merge group
153190
new_row = np.sum(correlograms[:, merge_unit_group_indices, :], axis=1)
154-
correlograms[:, merge_unit_group_indices[0], :] = new_row
155-
correlograms[:, merge_unit_group_indices[1:], :] = 0
156-
157-
if new_unit_id not in merge_unit_group:
158-
need_to_append = True
159-
delete_from = 0
160-
161-
# When new_id_strategy='append' is used, the new summed rows/columns to the
162-
# end of the correlogram matrix
163-
if need_to_append is True:
164-
old_num_units = np.shape(correlograms)[0]
165-
correlograms = np.pad(correlograms, ((0, len(new_unit_ids)), (0, len(new_unit_ids)), (0, 0)))
166-
for a, (new_unit_id, merge_unit_group) in enumerate(zip(new_unit_ids, merge_unit_groups)):
167-
168-
old_loc = self.sorting_analyzer.sorting.ids_to_indices([merge_unit_group[0]])[0]
169-
new_loc = old_num_units + a
170-
171-
correlograms[:, [old_loc, new_loc], :] = correlograms[:, [new_loc, old_loc], :]
172-
correlograms[[old_loc, new_loc], :, :] = correlograms[[new_loc, old_loc], :, :]
173191

174-
# Delete the leftover units from the merge
175-
units_to_delete = np.concatenate([merge_unit_group[delete_from:] for merge_unit_group in merge_unit_groups])
176-
indices_to_delete = self.sorting_analyzer.sorting.ids_to_indices(units_to_delete)
192+
for merge_unit_group_index in merge_unit_group_indices:
193+
correlograms[:, merge_unit_group_index, :] = new_row
177194

178-
correlograms = np.delete(correlograms, indices_to_delete, axis=0)
179-
correlograms = np.delete(correlograms, indices_to_delete, axis=1)
195+
# The new correlograms are in the old unit_id order. Hence we must transform
196+
# to the new unit_id order using a change of basis operation: C -> TCT^T
197+
new_correlograms = np.einsum("ij,jkz,lk->ilz", transformation_matrix, correlograms, transformation_matrix)
180198

181-
new_data = dict(ccgs=correlograms, bins=new_bins)
199+
new_data = dict(ccgs=new_correlograms, bins=new_bins)
182200
return new_data
183201

184202
def _run(self, verbose=False):

src/spikeinterface/postprocessing/tests/test_extension_merges.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,20 @@ def test_correlograms_merge():
2222
[["4", "1", "8"], ["2", "7", "0"], ["3", "9"], ["5", "6"]],
2323
]
2424

25-
for new_id_strategy in ["append", "take_first"]:
26-
for merge_unit_groups in trial_merges:
25+
new_unit_ids = [["2"], ["4"], ["4", "2"], ["1", "2", "3", "100"]]
26+
27+
for new_id_strategy in ["append", "take_first", "user"]:
28+
for merge_unit_groups, new_unit_id in zip(trial_merges, new_unit_ids):
2729

2830
# first, compute the correlograms of the merged units using the merge method
29-
merged_sorting_analyzer = sorting_analyzer.merge_units(
30-
merge_unit_groups=merge_unit_groups, new_id_strategy=new_id_strategy
31-
)
31+
if new_id_strategy == "user":
32+
merged_sorting_analyzer = sorting_analyzer.merge_units(
33+
merge_unit_groups=merge_unit_groups, new_unit_ids=new_unit_id
34+
)
35+
else:
36+
merged_sorting_analyzer = sorting_analyzer.merge_units(
37+
merge_unit_groups=merge_unit_groups, new_id_strategy=new_id_strategy
38+
)
3239
computed_correlograms = merged_sorting_analyzer.get_extension("correlograms").get_data()
3340

3441
# Then re-compute, and compare

0 commit comments

Comments
 (0)