Skip to content

Commit c094195

Browse files
committed
parallel rms, remove export to phy, clean up
1 parent 74a813d commit c094195

3 files changed

Lines changed: 328 additions & 205 deletions

File tree

src/spikeinterface/exporters/tests/common.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ def make_sorting_analyzer(sparse=True, with_group=False):
4545
sorting_analyzer.compute("noise_levels")
4646
sorting_analyzer.compute("principal_components")
4747
sorting_analyzer.compute("template_similarity")
48-
sorting_analyzer.compute("quality_metrics", metric_names=["snr"])
48+
sorting_analyzer.compute(
49+
"quality_metrics", metric_names=["snr", "amplitude_median", "isi_violation", "amplitude_cutoff"]
50+
)
51+
sorting_analyzer.compute(["spike_amplitudes", "spike_locations"])
4952

5053
return sorting_analyzer
5154

Lines changed: 97 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,115 @@
1-
import shutil
2-
3-
import numpy as np
1+
import pytest
42

3+
from spikeinterface.preprocessing import bandpass_filter, decimate
54
from spikeinterface.exporters import export_to_ibl
65

76
from spikeinterface.exporters.tests.common import (
87
make_sorting_analyzer,
98
sorting_analyzer_sparse_for_export,
109
)
1110

11+
required_output_files = [
12+
"spikes.times.npy",
13+
"spikes.clusters.npy",
14+
"spikes.depths.npy",
15+
"spikes.amps.npy",
16+
"clusters.waveforms.npy",
17+
"clusters.peakToTrough.npy",
18+
"clusters.channels.npy",
19+
"clusters.metrics.csv",
20+
"channels.localCoordinates.npy",
21+
"channels.rawInd.npy",
22+
]
23+
ap_output_files = ["_iblqc_ephysTimeRmsAP.rms.npy", "_iblqc_ephysTimeRmsAP.timestamps.npy"]
24+
lfp_output_files = [
25+
"_iblqc_ephysTimeRmsLF.rms.npy",
26+
"_iblqc_ephysTimeRmsLF.timestamps.npy",
27+
"_iblqc_ephysSpectralDensityLF.power.npy",
28+
"_iblqc_ephysSpectralDensityLF.freqs.npy",
29+
]
30+
31+
good_units_query = "amplitude_median < -30"
32+
1233

13-
def test_export_to_ibl(sorting_analyzer_sparse_for_export, create_cache_folder):
34+
def test_export_ap_to_ibl(sorting_analyzer_sparse_for_export, create_cache_folder):
1435
cache_folder = create_cache_folder
15-
output_folder = cache_folder / "ibl_output"
16-
for f in (output_folder,):
17-
if f.is_dir():
18-
shutil.rmtree(f)
36+
output_folder = cache_folder / "ibl_ap_output"
1937

38+
sorting_analyzer = sorting_analyzer_sparse_for_export
39+
# AP, but no LFP
2040
export_to_ibl(
21-
sorting_analyzer_sparse_for_export,
41+
sorting_analyzer,
2242
output_folder,
23-
lfp_recording=sorting_analyzer_sparse_for_export.recording,
43+
# good_units_query=good_units_query,
44+
verbose=True,
45+
n_jobs=-1,
2446
)
47+
for f in required_output_files:
48+
assert (output_folder / f).exists(), f"Missing file: {f}"
49+
for f in ap_output_files:
50+
assert (output_folder / f).exists(), f"Missing file: {f}"
51+
for f in lfp_output_files:
52+
assert not (output_folder / f).exists(), f"Unexpected file: {f}"
53+
54+
55+
def test_export_recordingless_to_ibl(sorting_analyzer_sparse_for_export, create_cache_folder):
56+
cache_folder = create_cache_folder
57+
output_folder = cache_folder / "ibl_recordingless_output"
58+
59+
sorting_analyzer = sorting_analyzer_sparse_for_export
60+
recording = sorting_analyzer.recording
61+
sorting_analyzer._recording = None
62+
63+
# AP, but no LFP
64+
export_to_ibl(sorting_analyzer_sparse_for_export, output_folder, good_units_query=good_units_query, n_jobs=-1)
65+
for f in required_output_files:
66+
assert (output_folder / f).exists(), f"Missing file: {f}"
67+
for f in ap_output_files:
68+
assert not (output_folder / f).exists(), f"Missing file: {f}"
69+
for f in lfp_output_files:
70+
assert not (output_folder / f).exists(), f"Unexpected file: {f}"
71+
72+
sorting_analyzer._recording = recording
73+
74+
75+
def test_export_lfp_to_ibl(sorting_analyzer_sparse_for_export, create_cache_folder):
76+
cache_folder = create_cache_folder
77+
output_folder = cache_folder / "ibl_lfp_output"
78+
79+
sorting_analyzer = sorting_analyzer_sparse_for_export
80+
recording = sorting_analyzer.recording
81+
recording_lfp = bandpass_filter(recording, freq_min=0.5, freq_max=300)
82+
recording_lfp = decimate(recording_lfp, 10)
83+
# LFP, but no AP
84+
export_to_ibl(
85+
sorting_analyzer, output_folder, lfp_recording=recording_lfp, good_units_query=good_units_query, n_jobs=-1
86+
)
87+
for f in required_output_files:
88+
assert (output_folder / f).exists(), f"Missing file: {f}"
89+
for f in ap_output_files:
90+
assert (output_folder / f).exists(), f"Unexpected file: {f}"
91+
for f in lfp_output_files:
92+
assert (output_folder / f).exists(), f"Missing file: {f}"
93+
94+
95+
def test_missing_info(sorting_analyzer_sparse_for_export, create_cache_folder):
96+
cache_folder = create_cache_folder
97+
output_folder = cache_folder / "ibl_missing_info_output"
98+
99+
sorting_analyzer = sorting_analyzer_sparse_for_export
100+
101+
# missing metrics
102+
good_units_query = "rp_violations < 0.2"
103+
104+
with pytest.raises(ValueError, match="Missing required quality metrics"):
105+
export_to_ibl(sorting_analyzer, output_folder, good_units_query=good_units_query, n_jobs=-1)
106+
107+
sorting_analyzer.delete_extension("spike_amplitudes")
108+
109+
with pytest.raises(ValueError, match="Missing required extension"):
110+
export_to_ibl(sorting_analyzer, output_folder, n_jobs=-1)
25111

26112

27113
if __name__ == "__main__":
28114
sorting_analyzer = make_sorting_analyzer(sparse=True)
29-
test_export_to_ibl(sorting_analyzer)
115+
test_export_ap_to_ibl(sorting_analyzer)

0 commit comments

Comments
 (0)