From a9dff486280e737d2c7399c1c1e826212c185f74 Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Tue, 13 Oct 2026 12:39:49 +0200 Subject: [PATCH 1/4] fix(openephys): check channel maps on same signal chain as NP probe --- src/probeinterface/neuropixels_tools.py | 25 +- .../settings.xml | 772 ++++++++++++++++++ tests/test_io/test_openephys.py | 15 + 3 files changed, 804 insertions(+), 8 deletions(-) create mode 100644 tests/data/openephys/OE_1.0_Neuropix-multiple-chains/settings.xml diff --git a/src/probeinterface/neuropixels_tools.py b/src/probeinterface/neuropixels_tools.py index ef09d605..d93f1aa5 100644 --- a/src/probeinterface/neuropixels_tools.py +++ b/src/probeinterface/neuropixels_tools.py @@ -1031,29 +1031,38 @@ def _parse_openephys_settings( channel_map = None channel_map_position = None record_node_position = None - proc_counter = 0 + channel_map_chain = None + record_node_chain = None + probe_chain = None - for signal_chain in root.findall("SIGNALCHAIN"): + for chain_index, signal_chain in enumerate(root.findall("SIGNALCHAIN")): + proc_counter = 0 for processor in signal_chain: if "PROCESSOR" == processor.tag: name = processor.attrib["name"] if "Neuropix-PXI" in name: neuropix_pxi_processor = processor + probe_chain = chain_index if "OneBox" in name: onebox_processor = processor + probe_chain = chain_index if "ONIX" in name: onix_processor = processor + probe_chain = chain_index if "Channel Map" in name: channel_map = processor channel_map_position = proc_counter + channel_map_chain = chain_index if "Record Node" in name: record_node_position = proc_counter + record_node_chain = chain_index proc_counter += 1 - # Check if Channel Map comes before Record Node + # Channel Map must be in the same signal chain as the probe and the Record Node, and come before the latter channel_map_before_record_node = ( channel_map_position is not None and record_node_position is not None + and channel_map_chain == record_node_chain == probe_chain and channel_map_position < record_node_position ) @@ -1719,14 +1728,14 @@ def get_saved_channel_indices_from_openephys_settings(settings_file: str | Path, tree = ET.parse(str(settings_file)) root = tree.getroot() - signal_chain = root.find("SIGNALCHAIN") record_node = None - for processor in signal_chain: - if "PROCESSOR" == processor.tag: - name = processor.attrib["name"] - if "Record Node" in name: + for signal_chain in root.findall("SIGNALCHAIN"): + for processor in signal_chain: + if "PROCESSOR" == processor.tag and "Record Node" in processor.attrib["name"]: record_node = processor break + if record_node is not None: + break chans_saved = None if record_node is not None: custom_params = record_node.find("CUSTOM_PARAMETERS") diff --git a/tests/data/openephys/OE_1.0_Neuropix-multiple-chains/settings.xml b/tests/data/openephys/OE_1.0_Neuropix-multiple-chains/settings.xml new file mode 100644 index 00000000..38e294a4 --- /dev/null +++ b/tests/data/openephys/OE_1.0_Neuropix-multiple-chains/settings.xml @@ -0,0 +1,772 @@ + + + + + 1.1.0-preview + 10 + 27 May 2026 11:17:04 + Windows 11 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_io/test_openephys.py b/tests/test_io/test_openephys.py index de51616b..13dc5d41 100644 --- a/tests/test_io/test_openephys.py +++ b/tests/test_io/test_openephys.py @@ -348,6 +348,21 @@ def test_quadbase_custom_names(): ) +def test_probe_with_channel_map_on_different_chain(): + # Tests that a NP probe is correctly instantiated if the settings has a channel map on a different signal chain + probe = read_openephys_neuropixels( + data_path / "OE_1.0_Neuropix-multiple-chains" / "settings.xml", probe_name="ProbeA" + ) + probe_dict = probe.to_dict(array_as_list=True) + validate_probe_dict(probe_dict) + assert probe.get_shank_count() == 4 + assert probe.get_contact_count() == 384 + assert set(probe.shank_ids) == set(["0", "1", "2", "3"]) + assert probe.name == "ProbeA" + assert "adc_group" in probe.contact_annotations + assert "adc_sample_order" in probe.contact_annotations + + def test_onebox(): # This dataset has a Neuropixels Ultra probe with a onebox probe = read_openephys_neuropixels(data_path / "OE_OneBox-NP-Ultra" / "settings.xml") From f3b01818b05e1d53ed453c489cf4b6cf48175d91 Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Tue, 13 Oct 2026 12:50:23 +0200 Subject: [PATCH 2/4] build: v0.4.1 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6f148c66..69490d28 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "probeinterface" -version = "0.4.0" +version = "0.4.1" authors = [ { name="Samuel Garcia", email="sam.garcia.die@gmail.com" }, { name="Alessio Buccino", email="alessiop.buccino@gmail.com" }, From f07922be29eafbb834ecf38a0124ff4eef6b6327 Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Tue, 13 Oct 2026 12:51:41 +0200 Subject: [PATCH 3/4] bump up to v0.4.1 --- doc/release_notes.rst | 1 + doc/releases/0.4.1.rst | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 doc/releases/0.4.1.rst diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 01be54e9..5e1cb072 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -6,6 +6,7 @@ Release notes .. toctree:: :maxdepth: 1 + releases/0.4.1.rst releases/0.4.0.rst releases/0.3.2.rst releases/0.3.1.rst diff --git a/doc/releases/0.4.1.rst b/doc/releases/0.4.1.rst new file mode 100644 index 00000000..acf64f25 --- /dev/null +++ b/doc/releases/0.4.1.rst @@ -0,0 +1,9 @@ +probeinterface 0.4.1 +-------------------- + +Oct, 13th 2026 + + +Bug fixes +^^^^^^^^^ +* OpenEphys: check channel maps on same signal chain as NP probe (#471) \ No newline at end of file From 91ec74a7c2660a8e2330c86b016dc4d164fb6e2c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 13 Oct 2026 10:51:58 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/releases/0.4.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/releases/0.4.1.rst b/doc/releases/0.4.1.rst index acf64f25..9eb0b6e7 100644 --- a/doc/releases/0.4.1.rst +++ b/doc/releases/0.4.1.rst @@ -6,4 +6,4 @@ Oct, 13th 2026 Bug fixes ^^^^^^^^^ -* OpenEphys: check channel maps on same signal chain as NP probe (#471) \ No newline at end of file +* OpenEphys: check channel maps on same signal chain as NP probe (#471)