From d529e0decf39c533cc62ae8a9204a526167d0fc6 Mon Sep 17 00:00:00 2001 From: Ben Dichter Date: Sun, 8 Dec 2024 09:26:59 +0300 Subject: [PATCH 1/9] add json validation to tests --- resources/probe.json.schema | 8 ++++++-- src/probeinterface/testing.py | 12 ++++++++++++ tests/test_io/test_spikeglx.py | 16 ++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 src/probeinterface/testing.py diff --git a/resources/probe.json.schema b/resources/probe.json.schema index eecdda1..9d09e1b 100644 --- a/resources/probe.json.schema +++ b/resources/probe.json.schema @@ -26,10 +26,10 @@ "annotations": { "type": "object", "properties": { - "name": { "type": "string" }, + "model_name": { "type": "string" }, "manufacturer": { "type": "string" } }, - "required": ["name", "manufacturer"], + "required": ["model_name", "manufacturer"], "additionalProperties": true }, "contact_annotations": { @@ -101,6 +101,10 @@ "shank_ids": { "type": "array", "items": { "type": "string" } + }, + "device_channel_indices": { + "type": "array", + "items": { "type": "integer" } } }, "required": [ diff --git a/src/probeinterface/testing.py b/src/probeinterface/testing.py new file mode 100644 index 0000000..64af93d --- /dev/null +++ b/src/probeinterface/testing.py @@ -0,0 +1,12 @@ +import json +from pathlib import Path + +from probeinterface import __version__ as version +import jsonschema + +json_schema_file = Path(__file__).absolute().parent.parent.parent / "resources" / "probe.json.schema" +schema = json.load(open(json_schema_file, "r")) + +def validate_probe_dict(probe_dict): + instance = dict(specification="probeinterface", version=version, probes=[probe_dict]) + jsonschema.validate(instance=instance, schema=schema) diff --git a/tests/test_io/test_spikeglx.py b/tests/test_io/test_spikeglx.py index f32ee6e..925cef1 100644 --- a/tests/test_io/test_spikeglx.py +++ b/tests/test_io/test_spikeglx.py @@ -4,10 +4,12 @@ import pytest from probeinterface import ( + __version__ as version, read_spikeglx, parse_spikeglx_meta, get_saved_channel_indices_from_spikeglx_meta, ) +from probeinterface.testing import validate_probe_dict data_path = Path(__file__).absolute().parent.parent / "data" / "spikeglx" @@ -34,6 +36,7 @@ def test_get_saved_channel_indices_from_spikeglx_meta(): def test_NP1(): probe = read_spikeglx(data_path / "Noise_g0_t0.imec0.ap.meta") assert "1.0" in probe.model_name + validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NP_phase3A(): @@ -54,12 +57,14 @@ def test_NP_phase3A(): assert np.all(probe.contact_shape_params == {"width": contact_width}) assert np.all(probe.contact_shapes == contact_shape) + validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NP2_1_shanks(): probe = read_spikeglx(data_path / "p2_g0_t0.imec0.ap.meta") assert "2.0" in probe.model_name assert probe.get_shank_count() == 1 + validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NP2_4_shanks(): @@ -83,6 +88,7 @@ def test_NP2_4_shanks(): # This file does not save the channnels from 0 as the one above (NP2_4_shanks_g0_t0.imec0.ap.meta) ypos = probe.contact_positions[:, 1] assert np.min(ypos) == pytest.approx(0) + validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NP2_2013_all(): @@ -108,6 +114,7 @@ def test_NP2_2013_all(): # This file does not save the channnels from 0 as the one above (NP2_4_shanks_g0_t0.imec0.ap.meta) ypos = probe.contact_positions[:, 1] assert np.min(ypos) == pytest.approx(0) + validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NP2_2013_subset(): @@ -133,6 +140,7 @@ def test_NP2_2013_subset(): # This file does not save the channnels from 0 as the one above (NP2_4_shanks_g0_t0.imec0.ap.meta) ypos = probe.contact_positions[:, 1] assert np.min(ypos) == pytest.approx(0) + validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NP2_4_shanks_with_different_electrodes_saved(): @@ -158,6 +166,7 @@ def test_NP2_4_shanks_with_different_electrodes_saved(): ypos = probe.contact_positions[:, 1] assert np.min(ypos) == pytest.approx(4080.0) assert np.max(ypos) == pytest.approx(4785.0) + validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NP1_large_depth_span(): @@ -167,6 +176,7 @@ def test_NP1_large_depth_span(): assert probe.get_shank_count() == 1 ypos = probe.contact_positions[:, 1] assert (np.max(ypos) - np.min(ypos)) > 7600 + validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NP1_other_example(): @@ -177,6 +187,7 @@ def test_NP1_other_example(): assert probe.get_shank_count() == 1 ypos = probe.contact_positions[:, 1] assert (np.max(ypos) - np.min(ypos)) > 7600 + validate_probe_dict(probe.to_dict(array_as_list=True)) def tes_NP1_384_channels(): @@ -185,6 +196,7 @@ def tes_NP1_384_channels(): assert probe.get_shank_count() == 1 assert probe.get_contact_count() == 151 assert 152 not in probe.contact_annotations["channel_ids"] + validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NPH_long_staggered(): @@ -241,6 +253,7 @@ def test_NPH_long_staggered(): assert np.allclose(banks, 0) assert np.allclose(references, 0) assert np.allclose(filters, 1) + validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NPH_short_linear_probe_type_0(): @@ -291,6 +304,7 @@ def test_NPH_short_linear_probe_type_0(): assert np.allclose(banks, 0) assert np.allclose(references, 0) assert np.allclose(filters, 1) + validate_probe_dict(probe.to_dict(array_as_list=True)) def test_ultra_probe(): @@ -319,11 +333,13 @@ def test_ultra_probe(): expected_electode_rows = 48 unique_y_values = np.unique(y) assert unique_y_values.size == expected_electode_rows + validate_probe_dict(probe.to_dict(array_as_list=True)) def test_CatGT_NP1(): probe = read_spikeglx(data_path / "catgt.meta") assert "1.0" in probe.model_name + validate_probe_dict(probe.to_dict(array_as_list=True)) if __name__ == "__main__": From 6b2cc772c6ab56481f10d279ae3da8133c113634 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 8 Dec 2024 06:29:37 +0000 Subject: [PATCH 2/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/probeinterface/testing.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/probeinterface/testing.py b/src/probeinterface/testing.py index 64af93d..1b3131c 100644 --- a/src/probeinterface/testing.py +++ b/src/probeinterface/testing.py @@ -7,6 +7,7 @@ json_schema_file = Path(__file__).absolute().parent.parent.parent / "resources" / "probe.json.schema" schema = json.load(open(json_schema_file, "r")) + def validate_probe_dict(probe_dict): instance = dict(specification="probeinterface", version=version, probes=[probe_dict]) jsonschema.validate(instance=instance, schema=schema) From 1d7a4fa1d286603638ee9c627adfa8ef0c612204 Mon Sep 17 00:00:00 2001 From: Ben Dichter Date: Sun, 8 Dec 2024 09:31:38 +0300 Subject: [PATCH 3/9] add jsonschema to testing requirements --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index cbdbbda..23bf8b9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,7 @@ package-dir = {"probeinterface" = "src/probeinterface"} [project.optional-dependencies] test = [ + "jsonschema", "pytest", "pytest-cov", "matplotlib", From 2554af342525d7d3779ece12e8fe85d233137b0f Mon Sep 17 00:00:00 2001 From: Ben Dichter Date: Sun, 8 Dec 2024 09:35:33 +0300 Subject: [PATCH 4/9] rmv old import --- tests/test_io/test_spikeglx.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_io/test_spikeglx.py b/tests/test_io/test_spikeglx.py index 925cef1..a4543fe 100644 --- a/tests/test_io/test_spikeglx.py +++ b/tests/test_io/test_spikeglx.py @@ -4,7 +4,6 @@ import pytest from probeinterface import ( - __version__ as version, read_spikeglx, parse_spikeglx_meta, get_saved_channel_indices_from_spikeglx_meta, From 16bd39a8db2bc2cd1577f9df1a1a8a827cd9c5fd Mon Sep 17 00:00:00 2001 From: Ben Dichter Date: Sun, 8 Dec 2024 10:23:18 +0300 Subject: [PATCH 5/9] refactor dict tests --- tests/test_io/test_spikeglx.py | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/tests/test_io/test_spikeglx.py b/tests/test_io/test_spikeglx.py index a4543fe..fcb875e 100644 --- a/tests/test_io/test_spikeglx.py +++ b/tests/test_io/test_spikeglx.py @@ -1,3 +1,4 @@ +import glob from pathlib import Path import numpy as np @@ -11,8 +12,14 @@ from probeinterface.testing import validate_probe_dict data_path = Path(__file__).absolute().parent.parent / "data" / "spikeglx" +meta_files = glob.glob(str(data_path / "*.meta")) +@pytest.mark.parametrize("meta_file", meta_files) +def test_valid_probe_dict(meta_file: str): + probe = read_spikeglx(data_path / meta_file) + validate_probe_dict(probe.to_dict(array_as_list=True)) + def test_parse_meta(): for meta_file in [ "doppio-checkerboard_t0.imec0.ap.meta", @@ -35,7 +42,7 @@ def test_get_saved_channel_indices_from_spikeglx_meta(): def test_NP1(): probe = read_spikeglx(data_path / "Noise_g0_t0.imec0.ap.meta") assert "1.0" in probe.model_name - validate_probe_dict(probe.to_dict(array_as_list=True)) + def test_NP_phase3A(): @@ -56,14 +63,12 @@ def test_NP_phase3A(): assert np.all(probe.contact_shape_params == {"width": contact_width}) assert np.all(probe.contact_shapes == contact_shape) - validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NP2_1_shanks(): probe = read_spikeglx(data_path / "p2_g0_t0.imec0.ap.meta") assert "2.0" in probe.model_name assert probe.get_shank_count() == 1 - validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NP2_4_shanks(): @@ -87,7 +92,6 @@ def test_NP2_4_shanks(): # This file does not save the channnels from 0 as the one above (NP2_4_shanks_g0_t0.imec0.ap.meta) ypos = probe.contact_positions[:, 1] assert np.min(ypos) == pytest.approx(0) - validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NP2_2013_all(): @@ -113,7 +117,6 @@ def test_NP2_2013_all(): # This file does not save the channnels from 0 as the one above (NP2_4_shanks_g0_t0.imec0.ap.meta) ypos = probe.contact_positions[:, 1] assert np.min(ypos) == pytest.approx(0) - validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NP2_2013_subset(): @@ -139,7 +142,6 @@ def test_NP2_2013_subset(): # This file does not save the channnels from 0 as the one above (NP2_4_shanks_g0_t0.imec0.ap.meta) ypos = probe.contact_positions[:, 1] assert np.min(ypos) == pytest.approx(0) - validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NP2_4_shanks_with_different_electrodes_saved(): @@ -165,7 +167,6 @@ def test_NP2_4_shanks_with_different_electrodes_saved(): ypos = probe.contact_positions[:, 1] assert np.min(ypos) == pytest.approx(4080.0) assert np.max(ypos) == pytest.approx(4785.0) - validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NP1_large_depth_span(): @@ -175,7 +176,6 @@ def test_NP1_large_depth_span(): assert probe.get_shank_count() == 1 ypos = probe.contact_positions[:, 1] assert (np.max(ypos) - np.min(ypos)) > 7600 - validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NP1_other_example(): @@ -186,7 +186,6 @@ def test_NP1_other_example(): assert probe.get_shank_count() == 1 ypos = probe.contact_positions[:, 1] assert (np.max(ypos) - np.min(ypos)) > 7600 - validate_probe_dict(probe.to_dict(array_as_list=True)) def tes_NP1_384_channels(): @@ -195,7 +194,6 @@ def tes_NP1_384_channels(): assert probe.get_shank_count() == 1 assert probe.get_contact_count() == 151 assert 152 not in probe.contact_annotations["channel_ids"] - validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NPH_long_staggered(): @@ -252,7 +250,6 @@ def test_NPH_long_staggered(): assert np.allclose(banks, 0) assert np.allclose(references, 0) assert np.allclose(filters, 1) - validate_probe_dict(probe.to_dict(array_as_list=True)) def test_NPH_short_linear_probe_type_0(): @@ -303,7 +300,6 @@ def test_NPH_short_linear_probe_type_0(): assert np.allclose(banks, 0) assert np.allclose(references, 0) assert np.allclose(filters, 1) - validate_probe_dict(probe.to_dict(array_as_list=True)) def test_ultra_probe(): @@ -332,13 +328,12 @@ def test_ultra_probe(): expected_electode_rows = 48 unique_y_values = np.unique(y) assert unique_y_values.size == expected_electode_rows - validate_probe_dict(probe.to_dict(array_as_list=True)) def test_CatGT_NP1(): probe = read_spikeglx(data_path / "catgt.meta") assert "1.0" in probe.model_name - validate_probe_dict(probe.to_dict(array_as_list=True)) + if __name__ == "__main__": From b9c258e38c716686df95d8780d5ed90cf9cd428e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 8 Dec 2024 07:23:32 +0000 Subject: [PATCH 6/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_io/test_spikeglx.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_io/test_spikeglx.py b/tests/test_io/test_spikeglx.py index fcb875e..e6bc657 100644 --- a/tests/test_io/test_spikeglx.py +++ b/tests/test_io/test_spikeglx.py @@ -20,6 +20,7 @@ def test_valid_probe_dict(meta_file: str): probe = read_spikeglx(data_path / meta_file) validate_probe_dict(probe.to_dict(array_as_list=True)) + def test_parse_meta(): for meta_file in [ "doppio-checkerboard_t0.imec0.ap.meta", @@ -44,7 +45,6 @@ def test_NP1(): assert "1.0" in probe.model_name - def test_NP_phase3A(): # Data provided by rtraghavan probe = read_spikeglx(data_path / "phase3a.imec.ap.meta") @@ -335,6 +335,5 @@ def test_CatGT_NP1(): assert "1.0" in probe.model_name - if __name__ == "__main__": test_NP2_1_shanks() From 8d54bfd51146c35e87ce339009ce39031b9d3598 Mon Sep 17 00:00:00 2001 From: Ben Dichter Date: Sun, 8 Dec 2024 16:46:17 +0300 Subject: [PATCH 7/9] add dict json schema validation for 3brian, imro, maxwell --- src/probeinterface/probe.py | 1 - tests/test_io/test_3brain.py | 12 ++++++++++++ tests/test_io/test_imro.py | 11 +++++++++++ tests/test_io/test_maxwell.py | 9 +++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/probeinterface/probe.py b/src/probeinterface/probe.py index 2fc137a..4cbf5a4 100644 --- a/src/probeinterface/probe.py +++ b/src/probeinterface/probe.py @@ -2,7 +2,6 @@ import numpy as np from typing import Optional from pathlib import Path -import json from .shank import Shank diff --git a/tests/test_io/test_3brain.py b/tests/test_io/test_3brain.py index 11a4473..bf48ea9 100644 --- a/tests/test_io/test_3brain.py +++ b/tests/test_io/test_3brain.py @@ -1,3 +1,4 @@ +import glob from pathlib import Path import numpy as np @@ -5,8 +6,19 @@ from probeinterface import read_3brain +from probeinterface.testing import validate_probe_dict + + data_path = Path(__file__).absolute().parent.parent / "data" / "3brain" +brw_files = glob.glob(str(data_path / "*.brw")) + +@pytest.mark.parametrize("file_", brw_files) +def test_valid_probe_dict(file_: str): + probe = read_3brain(data_path / file_) + probe_dict = probe.to_dict(array_as_list=True) + probe_dict["annotations"].update(model_name="placeholder") + validate_probe_dict(probe_dict) def test_3brain(): """Files on ephy_test_data""" diff --git a/tests/test_io/test_imro.py b/tests/test_io/test_imro.py index 9e6e269..a579047 100644 --- a/tests/test_io/test_imro.py +++ b/tests/test_io/test_imro.py @@ -1,11 +1,22 @@ +import glob from pathlib import Path import pytest import numpy as np from probeinterface import read_imro, write_imro +from probeinterface.testing import validate_probe_dict data_path = Path(__file__).absolute().parent.parent / "data" / "imro" +imro_files = glob.glob(str(data_path / "*.imro")) + +imro_files.pop(imro_files.index(str(data_path / "test_non_standard.imro"))) + + +@pytest.mark.parametrize("file_", imro_files) +def test_valid_probe_dict(file_: str): + probe = read_imro(data_path / file_) + validate_probe_dict(probe.to_dict(array_as_list=True)) def test_reading_multishank_imro(tmp_path): diff --git a/tests/test_io/test_maxwell.py b/tests/test_io/test_maxwell.py index f6b6851..664b5d6 100644 --- a/tests/test_io/test_maxwell.py +++ b/tests/test_io/test_maxwell.py @@ -4,10 +4,19 @@ import pytest from probeinterface import read_maxwell +from probeinterface.testing import validate_probe_dict data_path = Path(__file__).absolute().parent.parent / "data" / "maxwell" +def test_valid_probe_dict(): + file_ = "data.raw.h5" + probe = read_maxwell(data_path / file_) + probe_dict = probe.to_dict(array_as_list=True) + probe_dict["annotations"].update(model_name="placeholder") + validate_probe_dict(probe_dict) + + def test_maxwell(): """Basic file taken from the ephys data repository and provided by Alessio Buccino""" From 18a982a61b8ce30ad4352e8947695d05fe4291fe Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 8 Dec 2024 13:47:13 +0000 Subject: [PATCH 8/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_io/test_3brain.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_io/test_3brain.py b/tests/test_io/test_3brain.py index bf48ea9..1128a23 100644 --- a/tests/test_io/test_3brain.py +++ b/tests/test_io/test_3brain.py @@ -20,6 +20,7 @@ def test_valid_probe_dict(file_: str): probe_dict["annotations"].update(model_name="placeholder") validate_probe_dict(probe_dict) + def test_3brain(): """Files on ephy_test_data""" From 11e1242aebb322918461b8b1830cf40014f2ce07 Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Tue, 7 Jan 2025 16:13:50 +0100 Subject: [PATCH 9/9] Add validation for Open Ephys and SpikeGadgets tests --- tests/test_io/test_openephys.py | 43 ++++++++++++++++++++++++++++-- tests/test_io/test_spikegadgets.py | 6 +++-- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/tests/test_io/test_openephys.py b/tests/test_io/test_openephys.py index bf18711..bb90a71 100644 --- a/tests/test_io/test_openephys.py +++ b/tests/test_io/test_openephys.py @@ -1,10 +1,12 @@ from pathlib import Path import numpy as np +import glob import pytest from probeinterface import read_openephys +from probeinterface.testing import validate_probe_dict data_path = Path(__file__).absolute().parent.parent / "data" / "openephys" @@ -12,6 +14,8 @@ def test_NP2_OE_1_0(): # NP2 1-shank probeA = read_openephys(data_path / "OE_1.0_Neuropix-PXI-multi-probe" / "settings.xml", probe_name="ProbeA") + probe_dict = probeA.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert probeA.get_shank_count() == 1 assert "2.0" in probeA.model_name assert probeA.get_contact_count() == 384 @@ -20,6 +24,8 @@ def test_NP2_OE_1_0(): def test_NP2(): # NP2 probe = read_openephys(data_path / "OE_Neuropix-PXI" / "settings.xml") + probe_dict = probe.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert probe.get_shank_count() == 1 assert "2.0 - Single Shank" in probe.model_name @@ -27,6 +33,8 @@ def test_NP2(): def test_NP2_four_shank(): # NP2 probe = read_openephys(data_path / "OE_Neuropix-PXI-NP2-4shank" / "settings.xml") + probe_dict = probe.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) # on this case, only shanks 2-3 are used assert probe.get_shank_count() == 2 assert "2.0 - Four Shank" in probe.model_name @@ -38,6 +46,8 @@ def test_NP_Ultra(): data_path / "OE_Neuropix-PXI-NP-Ultra" / "settings.xml", probe_name="ProbeA", ) + probe_dict = probeA.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert "Ultra" in probeA.model_name assert probeA.get_shank_count() == 1 assert probeA.get_contact_count() == 384 @@ -46,6 +56,8 @@ def test_NP_Ultra(): data_path / "OE_Neuropix-PXI-NP-Ultra" / "settings.xml", probe_name="ProbeB", ) + probe_dict = probeB.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert "Ultra" in probeB.model_name assert probeB.get_shank_count() == 1 assert probeB.get_contact_count() == 384 @@ -54,6 +66,8 @@ def test_NP_Ultra(): data_path / "OE_Neuropix-PXI-NP-Ultra" / "settings.xml", probe_name="ProbeF", ) + probe_dict = probeF.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert "Ultra" in probeF.model_name assert probeF.get_shank_count() == 1 assert probeF.get_contact_count() == 384 @@ -62,6 +76,8 @@ def test_NP_Ultra(): data_path / "OE_Neuropix-PXI-NP-Ultra" / "settings.xml", probe_name="ProbeD", ) + probe_dict = probeD.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert "Ultra" in probeD.model_name and "Type 2" in probeD.model_name assert probeD.get_shank_count() == 1 assert probeD.get_contact_count() == 384 @@ -72,12 +88,16 @@ def test_NP_Ultra(): def test_NP1_subset(): # NP1 - 200 channels selected by recording_state in Record Node probe_ap = read_openephys(data_path / "OE_Neuropix-PXI-subset" / "settings.xml", stream_name="ProbeA-AP") + probe_dict = probe_ap.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert probe_ap.get_shank_count() == 1 assert "1.0" in probe_ap.model_name assert probe_ap.get_contact_count() == 200 probe_lf = read_openephys(data_path / "OE_Neuropix-PXI-subset" / "settings.xml", stream_name="ProbeA-LFP") + probe_dict = probe_lf.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert probe_lf.get_shank_count() == 1 assert "1.0" in probe_lf.model_name @@ -92,6 +112,8 @@ def test_NP1_subset(): def test_multiple_probes(): # multiple probes probeA = read_openephys(data_path / "OE_Neuropix-PXI-multi-probe" / "settings.xml", probe_name="ProbeA") + probe_dict = probeA.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert probeA.get_shank_count() == 1 assert "1.0" in probeA.model_name @@ -100,6 +122,8 @@ def test_multiple_probes(): data_path / "OE_Neuropix-PXI-multi-probe" / "settings.xml", stream_name="RecordNode#ProbeB", ) + probe_dict = probeB.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert probeB.get_shank_count() == 1 @@ -107,10 +131,14 @@ def test_multiple_probes(): data_path / "OE_Neuropix-PXI-multi-probe" / "settings.xml", serial_number="20403311714", ) + probe_dict = probeC.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert probeC.get_shank_count() == 1 probeD = read_openephys(data_path / "OE_Neuropix-PXI-multi-probe" / "settings.xml", probe_name="ProbeD") + probe_dict = probeD.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert probeD.get_shank_count() == 1 @@ -146,11 +174,16 @@ def test_multiple_probes_enabled(): probe = read_openephys( data_path / "OE_6.7_enabled_disabled_Neuropix-PXI" / "settings_enabled-enabled.xml", probe_name="ProbeA" ) + probe_dict = probe.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) + assert probe.get_shank_count() == 1 probe = read_openephys( data_path / "OE_6.7_enabled_disabled_Neuropix-PXI" / "settings_enabled-enabled.xml", probe_name="ProbeB" ) + probe_dict = probe.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert probe.get_shank_count() == 4 @@ -159,7 +192,8 @@ def test_multiple_probes_disabled(): probe = read_openephys( data_path / "OE_6.7_enabled_disabled_Neuropix-PXI" / "settings_enabled-disabled.xml", probe_name="ProbeA" ) - + probe_dict = probe.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert probe.get_shank_count() == 1 # Fail as this is disabled: @@ -173,6 +207,8 @@ def test_multiple_probes_disabled(): def test_np_opto_with_sync(): probe = read_openephys(data_path / "OE_Neuropix-PXI-opto-with-sync" / "settings.xml") + probe_dict = probe.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert probe.model_name == "Neuropixels Opto" assert probe.get_shank_count() == 1 assert probe.get_contact_count() == 384 @@ -182,7 +218,8 @@ def test_older_than_06_format(): ## Test with the open ephys < 0.6 format probe = read_openephys(data_path / "OE_5_Neuropix-PXI-multi-probe" / "settings.xml", probe_name="100.0") - + probe_dict = probe.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert probe.get_shank_count() == 4 assert "2.0 - Four Shank" in probe.model_name ypos = probe.contact_positions[:, 1] @@ -193,6 +230,8 @@ def test_multiple_signal_chains(): # tests that the probe information can be loaded even if the Neuropix-PXI plugin # is not in the first signalchain probe = read_openephys(data_path / "OE_Neuropix-PXI-multiple-signalchains" / "settings.xml") + probe_dict = probe.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert probe.model_name == "Neuropixels 1.0" diff --git a/tests/test_io/test_spikegadgets.py b/tests/test_io/test_spikegadgets.py index 7415db9..6cff88d 100644 --- a/tests/test_io/test_spikegadgets.py +++ b/tests/test_io/test_spikegadgets.py @@ -1,10 +1,10 @@ from pathlib import Path from xml.etree import ElementTree -import pytest - from probeinterface import read_spikegadgets from probeinterface.io import parse_spikegadgets_header +from probeinterface.testing import validate_probe_dict + data_path = Path(__file__).absolute().parent.parent / "data" / "spikegadgets" test_file = "SpikeGadgets_test_data_2xNpix1.0_20240318_173658_header_only.rec" @@ -22,6 +22,8 @@ def test_neuropixels_1_reader(): probe_group = read_spikegadgets(data_path / test_file, raise_error=False) assert len(probe_group.probes) == 2 for probe in probe_group.probes: + probe_dict = probe.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) assert "1.0" in probe.model_name assert probe.get_shank_count() == 1 assert probe.get_contact_count() == 384