Skip to content

Commit

Permalink
some adjustments to the behavioral tutorial
Browse files Browse the repository at this point in the history
  • Loading branch information
bendichter committed Apr 29, 2022
1 parent af75b33 commit 55cd668
Showing 1 changed file with 62 additions and 81 deletions.
143 changes: 62 additions & 81 deletions docs/gallery/domain/plot_behavior.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@
Behavior Data
==================================
This tutorial will demonstrate the usage of the :py:class:`~pynwb.behavior` module for adding
behavior data to an :py:class:`~pynwb.file.NWBFile`.
An :py:class:`~pynwb.file.NWBFile` represents a single session of an experiment.
It contains all the data of that session and the metadata required to understand the data.
This tutorial will demonstrate the usage of the :py:mod:`pynwb.behavior` module for adding
behavioral data to an :py:class:`~pynwb.file.NWBFile`.
.. seealso::
You can learn more about the :py:class:`~pynwb.file.NWBFile` format in the :ref:`basics` tutorial.
Expand Down Expand Up @@ -40,7 +36,7 @@

####################
# Create an NWB File
# ------------
# ------------------
#
# Create an :py:class:`~pynwb.file.NWBFile` object with the required fields
# (``session_description``, ``identifier``, ``session_start_time``) and additional metadata.
Expand All @@ -61,14 +57,12 @@
nwbfile

####################
# Position
# ------------
#
# Spatial Series
# ^^^^^^^^^^^^^^^
# SpatialSeries
# --------------
#
# :py:class:`~pynwb.behavior.SpatialSeries` is a subclass of :py:class:`~pynwb.base.TimeSeries`
# that represents the spatial direction, e.g., of gaze or travel, or position of an animal over time.
# that represents data in space, such as the spatial direction, e.g., of gaze or travel,
# or position of an animal over time.
#
# .. seealso::
# You can learn more about the :py:class:`~pynwb.behavior.SpatialSeries` data type and
Expand Down Expand Up @@ -111,9 +105,13 @@
# You can learn more about best practices that can be applied to
# :py:class:`~pynwb.behavior.SpatialSeries` `here <https://www.nwb.org/best-practices/#timeseries>`_.
#
# Position
# --------
#
# To help data analysis and visualization tools know that this :py:class:`~pynwb.behavior.SpatialSeries` object
# represents the position of the subject, store the :py:class:`~pynwb.behavior.SpatialSeries` object inside
# of a :py:class:`~pynwb.behavior.Position` object, which can hold one or more :py:class:`~pynwb.behavior.SpatialSeries` objects.
# a :py:class:`~pynwb.behavior.Position` object, which can hold one or more :py:class:`~pynwb.behavior.SpatialSeries`
# objects.

position = Position(spatial_series=position_spatial_series)

Expand All @@ -126,8 +124,8 @@
# You can read more about the basic concepts of processing modules in the :ref:`modules_overview` tutorial.
#
# Create a processing module called ``"behavior"`` for storing behavioral data in the :py:class:`~pynwb.file.NWBFile`
# and add the :py:class:`~pynwb.behavior.Position` object to the processing module using the
# :py:meth:`~pynwb.file.NWBFile.create_processing_module` method:
# using the :py:meth:`~pynwb.file.NWBFile.create_processing_module` method, then and add the
# :py:class:`~pynwb.behavior.Position` object to the processing module.


behavior_module = nwbfile.create_processing_module(
Expand All @@ -139,10 +137,7 @@

####################
# CompassDirection
# ------------
#
# Spatial Series
# ^^^^^^^^^^^^^^^
# ----------------
#
# Analogous to how position can be stored, we can create a :py:class:`~pynwb.behavior.SpatialSeries`
# object for representing the view angle of the subject.
Expand All @@ -158,7 +153,7 @@
description="view angle",
data=view_angle_data,
timestamps=timestamps,
reference_frame="bottom left",
reference_frame="straight ahead",
unit="radians",
)

