Skip to content

Commit 23906aa

Browse files
authored
Merge pull request #4113 from samuelgarcia/isosplit
Implement isosplit6 into spikeinterface in pure numpy/numba
2 parents b771821 + 715944c commit 23906aa

13 files changed

Lines changed: 865 additions & 373 deletions

File tree

src/spikeinterface/extractors/phykilosortextractors.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class BasePhyKilosortSortingExtractor(BaseSorting):
4040
The cluster_id column is used as the merge key to combine properties from multiple files.
4141
All loaded properties are added to the sorting extractor as unit properties, with some
4242
renamed for SpikeInterface conventions: 'group' becomes 'quality', 'cluster_id'
43-
becomes 'original_cluster_id'. These properties can be accessed via ``sorting.get_property()``
43+
becomes 'original_cluster_id'. These properties can be accessed via ``sorting.get_property()``
4444
function.
4545
"""
4646

src/spikeinterface/sorters/internal/tridesclous2.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,22 @@ class Tridesclous2Sorter(ComponentsBasedSorter):
5757
# "allow_single_cluster": True,
5858
# "cluster_selection_method": "eom",
5959
# },
60-
"clusterer": "isosplit6",
61-
"clusterer_kwargs": {},
60+
# "clusterer": "isosplit6",
61+
# "clusterer_kwargs": {},
62+
"clusterer": "isosplit",
63+
"clusterer_kwargs": {
64+
"n_init": 50,
65+
"min_cluster_size": 10,
66+
"max_iterations_per_pass": 500,
67+
"isocut_threshold": 2.0,
68+
},
6269
"do_merge": True,
6370
"merge_kwargs": {
6471
"similarity_metric": "l1",
6572
"num_shifts": 4,
6673
"similarity_thresh": 0.75,
6774
},
75+
"min_size_split": 25,
6876
},
6977
"templates": {
7078
"ms_before": 2.0,
@@ -98,7 +106,7 @@ class Tridesclous2Sorter(ComponentsBasedSorter):
98106

99107
@classmethod
100108
def get_sorter_version(cls):
101-
return "2025.07"
109+
return "2025.08"
102110

103111
@classmethod
104112
def _run_from_folder(cls, sorter_output_folder, params, verbose):
@@ -194,20 +202,11 @@ def _run_from_folder(cls, sorter_output_folder, params, verbose):
194202
clustering_kwargs["clustering"] = params["clustering"].copy()
195203

196204
if clustering_kwargs["clustering"]["clusterer"] == "isosplit6":
197-
# this is a patch to make the github CI because isosplit is installable on python > 3.11
198205
have_sisosplit6 = importlib.util.find_spec("isosplit6") is not None
199206
if not have_sisosplit6:
200-
if verbose:
201-
print(
202-
"By default tridesclous2 need isosplit6 package for better reults please install it, automatically switch to hdbscan instead"
203-
)
204-
clustering_kwargs["clustering"]["clusterer"] = "hdbscan"
205-
clustering_kwargs["clustering"]["clusterer_kwargs"] = {
206-
"min_cluster_size": 10,
207-
"min_samples": 1,
208-
"allow_single_cluster": True,
209-
"cluster_selection_method": "eom",
210-
}
207+
raise ValueError(
208+
"You want to run tridesclous2 with the isosplit6 (the C++) implementation, but this is not installed, please `pip install isosplit6`"
209+
)
211210

212211
unit_ids, clustering_label, more_outs = find_cluster_from_peaks(
213212
recording, peaks, method="tdc-clustering", method_kwargs=clustering_kwargs, extra_outputs=True, **job_kwargs

src/spikeinterface/sortingcomponents/clustering/circus.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class CircusClustering:
3131
"""
3232

3333
_default_params = {
34-
"clusterer": "hdbscan", # 'isosplit6', 'hdbscan', 'isocut5'
34+
"clusterer": "hdbscan", # 'isosplit6', 'hdbscan', 'isosplit'
3535
"clusterer_kwargs": {
3636
"min_cluster_size": 20,
3737
"cluster_selection_epsilon": 0.5,
@@ -77,8 +77,8 @@ def main_function(cls, recording, peaks, params, job_kwargs=dict()):
7777
assert clusterer in [
7878
"isosplit6",
7979
"hdbscan",
80-
"isocut5",
81-
], "Circus clustering only supports isosplit6, isocut5 or hdbscan"
80+
"isosplit",
81+
], "Circus clustering only supports isosplit6, isosplit or hdbscan"
8282
if clusterer in ["isosplit6", "hdbscan"]:
8383
have_dep = importlib.util.find_spec(clusterer) is not None
8484
if not have_dep:

src/spikeinterface/sortingcomponents/clustering/clustering_tools.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -682,10 +682,10 @@ def remove_duplicates_via_matching(
682682
return labels, new_labels
683683

684684

685-
def remove_duplicates_via_dip(wfs_arrays, peak_labels, dip_threshold=1, cosine_threshold=None):
685+
def remove_duplicates_via_dip(wfs_arrays, peak_labels, dip_threshold=2.0, cosine_threshold=None):
686686
import sklearn
687687

688-
from spikeinterface.sortingcomponents.clustering.isocut5 import isocut5
688+
from spikeinterface.sortingcomponents.clustering.isosplit_isocut import isocut
689689

690690
new_labels = peak_labels.copy()
691691

@@ -756,7 +756,7 @@ def remove_duplicates_via_dip(wfs_arrays, peak_labels, dip_threshold=1, cosine_t
756756
v = t_i - t_j
757757
pr_i = np.dot(data_i, v)
758758
pr_j = np.dot(data_j, v)
759-
diptest, _ = isocut5(np.concatenate((pr_i, pr_j)))
759+
diptest, _ = isocut(np.concatenate((pr_i, pr_j)))
760760
diptests[i][j] = diptest
761761

762762
if diptest < min_dip:

src/spikeinterface/sortingcomponents/clustering/isocut5.py

Lines changed: 0 additions & 211 deletions
This file was deleted.

0 commit comments

Comments
 (0)