diff --git a/doc/source/authors.rst b/doc/source/authors.rst index c4065ac6c..a2e15bdba 100644 --- a/doc/source/authors.rst +++ b/doc/source/authors.rst @@ -102,6 +102,7 @@ and may not be the current affiliation of a contributor. * LizzyMcKay (github) * Reema Gupta [50] * Sai Asish Yamani [51] +* Kevin Doran [52] 1. Centre de Recherche en Neuroscience de Lyon, CNRS UMR5292 - INSERM U1028 - Université Claude Bernard Lyon 1 2. Unité de Neuroscience, Information et Complexité, CNRS UPR 3293, Gif-sur-Yvette, France @@ -154,6 +155,7 @@ and may not be the current affiliation of a contributor. 49. Swartz Center for Computational Neuroscience, University of California, San Diego 50. Ludwig-Maximilians-Universität München, Munich, Germany 51. Stony Brook University, Stony Brook, NY, USA +52. University of Sussex, Brighton, UK diff --git a/neo/rawio/biocamrawio.py b/neo/rawio/biocamrawio.py index 3aac8d2fc..d62cd6581 100644 --- a/neo/rawio/biocamrawio.py +++ b/neo/rawio/biocamrawio.py @@ -213,7 +213,9 @@ def open_biocam_file_header(filename) -> dict: if "3BRecInfo" in rf.keys(): # brw v3.x # Read recording variables rec_vars = rf.require_group("3BRecInfo/3BRecVars/") - bit_depth = rec_vars["BitDepth"][0] + # Biocam v3.x stores BitDepth as a np.uint8. + # Convert to int to avoid overflow when calculating gain. + bit_depth = int(rec_vars["BitDepth"][0]) max_uv = rec_vars["MaxVolt"][0] min_uv = rec_vars["MinVolt"][0] num_frames = rec_vars["NRecFrames"][0] diff --git a/neo/test/rawiotest/test_biocamrawio.py b/neo/test/rawiotest/test_biocamrawio.py index b7dd0c906..12ebf39ad 100644 --- a/neo/test/rawiotest/test_biocamrawio.py +++ b/neo/test/rawiotest/test_biocamrawio.py @@ -3,6 +3,10 @@ """ import unittest +import pytest + +import numpy as np +import h5py from neo.rawio.biocamrawio import BiocamRawIO from neo.test.rawiotest.common_rawio_test import BaseTestRawIO @@ -23,5 +27,39 @@ class TestBiocamRawIO( ] +def test_biocamrawio_gain(tmp_path): + """Test that BiocamRawIO correctly reads the gain from a Biocam HDF5 file. + + A test case, from Issue #1883 (https://github.com/NeuralEnsemble/python-neo/issues/1883). + Previously, BiocamRawIO would return a gain of `inf`, due to a numpy dtype + overflow bug. + """ + # Setup + n_ch = 4 + n_frames = 10 + path = tmp_path / "minimal_v3.brw" + bit_depth = 12 + max_volt = 4125.0 + min_volt = -4125.0 + with h5py.File(path, "w") as f: + rv = f.create_group("3BRecInfo/3BRecVars") + rv.create_dataset("BitDepth", data=np.array([bit_depth], dtype=np.uint8)) + rv.create_dataset("MaxVolt", data=np.array([max_volt])) + rv.create_dataset("MinVolt", data=np.array([min_volt])) + rv.create_dataset("NRecFrames", data=np.array([n_frames], dtype=np.int64)) + rv.create_dataset("SamplingRate", data=np.array([17852.77])) + rv.create_dataset("SignalInversion", data=np.array([1], dtype=np.int32)) + f.create_dataset("3BRecInfo/3BMeaStreams/Raw/Chs", data=np.arange(2 * n_ch, dtype=np.int32).reshape(n_ch, 2)) + f.create_dataset("3BData/Raw", data=np.zeros(n_ch * n_frames, dtype=np.uint16)) + f["3BData"].attrs["Version"] = 102 + + # Test + r = BiocamRawIO(filename=path) + r.parse_header() + expected_gain = (max_volt - min_volt) / 2**bit_depth # ~ 2.014 + gain = r.header["signal_channels"]["gain"][0] + assert expected_gain == pytest.approx(gain) + + if __name__ == "__main__": unittest.main()