Skip to content

Commit 298e57a

Browse files
authored
Merge pull request #3447 from samuelgarcia/refactor_matching
Refactor matching with nodepiepeline
2 parents 69bf6e4 + 80e6b40 commit 298e57a

13 files changed

Lines changed: 636 additions & 918 deletions

File tree

src/spikeinterface/core/node_pipeline.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def compute(self, traces, start_frame, end_frame, segment_index, max_margin, *ar
8080

8181

8282
class PeakSource(PipelineNode):
83-
# base class for peak detector
83+
8484
def get_trace_margin(self):
8585
raise NotImplementedError
8686

@@ -99,6 +99,7 @@ def get_peak_slice(
9999

100100
# this is used in sorting components
101101
class PeakDetector(PeakSource):
102+
# base class for peak detector or template matching
102103
pass
103104

104105

src/spikeinterface/sorters/internal/tests/test_spykingcircus2.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@
44

55
from spikeinterface.sorters import Spykingcircus2Sorter
66

7+
from pathlib import Path
8+
79

810
class SpykingCircus2SorterCommonTestSuite(SorterCommonTestSuite, unittest.TestCase):
911
SorterClass = Spykingcircus2Sorter
1012

1113

1214
if __name__ == "__main__":
15+
from spikeinterface import set_global_job_kwargs
16+
17+
set_global_job_kwargs(n_jobs=1, progress_bar=False)
1318
test = SpykingCircus2SorterCommonTestSuite()
19+
test.cache_folder = Path(__file__).resolve().parents[4] / "cache_folder" / "sorters"
1420
test.setUp()
1521
test.test_with_run()

src/spikeinterface/sorters/internal/tests/test_tridesclous2.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44

55
from spikeinterface.sorters import Tridesclous2Sorter
66

7+
from pathlib import Path
8+
79

810
class Tridesclous2SorterCommonTestSuite(SorterCommonTestSuite, unittest.TestCase):
911
SorterClass = Tridesclous2Sorter
1012

1113

1214
if __name__ == "__main__":
1315
test = Tridesclous2SorterCommonTestSuite()
16+
test.cache_folder = Path(__file__).resolve().parents[4] / "cache_folder" / "sorters"
1417
test.setUp()
1518
test.test_with_run()

src/spikeinterface/sorters/internal/tridesclous2.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ def _run_from_folder(cls, sorter_output_folder, params, verbose):
226226
matching_method = params["matching"]["method"]
227227
matching_params = params["matching"]["method_kwargs"].copy()
228228
matching_params["templates"] = templates
229-
matching_params["noise_levels"] = noise_levels
229+
if params["matching"]["method"] in ("tdc-peeler",):
230+
matching_params["noise_levels"] = noise_levels
230231
spikes = find_spikes_from_templates(
231232
recording_for_peeler, method=matching_method, method_kwargs=matching_params, **job_kwargs
232233
)

src/spikeinterface/sortingcomponents/clustering/clustering_tools.py

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -602,21 +602,11 @@ def detect_mixtures(templates, method_kwargs={}, job_kwargs={}, tmp_folder=None,
602602

603603
sub_recording = recording.frame_slice(t_start, t_stop)
604604
local_params.update({"ignore_inds": ignore_inds + [i]})
605-
spikes, computed = find_spikes_from_templates(
605+
606+
spikes, more_outputs = find_spikes_from_templates(
606607
sub_recording, method="circus-omp-svd", method_kwargs=local_params, extra_outputs=True, **job_kwargs
607608
)
608-
local_params.update(
609-
{
610-
"overlaps": computed["overlaps"],
611-
"normed_templates": computed["normed_templates"],
612-
"norms": computed["norms"],
613-
"temporal": computed["temporal"],
614-
"spatial": computed["spatial"],
615-
"singular": computed["singular"],
616-
"units_overlaps": computed["units_overlaps"],
617-
"unit_overlaps_indices": computed["unit_overlaps_indices"],
618-
}
619-
)
609+
local_params["precomputed"] = more_outputs
620610
valid = (spikes["sample_index"] >= 0) * (spikes["sample_index"] < duration + 2 * margin)
621611

622612
if np.sum(valid) > 0:
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import numpy as np
2+
from spikeinterface.core import Templates
3+
from spikeinterface.core.node_pipeline import PeakDetector
4+
5+
_base_matching_dtype = [
6+
("sample_index", "int64"),
7+
("channel_index", "int64"),
8+
("cluster_index", "int64"),
9+
("amplitude", "float64"),
10+
("segment_index", "int64"),
11+
]
12+
13+
14+
class BaseTemplateMatching(PeakDetector):
15+
def __init__(self, recording, templates, return_output=True, parents=None):
16+
# TODO make a sharedmem of template here
17+
# TODO maybe check that channel_id are the same with recording
18+
19+
assert isinstance(
20+
templates, Templates
21+
), f"The templates supplied is of type {type(templates)} and must be a Templates"
22+
self.templates = templates
23+
PeakDetector.__init__(self, recording, return_output=return_output, parents=parents)
24+
25+
def get_dtype(self):
26+
return np.dtype(_base_matching_dtype)
27+
28+
def get_trace_margin(self):
29+
raise NotImplementedError
30+
31+
def compute(self, traces, start_frame, end_frame, segment_index, max_margin):
32+
spikes = self.compute_matching(traces, start_frame, end_frame, segment_index)
33+
spikes["segment_index"] = segment_index
34+
35+
margin = self.get_trace_margin()
36+
if margin > 0 and spikes.size > 0:
37+
keep = (spikes["sample_index"] >= margin) & (spikes["sample_index"] < (traces.shape[0] - margin))
38+
spikes = spikes[keep]
39+
40+
# node pipeline need to return a tuple
41+
return (spikes,)
42+
43+
def compute_matching(self, traces, start_frame, end_frame, segment_index):
44+
raise NotImplementedError
45+
46+
def get_extra_outputs(self):
47+
# can be overwritten if need to ouput some variables with a dict
48+
return None

0 commit comments

Comments
 (0)