Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update tests to fix validation errors and warning #1839

Merged
merged 4 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ version: 2
build:
os: ubuntu-20.04
tools:
python: '3.8'
python: '3.11'

# Build documentation in the docs/ directory with Sphinx
sphinx:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Expose `starting_time` in `mock_ElectricalSeries`. @h-mayorquin [#1805](https://github.com/NeurodataWithoutBorders/pynwb/pull/1805)
- Enhance `get_data_in_units()` to work with objects that have a `channel_conversion` attribute like the `ElectricalSeries`. @h-mayorquin [#1806](https://github.com/NeurodataWithoutBorders/pynwb/pull/1806)
- Refactor validation CLI tests to use `{sys.executable} -m coverage` to use the same Python version and run correctly on Debian systems. @yarikoptic [#1811](https://github.com/NeurodataWithoutBorders/pynwb/pull/1811)
- Fixed tests to address newly caught validation errors. @rly [#1839](https://github.com/NeurodataWithoutBorders/pynwb/pull/1839)

### Bug fixes
- Fix bug where namespaces were loaded in "w-" mode. @h-mayorquin [#1795](https://github.com/NeurodataWithoutBorders/pynwb/pull/1795)
Expand Down
2 changes: 1 addition & 1 deletion docs/source/overview_citing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ If you use PyNWB in your research, please use the following citation:
Using RRID
----------

* ResourceID: `SCR_017452 <https://scicrunch.org/browse/resources/SCR_017452>`_
* ResourceID: `SCR_017452 <https://scicrunch.org/resolver/SCR_017452>`_
* Proper Citation: **(PyNWB, RRID:SCR_017452)**


Expand Down
2 changes: 1 addition & 1 deletion requirements-min.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# minimum versions of package dependencies for installing PyNWB
h5py==2.10 # support for selection of datasets with list of indices added in 2.10
hdmf==3.9.0
hdmf==3.12.0
numpy==1.18
pandas==1.1.5
python-dateutil==2.7.3
Expand Down
10 changes: 5 additions & 5 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# pinned dependencies to reproduce an entire development environment to use PyNWB
h5py==3.8.0
hdmf==3.9.0
numpy==1.24.2
pandas==2.0.0
h5py==3.10.0
hdmf==3.12.0
numpy==1.26.1
pandas==2.1.2
python-dateutil==2.8.2
setuptools==65.5.1
setuptools==65.5.1
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

reqs = [
'h5py>=2.10',
'hdmf>=3.9.0',
'hdmf>=3.12.0',
'numpy>=1.16',
'pandas>=1.1.5',
'python-dateutil>=2.7.3',
Expand Down
6 changes: 5 additions & 1 deletion src/pynwb/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,11 @@ def _get_cached_namespaces_to_validate(
is_method=False,
)
def validate(**kwargs):
"""Validate NWB file(s) against a namespace or its cached namespaces."""
"""Validate NWB file(s) against a namespace or its cached namespaces.

NOTE: If an io object is provided and no namespace name is specified, then the file will be validated
against the core namespace, even if use_cached_namespaces is True.
"""
from . import NWBHDF5IO # TODO: modularize to avoid circular import

io, paths, use_cached_namespaces, namespace, verbose, driver = getargs(
Expand Down
6 changes: 6 additions & 0 deletions tests/back_compat/test_read.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ class TestReadOldVersions(TestCase):
"- expected an array of shape '[None]', got non-array data 'one publication'")],
'1.0.3_str_pub.nwb': [("root/general/related_publications (general/related_publications): incorrect shape "
"- expected an array of shape '[None]', got non-array data 'one publication'")],
'1.5.1_timeseries_no_data.nwb': [("TimeSeries/data/data (acquisition/test_timeseries/data): argument missing")],
'1.5.1_timeseries_no_unit.nwb': [("TimeSeries/data/unit (acquisition/test_timeseries/data): argument missing")],
'1.5.1_imageseries_no_data.nwb': [("ImageSeries/data/data (acquisition/test_imageseries/data): "
"argument missing")],
'1.5.1_imageseries_no_unit.nwb': [("ImageSeries/data/unit (acquisition/test_imageseries/data): "
"argument missing")],
}

def get_io(self, path):
Expand Down
93 changes: 65 additions & 28 deletions tests/integration/hdf5/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,20 +109,36 @@ class TestDecompositionSeriesIO(NWBH5IOMixin, TestCase):

def setUpContainer(self):
""" Return the test DecompositionSeries to read/write """
self.timeseries = TimeSeries(name='dummy timeseries', description='desc',
data=np.ones((3, 3)), unit='flibs',
timestamps=np.ones((3,)))
bands = DynamicTable(name='bands', description='band info for LFPSpectralAnalysis', columns=[
VectorData(name='band_name', description='name of bands', data=['alpha', 'beta', 'gamma']),
VectorData(name='band_limits', description='low and high cutoffs in Hz', data=np.ones((3, 2)))
])
spec_anal = DecompositionSeries(name='LFPSpectralAnalysis',
description='my description',
data=np.ones((3, 3, 3)),
timestamps=np.ones((3,)),
source_timeseries=self.timeseries,
metric='amplitude',
bands=bands)
self.timeseries = TimeSeries(
name='dummy timeseries',
description='desc',
data=np.ones((3, 3)),
unit='flibs',
timestamps=np.ones((3,)),
)
bands = DynamicTable(
name='bands',
description='band info for LFPSpectralAnalysis',
columns=[
VectorData(name='band_name', description='name of bands', data=['alpha', 'beta', 'gamma']),
VectorData(name='band_limits', description='low and high cutoffs in Hz', data=np.ones((3, 2))),
VectorData(name='band_mean', description='mean gaussian filters in Hz', data=np.ones((3,))),
VectorData(
name='band_stdev',
description='standard deviation of gaussian filters in Hz',
data=np.ones((3,))
),
],
)
spec_anal = DecompositionSeries(
name='LFPSpectralAnalysis',
description='my description',
data=np.ones((3, 3, 3)),
timestamps=np.ones((3,)),
source_timeseries=self.timeseries,
metric='amplitude',
bands=bands,
)

return spec_anal

Expand All @@ -144,27 +160,48 @@ def make_electrode_table(self):
""" Make an electrode table, electrode group, and device """
self.table = get_electrode_table()
self.dev1 = Device(name='dev1')
self.group = ElectrodeGroup(name='tetrode1',
description='tetrode description',
location='tetrode location',
device=self.dev1)
for i in range(4):
self.group = ElectrodeGroup(
name='tetrode1',
description='tetrode description',
location='tetrode location',
device=self.dev1
)
for _ in range(4):
self.table.add_row(location='CA1', group=self.group, group_name='tetrode1')

def setUpContainer(self):
""" Return the test ElectricalSeries to read/write """
self.make_electrode_table(self)
region = DynamicTableRegion(name='source_channels',
data=[0, 2],
description='the first and third electrodes',
table=self.table)
region = DynamicTableRegion(
name='source_channels',
data=[0, 2],
description='the first and third electrodes',
table=self.table
)
data = np.random.randn(100, 2, 30)
timestamps = np.arange(100)/100
ds = DecompositionSeries(name='test_DS',
data=data,
source_channels=region,
timestamps=timestamps,
metric='amplitude')
bands = DynamicTable(
name='bands',
description='band info for LFPSpectralAnalysis',
columns=[
VectorData(name='band_name', description='name of bands', data=['alpha', 'beta', 'gamma']),
VectorData(name='band_limits', description='low and high cutoffs in Hz', data=np.ones((3, 2))),
VectorData(name='band_mean', description='mean gaussian filters in Hz', data=np.ones((3,))),
VectorData(
name='band_stdev',
description='standard deviation of gaussian filters in Hz',
data=np.ones((3,))
),
],
)
ds = DecompositionSeries(
name='test_DS',
data=data,
source_channels=region,
timestamps=timestamps,
metric='amplitude',
bands=bands,
)
return ds

def addContainer(self, nwbfile):
Expand Down
29 changes: 21 additions & 8 deletions tests/integration/ros3/test_ros3.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from pynwb.testing import TestCase
import urllib.request
import h5py
import warnings


class TestRos3Streaming(TestCase):
Expand All @@ -28,16 +29,28 @@ def setUp(self):

def test_read(self):
s3_path = 'https://dandiarchive.s3.amazonaws.com/ros3test.nwb'
with NWBHDF5IO(s3_path, mode='r', driver='ros3') as io:
nwbfile = io.read()
test_data = nwbfile.acquisition['ts_name'].data[:]
self.assertEqual(len(test_data), 3)
with warnings.catch_warnings():
warnings.filterwarnings(
"ignore",
message=r"Ignoring cached namespace .*",
category=UserWarning,
)
with NWBHDF5IO(s3_path, mode='r', driver='ros3') as io:
nwbfile = io.read()
test_data = nwbfile.acquisition['ts_name'].data[:]
self.assertEqual(len(test_data), 3)

def test_dandi_read(self):
with NWBHDF5IO(path=self.s3_test_path, mode='r', driver='ros3') as io:
nwbfile = io.read()
test_data = nwbfile.acquisition['TestData'].data[:]
self.assertEqual(len(test_data), 3)
with warnings.catch_warnings():
warnings.filterwarnings(
"ignore",
message=r"Ignoring cached namespace .*",
category=UserWarning,
)
with NWBHDF5IO(path=self.s3_test_path, mode='r', driver='ros3') as io:
nwbfile = io.read()
test_data = nwbfile.acquisition['TestData'].data[:]
self.assertEqual(len(test_data), 3)

def test_dandi_get_cached_namespaces(self):
expected_namespaces = ["core"]
Expand Down
10 changes: 9 additions & 1 deletion tests/unit/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,13 @@ def test_init(self):
timestamps=[1., 2., 3.])
bands = DynamicTable(name='bands', description='band info for LFPSpectralAnalysis', columns=[
VectorData(name='band_name', description='name of bands', data=['alpha', 'beta', 'gamma']),
VectorData(name='band_limits', description='low and high cutoffs in Hz', data=np.ones((3, 2)))
VectorData(name='band_limits', description='low and high cutoffs in Hz', data=np.ones((3, 2))),
VectorData(name='band_mean', description='mean gaussian filters in Hz', data=np.ones((3,))),
VectorData(
name='band_stdev',
description='standard deviation of gaussian filters in Hz',
data=np.ones((3,))
),
])
spec_anal = DecompositionSeries(name='LFPSpectralAnalysis',
description='my description',
Expand All @@ -49,6 +55,8 @@ def test_init(self):
np.testing.assert_equal(spec_anal.timestamps, [1., 2., 3.])
self.assertEqual(spec_anal.bands['band_name'].data, ['alpha', 'beta', 'gamma'])
np.testing.assert_equal(spec_anal.bands['band_limits'].data, np.ones((3, 2)))
np.testing.assert_equal(spec_anal.bands['band_mean'].data, np.ones((3,)))
np.testing.assert_equal(spec_anal.bands['band_stdev'].data, np.ones((3,)))
self.assertEqual(spec_anal.source_timeseries, timeseries)
self.assertEqual(spec_anal.metric, 'amplitude')

Expand Down
Loading