From 51c96b929b80c3c803023b5f4978fad1185d8b72 Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Tue, 26 Apr 2022 14:38:12 +0200 Subject: [PATCH 01/16] add new tutorial about behavior data types --- docs/gallery/domain/plot_behavior.py | 220 +++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 docs/gallery/domain/plot_behavior.py diff --git a/docs/gallery/domain/plot_behavior.py b/docs/gallery/domain/plot_behavior.py new file mode 100644 index 000000000..9527bb51d --- /dev/null +++ b/docs/gallery/domain/plot_behavior.py @@ -0,0 +1,220 @@ +""" +.. _behavior_basics: + +Behavior Data +================================== + +This tutorial will demonstrate how to add basic behavior data to an NWB File. + +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. + + +.. seealso:: + You can learn more about the :py:class:`~pynwb.file.NWBFile` format in the :ref:`basics` tutorial. + + +The following examples will reference variables that may not be defined within the block they are used in. For +clarity, we define them here: +""" +from datetime import datetime + +import numpy as np +from dateutil import tz + +from pynwb import NWBFile, TimeSeries +from pynwb.behavior import SpatialSeries, BehavioralTimeSeries, Position, \ + BehavioralEvents, CompassDirection + +#################### +# 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. + +session_start_time = datetime(2018, 4, 25, 2, 30, 3, tzinfo=tz.gettz("US/Pacific")) + +nwbfile = NWBFile( + session_description="Mouse exploring an open field", # required + identifier="Mouse5_Day3", # required + session_start_time=session_start_time, # required + session_id="session_1234", # optional + experimenter="My Name", # optional + lab="My Lab Name", # optional + institution="University of My Institution", # optional + related_publications="DOI:10.1016/j.neuron.2016.12.011", # optional +) + +nwbfile + +#################### +# Position +# ------------ +# +# Spatial Series +# ^^^^^^^^^^^^^^^ +# +# :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. +# +# .. seealso:: +# You can learn more about the :py:class:`~pynwb.behavior.SpatialSeries` data type and +# :py:class:`~pynwb.behavior.Position` interface in the :ref:`basic_spatialseries` tutorial. +# +# Create data that corresponds to x, y position over time. + +position_data = np.array([np.linspace(0, 10, 50), np.linspace(0, 8, 50)]).T + +position_data.shape + +#################### +# In :py:class:`~pynwb.behavior.SpatialSeries` ``data``, the first dimension is always time (in seconds), +# the second dimension represents the x, y position (in meters). +# +# .. note:: +# :py:class:`~pynwb.behavior.SpatialSeries` data should be stored as one continuous stream, +# as it is acquired, not by trial as is often reshaped for analysis. +# Data can be trial-aligned on-the-fly using the trials table. See the :ref:`basic_trials` tutorial +# for further information. +# +# For position data ``reference_frame`` indicates the zero-position, e.g. +# the 0,0 point might be the bottom-left corner of an enclosure, as viewed from the tracking camera. + +timestamps = np.linspace(0, 50) / 200 + +position_spatial_series = SpatialSeries( + name="SpatialSeries", + description="(x,y) position in open field", + data=position_data, + timestamps=timestamps, + reference_frame="(0,0) is bottom left corner", +) + +position_spatial_series + +#################### +# +# .. seealso:: +# You can learn more about best practices that can be applied to +# :py:class:`~pynwb.behavior.SpatialSeries` `here `_. +# +# 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. + +position = Position(spatial_series=position_spatial_series) + +#################### +# 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. +# +# For direction data ``reference_frame`` indicates the zero-axes, for instance +# “straight-ahead” might be a specific pixel on the monitor, or some other point in space. +# The unit of measurement for the :py:class:`~pynwb.behavior.SpatialSeries` object should be radians or degrees. + +view_angle_data = np.linspace(0, 4, 50) + +direction_spatial_series = SpatialSeries( + name="SpatialSeries", + description="view angle", + data=view_angle_data, + timestamps=timestamps, + reference_frame="bottom left", + unit="radians" +) + +direction = CompassDirection(spatial_series=direction_spatial_series, + name='CompassDirection') + +#################### +# TODO +# mention compression of data, timestamps with H5DataIO +# H5DataIO(timestamps, compression="gzip") + + +#################### +# 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. + +speed_data = np.linspace(0, 0.4, 50) + +speed_time_series = TimeSeries( + name="speed", + data=speed_data, + timestamps=timestamps, + unit="m/s", +) + +behavioral_time_series = BehavioralTimeSeries(time_series=speed_time_series, + name='BehavioralTimeSeries') + +#################### +# 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. + +duration_of_stimulus = np.full(50, np.nan) +x = np.ones(10, dtype=float) +duration_of_stimulus[::5] = x + +time_series = TimeSeries( + name="stimulus_duration", + data=duration_of_stimulus, + timestamps=timestamps, + unit="seconds", +) + +behavioral_events = BehavioralEvents(time_series=time_series, + name='BehavioralEvents') + +#################### +# BehavioralEpochs +# ------------ +# TODO + +#################### +# Create a Behavior Processing Module +# -------------------------- +# +# .. seealso:: +# 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: + + +behavior_module = nwbfile.create_processing_module( + name="behavior", description="processed behavioral data" +) + +behavior_module.add(position) + +#################### +# Analogous to how position can be added to the ``behavior`` processing module, +# we can add the other behavior data: + +behavior_module.add(direction) +behavior_module.add(behavioral_time_series) +behavior_module.add(behavioral_events) + +#################### +# Writing the file +# TODO +# Reading the file +# TODO +# Access the data \ No newline at end of file From 01eca7015b97a58e3c662125033ea13050a67c89 Mon Sep 17 00:00:00 2001 From: Szonja Weigl Date: Tue, 26 Apr 2022 17:22:52 +0200 Subject: [PATCH 02/16] Update docs/gallery/domain/plot_behavior.py Co-authored-by: Ben Dichter --- docs/gallery/domain/plot_behavior.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/gallery/domain/plot_behavior.py b/docs/gallery/domain/plot_behavior.py index 9527bb51d..ed18b73cf 100644 --- a/docs/gallery/domain/plot_behavior.py +++ b/docs/gallery/domain/plot_behavior.py @@ -155,8 +155,10 @@ unit="m/s", ) -behavioral_time_series = BehavioralTimeSeries(time_series=speed_time_series, - name='BehavioralTimeSeries') +behavioral_time_series = BehavioralTimeSeries( + time_series=speed_time_series, + name="BehavioralTimeSeries", + ) #################### # BehavioralEvents From b5727c759c5f717922e192cf7a72d65fc788de4c Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Tue, 26 Apr 2022 17:26:19 +0200 Subject: [PATCH 03/16] black formatter --- docs/gallery/domain/plot_behavior.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/docs/gallery/domain/plot_behavior.py b/docs/gallery/domain/plot_behavior.py index ed18b73cf..f8570098c 100644 --- a/docs/gallery/domain/plot_behavior.py +++ b/docs/gallery/domain/plot_behavior.py @@ -23,8 +23,13 @@ from dateutil import tz from pynwb import NWBFile, TimeSeries -from pynwb.behavior import SpatialSeries, BehavioralTimeSeries, Position, \ - BehavioralEvents, CompassDirection +from pynwb.behavior import ( + SpatialSeries, + BehavioralTimeSeries, + Position, + BehavioralEvents, + CompassDirection, +) #################### # Create an NWB File @@ -127,11 +132,12 @@ data=view_angle_data, timestamps=timestamps, reference_frame="bottom left", - unit="radians" + unit="radians", ) -direction = CompassDirection(spatial_series=direction_spatial_series, - name='CompassDirection') +direction = CompassDirection( + spatial_series=direction_spatial_series, name="CompassDirection" +) #################### # TODO @@ -158,7 +164,7 @@ behavioral_time_series = BehavioralTimeSeries( time_series=speed_time_series, name="BehavioralTimeSeries", - ) +) #################### # BehavioralEvents @@ -180,8 +186,7 @@ unit="seconds", ) -behavioral_events = BehavioralEvents(time_series=time_series, - name='BehavioralEvents') +behavioral_events = BehavioralEvents(time_series=time_series, name="BehavioralEvents") #################### # BehavioralEpochs @@ -219,4 +224,4 @@ # TODO # Reading the file # TODO -# Access the data \ No newline at end of file +# Access the data From db4c462ab10130efc9266f26ca7c3247fd6183a9 Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Fri, 29 Apr 2022 16:09:03 +0200 Subject: [PATCH 04/16] add BehavioralEpochs to tutorial --- docs/gallery/domain/plot_behavior.py | 69 +++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/docs/gallery/domain/plot_behavior.py b/docs/gallery/domain/plot_behavior.py index f8570098c..bd14c9705 100644 --- a/docs/gallery/domain/plot_behavior.py +++ b/docs/gallery/domain/plot_behavior.py @@ -21,6 +21,9 @@ import numpy as np from dateutil import tz +from pynwb.misc import IntervalSeries + +from pynwb.epoch import TimeIntervals from pynwb import NWBFile, TimeSeries from pynwb.behavior import ( @@ -29,6 +32,7 @@ Position, BehavioralEvents, CompassDirection, + BehavioralEpochs, ) #################### @@ -175,14 +179,17 @@ # 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. -duration_of_stimulus = np.full(50, np.nan) -x = np.ones(10, dtype=float) -duration_of_stimulus[::5] = x +data = np.full(50, np.nan) +duration_of_stimulus = np.ones(10, dtype=float) +data[::5] = duration_of_stimulus + +events_timestamps = np.full(50, np.nan) +events_timestamps[::5] = timestamps[np.where(~np.isnan(data))] time_series = TimeSeries( name="stimulus_duration", - data=duration_of_stimulus, - timestamps=timestamps, + data=data, + timestamps=events_timestamps, unit="seconds", ) @@ -191,7 +198,56 @@ #################### # BehavioralEpochs # ------------ -# TODO +# :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. + + +run_intervals_1 = IntervalSeries( + name="run_intervals_1", + description="intervals when the animal was running", + data=np.arange(6.12, 18.36, 0.2), + timestamps=np.arange(6.12, 18.36, 0.2), +) + +run_intervals_2 = IntervalSeries( + name="run_intervals_2", + description="intervals when the animal was running", + data=np.arange(6.12, 18.36, 0.2), + timestamps=np.arange(6.12, 18.36, 0.2), +) + + +behavioral_epochs = BehavioralEpochs(name="BehavioralEpochs") + +behavioral_epochs.add_interval_series(run_intervals_1) +behavioral_epochs.add_interval_series(run_intervals_2) + +#################### +# 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. +# +# Create a :py:class:`~pynwb.epoch.TimeIntervals` object that represents the time +# intervals when the animal was sleeping. + +sleep_intervals = TimeIntervals( + name="sleep_intervals", + description="intervals when the animal was sleeping", +) + +sleep_intervals.add_column(name="stage", description="stage of sleep") + +sleep_intervals.add_row(start_time=0.3, stop_time=0.35, stage=1) +sleep_intervals.add_row(start_time=0.7, stop_time=0.9, stage=2) +sleep_intervals.add_row(start_time=1.3, stop_time=3.0, stage=3) + +nwbfile.add_time_intervals(sleep_intervals) #################### # Create a Behavior Processing Module @@ -218,6 +274,7 @@ behavior_module.add(direction) behavior_module.add(behavioral_time_series) behavior_module.add(behavioral_events) +behavior_module.add(behavioral_epochs) #################### # Writing the file From a63c019a94caa12581830e61c4185f02463f8ee2 Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Fri, 29 Apr 2022 17:06:36 +0200 Subject: [PATCH 05/16] add PupilTracking and EyeTracking to tutorial --- docs/gallery/domain/plot_behavior.py | 110 ++++++++++++++++++++++----- 1 file changed, 92 insertions(+), 18 deletions(-) diff --git a/docs/gallery/domain/plot_behavior.py b/docs/gallery/domain/plot_behavior.py index bd14c9705..64de7e9c1 100644 --- a/docs/gallery/domain/plot_behavior.py +++ b/docs/gallery/domain/plot_behavior.py @@ -33,6 +33,8 @@ BehavioralEvents, CompassDirection, BehavioralEpochs, + PupilTracking, + EyeTracking, ) #################### @@ -114,6 +116,26 @@ position = Position(spatial_series=position_spatial_series) + +#################### +# Create a Behavior Processing Module +# -------------------------- +# +# .. seealso:: +# 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: + + +behavior_module = nwbfile.create_processing_module( + name="behavior", description="processed behavioral data" +) + +behavior_module.add(position) + + #################### # CompassDirection # ------------ @@ -144,9 +166,10 @@ ) #################### -# TODO -# mention compression of data, timestamps with H5DataIO -# H5DataIO(timestamps, compression="gzip") +# We can add a :py:class:`~pynwb.behavior.CompassDirection` object to the ``behavior`` processing module +# the same way as we have added the position data: + +behavior_module.add(direction) #################### @@ -250,31 +273,82 @@ nwbfile.add_time_intervals(sleep_intervals) #################### -# Create a Behavior Processing Module +# 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 # -------------------------- # -# .. seealso:: -# You can read more about the basic concepts of processing modules in the :ref:`modules_overview` tutorial. +# :py:class:`~pynwb.behavior.PupilTracking` is for storing eye-tracking data which +# represents pupil size. :py:class:`~pynwb.behavior.PupilTracking` holds one or more +# :py:class:`~pynwb.base.TimeSeries` objects that can represent different features +# such as the dilation of the pupil measured over time by a pupil tracking algorithm. # -# 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: +pupil_diameter = TimeSeries( + name="pupil_diameter", + description="pupil diameter extracted from the video of the right eye", + data=np.linspace(0.001, 0.002, 50), + timestamps=timestamps, + unit="meters", +) -behavior_module = nwbfile.create_processing_module( - name="behavior", description="processed behavioral data" + +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. +# + +right_eye_position = np.linspace(-20, 30, 50) + +right_eye_positions = SpatialSeries( + name="right_eye_position", + description="position of the right eye", + data=right_eye_position, + timestamps=timestamps, + reference_frame="bottom left", + unit="degrees", ) -behavior_module.add(position) +eye_tracking = EyeTracking(name="EyeTracking", spatial_series=right_eye_positions) #################### -# Analogous to how position can be added to the ``behavior`` processing module, -# we can add the other behavior data: +# We can add another :py:class:`~pynwb.behavior.SpatialSeries` representing the position +# of the left eye in degrees. + +left_eye_position = np.linspace(-2, 20, 50) + +left_eye_positions = SpatialSeries( + name="left_eye_position", + description="position of the left eye", + data=left_eye_position, + timestamps=timestamps, + reference_frame="bottom left", + unit="degrees", +) + +eye_tracking.add_spatial_series(spatial_series=left_eye_positions) -behavior_module.add(direction) -behavior_module.add(behavioral_time_series) -behavior_module.add(behavioral_events) -behavior_module.add(behavioral_epochs) #################### # Writing the file From af75b33216860fd0135fd234444f4985a4cf4e05 Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Fri, 29 Apr 2022 18:14:55 +0200 Subject: [PATCH 06/16] add writing and accessing data --- docs/gallery/domain/plot_behavior.py | 81 +++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 12 deletions(-) diff --git a/docs/gallery/domain/plot_behavior.py b/docs/gallery/domain/plot_behavior.py index 64de7e9c1..28a4bca83 100644 --- a/docs/gallery/domain/plot_behavior.py +++ b/docs/gallery/domain/plot_behavior.py @@ -4,7 +4,8 @@ Behavior Data ================================== -This tutorial will demonstrate how to add basic behavior data to an NWB File. +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. @@ -25,7 +26,7 @@ from pynwb.epoch import TimeIntervals -from pynwb import NWBFile, TimeSeries +from pynwb import NWBFile, TimeSeries, NWBHDF5IO from pynwb.behavior import ( SpatialSeries, BehavioralTimeSeries, @@ -232,18 +233,17 @@ run_intervals_1 = IntervalSeries( name="run_intervals_1", description="intervals when the animal was running", - data=np.arange(6.12, 18.36, 0.2), - timestamps=np.arange(6.12, 18.36, 0.2), + 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(6.12, 18.36, 0.2), - timestamps=np.arange(6.12, 18.36, 0.2), + data=np.arange(22, 34, 1), + timestamps=np.arange(22, 34, 1).astype(float), ) - behavioral_epochs = BehavioralEpochs(name="BehavioralEpochs") behavioral_epochs.add_interval_series(run_intervals_1) @@ -349,10 +349,67 @@ 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) + + +#################### +# Writing the behavior data to an NWB file +# ------------------- +# +# As demonstrated in the :ref:`basic_writing` tutorial, we will use :py:class:`~pynwb.NWBHDF5IO` +# to write the file. + +with NWBHDF5IO("behavioral_tutorial.nwb", "w") as io: + io.write(nwbfile) + +#################### +# Reading and accessing the behavior data +# ------------------- +# +# To read the NWB file we just wrote, use another :py:class:`~pynwb.NWBHDF5IO` object, +# and use the :py:meth:`~pynwb.NWBHDF5IO.read` method to retrieve an +# :py:class:`~pynwb.file.NWBFile` object. +# +# We can access the behavior processing module by indexing ``nwbfile.processing`` +# with the name of the processing module ``"behavior"``. We can also inspect the objects +# hierarchy within this processing module with the ``.children`` attribute. + +with NWBHDF5IO("behavioral_tutorial.nwb", "r") as io: + read_nwbfile = io.read() + print(read_nwbfile.processing["behavior"].children) #################### -# Writing the file -# TODO -# Reading the file -# TODO -# Access the data +# 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`` +# 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 +# :py:class:`~pynwb.behavior.Position` object by indexing it with the name of the +# :py:class:`~pynwb.behavior.SpatialSeries` object, ``"SpatialSeries"``. + + +with NWBHDF5IO("behavioral_tutorial.nwb", "r") as io: + read_nwbfile = io.read() + print(read_nwbfile.processing["behavior"]["Position"]["SpatialSeries"]) + +#################### +# Data arrays are read passively from the file. +# Accessing the ``data`` attribute of the :py:class:`~pynwb.behavior.SpatialSeries` object +# does not read the data values, but presents an HDF5 object that can be indexed to read data. +# You can use the ``[:]`` operator to read the entire data array into memory. + +with NWBHDF5IO("behavioral_tutorial.nwb", "r") as io: + read_nwbfile = io.read() + print(read_nwbfile.processing["behavior"]["Position"]["SpatialSeries"].data[:]) + +#################### +# Alternatively, you can read only a portion of the data by indexing or slicing into +# the ``data`` attribute just like if you were indexing or slicing a numpy array. + +with NWBHDF5IO("behavioral_tutorial.nwb", "r") as io: + read_nwbfile = io.read() + print(read_nwbfile.processing["behavior"]["Position"]["SpatialSeries"].data[:2]) From 55cd668bb6eeb8c365eabf56fe81d9c1daad6b75 Mon Sep 17 00:00:00 2001 From: bendichter Date: Fri, 29 Apr 2022 14:29:00 -0400 Subject: [PATCH 07/16] some adjustments to the behavioral tutorial --- docs/gallery/domain/plot_behavior.py | 143 ++++++++++++--------------- 1 file changed, 62 insertions(+), 81 deletions(-) diff --git a/docs/gallery/domain/plot_behavior.py b/docs/gallery/domain/plot_behavior.py index 28a4bca83..7fa4c1d07 100644 --- a/docs/gallery/domain/plot_behavior.py +++ b/docs/gallery/domain/plot_behavior.py @@ -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. @@ -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. @@ -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 @@ -111,9 +105,13 @@ # You can learn more about best practices that can be applied to # :py:class:`~pynwb.behavior.SpatialSeries` `here `_. # +# 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) @@ -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( @@ -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. @@ -158,7 +153,7 @@ description="view angle", data=view_angle_data, timestamps=timestamps, - reference_frame="bottom left", + reference_frame="straight ahead", unit="radians", ) @@ -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) @@ -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. @@ -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 @@ -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) @@ -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) @@ -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"``. From f540a4bde877646dd8245fb8148b85f954175ce9 Mon Sep 17 00:00:00 2001 From: Szonja Weigl Date: Sat, 30 Apr 2022 10:35:33 +0200 Subject: [PATCH 08/16] Update docs/gallery/domain/plot_behavior.py --- docs/gallery/domain/plot_behavior.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/gallery/domain/plot_behavior.py b/docs/gallery/domain/plot_behavior.py index 7fa4c1d07..fc7ab782c 100644 --- a/docs/gallery/domain/plot_behavior.py +++ b/docs/gallery/domain/plot_behavior.py @@ -173,7 +173,7 @@ # -------------------- # # :py:class:`~pynwb.behavior.BehavioralTimeSeries` is an interface for storing continuous behavior data, such as the -# speed of an subject. +# speed of a subject. speed_data = np.linspace(0, 0.4, 50) From 30c2e28b6a05cd3fc590472d4cec5f8881971862 Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Mon, 2 May 2022 13:57:57 +0200 Subject: [PATCH 09/16] extend section descriptions --- docs/gallery/domain/plot_behavior.py | 40 +++++++++++++++------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/docs/gallery/domain/plot_behavior.py b/docs/gallery/domain/plot_behavior.py index fc7ab782c..8bced1302 100644 --- a/docs/gallery/domain/plot_behavior.py +++ b/docs/gallery/domain/plot_behavior.py @@ -57,17 +57,13 @@ nwbfile #################### -# SpatialSeries +# SpatialSeries: Storing continuous spatial data # -------------- # # :py:class:`~pynwb.behavior.SpatialSeries` is a subclass of :py:class:`~pynwb.base.TimeSeries` # 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 -# :py:class:`~pynwb.behavior.Position` interface in the :ref:`basic_spatialseries` tutorial. -# # Create data that corresponds to x, y position over time. position_data = np.array([np.linspace(0, 10, 50), np.linspace(0, 8, 50)]).T @@ -100,12 +96,7 @@ position_spatial_series #################### -# -# .. seealso:: -# You can learn more about best practices that can be applied to -# :py:class:`~pynwb.behavior.SpatialSeries` `here `_. -# -# Position +# Position: Storing position measured over time # -------- # # To help data analysis and visualization tools know that this :py:class:`~pynwb.behavior.SpatialSeries` object @@ -115,14 +106,21 @@ position = Position(spatial_series=position_spatial_series) +#################### +# +# .. seealso:: +# You can learn more about the :py:class:`~pynwb.behavior.SpatialSeries` data type and +# :py:class:`~pynwb.behavior.Position` interface in the :ref:`basic_spatialseries` tutorial. +# +# .. seealso:: +# You can learn more about best practices that can be applied to +# :py:class:`~pynwb.behavior.SpatialSeries` `here `_. +# #################### # Create a Behavior Processing Module # -------------------------- # -# .. seealso:: -# 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` # 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. @@ -134,9 +132,13 @@ behavior_module.add(position) +#################### +# .. seealso:: +# You can read more about the basic concepts of processing modules in the :ref:`modules_overview` tutorial. +# #################### -# CompassDirection +# CompassDirection: Storing view angle measured over time # ---------------- # # Analogous to how position can be stored, we can create a :py:class:`~pynwb.behavior.SpatialSeries` @@ -169,7 +171,7 @@ #################### -# BehavioralTimeSeries +# BehavioralTimeSeries: Storing continuous behavior data # -------------------- # # :py:class:`~pynwb.behavior.BehavioralTimeSeries` is an interface for storing continuous behavior data, such as the @@ -213,7 +215,7 @@ behavior_module.add(behavioral_events) #################### -# BehavioralEpochs +# BehavioralEpochs: Storing intervals of behavior data # ---------------- # :py:class:`~pynwb.behavior.BehavioralEpochs` is for storing intervals of behavior data. # :py:class:`~pynwb.behavior.BehavioralEpochs` uses :py:class:`~pynwb.misc.IntervalSeries` @@ -273,7 +275,7 @@ #################### -# PupilTracking +# PupilTracking: : Storing continuous eye-tracking data of pupil size # ------------- # # :py:class:`~pynwb.behavior.PupilTracking` is for storing eye-tracking data which @@ -295,7 +297,7 @@ behavior_module.add(pupil_tracking) #################### -# EyeTracking +# EyeTracking: Storing continuous eye-tracking data of gaze direction # ----------- # # :py:class:`~pynwb.behavior.EyeTracking` is for storing eye-tracking data which From 816599ed218b746ad734e287a47242dfa98abb32 Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Mon, 2 May 2022 14:03:15 +0200 Subject: [PATCH 10/16] fix title underline warnings --- docs/gallery/domain/plot_behavior.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/gallery/domain/plot_behavior.py b/docs/gallery/domain/plot_behavior.py index 8bced1302..2bc754e1c 100644 --- a/docs/gallery/domain/plot_behavior.py +++ b/docs/gallery/domain/plot_behavior.py @@ -58,7 +58,7 @@ #################### # SpatialSeries: Storing continuous spatial data -# -------------- +# ---------------------------------------------- # # :py:class:`~pynwb.behavior.SpatialSeries` is a subclass of :py:class:`~pynwb.base.TimeSeries` # that represents data in space, such as the spatial direction, e.g., of gaze or travel, @@ -97,7 +97,7 @@ #################### # Position: Storing position measured over time -# -------- +# --------------------------------------------- # # 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 @@ -119,7 +119,7 @@ #################### # Create a Behavior Processing Module -# -------------------------- +# ----------------------------------- # # Create a processing module called ``"behavior"`` for storing behavioral data in the :py:class:`~pynwb.file.NWBFile` # using the :py:meth:`~pynwb.file.NWBFile.create_processing_module` method, then and add the @@ -139,7 +139,7 @@ #################### # CompassDirection: Storing view angle measured over time -# ---------------- +# ------------------------------------------------------- # # 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. @@ -172,7 +172,7 @@ #################### # BehavioralTimeSeries: Storing continuous behavior data -# -------------------- +# ------------------------------------------------------ # # :py:class:`~pynwb.behavior.BehavioralTimeSeries` is an interface for storing continuous behavior data, such as the # speed of a subject. @@ -194,8 +194,8 @@ behavior_module.add(behavioral_time_series) #################### -# BehavioralEvents -# ---------------- +# BehavioralEvents: Storing behavioral events +# ------------------------------------------- # # :py:class:`~pynwb.behavior.BehavioralEvents` is an interface for storing behavioral events. # We can use it for storing the timing and amount of rewards (e.g. water amount) or lever press times. @@ -216,7 +216,7 @@ #################### # BehavioralEpochs: Storing intervals of behavior data -# ---------------- +# ---------------------------------------------------- # :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. @@ -276,7 +276,7 @@ #################### # PupilTracking: : Storing continuous eye-tracking data of pupil size -# ------------- +# ------------------------------------------------------------------- # # :py:class:`~pynwb.behavior.PupilTracking` is for storing eye-tracking data which # represents pupil size. :py:class:`~pynwb.behavior.PupilTracking` holds one or more @@ -298,7 +298,7 @@ #################### # EyeTracking: Storing continuous eye-tracking data of gaze direction -# ----------- +# ------------------------------------------------------------------- # # :py:class:`~pynwb.behavior.EyeTracking` is for storing eye-tracking data which # represents direction of gaze as measured by an eye tracking algorithm. @@ -341,7 +341,7 @@ #################### # Writing the behavior data to an NWB file -# ------------------- +# ---------------------------------------- # # As demonstrated in the :ref:`basic_writing` tutorial, we will use :py:class:`~pynwb.NWBHDF5IO` # to write the file. @@ -351,7 +351,7 @@ #################### # Reading and accessing the behavior data -# ------------------- +# --------------------------------------- # # To read the NWB file we just wrote, use another :py:class:`~pynwb.NWBHDF5IO` object, # and use the :py:meth:`~pynwb.NWBHDF5IO.read` method to retrieve an From 90deba7d037a97744c7e238b94684bddc4177cb6 Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Mon, 2 May 2022 15:31:36 +0200 Subject: [PATCH 11/16] mention ndx-events extension --- docs/gallery/domain/plot_behavior.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/gallery/domain/plot_behavior.py b/docs/gallery/domain/plot_behavior.py index 2bc754e1c..c43d90b3b 100644 --- a/docs/gallery/domain/plot_behavior.py +++ b/docs/gallery/domain/plot_behavior.py @@ -214,6 +214,14 @@ behavior_module.add(behavioral_events) +#################### +# Storing only the timestamps of the events is possible with the `ndx-events `_ +# NWB extension. You can also add labels associated with the events with this extension. +# You can find information about installation and example usage `here `_. +# +# .. seealso:: +# You can learn more about using extensions in the :ref:`tutorial-extending-nwb` tutorial. + #################### # BehavioralEpochs: Storing intervals of behavior data # ---------------------------------------------------- From a59ad0f775b2d03891929547e44f1eac51c26e8d Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Mon, 2 May 2022 17:28:52 +0200 Subject: [PATCH 12/16] extend descriptions --- docs/gallery/domain/plot_behavior.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/docs/gallery/domain/plot_behavior.py b/docs/gallery/domain/plot_behavior.py index c43d90b3b..089220387 100644 --- a/docs/gallery/domain/plot_behavior.py +++ b/docs/gallery/domain/plot_behavior.py @@ -87,7 +87,7 @@ position_spatial_series = SpatialSeries( name="SpatialSeries", - description="(x,y) position in open field", + description="Position (x, y) in an open field.", data=position_data, timestamps=timestamps, reference_frame="(0,0) is bottom left corner", @@ -127,7 +127,7 @@ behavior_module = nwbfile.create_processing_module( - name="behavior", description="processed behavioral data" + name="behavior", description="Processed behavioral data" ) behavior_module.add(position) @@ -152,7 +152,7 @@ direction_spatial_series = SpatialSeries( name="SpatialSeries", - description="view angle", + description="View angle of the subject measured in radians.", data=view_angle_data, timestamps=timestamps, reference_frame="straight ahead", @@ -183,6 +183,7 @@ name="speed", data=speed_data, timestamps=timestamps, + description="The speed of the subject measured over time.", unit="m/s", ) @@ -207,6 +208,7 @@ name="lever_presses", data=reward_amount, timestamps=events_timestamps, + description="The water amount the subject received as a reward.", unit="ml", ) @@ -236,7 +238,7 @@ run_intervals = IntervalSeries( name="running", - description="intervals when the animal was 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], ) @@ -251,7 +253,7 @@ sleep_intervals = IntervalSeries( name="sleeping", - description="intervals when the animal was sleeping.", + description="Intervals when the animal was sleeping.", data=[1, -1, 1, -1], timestamps=[15.0, 30.0, 60.0, 95.0], ) @@ -270,10 +272,10 @@ sleep_intervals = TimeIntervals( name="sleep_intervals", - description="intervals when the animal was sleeping", + description="Intervals when the animal was sleeping.", ) -sleep_intervals.add_column(name="stage", description="stage of sleep") +sleep_intervals.add_column(name="stage", description="The stage of sleep.") sleep_intervals.add_row(start_time=0.3, stop_time=0.35, stage=1) sleep_intervals.add_row(start_time=0.7, stop_time=0.9, stage=2) @@ -283,7 +285,7 @@ #################### -# PupilTracking: : Storing continuous eye-tracking data of pupil size +# PupilTracking: Storing continuous eye-tracking data of pupil size # ------------------------------------------------------------------- # # :py:class:`~pynwb.behavior.PupilTracking` is for storing eye-tracking data which @@ -294,7 +296,7 @@ pupil_diameter = TimeSeries( name="pupil_diameter", - description="pupil diameter extracted from the video of the right eye", + description="Pupil diameter extracted from the video of the right eye.", data=np.linspace(0.001, 0.002, 50), timestamps=timestamps, unit="meters", @@ -318,7 +320,7 @@ right_eye_positions = SpatialSeries( name="right_eye_position", - description="position of the right eye", + description="The position of the right eye measured in degrees.", data=right_eye_position, timestamps=timestamps, reference_frame="bottom left", @@ -335,7 +337,7 @@ left_eye_positions = SpatialSeries( name="left_eye_position", - description="position of the left eye", + description="The position of the left eye measured in degrees.", data=left_eye_position, timestamps=timestamps, reference_frame="bottom left", From 07d9639e4ae198ae530c2d5b78b82a2f4d24da4f Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Mon, 2 May 2022 17:59:00 +0200 Subject: [PATCH 13/16] describe workflow for adding behavior data to NWB --- docs/gallery/domain/plot_behavior.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/gallery/domain/plot_behavior.py b/docs/gallery/domain/plot_behavior.py index 089220387..d6f71e213 100644 --- a/docs/gallery/domain/plot_behavior.py +++ b/docs/gallery/domain/plot_behavior.py @@ -10,6 +10,22 @@ .. seealso:: You can learn more about the :py:class:`~pynwb.file.NWBFile` format in the :ref:`basics` tutorial. +The examples below follow this general workflow for adding behavior data to an :py:class:`~pynwb.file.NWBFile`: +(1) create an object: +- :py:class:`~pynwb.base.TimeSeries` for continuous time series data, +- :py:class:`~pynwb.base.SpatialSeries` for continuous spatial data (e.g. position, direction +relative to some reference frame), +- :py:class:`~pynwb.misc.IntervalSeries` or :py:class:`~pynwb.epoch.TimeIntervals` for time intervals +(2) store that object inside a behavior interface object: +- :py:class:`~pynwb.behavior.Position` for position measured over time +- :py:class:`~pynwb.behavior.CompassDirection` for view angle measured over time +- :py:class:`~pynwb.behavior.BehavioralTimeSeries` for continuous time series data +- :py:class:`~pynwb.behavior.BehavioralEvents` for behavioral events (e.g. reward amount) +- :py:class:`~pynwb.behavior.BehavioralEpochs` for behavioral intervals (e.g. sleep intervals) +- :py:class:`~pynwb.behavior.PupilTracking` for eye-tracking data of pupil size +- :py:class:`~pynwb.behavior.EyeTracking` for eye-tracking data of gaze direction +(3) create a behavior processing module for the :py:class:`~pynwb.file.NWBFile` and add the interface object(s) to it + The following examples will reference variables that may not be defined within the block they are used in. For clarity, we define them here: From e74400ff717440b0a1d3f92428e41a18d2f0e46a Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Mon, 2 May 2022 22:31:19 +0200 Subject: [PATCH 14/16] describe workflow for adding behavior data to NWB --- docs/gallery/domain/plot_behavior.py | 34 ++++++++++++++++------------ 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/docs/gallery/domain/plot_behavior.py b/docs/gallery/domain/plot_behavior.py index d6f71e213..5a1ab1582 100644 --- a/docs/gallery/domain/plot_behavior.py +++ b/docs/gallery/domain/plot_behavior.py @@ -11,20 +11,24 @@ You can learn more about the :py:class:`~pynwb.file.NWBFile` format in the :ref:`basics` tutorial. The examples below follow this general workflow for adding behavior data to an :py:class:`~pynwb.file.NWBFile`: -(1) create an object: -- :py:class:`~pynwb.base.TimeSeries` for continuous time series data, -- :py:class:`~pynwb.base.SpatialSeries` for continuous spatial data (e.g. position, direction -relative to some reference frame), -- :py:class:`~pynwb.misc.IntervalSeries` or :py:class:`~pynwb.epoch.TimeIntervals` for time intervals -(2) store that object inside a behavior interface object: -- :py:class:`~pynwb.behavior.Position` for position measured over time -- :py:class:`~pynwb.behavior.CompassDirection` for view angle measured over time -- :py:class:`~pynwb.behavior.BehavioralTimeSeries` for continuous time series data -- :py:class:`~pynwb.behavior.BehavioralEvents` for behavioral events (e.g. reward amount) -- :py:class:`~pynwb.behavior.BehavioralEpochs` for behavioral intervals (e.g. sleep intervals) -- :py:class:`~pynwb.behavior.PupilTracking` for eye-tracking data of pupil size -- :py:class:`~pynwb.behavior.EyeTracking` for eye-tracking data of gaze direction -(3) create a behavior processing module for the :py:class:`~pynwb.file.NWBFile` and add the interface object(s) to it + +* create an object: + + * :py:class:`~pynwb.base.TimeSeries` for continuous time series data, + * :py:class:`~pynwb.base.SpatialSeries` for continuous spatial data (e.g. position, direction relative to some reference frame), + * :py:class:`~pynwb.misc.IntervalSeries` or :py:class:`~pynwb.epoch.TimeIntervals` for time intervals + +* store that object inside a behavior interface object: + + * :py:class:`~pynwb.behavior.Position` for position measured over time + * :py:class:`~pynwb.behavior.CompassDirection` for view angle measured over time + * :py:class:`~pynwb.behavior.BehavioralTimeSeries` for continuous time series data + * :py:class:`~pynwb.behavior.BehavioralEvents` for behavioral events (e.g. reward amount) + * :py:class:`~pynwb.behavior.BehavioralEpochs` for behavioral intervals (e.g. sleep intervals) + * :py:class:`~pynwb.behavior.PupilTracking` for eye-tracking data of pupil size + * :py:class:`~pynwb.behavior.EyeTracking` for eye-tracking data of gaze direction + +* create a behavior processing module for the :py:class:`~pynwb.file.NWBFile` and add the interface object(s) to it The following examples will reference variables that may not be defined within the block they are used in. For @@ -130,7 +134,7 @@ # # .. seealso:: # You can learn more about best practices that can be applied to -# :py:class:`~pynwb.behavior.SpatialSeries` `here `_. +# :py:class:`~pynwb.behavior.SpatialSeries` at `NWB Best Practices `_. # #################### From b24beeff97f943559522b8e3eba7bac5f61b6aee Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Mon, 2 May 2022 22:36:43 +0200 Subject: [PATCH 15/16] update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bc20f438..2a6235c1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Documentation and tutorial enhancements: - Add copy button to code blocks @weiglszonja (#1460) +- Create behavioral tutorial (#1464) ## PyNWB 2.0.1 (March 16, 2022) From 0892d10fc531ef414fe4a33feabdfa8f697db019 Mon Sep 17 00:00:00 2001 From: Oliver Ruebel Date: Tue, 3 May 2022 12:17:06 -0700 Subject: [PATCH 16/16] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a6235c1f..c426d8a36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ ### Documentation and tutorial enhancements: - Add copy button to code blocks @weiglszonja (#1460) -- Create behavioral tutorial (#1464) +- Create behavioral tutorial @weiglszonja (#1464) ## PyNWB 2.0.1 (March 16, 2022)