Skip to content

Commit

Permalink
Fix channel gains in NwbRecordingExtractor with backend (#2661)
Browse files Browse the repository at this point in the history
* add failing test

* add passing test

* update pynwb

* re-vert in streaming extractors

---------

Co-authored-by: Alessio Buccino <[email protected]>
  • Loading branch information
h-mayorquin and alejoe91 authored Apr 4, 2024
1 parent ea83a86 commit 74abe6c
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 19 deletions.
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ changelog = "https://spikeinterface.readthedocs.io/en/latest/whatisnew.html"

extractors = [
"MEArec>=1.8",
"pynwb>=2.3.0",
"pynwb>=2.6.0",
"hdmf-zarr>=0.5.0",
"pyedflib>=0.1.30",
"sonpy;python_version<'3.10'",
Expand All @@ -77,10 +77,10 @@ streaming_extractors = [
"scipy<1.13", # ibl has a dependency on scipy but it does not have an upper bound
# Remove this once https://github.com/int-brain-lab/ibllib/issues/753
# Following dependencies are for streaming with nwb files
"pynwb>=2.6.0",
"fsspec",
"aiohttp",
"requests",
"pynwb>=2.3.0",
"hdmf-zarr>=0.5.0",
"remfile",
"s3fs"
Expand Down
3 changes: 2 additions & 1 deletion src/spikeinterface/extractors/nwbextractors.py
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,8 @@ def _fetch_main_properties_backend(self):
data_attributes = self.electrical_series["data"].attrs
electrical_series_conversion = data_attributes["conversion"]
gains = electrical_series_conversion * 1e6
if "channel_conversion" in data_attributes:
channel_conversion = self.electrical_series.get("channel_conversion", None)
if channel_conversion:
gains *= self.electrical_series["channel_conversion"][:]

# Channel offsets
Expand Down
39 changes: 23 additions & 16 deletions src/spikeinterface/extractors/tests/test_nwbextractors.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class NwbSortingTest(SortingCommonTestSuite, unittest.TestCase):


def nwbfile_with_ecephys_content():
to_micro_volts = 1e6

nwbfile = mock_NWBFile()
device = mock_Device(name="probe")
nwbfile.add_device(device)
Expand All @@ -48,7 +50,7 @@ def nwbfile_with_ecephys_content():
nwbfile.add_electrode_group(electrode_group)
rel_x = 0.0
property_value = "A"
offset = 1.0
offset = 1.0 * to_micro_volts
electrical_series_name = "ElectricalSeries1"
electrode_indices = [0, 1, 2, 3, 4]

Expand All @@ -67,15 +69,20 @@ def nwbfile_with_ecephys_content():
nwbfile.add_electrode(id=index, **electrodes_info)

electrode_region = nwbfile.create_electrode_table_region(region=electrode_indices, description="electrodes")
electrical_series = mock_ElectricalSeries(name=electrical_series_name, electrodes=electrode_region)
channel_conversion = 2.0 * np.ones(len(electrode_indices)) * to_micro_volts
electrical_series = mock_ElectricalSeries(
name=electrical_series_name,
electrodes=electrode_region,
channel_conversion=channel_conversion,
)
nwbfile.add_acquisition(electrical_series)

electrode_group = mock_ElectrodeGroup(device=device)
nwbfile.add_electrode_group(electrode_group)

rel_x = 3.0
property_value = "B"
offset = 2.0
offset = 2.0 * to_micro_volts
electrical_series_name = "ElectricalSeries2"
electrode_indices = [5, 6, 7, 8, 9]

Expand All @@ -98,8 +105,8 @@ def nwbfile_with_ecephys_content():
rng = np.random.default_rng(0)
data = rng.random(size=(num_frames, len(electrode_indices)))
rate = 30_000.0
conversion = 5.0
a_different_offset = offset + 1.0
conversion = 5.0 * to_micro_volts
a_different_offset = offset + 1.0 * to_micro_volts
electrical_series = ElectricalSeries(
name=electrical_series_name,
data=data,
Expand All @@ -115,8 +122,8 @@ def nwbfile_with_ecephys_content():
electrode_indices = [5, 6, 7, 8, 9]
data = rng.random(size=(num_frames, len(electrode_indices)))
rate = 30_000.0
conversion = 5.0
a_different_offset = offset + 1.0
conversion = 5.0 * to_micro_volts
a_different_offset = offset + 1.0 * to_micro_volts
electrical_series = ElectricalSeries(
name=electrical_series_name,
data=data,
Expand All @@ -130,13 +137,13 @@ def nwbfile_with_ecephys_content():
ecephys_mod.data_interfaces["LFP"].add_electrical_series(electrical_series)

# custom module
# add electrical series in processing
# add electrical series in custom preprocessing module
electrical_series_name = "ElectricalSeries2"
electrode_indices = [0, 1, 2, 3, 4]
data = rng.random(size=(num_frames, len(electrode_indices)))
rate = 30_000.0
conversion = 5.0
a_different_offset = offset + 1.0
conversion = 5.0 * to_micro_volts
a_different_offset = offset + 1.0 * to_micro_volts
electrical_series = ElectricalSeries(
name=electrical_series_name,
data=data,
Expand Down Expand Up @@ -312,22 +319,22 @@ def test_retrieving_from_processing(generate_nwbfile, use_pynwb):
assert np.array_equal(electrical_series_custom.data[:], recording_extractor_custom.get_traces())


@pytest.mark.parametrize("electrical_series_name", ["acquisition/ElectricalSeries1", "acquisition/ElectricalSeries2"])
def test_that_hdf5_and_pynwb_extractors_return_the_same_data(generate_nwbfile, electrical_series_name):
@pytest.mark.parametrize("electrical_series_path", ["acquisition/ElectricalSeries1", "acquisition/ElectricalSeries2"])
def test_recording_equality_with_pynwb_and_backend(generate_nwbfile, electrical_series_path):
path_to_nwbfile, _ = generate_nwbfile
recording_extractor_hdf5 = NwbRecordingExtractor(
recording_extractor_backend = NwbRecordingExtractor(
path_to_nwbfile,
electrical_series_path=electrical_series_name,
electrical_series_path=electrical_series_path,
use_pynwb=False,
)

recording_extractor_pynwb = NwbRecordingExtractor(
path_to_nwbfile,
electrical_series_path=electrical_series_name,
electrical_series_path=electrical_series_path,
use_pynwb=True,
)

check_recordings_equal(recording_extractor_hdf5, recording_extractor_pynwb)
check_recordings_equal(recording_extractor_backend, recording_extractor_pynwb)


@pytest.mark.parametrize("use_pynwb", [True, False])
Expand Down

0 comments on commit 74abe6c

Please sign in to comment.