Skip to content

Commit fb96fc9

Browse files
authored
Merge pull request #1703 from AllenInstitute/rc/2.3.0
rc/2.3.0
2 parents a9b9cdb + f8c1b43 commit fb96fc9

34 files changed

+2161
-566
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
# Change Log
22
All notable changes to this project will be documented in this file.
33

4+
## [2.3.0] = 2020-10-09
5+
6+
### Added
7+
- Adds load sync data for individual plane sets to relate accurate event timings to mesoscope data.
8+
- Adds public API method to access the behavior\_session\_id from an instance of BehaviorOphysSession.
9+
10+
### Changes
11+
- Visual behavior running speed is now low-pass filtered at 10Hz. The raw running speed data is still available. The running speed is corrected for encoder threshold croissing artifacts.
12+
- Support for stimulus gratings for visual behavior.
13+
- Updates to some visual behavior pynwb implementations.
14+
15+
### Bug Fixes
16+
- Fixed an eye-tracking sync problem.
17+
418
## [2.2.0] = 2020-09-03
519

620
### Added

allensdk/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838

3939

40-
__version__ = '2.2.0'
40+
__version__ = '2.3.0'
4141

4242

4343
try:

allensdk/brain_observatory/behavior/behavior_data_session.py

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ def __init__(self, api: Optional[BehaviorDataApi] = None):
1919
self._rewards = None
2020
self._running_data_df = None
2121
self._running_speed = None
22+
self._raw_running_data_df = None
23+
self._raw_running_speed = None
2224
self._stimulus_presentations = None
2325
self._stimulus_templates = None
2426
self._stimulus_timestamps = None
@@ -92,17 +94,39 @@ def rewards(self) -> pd.DataFrame:
9294
def rewards(self, value):
9395
self._rewards = value
9496

97+
@property
98+
def raw_running_data_df(self) -> pd.DataFrame:
99+
"""Get running speed data without the 10Hz low pass filter.
100+
101+
Returns
102+
-------
103+
pd.DataFrame
104+
Dataframe containing various signals used to compute running
105+
speed, and the unfiltered speed.
106+
"""
107+
if self._raw_running_data_df is None:
108+
self._raw_running_data_df = self.api.get_running_data_df(
109+
lowpass=False)
110+
return self._raw_running_data_df
111+
112+
@raw_running_data_df.setter
113+
def raw_running_data_df(self, value):
114+
self._raw_running_data_df = value
115+
95116
@property
96117
def running_data_df(self) -> pd.DataFrame:
97-
"""Get running speed data.
118+
"""Get running speed data. By default applies a 10Hz low pass
119+
filter to the data. To get the running speed without the filter,
120+
use `raw_running_data_df`.
98121
99122
Returns
100123
-------
101124
pd.DataFrame
102-
Dataframe containing various signals used to compute running speed.
125+
Dataframe containing various signals used to compute running
126+
speed, and the filtered speed.
103127
"""
104128
if self._running_data_df is None:
105-
self._running_data_df = self.api.get_running_data_df()
129+
self._running_data_df = self.api.get_running_data_df(lowpass=True)
106130
return self._running_data_df
107131

108132
@running_data_df.setter
@@ -112,7 +136,8 @@ def running_data_df(self, value):
112136
@property
113137
def running_speed(self) -> RunningSpeed:
114138
"""Get running speed using timestamps from
115-
self.get_stimulus_timestamps.
139+
self.get_stimulus_timestamps. Applies a 10Hz filter to the
140+
speed. To get the unfiltered speed, use `raw_running_speed`.
116141
117142
NOTE: Do not correct for monitor delay.
118143
@@ -125,13 +150,36 @@ def running_speed(self) -> RunningSpeed:
125150
Running speed of the experimental subject (in cm / s).
126151
"""
127152
if self._running_speed is None:
128-
self._running_speed = self.api.get_running_speed()
153+
self._running_speed = self.api.get_running_speed(lowpass=True)
129154
return self._running_speed
130155

131156
@running_speed.setter
132157
def running_speed(self, value):
133158
self._running_speed = value
134159

160+
@property
161+
def raw_running_speed(self) -> RunningSpeed:
162+
"""Get running speed using timestamps from
163+
self.get_stimulus_timestamps. Does not apply the 10Hz filter.
164+
165+
NOTE: Do not correct for monitor delay.
166+
167+
Returns
168+
-------
169+
RunningSpeed (NamedTuple with two fields)
170+
timestamps : np.ndarray
171+
Timestamps of running speed data samples
172+
values : np.ndarray
173+
Running speed of the experimental subject (in cm / s).
174+
"""
175+
if self._raw_running_speed is None:
176+
self._raw_running_speed = self.api.get_running_speed(lowpass=False)
177+
return self._raw_running_speed
178+
179+
@raw_running_speed.setter
180+
def raw_running_speed(self, value):
181+
self._raw_running_speed = value
182+
135183
@property
136184
def stimulus_presentations(self) -> pd.DataFrame:
137185
"""Get stimulus presentation data.

