Skip to content

Commit

Permalink
add empty TimeSeriesReference method
Browse files Browse the repository at this point in the history
  • Loading branch information
stephprince committed Jan 10, 2024
1 parent efae480 commit adfaf2e
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 4 deletions.
8 changes: 4 additions & 4 deletions docs/gallery/domain/plot_icephys.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@

# Import additional core datatypes used in the example
from pynwb.core import DynamicTable, VectorData
from pynwb.base import TimeSeriesReferenceVectorData
from pynwb.base import TimeSeriesReference, TimeSeriesReferenceVectorData

# Import icephys TimeSeries types used
from pynwb.icephys import VoltageClampSeries, VoltageClampStimulusSeries
Expand Down Expand Up @@ -465,9 +465,9 @@

nwbfile.intracellular_recordings.add_column(
name="stimulus_template",
data=[(0, 5, stimulus), # (start_index, index_count, stimulus_template) can be specified as a tuple
(1, 3, stimulus),
(-1, -1, stimulus)],
data=[TimeSeriesReference(0, 5, stimulus), # (start_index, index_count, stimulus_template)
TimeSeriesReference(1, 3, stimulus),
TimeSeriesReference.empty(stimulus)], # if there was no data for that recording, use an empty reference
description="Column storing the reference to the stimulus template for the recording (rows).",
category="stimuli",
col_cls=TimeSeriesReferenceVectorData
Expand Down
19 changes: 19 additions & 0 deletions src/pynwb/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,25 @@ def data(self):
# load the data from the timeseries
return self.timeseries.data[self.idx_start: (self.idx_start + self.count)]

@classmethod
@docval({'name': 'timeseries', 'type': TimeSeries, 'doc': 'the timeseries object to reference.'})
def empty(cls, timeseries):
"""
Creates an empty TimeSeriesReference class to represent missing data.
When missing data needs to be represented, NWB defines ``None`` for the complex data type ``(idx_start,
count, TimeSeries)`` as (-1, -1, TimeSeries) for storage. The exact timeseries object will technically not
matter since the empty reference is a way of indicating a NaN value. In practice, this may be used in the
:py:class:`~pynwb.icephys.IntracellularRecordingsTable` where only one of stimulus or response data was
recorded. In such cases, the timeseries object for the empty stimulus TimeSeriesReference could be set to the
response series or vice versa (the timeseries object for the empty response TimeSeriesReference could be set
to the stimulus)
:returns: Returns :py:class:`~pynwb.base.TimeSeriesReference`
"""

return cls(-1, -1, timeseries)


@register_class('TimeSeriesReferenceVectorData', CORE_NAMESPACE)
class TimeSeriesReferenceVectorData(VectorData):
Expand Down
11 changes: 11 additions & 0 deletions tests/unit/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -877,3 +877,14 @@ def test_data_property_bad_reference(self):
IndexError, "'idx_start + count' out of range for timeseries 'test'"
):
tsr.data

def test_empty_reference_creation(self):
tsr = TimeSeriesReference.empty(self._create_time_series_with_rate())
self.assertFalse(tsr.isvalid())
self.assertIsNone(tsr.data)
self.assertIsNone(tsr.timestamps)

def test_empty_reference_creation_invalid_type(self):
tsr = TimeSeriesReference.empty(None)
with self.assertRaisesWith(TypeError, "timeseries must be of type TimeSeries. <class 'NoneType'>"):
tsr.check_types()

0 comments on commit adfaf2e

Please sign in to comment.