Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ package-dir = {"probeinterface" = "src/probeinterface"}
[project.optional-dependencies]

test = [
"jsonschema",
"pytest",
"pytest-cov",
"matplotlib",
Expand Down
8 changes: 6 additions & 2 deletions resources/probe.json.schema
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@
"annotations": {
"type": "object",
"properties": {
"name": { "type": "string" },
"model_name": { "type": "string" },
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure about this name change. Both "name" and "model_name" are present as metadata, and neither required by the probe object. Should we make it required here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want the json_schema to map perfectly onto the Probe object, or might it make sense of have them hav slightly different requirements?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @bendichter

I think it makes sense to have model_name and not name as required. name is a custom name that can be defined for a probe (e.g., ProbeA-B-C for Open Ephys system), but definitely not a requirement.

"manufacturer": { "type": "string" }
},
"required": ["name", "manufacturer"],
"required": ["model_name", "manufacturer"],
"additionalProperties": true
},
"contact_annotations": {
Expand Down Expand Up @@ -101,6 +101,10 @@
"shank_ids": {
"type": "array",
"items": { "type": "string" }
},
"device_channel_indices": {
"type": "array",
"items": { "type": "integer" }
}
},
"required": [
Expand Down
1 change: 0 additions & 1 deletion src/probeinterface/probe.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import numpy as np
from typing import Optional
from pathlib import Path
import json

from .shank import Shank

Expand Down
13 changes: 13 additions & 0 deletions src/probeinterface/testing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
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)
12 changes: 12 additions & 0 deletions tests/test_io/test_3brain.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
import glob
from pathlib import Path
import numpy as np

import pytest

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"""
Expand Down
11 changes: 11 additions & 0 deletions tests/test_io/test_imro.py
Original file line number Diff line number Diff line change
@@ -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):
Expand Down
9 changes: 9 additions & 0 deletions tests/test_io/test_maxwell.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"""

Expand Down
9 changes: 9 additions & 0 deletions tests/test_io/test_spikeglx.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import glob
from pathlib import Path
import numpy as np

Expand All @@ -8,8 +9,16 @@
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"
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():
Expand Down
Loading