Skip to content

Commit

Permalink
IndexSeries tutorial (#1602)
Browse files Browse the repository at this point in the history
* IndexSeries tutorial

* improve text

* Update CHANGELOG.md

* Update docs/gallery/domain/images.py

Co-authored-by: Cody Baker <[email protected]>

* Update docs/gallery/domain/images.py

Co-authored-by: Cody Baker <[email protected]>

* rmv indexed_images from IndexSeres.__nwbfields__

Co-authored-by: Cody Baker <[email protected]>
  • Loading branch information
bendichter and CodyCBakerPhD authored Nov 29, 2022
1 parent e03b0a9 commit c1afdc1
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 13 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
[#1586](https://github.com/NeurodataWithoutBorders/pynwb/pull/1586)
- More informative error message for common installation error. @bendichter, @rly
[#1591](https://github.com/NeurodataWithoutBorders/pynwb/pull/1591)
- Update the [images tutorial](https://pynwb.readthedocs.io/en/stable/tutorials/domain/images.html) to provide example usage of an ``IndexSeries``
with a reference to ``Images``. @bendichter [#1602](https://github.com/NeurodataWithoutBorders/pynwb/pull/1602)

## PyNWB 2.2.0 (October 19, 2022)

Expand Down
52 changes: 52 additions & 0 deletions docs/gallery/domain/images.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,58 @@
nwbfile.add_acquisition(images)

####################
# IndexSeries for repeated images
# -------------------------------
#
# You may want to set up a time series of images where some images are repeated many
# times. You could create an :py:class:`~pynwb.image.ImageSeries` that repeats the data
# each time the image is shown, but that would be inefficient, becuase it would store
# the same data multiple times. A better solution would be to store the unique images
# once and reference those images. This is how :py:class:`~pynwb.image.IndexSeries`
# works. First, create an :py:class:`~pynwb.base.Images` container with the order of
# images defined using an :py:class:`~pynwb.base.ImageReferences`. Then create an
# :py:class:`~pynwb.image.IndexSeries` that indexes into the
# :py:class:`~pynwb.base.Images`.

from scipy import misc

from pynwb.image import Images, IndexSeries, GrayscaleImage, RGBImage
from pynwb.base import ImageReferences


gs_face = GrayscaleImage(
name="gs_face",
data=misc.face(gray=True),
description="Grayscale version of a raccoon.",
resolution=35.433071,
)

rgb_face = RGBImage(
name="rgb_face",
data=misc.face(),
resolution=70.0,
description="RGB version of a raccoon.",
)

images = Images(
name="raccoons",
images=[rgb_face, gs_face],
description="A collection of raccoons.",
order_of_images=ImageReferences("order_of_images", [rgb_face, gs_face]),
)

idx_series = IndexSeries(
name="stimuli",
data=[0, 1, 0, 1],
indexed_images=images,
unit="N/A",
timestamps=[.1, .2, .3, .4],
)

####################
# Here `data` contains the (0-indexed) index of the displayed image as they are ordered
# in the :py:class:`~pynwb.base.ImageReference`.
#
# Writing the images to an NWB File
# ---------------------------------------
# As demonstrated in the :ref:`basic_writing` tutorial, we will use :py:class:`~pynwb.NWBHDF5IO`
Expand Down
49 changes: 36 additions & 13 deletions src/pynwb/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,23 +212,46 @@ class IndexSeries(TimeSeries):
array indicates when that image was displayed.
'''

__nwbfields__ = ('indexed_timeseries',)
__nwbfields__ = ("indexed_timeseries",)

# # value used when an ImageSeries is read and missing data
# DEFAULT_UNIT = 'N/A'

@docval(*get_docval(TimeSeries.__init__, 'name'), # required
{'name': 'data', 'type': ('array_data', 'data', TimeSeries), 'shape': (None, ), # required
'doc': ('The data values. Must be 1D, where the first dimension must be time (frame)')},
*get_docval(TimeSeries.__init__, 'unit'), # required
{'name': 'indexed_timeseries', 'type': TimeSeries, # required
'doc': 'Link to TimeSeries containing images that are indexed.', 'default': None},
{'name': 'indexed_images', 'type': Images, # required
'doc': ("Link to Images object containing an ordered set of images that are indexed. The Images object "
"must contain a 'ordered_images' dataset specifying the order of the images in the Images type."),
'default': None},
*get_docval(TimeSeries.__init__, 'resolution', 'conversion', 'timestamps', 'starting_time', 'rate',
'comments', 'description', 'control', 'control_description', 'offset'))
@docval(
*get_docval(TimeSeries.__init__, 'name'), # required
{
'name': 'data',
'type': ('array_data', 'data', TimeSeries),
'shape': (None,), # required
'doc': 'The data values. Must be 1D, where the first dimension must be time (frame)',
},
*get_docval(TimeSeries.__init__, 'unit'), # required
{
'name': 'indexed_timeseries', 'type': TimeSeries, # required
'doc': 'Link to TimeSeries containing images that are indexed.',
'default': None,
},
{
'name': 'indexed_images',
'type': Images, # required
'doc': "Link to Images object containing an ordered set of images that are indexed. The Images object must "
"contain a 'ordered_images' dataset specifying the order of the images in the Images type.",
'default': None
},
*get_docval(
TimeSeries.__init__,
'resolution',
'conversion',
'timestamps',
'starting_time',
'rate',
'comments',
'description',
'control',
'control_description',
'offset',
),
)
def __init__(self, **kwargs):
indexed_timeseries, indexed_images = popargs('indexed_timeseries', 'indexed_images', kwargs)
if kwargs['unit'] and kwargs['unit'] != 'N/A':
Expand Down

0 comments on commit c1afdc1

Please sign in to comment.