allensdk/brain_observatory/behavior/behavior_ophys_api/behavior_ophys_nwb_api.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@
1818
from allensdk.brain_observatory.nwb.nwb_api import NwbApi
1919
from allensdk.brain_observatory.nwb.nwb_utils import set_omitted_stop_time
2020
from allensdk.brain_observatory.behavior.trials_processing import TRIAL_COLUMN_DESCRIPTION_DICT
21-
from allensdk.brain_observatory.behavior.schemas import OphysBehaviorMetaDataSchema, OphysBehaviorTaskParametersSchema
22-
from allensdk.brain_observatory.nwb.metadata import load_LabMetaData_extension
21+
from allensdk.brain_observatory.behavior.schemas import OphysBehaviorMetadataSchema, BehaviorTaskParametersSchema
22+
from allensdk.brain_observatory.nwb.metadata import load_pynwb_extension
2323
from allensdk.brain_observatory.behavior.behavior_ophys_api import BehaviorOphysApiBase
2424

2525

26-
load_LabMetaData_extension(OphysBehaviorMetaDataSchema, 'AIBS_ophys_behavior')
27-
load_LabMetaData_extension(OphysBehaviorTaskParametersSchema, 'AIBS_ophys_behavior')
26+
load_pynwb_extension(OphysBehaviorMetadataSchema, 'ndx-aibs-behavior-ophys')
27+
load_pynwb_extension(BehaviorTaskParametersSchema, 'ndx-aibs-behavior-ophys')
2828

2929

3030
class BehaviorOphysNwbApi(NwbApi, BehaviorOphysApiBase):
@@ -170,16 +170,26 @@ def get_segmentation_mask_image(self, image_api=None) -> sitk.Image:
170170
def get_metadata(self) -> dict:
171171

172172
metadata_nwb_obj = self.nwbfile.lab_meta_data['metadata']
173-
data = OphysBehaviorMetaDataSchema(exclude=['experiment_datetime']).dump(metadata_nwb_obj)
173+
data = OphysBehaviorMetadataSchema(exclude=['experiment_datetime']).dump(metadata_nwb_obj)
174+
175+
# Add subject related metadata to behavior ophys metadata
176+
nwb_subject = self.nwbfile.subject
177+
data['LabTracks_ID'] = int(nwb_subject.subject_id)
178+
data['sex'] = nwb_subject.sex
179+
data['age'] = nwb_subject.age
180+
data['full_genotype'] = nwb_subject.genotype
181+
data['reporter_line'] = list(nwb_subject.reporter_line)
182+
data['driver_line'] = list(nwb_subject.driver_line)
183+
174184
experiment_datetime = metadata_nwb_obj.experiment_datetime
175-
data['experiment_datetime'] = OphysBehaviorMetaDataSchema().load({'experiment_datetime': experiment_datetime}, partial=True)['experiment_datetime']
185+
data['experiment_datetime'] = OphysBehaviorMetadataSchema().load({'experiment_datetime': experiment_datetime}, partial=True)['experiment_datetime']
176186
data['behavior_session_uuid'] = uuid.UUID(data['behavior_session_uuid'])
177187
return data
178188

179189
def get_task_parameters(self) -> dict:
180190

181191
metadata_nwb_obj = self.nwbfile.lab_meta_data['task_parameters']
182-
data = OphysBehaviorTaskParametersSchema().dump(metadata_nwb_obj)
192+
data = BehaviorTaskParametersSchema().dump(metadata_nwb_obj)
183193
return data
184194

185195
def get_cell_specimen_table(self) -> pd.DataFrame:

allensdk/brain_observatory/behavior/behavior_ophys_session.py

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import numpy as np
22
import pandas as pd
33
import xarray as xr
4-
from typing import Any
4+
from typing import Any, Optional
55
import logging
66

77