Expand All @@ -175,10 +170,10 @@

####################
# BehavioralTimeSeries
# ------------
# --------------------
#
# :py:class:`~pynwb.behavior.BehavioralTimeSeries` is an interface for storing continuous behavior data.
# Create a :py:class:`~pynwb.base.TimeSeries` object that represents the speed/velocity of an animal.
# :py:class:`~pynwb.behavior.BehavioralTimeSeries` is an interface for storing continuous behavior data, such as the
# speed of an subject.

speed_data = np.linspace(0, 0.4, 50)

Expand All @@ -194,67 +189,71 @@
name="BehavioralTimeSeries",
)

behavior_module.add(behavioral_time_series)

####################
# BehavioralEvents
# ------------
# ----------------
#
# :py:class:`~pynwb.behavior.BehavioralEvents` is an interface for storing behavioral events.
# We can use it for storing the amount of reward (e.g. water amount) - floats
# or duration of stimulus (floats of timestamps) happened irregularly
# Create a :py:class:`~pynwb.base.TimeSeries` object that represents the speed/velocity of an animal.

data = np.full(50, np.nan)
duration_of_stimulus = np.ones(10, dtype=float)
data[::5] = duration_of_stimulus
# We can use it for storing the timing and amount of rewards (e.g. water amount) or lever press times.

events_timestamps = np.full(50, np.nan)
events_timestamps[::5] = timestamps[np.where(~np.isnan(data))]
reward_amount = [1., 1.5, 1., 1.5]
events_timestamps = [1., 2., 5., 6.]

time_series = TimeSeries(
name="stimulus_duration",
data=data,
name="lever_presses",
data=reward_amount,
timestamps=events_timestamps,
unit="seconds",
unit="ml",
)

behavioral_events = BehavioralEvents(time_series=time_series, name="BehavioralEvents")

behavior_module.add(behavioral_events)

####################
# BehavioralEpochs
# ------------
# ----------------
# :py:class:`~pynwb.behavior.BehavioralEpochs` is for storing intervals of behavior data.
# :py:class:`~pynwb.behavior.BehavioralEpochs` uses :py:class:`~pynwb.misc.IntervalSeries`
# to represent behavioral epochs.
#
# Create :py:class:`~pynwb.misc.IntervalSeries` object that represents the time intervals
# when the animal was running.
# when the animal was running. :py:class:`~pynwb.misc.IntervalSeries` uses 1 to indicate
# the beginning of an interval and -1 to indicate the end.


run_intervals_1 = IntervalSeries(
name="run_intervals_1",
description="intervals when the animal was running",
data=np.arange(6, 18, 1),
timestamps=np.arange(6, 18, 1).astype(float),
)

