From 7847567945055c5a9f42f78f3462ccb344b5545f Mon Sep 17 00:00:00 2001 From: Pierre Yger Date: Wed, 17 Dec 2025 16:38:59 +0100 Subject: [PATCH 1/6] Docs --- doc/get_started/install_sorters.rst | 20 +++++++++++++++++--- doc/how_to/analyze_neuropixels.rst | 2 +- doc/modules/sorters.rst | 5 +++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/doc/get_started/install_sorters.rst b/doc/get_started/install_sorters.rst index 82bef42c14..fa3d883da9 100644 --- a/doc/get_started/install_sorters.rst +++ b/doc/get_started/install_sorters.rst @@ -284,7 +284,7 @@ working not only at peak times but at all times, recovering more spikes close to pip install hdbscan pip install spikeinterface - pip install numba (or conda install numba as recommended by conda authors) + pip install numba (or conda install numba as recommended by conda authors) Tridesclous2 @@ -294,11 +294,25 @@ This is an upgraded version of Tridesclous, natively written in SpikeInterface. * Python -* Requires: HDBSCAN and Numba +* Requires: Numba * Authors: Samuel Garcia * Installation:: - pip install hdbscan + pip install spikeinterface + pip install numba + + +Lupin +^^^^^ + +This is a representative spike sorting pipeline, natively written in SpikeInterface. + + +* Python +* Requires: Numba +* Authors: Samuel Garcia & Pierre Yger +* Installation:: + pip install spikeinterface pip install numba diff --git a/doc/how_to/analyze_neuropixels.rst b/doc/how_to/analyze_neuropixels.rst index a1a1a6b8e2..fb37441ab3 100644 --- a/doc/how_to/analyze_neuropixels.rst +++ b/doc/how_to/analyze_neuropixels.rst @@ -516,7 +516,7 @@ pipeline, in SpikeInterface this is dead-simple: one function. - most of sorters are wrapped from external tools (kilosort, kisolort2.5, spykingcircus, montainsort4 …) that often also need other requirements (e.g., MATLAB, CUDA) -- some sorters are internally developed (spyekingcircus2) +- some sorters are internally developed (spykingcircus2, tridesclous2, lupin) - external sorter can be run inside a container (docker, singularity) WITHOUT pre-installation diff --git a/doc/modules/sorters.rst b/doc/modules/sorters.rst index 78ac514b6d..83475bf6a7 100644 --- a/doc/modules/sorters.rst +++ b/doc/modules/sorters.rst @@ -546,8 +546,9 @@ Internal sorters In 2022, we started the :py:mod:`spikeinterface.sortingcomponents` module to break into components a sorting pipeline. These components can be gathered to create a new sorter. We already have 2 sorters to showcase this new module: -* :code:`spykingcircus2` (experimental, but ready to be tested) -* :code:`tridesclous2` (experimental, not ready to be used) +* :code:`spykingcircus2` +* :code:`tridesclous2` +* :code:`lupin` There are some benefits of using these sorters: * they directly handle SpikeInterface objects, so they do not need any data copy. From 7a95892116e8ab90e2708aaf08455bdaa6c2d0aa Mon Sep 17 00:00:00 2001 From: Pierre Yger Date: Wed, 17 Dec 2025 16:43:24 +0100 Subject: [PATCH 2/6] WIP --- src/spikeinterface/sorters/internal/lupin.py | 39 ++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/spikeinterface/sorters/internal/lupin.py b/src/spikeinterface/sorters/internal/lupin.py index 40bf32e005..8781c7b50d 100644 --- a/src/spikeinterface/sorters/internal/lupin.py +++ b/src/spikeinterface/sorters/internal/lupin.py @@ -125,6 +125,45 @@ def _run_from_folder(cls, sorter_output_folder, params, verbose): apply_cmr = num_chans >= 32 + if verbose: + version = cls.get_sorter_version() + lupin_ascii_art = f""" + ................. + ..::=+##%%%%%@@@@@@@%%@@@%+-.. + .+@@@+:=%@@@@@@@@@@@@@@@# ....-@@+. + .+@@**%@@@@@@@@@@@@@@@@@@@@@@:. ..@@=. + -@@%@@@@@@@@@@@@@@@@@@@@@@@@@@-. .=@@+. + *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+.. .:@@*. + =@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*=. ..%@#. + .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@**. .#@#. + .#@*@@@@@@@@@@@@@@@@@@@@@@@@%@#+- .*@%. + =@*@@@@@@@@@@@@@@@@@@@@@@@@#@%== .##@. + .@%%@@@@@@@@@@@@@@@@@@@@@@@#@%-*. .#*@. + .%@#@@@@@@@@@@@@@@@@@@@@@@@#@@:#. .*+@. + .*@*@@@@@@@@@@@@@@@@@@@@@@@#%@:#. .++@: + .=@+@@@@@@@@@@@@@@@@@@@@@@@%#@-#. .=*@- + :@+%@@@@@@@@@@@@@@@@@@@@@@%+@+#. .-%%= + .@%+@@@@@@@@@@@@@@@@@@@@@@@=@**: .:@%+ + .+@-%@@@@@@@@@@@@@@@@@@@@@@-@%+- ..@%* + .:@++@@@@@@@@@@@@@@@@@@@@@@=@@=+ %%%. + ..@%+*@@@@@@@@@@@@@@@@@@@@@*%@=* *@%. + .#@%++#@@@@@@@@@@@@@@@@@@@%#@-* +@@. + .*@@%*#@@@@@@@@@@@@@@@@@@@@%@=+ -@@: + ...-+**+-+@@@@@@@@@@@@@@@@@@@@@@@@=: :@@- ........ + -%###%%#*+*@@%##@@@@@@@@@@@@@@@@@@#. .=@%%@@@@@@@@%+. + ..#%%@@@@@@@@@@%++#@@@@@@@@@@@@@@@@@+==+*#@@@@##@@@@@@@@@@@@@: + .%@@@@@@@@@@@@@@@@@%==#@@@@@@@@@@%%%#*+=:..::-.:@@@@@@@@@#@#@= + -@%@@@@@@@@@@@@@@@@@@@@%:+@@@*.:=*####%@@*:-#:..@@@@@@@@@%*#@= + .=@**@@@@@@@@@@@@@@@@@@@@@@@+-#@@%+..........:=*%@@@@@@@@@#%%@: + .-@%@@@@@@@@@@@@@@@@@@@@@@@@@@@#=+%@@#%@@#****#@@@@@@@@@@%##@- + .#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+=+%@@@@@@@@@@@@@@@@@@*%@-. + *@@@@@@@@@@@@@@@@@@@@@@%#+-:. ..:=*+:=#@@@@@@@@@@@@+#@* + ..#@@@@@@@@@@@@@@@*:.. ..+@#+=---+#@@@-. + ..:+%@@@@@@@*-... .....:::::.... + LUPIN version {version} + """ + print(lupin_ascii_art) + # preprocessing if params["apply_preprocessing"]: if params["apply_motion_correction"]: From 8407b1ba17b369c4afd276b7dd6ffdfef701552a Mon Sep 17 00:00:00 2001 From: Pierre Yger Date: Thu, 18 Dec 2025 10:07:36 +0100 Subject: [PATCH 3/6] Ascii art --- src/spikeinterface/sorters/internal/lupin.py | 55 ++++++++------------ 1 file changed, 22 insertions(+), 33 deletions(-) diff --git a/src/spikeinterface/sorters/internal/lupin.py b/src/spikeinterface/sorters/internal/lupin.py index 8781c7b50d..dd33c28ca6 100644 --- a/src/spikeinterface/sorters/internal/lupin.py +++ b/src/spikeinterface/sorters/internal/lupin.py @@ -128,39 +128,28 @@ def _run_from_folder(cls, sorter_output_folder, params, verbose): if verbose: version = cls.get_sorter_version() lupin_ascii_art = f""" - ................. - ..::=+##%%%%%@@@@@@@%%@@@%+-.. - .+@@@+:=%@@@@@@@@@@@@@@@# ....-@@+. - .+@@**%@@@@@@@@@@@@@@@@@@@@@@:. ..@@=. - -@@%@@@@@@@@@@@@@@@@@@@@@@@@@@-. .=@@+. - *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+.. .:@@*. - =@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*=. ..%@#. - .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@**. .#@#. - .#@*@@@@@@@@@@@@@@@@@@@@@@@@%@#+- .*@%. - =@*@@@@@@@@@@@@@@@@@@@@@@@@#@%== .##@. - .@%%@@@@@@@@@@@@@@@@@@@@@@@#@%-*. .#*@. - .%@#@@@@@@@@@@@@@@@@@@@@@@@#@@:#. .*+@. - .*@*@@@@@@@@@@@@@@@@@@@@@@@#%@:#. .++@: - .=@+@@@@@@@@@@@@@@@@@@@@@@@%#@-#. .=*@- - :@+%@@@@@@@@@@@@@@@@@@@@@@%+@+#. .-%%= - .@%+@@@@@@@@@@@@@@@@@@@@@@@=@**: .:@%+ - .+@-%@@@@@@@@@@@@@@@@@@@@@@-@%+- ..@%* - .:@++@@@@@@@@@@@@@@@@@@@@@@=@@=+ %%%. - ..@%+*@@@@@@@@@@@@@@@@@@@@@*%@=* *@%. - .#@%++#@@@@@@@@@@@@@@@@@@@%#@-* +@@. - .*@@%*#@@@@@@@@@@@@@@@@@@@@%@=+ -@@: - ...-+**+-+@@@@@@@@@@@@@@@@@@@@@@@@=: :@@- ........ - -%###%%#*+*@@%##@@@@@@@@@@@@@@@@@@#. .=@%%@@@@@@@@%+. - ..#%%@@@@@@@@@@%++#@@@@@@@@@@@@@@@@@+==+*#@@@@##@@@@@@@@@@@@@: - .%@@@@@@@@@@@@@@@@@%==#@@@@@@@@@@%%%#*+=:..::-.:@@@@@@@@@#@#@= - -@%@@@@@@@@@@@@@@@@@@@@%:+@@@*.:=*####%@@*:-#:..@@@@@@@@@%*#@= - .=@**@@@@@@@@@@@@@@@@@@@@@@@+-#@@%+..........:=*%@@@@@@@@@#%%@: - .-@%@@@@@@@@@@@@@@@@@@@@@@@@@@@#=+%@@#%@@#****#@@@@@@@@@@%##@- - .#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+=+%@@@@@@@@@@@@@@@@@@*%@-. - *@@@@@@@@@@@@@@@@@@@@@@%#+-:. ..:=*+:=#@@@@@@@@@@@@+#@* - ..#@@@@@@@@@@@@@@@*:.. ..+@#+=---+#@@@-. - ..:+%@@@@@@@*-... .....:::::.... - LUPIN version {version} + .::----::.. + ..:-+#%*+#%@@@@@@@+..:+#+. + .+@%%@@@@@@@@@@@@@@#: .=@= + -@@@@@@@@@@@@@@@@@@%-. .=@* + .@@@@@@@@@@@@@@@@@@@*. .-%# + %@@@@@@@@@@@@@@@@@@*. :#% + =%%@@@@@@@@@@@@@@%%+: .+@. + -%#@@@@@@@@@@@@@@%*== .-@. + :#%@@@@@@@@@@@@@@%#+# .=@. + .+%@@@@@@@@@@@@@@@%#@. .+@. + .+*#@@@@@@@@@@@@@@@%@. .+@: + .=%+@@@@@@@@@@@@@@@@*. =%-. + :#%##@@@@@@@@@@@@%%-. :%+. + ..:=**%@@@@@@@@@@@@@@@:. .%%...... + .+#@%%%@**@%@@@@@@@@@@@*....=%@%@@@@@%=.. + .*@@@@@@@@@@@=#@@@@@@@@@@*=:.:.#@@@@@@%%-. + .-%%@@@@@@@@@@@@@#+%@+-::-+=:=::+@@@@@@##-. + .:%@@@@@@@@@@@@@@@@@%+%##*%%%**%@@@@@@##+. + .+@@@@@@@@@@@@@@@@#***++***@@@@@@@@%%%=. + .:*@@@@@@@@%=-..... ....:-*%%%%%+-. + ..:-:.. + LUPIN version {version} """ print(lupin_ascii_art) From 2eda3dfea65920e882d17f3a0e755895aa96029b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:10:32 +0000 Subject: [PATCH 4/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/spikeinterface/sorters/internal/lupin.py | 46 ++++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/spikeinterface/sorters/internal/lupin.py b/src/spikeinterface/sorters/internal/lupin.py index dd33c28ca6..c35facaf11 100644 --- a/src/spikeinterface/sorters/internal/lupin.py +++ b/src/spikeinterface/sorters/internal/lupin.py @@ -127,32 +127,32 @@ def _run_from_folder(cls, sorter_output_folder, params, verbose): if verbose: version = cls.get_sorter_version() - lupin_ascii_art = f""" - .::----::.. - ..:-+#%*+#%@@@@@@@+..:+#+. - .+@%%@@@@@@@@@@@@@@#: .=@= - -@@@@@@@@@@@@@@@@@@%-. .=@* - .@@@@@@@@@@@@@@@@@@@*. .-%# - %@@@@@@@@@@@@@@@@@@*. :#% - =%%@@@@@@@@@@@@@@%%+: .+@. - -%#@@@@@@@@@@@@@@%*== .-@. - :#%@@@@@@@@@@@@@@%#+# .=@. - .+%@@@@@@@@@@@@@@@%#@. .+@. - .+*#@@@@@@@@@@@@@@@%@. .+@: - .=%+@@@@@@@@@@@@@@@@*. =%-. - :#%##@@@@@@@@@@@@%%-. :%+. - ..:=**%@@@@@@@@@@@@@@@:. .%%...... - .+#@%%%@**@%@@@@@@@@@@@*....=%@%@@@@@%=.. - .*@@@@@@@@@@@=#@@@@@@@@@@*=:.:.#@@@@@@%%-. - .-%%@@@@@@@@@@@@@#+%@+-::-+=:=::+@@@@@@##-. - .:%@@@@@@@@@@@@@@@@@%+%##*%%%**%@@@@@@##+. - .+@@@@@@@@@@@@@@@@#***++***@@@@@@@@%%%=. - .:*@@@@@@@@%=-..... ....:-*%%%%%+-. - ..:-:.. + lupin_ascii_art = f""" + .::----::.. + ..:-+#%*+#%@@@@@@@+..:+#+. + .+@%%@@@@@@@@@@@@@@#: .=@= + -@@@@@@@@@@@@@@@@@@%-. .=@* + .@@@@@@@@@@@@@@@@@@@*. .-%# + %@@@@@@@@@@@@@@@@@@*. :#% + =%%@@@@@@@@@@@@@@%%+: .+@. + -%#@@@@@@@@@@@@@@%*== .-@. + :#%@@@@@@@@@@@@@@%#+# .=@. + .+%@@@@@@@@@@@@@@@%#@. .+@. + .+*#@@@@@@@@@@@@@@@%@. .+@: + .=%+@@@@@@@@@@@@@@@@*. =%-. + :#%##@@@@@@@@@@@@%%-. :%+. + ..:=**%@@@@@@@@@@@@@@@:. .%%...... + .+#@%%%@**@%@@@@@@@@@@@*....=%@%@@@@@%=.. + .*@@@@@@@@@@@=#@@@@@@@@@@*=:.:.#@@@@@@%%-. + .-%%@@@@@@@@@@@@@#+%@+-::-+=:=::+@@@@@@##-. + .:%@@@@@@@@@@@@@@@@@%+%##*%%%**%@@@@@@##+. + .+@@@@@@@@@@@@@@@@#***++***@@@@@@@@%%%=. + .:*@@@@@@@@%=-..... ....:-*%%%%%+-. + ..:-:.. LUPIN version {version} """ print(lupin_ascii_art) - + # preprocessing if params["apply_preprocessing"]: if params["apply_motion_correction"]: From 61c881ef0ed48a763d3313b961062a1398f700b4 Mon Sep 17 00:00:00 2001 From: Pierre Yger Date: Thu, 18 Dec 2025 15:41:32 +0100 Subject: [PATCH 5/6] Docs --- doc/modules/sorters.rst | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/doc/modules/sorters.rst b/doc/modules/sorters.rst index 83475bf6a7..9897bf9a16 100644 --- a/doc/modules/sorters.rst +++ b/doc/modules/sorters.rst @@ -560,6 +560,37 @@ From the user's perspective, they behave exactly like the external sorters: .. code-block:: python sorting = run_sorter(sorter_name="spykingcircus2", recording=recording, folder="/tmp/folder") + +These sorters are based on the :py:mod:`spikeinterface.sortingcomponents`, allowing fast and modular implementations +of various algorithms often encountered in spike-sorting. + +SpyKING-CIRCUS 2 +^^^^^^^^^^^^^^^^ + +This is an updated version of SpyKING-CIRCUS \cite{yger2018spike} based on the modular +components. In summary, this spike sorting pipeline uses (when motion is present) the DREDGE motion +correction algorithm before filtering and whitening the data. On these whitened data, the chains of components +that are used are: matched filtering for peak detection, iterative splits for clustering (Iter-HDBSCAN), +and orthogonal matching pursuit for template reconstruction (Circus-OMP). + + +TriDesClous 2 +^^^^^^^^^^^^^ + +This is an updated version of TriDesClous based on the modular components. In summary, +the code uses (when motion is present) the DREDGE motion correction algorithm before filtering the data +. On these filtered data, the chains of components that are used are: locally exclusive for peak detection, +iterative splits for clustering (Iter-ISOPLIT), and fast greedy partial deconvolution, +only applied at peak times for template reconstruction (TDC-peeler). + +Lupin +^^^^^ + +In summary, the code uses (when motion is present) the DREDGE motion correction algorithm +before filtering and whitening the data. On these whitened data, the chains of components that are +used are: matched filtering for peak detection, iterative splits for clustering (Iter-ISOPLIT), +and augmented matching pursuit for the spike deconvolution (Wobble). + Read more in the :ref:`sorting-components-module` docs. From 114992c7b0c6d9f3fc649472fad652d5260e7db3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 14:42:01 +0000 Subject: [PATCH 6/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/modules/sorters.rst | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/doc/modules/sorters.rst b/doc/modules/sorters.rst index 9897bf9a16..972e77ad07 100644 --- a/doc/modules/sorters.rst +++ b/doc/modules/sorters.rst @@ -560,35 +560,35 @@ From the user's perspective, they behave exactly like the external sorters: .. code-block:: python sorting = run_sorter(sorter_name="spykingcircus2", recording=recording, folder="/tmp/folder") - + These sorters are based on the :py:mod:`spikeinterface.sortingcomponents`, allowing fast and modular implementations -of various algorithms often encountered in spike-sorting. +of various algorithms often encountered in spike-sorting. SpyKING-CIRCUS 2 ^^^^^^^^^^^^^^^^ -This is an updated version of SpyKING-CIRCUS \cite{yger2018spike} based on the modular -components. In summary, this spike sorting pipeline uses (when motion is present) the DREDGE motion -correction algorithm before filtering and whitening the data. On these whitened data, the chains of components -that are used are: matched filtering for peak detection, iterative splits for clustering (Iter-HDBSCAN), +This is an updated version of SpyKING-CIRCUS \cite{yger2018spike} based on the modular +components. In summary, this spike sorting pipeline uses (when motion is present) the DREDGE motion +correction algorithm before filtering and whitening the data. On these whitened data, the chains of components +that are used are: matched filtering for peak detection, iterative splits for clustering (Iter-HDBSCAN), and orthogonal matching pursuit for template reconstruction (Circus-OMP). TriDesClous 2 ^^^^^^^^^^^^^ -This is an updated version of TriDesClous based on the modular components. In summary, -the code uses (when motion is present) the DREDGE motion correction algorithm before filtering the data -. On these filtered data, the chains of components that are used are: locally exclusive for peak detection, -iterative splits for clustering (Iter-ISOPLIT), and fast greedy partial deconvolution, -only applied at peak times for template reconstruction (TDC-peeler). +This is an updated version of TriDesClous based on the modular components. In summary, +the code uses (when motion is present) the DREDGE motion correction algorithm before filtering the data +. On these filtered data, the chains of components that are used are: locally exclusive for peak detection, +iterative splits for clustering (Iter-ISOPLIT), and fast greedy partial deconvolution, +only applied at peak times for template reconstruction (TDC-peeler). Lupin ^^^^^ -In summary, the code uses (when motion is present) the DREDGE motion correction algorithm -before filtering and whitening the data. On these whitened data, the chains of components that are -used are: matched filtering for peak detection, iterative splits for clustering (Iter-ISOPLIT), +In summary, the code uses (when motion is present) the DREDGE motion correction algorithm +before filtering and whitening the data. On these whitened data, the chains of components that are +used are: matched filtering for peak detection, iterative splits for clustering (Iter-ISOPLIT), and augmented matching pursuit for the spike deconvolution (Wobble).