Skip to content

Commit ef3e820

Browse files
committed
Integrate the saturation detector
2 parents 5610518 + 02c940f commit ef3e820

File tree

103 files changed

+1514
-674
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+1514
-674
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ repos:
66
- id: end-of-file-fixer
77
- id: trailing-whitespace
88
- repo: https://github.com/psf/black-pre-commit-mirror
9-
rev: 25.12.0
9+
rev: 26.1.0
1010
hooks:
1111
- id: black
1212
files: ^src/

doc/modules/core.rst

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,36 @@ with 10 units:
157157
# times are not set, the samples are divided by the sampling frequency
158158
159159
160-
Internally, any sorting object can construct 2 internal caches:
161-
1. a list (per segment) of dict (per unit) of numpy.array. This cache is useful when accessing spike trains on a unit
162-
per unit basis across segments.
163-
2. a unique numpy.array with structured dtype aka "spikes vector". This is useful for processing by small chunks of
164-
time, like for extracting amplitudes from a recording.
160+
Efficiency and caching when fetching spiketrains
161+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
162+
163+
By design a Sorting object is lazy so that the constructor is fast: no data are fetched during init.
164+
Sortings that read data (the extractors) or modify data (select unit, remove spikes) behave
165+
the same: they are lazy. The spiketrain data are only fetched when the user requests them, e.g.
166+
using `sorting.get_unit_spike_train()`. This can lead to very slow access depending on how the
167+
underlying data is organized, but with the advantage that the `Sorting` object is agnostic of
168+
the underlying data organization.
169+
170+
To fix the slow access problem, we can create different internal representations of the spiketrain data and
171+
automatically cache them. Then the next time `sorting.get_unit_spike_train()` is called, the cached
172+
data is instantaneously returned. Further, we can create and cache different reorganizations of
173+
the spiketrain, which are optimally organized for specific types of calculation.
174+
175+
Computations involving combined recording-sorting information, such as fetching recording chunks and
176+
spiketrain chunks to accumulate waveforms, are often quickest when spikes are time-ordered. For
177+
this use case, we use an internal representation called the `spike_vector`. This is a unique buffer:
178+
a numpy.array with dtype `[("sample_index", "int64"), ("unit_index", "int64"), ("segment_index", "int64")]`.
179+
180+
For computations which are done unit-by-unit, like computing isi-violations per unit, it is better that
181+
spikes from a single unit are concurrent in memory. For these other cases, we can re-order the
182+
`spike_vector` in different ways:
183+
* order by unit, then segment, then sample
184+
* order by segment, then unit, then sample
185+
186+
This is done using `sorting.to_reordered_spike_vector()`. The first time a reordering is done, the
187+
reordered spiketrain is cached in memory by default. Users should rarely have to worry about these
188+
details, but developers should keep memory layout in mind when implementing new features.
189+
165190

166191
SortingAnalyzer
167192
---------------

src/spikeinterface/benchmark/benchmark_base.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ def _check_cases(cls, cases, levels=None, reference=None):
6565
assert isinstance(key, tuple), f"Case key {key} for cases is not homogeneous"
6666
num_levels = len(reference)
6767
assert len(key) == num_levels, f"Case key {key} for cases is not homogeneous, tuple negth differ"
68+
if levels is None:
69+
levels = [f"level{i}" for i in range(num_levels)]
70+
else:
71+
levels = list(levels)
6872
else:
6973
raise ValueError("Keys for cases must str or tuple")
7074
return levels

src/spikeinterface/benchmark/benchmark_matching.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import numpy as np
1414
from .benchmark_base import Benchmark, BenchmarkStudy, MixinStudyUnitCount
15-
from spikeinterface.core.basesorting import minimum_spike_dtype
15+
from spikeinterface.core.base import minimum_spike_dtype
1616

1717

1818
class MatchingBenchmark(Benchmark):

src/spikeinterface/benchmark/benchmark_peak_detection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import numpy as np
1414
from spikeinterface.core.job_tools import fix_job_kwargs, split_job_kwargs
1515
from .benchmark_base import Benchmark, BenchmarkStudy
16-
from spikeinterface.core.basesorting import minimum_spike_dtype
16+
from spikeinterface.core.base import minimum_spike_dtype
1717
from spikeinterface.core.sortinganalyzer import create_sorting_analyzer
1818
from .benchmark_plot_tools import fit_sigmoid, sigmoid
1919

src/spikeinterface/benchmark/benchmark_sorter.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from spikeinterface.sorters import run_sorter
99
from spikeinterface.comparison import compare_sorter_to_ground_truth
1010

11-
1211
# TODO later integrate CollisionGTComparison optionally in this class.
1312

1413

src/spikeinterface/benchmark/benchmark_sorter_without_gt.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
from spikeinterface.benchmark import analyse_residual
1212

13-
1413
# TODO later integrate CollisionGTComparison optionally in this class.
1514

1615

src/spikeinterface/benchmark/tests/test_residual_analysis.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
from spikeinterface.benchmark import analyse_residual
99

10-
1110
job_kwargs = dict(n_jobs=-1, progress_bar=True)
1211

1312

src/spikeinterface/comparison/tests/test_multisortingcomparison.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from spikeinterface.extractors import NumpySorting
1010
from spikeinterface.comparison import compare_multiple_sorters, MultiSortingComparison
1111

12-
1312
ON_GITHUB = bool(os.getenv("GITHUB_ACTIONS"))
1413

1514

src/spikeinterface/comparison/tests/test_templatecomparison.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from spikeinterface.core import create_sorting_analyzer, generate_ground_truth_recording
66
from spikeinterface.comparison import compare_templates, compare_multiple_templates
77

8-
98
# def setup_module():
109
# if test_dir.is_dir():
1110
# shutil.rmtree(test_dir)

0 commit comments

Comments
 (0)