@@ -71,6 +71,8 @@ def __init__(self, api=None,
7171
self._cell_specimen_table = None
7272
self._running_speed = None
7373
self._running_data_df = None
74+
self._raw_running_speed = None
75+
self._raw_running_data_df = None
7476
self._stimulus_presentations = None
7577
self._stimulus_templates = None
7678
self._licks = None
@@ -96,6 +98,13 @@ def ophys_experiment_id(self) -> int:
9698
"""
9799
return self.api.get_ophys_experiment_id()
98100

101+
@property
102+
def behavior_session_id(self) -> Optional[int]:
103+
"""Returns the unique identifier for the behavior session
104+
associated with this experiment, if applicable.
105+
"""
106+
return self.api.get_behavior_session_id()
107+
99108
@property
100109
def max_projection(self) -> Image:
101110
"""2D max projection image.
@@ -172,12 +181,16 @@ def cell_specimen_table(self, value):
172181

173182
@property
174183
def running_speed(self) -> RunningSpeed:
175-
"""Running speed of mouse. NamedTuple with two fields
184+
"""Running speed of mouse, filtered with 10Hz low pass filter,
185+
To get the unfiltered running speed, use `raw_running_speed`.
186+
Returns
187+
-------
188+
allensdk.brain_observatory.running_speed.RunningSpeed
189+
NamedTuple with two fields:
176190
timestamps : numpy.ndarray
177191
Timestamps of running speed data samples
178192
values : np.ndarray
179193
Running speed of the experimental subject (in cm / s).
180-
:rtype: allensdk.brain_observatory.running_speed.RunningSpeed
181194
"""
182195
if self._running_speed is None:
183196
self._running_speed = self.api.get_running_speed()
@@ -187,19 +200,66 @@ def running_speed(self) -> RunningSpeed:
187200
def running_speed(self, value):
188201
self._running_speed = value
189202

203+
@property
204+
def raw_running_speed(self) -> RunningSpeed:
205+
"""Running speed of mouse, unfiltered.
206+
207+
Returns
208+
-------
209+
allensdk.brain_observatory.running_speed.RunningSpeed
210+
NamedTuple with two fields:
211+
timestamps : numpy.ndarray
212+
Timestamps of running speed data samples
213+
values : np.ndarray
214+
Running speed of the experimental subject (in cm / s).
215+
"""
216+
if self._raw_running_speed is None:
217+
self._raw_running_speed = self.api.get_running_speed(lowpass=False)
218+
return self._raw_running_speed
219+
220+
@raw_running_speed.setter
221+
def raw_running_speed(self, value):
222+
self._raw_running_speed = value
223+
190224
@property
191225
def running_data_df(self) -> pd.DataFrame:
192-
"""Dataframe containing various signals used to compute running speed
193-
:rtype: pandas.DataFrame
226+
"""Get running speed data. By default applies a 10Hz low pass
227+
filter to the data. To get the running speed without the filter,
228+
use `raw_running_data_df`.
229+
230+
Returns
231+
-------
232+
pd.DataFrame
233+
Dataframe containing various signals used to compute running
234+
speed, and the filtered speed.
194235
"""
195236
if self._running_data_df is None:
196-
self._running_data_df = self.api.get_running_data_df()
237+
self._running_data_df = self.api.get_running_data_df(lowpass=True)
197238
return self._running_data_df
198239

199240
@running_data_df.setter
200241
def running_data_df(self, value):
201242
self._running_data_df = value
202243

244+
@property
245+
def raw_running_data_df(self) -> pd.DataFrame:
246+
"""Get running speed data. Does not apply the 10Hz filter.
247+
248+
Returns
249+
-------
250+
pd.DataFrame
251+
Dataframe containing various signals used to compute running
252+
speed, and the unfilteredfiltered speed.
253+
"""
254+
if self._raw_running_data_df is None:
255+
self._raw_running_data_df = self.api.get_running_data_df(
256+
lowpass=False)
257+
return self._raw_running_data_df
258+
259+
@raw_running_data_df.setter
260+
def raw_running_data_df(self, value):
261+
self._raw_running_data_df = value
262+
203263
@property
204264
def stimulus_presentations(self) -> pd.DataFrame:
205265
"""Table whose rows are stimulus presentations (i.e. a given image,

allensdk/brain_observatory/behavior/internal/behavior_base.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ class BehaviorBase(abc.ABC):
1414
Child classes should be instantiated with a fetch API that implements these
1515
methods.
1616
"""
17+
@abc.abstractmethod
18+
def get_behavior_session_id(self) -> int:
19+
"""Returns the behavior_session_id associated with this experiment,
20+
if applicable.
21+
"""
22+
raise NotImplementedError()
23+
1724
@abc.abstractmethod
1825
def get_licks(self) -> pd.DataFrame:
1926
"""Get lick data from pkl file.

allensdk/brain_observatory/behavior/internal/behavior_ophys_base.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import abc
2+
from typing import Optional
23

34
import numpy as np
45
import pandas as pd
@@ -12,8 +13,16 @@ class BehaviorOphysBase(BehaviorBase):
1213
behavior+ophys session data.
1314
1415
Child classes should be instantiated with a fetch API that implements these
15-
methods. Both fetch API and session object should inherit from this base.
16+
methods.
1617
"""
18+
19+
@abc.abstractmethod
20+
def get_ophys_session_id(self) -> Optional[int]:
21+
"""Returns the ophys_session_id associated with this experiment,
22+
if applicable.
23+
"""
24+
raise NotImplementedError()
25+
1726
@abc.abstractmethod
1827
def get_average_projection(self) -> Image:
1928
"""Get an image whose values are the average obtained values at

0 commit comments

Comments
 (0)