run_intervals_2 = IntervalSeries(
name="run_intervals_2",
description="intervals when the animal was running",
data=np.arange(22, 34, 1),
timestamps=np.arange(22, 34, 1).astype(float),
run_intervals = IntervalSeries(
name="running",
description="intervals when the animal was running.",
data=[1, -1, 1, -1, 1, -1],
timestamps=[0.5, 1.5, 3.5, 4.0, 7.0, 7.3],
)

behavioral_epochs = BehavioralEpochs(name="BehavioralEpochs")

behavioral_epochs.add_interval_series(run_intervals_1)
behavioral_epochs.add_interval_series(run_intervals_2)
behavioral_epochs.add_interval_series(run_intervals)

####################
# you can add more than one :py:class:`~pynwb.misc.IntervalSeries` to a
# :py:class:`~pynwb.behavior.BehavioralEpochs`

sleep_intervals = IntervalSeries(
name="sleeping",
description="intervals when the animal was sleeping.",
data=[1, -1, 1, -1],
timestamps=[15.0, 30.0, 60.0, 95.0],
)
behavioral_epochs.add_interval_series(sleep_intervals)

behavior_module.add(behavioral_epochs)

####################
# Using :py:class:`~pynwb.epoch.TimeIntervals` representing time intervals
# is preferred over :py:class:`~pynwb.behavior.BehavioralEpochs`.
# :py:class:`~pynwb.epoch.TimeIntervals` is a subclass of :py:class:`~pynwb.core.DynamicTable`
# which offers flexibility for tabular data by allowing the addition of optional columns
# which are not defined in the standard.
# is often preferred over :py:class:`~pynwb.behavior.BehavioralEpochs` and :py:class:`~pynwb.misc.IntervalSeries`.
# :py:class:`~pynwb.epoch.TimeIntervals` is a subclass of :py:class:`~pynwb.core.DynamicTable` which offers
# flexibility for tabular data by allowing the addition of optional columns which are not defined in the standard.
#
# Create a :py:class:`~pynwb.epoch.TimeIntervals` object that represents the time
# intervals when the animal was sleeping.
Expand All @@ -272,18 +271,10 @@

nwbfile.add_time_intervals(sleep_intervals)

####################
# Analogous to how position and direction data can be added to the ``behavior`` processing module,
# we can add the other behavior data:

behavior_module.add(behavioral_time_series)
behavior_module.add(behavioral_events)
behavior_module.add(behavioral_epochs)


####################
# PupilTracking
# --------------------------
# -------------
#
# :py:class:`~pynwb.behavior.PupilTracking` is for storing eye-tracking data which
# represents pupil size. :py:class:`~pynwb.behavior.PupilTracking` holds one or more
Expand All @@ -299,25 +290,19 @@
unit="meters",
)


pupil_tracking = PupilTracking(time_series=pupil_diameter, name="PupilTracking")

####################
# We can add a :py:class:`~pynwb.behavior.PupilTracking` object to the ``behavior``
# processing module the same way as we have added the other data types.

behavior_module.add(pupil_tracking)

####################
# EyeTracking
# --------------------------
# -----------
#
# :py:class:`~pynwb.behavior.EyeTracking` is for storing eye-tracking data which
# represents direction of gaze as measured by an eye tracking algorithm.
# An :py:class:`~pynwb.behavior.EyeTracking` object holds one or more
# :py:class:`~pynwb.behavior.SpatialSeries` objects that represents spatial features
# such as the vertical and horizontal gaze positions extracted from a video.
#
# :py:class:`~pynwb.behavior.SpatialSeries` objects that represents the vertical and
# horizontal gaze positions extracted from a video.

right_eye_position = np.linspace(-20, 30, 50)

Expand Down Expand Up @@ -349,10 +334,6 @@

eye_tracking.add_spatial_series(spatial_series=left_eye_positions)

####################
# We can add an :py:class:`~pynwb.behavior.EyeTracking` object to the ``behavior``
# processing module the same way as we have added the other data types.

behavior_module.add(eye_tracking)


Expand Down Expand Up @@ -385,9 +366,9 @@
####################
# For instance, we can access the :py:class:`~pynwb.behavior.SpatialSeries` data
# by referencing the names of the objects in the hierarchy that contain it.
# We can access the :py:class:`~pynwb.behavior.Position` object inside of the ``behavior``
# We can access the :py:class:`~pynwb.behavior.Position` object inside the ``behavior``
# processing module by indexing it with the name of the :py:class:`~pynwb.behavior.Position` object,
# ``"Position"``. Then, we can access the :py:class:`~pynwb.behavior.SpatialSeries` object inside of the
# ``"Position"``. Then, we can access the :py:class:`~pynwb.behavior.SpatialSeries` object inside the
# :py:class:`~pynwb.behavior.Position` object by indexing it with the name of the
# :py:class:`~pynwb.behavior.SpatialSeries` object, ``"SpatialSeries"``.

Expand Down

0 comments on commit 55cd668

Please sign in to comment.