From 2c44de4ac889963aeaee995a36631579137437a3 Mon Sep 17 00:00:00 2001 From: Ryan Ly Date: Tue, 19 Nov 2024 09:50:39 -0800 Subject: [PATCH] Deprecate EventWaveform class (#1940) --- docs/gallery/domain/ecephys.py | 2 +- docs/gallery/general/plot_file.py | 4 +--- src/pynwb/ecephys.py | 11 +++++++++-- tests/integration/hdf5/test_ecephys.py | 11 ++++------- tests/unit/test_ecephys.py | 22 ++-------------------- 5 files changed, 17 insertions(+), 33 deletions(-) diff --git a/docs/gallery/domain/ecephys.py b/docs/gallery/domain/ecephys.py index 30f05a031..3e49857a9 100644 --- a/docs/gallery/domain/ecephys.py +++ b/docs/gallery/domain/ecephys.py @@ -317,7 +317,7 @@ # :py:class:`~pynwb.ecephys.ElectricalSeries` objects as :ref:`acquisition ` data, and use # the :py:class:`~pynwb.ecephys.EventDetection` class for identifying the spike events in your raw traces. # If you do not want to store the raw voltage traces and only the waveform 'snippets' surrounding spike events, -# you should use :py:class:`~pynwb.ecephys.SpikeEventSeries` objects. +# you should store the snippets with :py:class:`~pynwb.ecephys.SpikeEventSeries` objects. # # The results of spike sorting (or clustering) should be stored in the top-level :py:class:`~pynwb.misc.Units` table. # The :py:class:`~pynwb.misc.Units` table can contain simply the spike times of sorted units, or you can also include diff --git a/docs/gallery/general/plot_file.py b/docs/gallery/general/plot_file.py index d80db10ac..659defa38 100644 --- a/docs/gallery/general/plot_file.py +++ b/docs/gallery/general/plot_file.py @@ -92,7 +92,6 @@ :py:class:`~pynwb.behavior.EyeTracking`. * **Extracellular electrophysiology:** :py:class:`~pynwb.ecephys.EventDetection`, - :py:class:`~pynwb.ecephys.EventWaveform`, :py:class:`~pynwb.ecephys.FeatureExtraction`, :py:class:`~pynwb.ecephys.FilteredEphys`, :py:class:`~pynwb.ecephys.LFP`. @@ -593,8 +592,7 @@ #################### # .. [#] Some data interface objects have a default name. This default name is the type of the data interface. For -# example, the default name for :py:class:`~pynwb.ophys.ImageSegmentation` is "ImageSegmentation" and the default -# name for :py:class:`~pynwb.ecephys.EventWaveform` is "EventWaveform". +# example, the default name for :py:class:`~pynwb.ophys.ImageSegmentation` is "ImageSegmentation". # # .. [#] HDF5 is the primary backend supported by NWB. # diff --git a/src/pynwb/ecephys.py b/src/pynwb/ecephys.py index e6dadbe97..07d584a4f 100644 --- a/src/pynwb/ecephys.py +++ b/src/pynwb/ecephys.py @@ -120,8 +120,7 @@ class SpikeEventSeries(ElectricalSeries): """ Stores "snapshots" of spike events (i.e., threshold crossings) in data. This may also be raw data, as reported by ephys hardware. If so, the TimeSeries::description field should describing how - events were detected. All SpikeEventSeries should reside in a module (under EventWaveform - interface) even if the spikes were reported and stored by hardware. All events span the same + events were detected. All events span the same recording channels and store snapshots of equal duration. TimeSeries::data array structure: [num events] [num channels] [num samples] (or [num events] [num samples] for single electrode). @@ -181,6 +180,7 @@ def __init__(self, **kwargs): @register_class('EventWaveform', CORE_NAMESPACE) class EventWaveform(MultiContainerInterface): """ + DEPRECATED as of NWB 2.8.0 and PyNWB 3.0.0. Spike data for spike events detected in raw data stored in this NWBFile, or events detect at acquisition """ @@ -193,6 +193,13 @@ class EventWaveform(MultiContainerInterface): 'create': 'create_spike_event_series' } + def __init__(self, **kwargs): + if not self._in_construct_mode: + raise ValueError( + "The EventWaveform neurodata type is deprecated. If you are interested in using it, " + "please create an issue on https://github.com/NeurodataWithoutBorders/nwb-schema/issues." + ) + @register_class('Clustering', CORE_NAMESPACE) class Clustering(NWBDataInterface): diff --git a/tests/integration/hdf5/test_ecephys.py b/tests/integration/hdf5/test_ecephys.py index c44725277..754c2a8f4 100644 --- a/tests/integration/hdf5/test_ecephys.py +++ b/tests/integration/hdf5/test_ecephys.py @@ -9,7 +9,6 @@ Clustering, ClusterWaveforms, SpikeEventSeries, - EventWaveform, EventDetection, FeatureExtraction, ) @@ -185,7 +184,7 @@ def roundtripExportContainer(self, cache_spec=False): return super().roundtripExportContainer(cache_spec) -class EventWaveformConstructor(NWBH5IOFlexMixin, TestCase): +class SpikeEventSeriesConstructor(NWBH5IOFlexMixin, TestCase): def getContainerType(self): return "SpikeEventSeries" @@ -202,18 +201,16 @@ def addContainer(self): description='the first and third electrodes', table=table) ses = SpikeEventSeries( - name='test_sES', + name='SpikeEventSeries', data=((1, 1), (2, 2), (3, 3)), timestamps=[0., 1., 2.], electrodes=region ) - ew = EventWaveform() - self.nwbfile.add_acquisition(ew) - ew.add_spike_event_series(ses) + self.nwbfile.add_acquisition(ses) def getContainer(self, nwbfile: NWBFile): - return nwbfile.acquisition['EventWaveform'] + return nwbfile.acquisition['SpikeEventSeries'] class ClusterWaveformsConstructor(AcquisitionH5IOMixin, TestCase): diff --git a/tests/unit/test_ecephys.py b/tests/unit/test_ecephys.py index 1415c3d30..0400916d3 100644 --- a/tests/unit/test_ecephys.py +++ b/tests/unit/test_ecephys.py @@ -267,27 +267,9 @@ def test_init(self): class EventWaveformConstructor(TestCase): - def _create_table_and_region(self): - table = make_electrode_table() - region = DynamicTableRegion( - name='electrodes', - data=[0, 2], - description='the first and third electrodes', - table=table - ) - return table, region - def test_init(self): - table, region = self._create_table_and_region() - sES = SpikeEventSeries('test_sES', list(range(10)), list(range(10)), region) - - pm = ProcessingModule(name='test_module', description='a test module') - ew = EventWaveform() - pm.add(table) - pm.add(ew) - ew.add_spike_event_series(sES) - self.assertEqual(ew.spike_event_series['test_sES'], sES) - self.assertEqual(ew['test_sES'], ew.spike_event_series['test_sES']) + with self.assertRaises(ValueError): + EventWaveform() class ClusteringConstructor(TestCase):