Skip to content

Commit 8f55db4

Browse files
authored
Merge pull request #1838 from AllenInstitute/rc/2.6.0
rc/2.6.0
2 parents 0dedae5 + 95979ef commit 8f55db4

37 files changed

+1995
-415
lines changed

CHANGELOG.md

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

4+
## [2.6.0] = 2021-02-05
5+
- Adds ability to write and read behavior only NWB files
6+
- Adds eye tracking ellipse fits and metadata as new NWB data stream
7+
- OPhys Behavior data retrieval methods no longer depend on ROIs being ordered identically in different files.
8+
49
## [2.5.0] = 2021-01-29
510
- Adds unfiltered running speed as new data stream
611
- run_demixing gracefully ignores any ROIs that are not in the input trace file

allensdk/__init__.py

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

3838

3939

40-
__version__ = '2.5.0'
40+
41+
__version__ = '2.6.0'
4142

4243

4344
try:

allensdk/brain_observatory/behavior/behavior_ophys_session.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,16 @@ def eye_tracking(self) -> pd.DataFrame:
437437
def eye_tracking(self, value):
438438
self._eye_tracking = value
439439

440+
@property
441+
def eye_tracking_rig_geometry(self) -> dict:
442+
"""Get the eye tracking rig geometry associated with an ophys experiment"""
443+
return self.api.get_eye_tracking_rig_geometry()
444+
445+
@property
446+
def eye_gaze_mapping_file_path(self) -> str:
447+
"""Get h5 filepath containing eye gaze behavior of the experiment's subject"""
448+
return self.api.get_eye_gaze_mapping_file_path()
449+
440450
def cache_clear(self) -> None:
441451
"""Convenience method to clear the api cache, if applicable."""
442452
try:

allensdk/brain_observatory/behavior/behavior_session.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import inspect
66

77
from allensdk.brain_observatory.behavior.session_apis.data_io import (
8-
BehaviorLimsApi)
8+
BehaviorLimsApi, BehaviorNwbApi)
99
from allensdk.brain_observatory.behavior.session_apis.abcs import BehaviorBase
1010
from allensdk.brain_observatory.running_speed import RunningSpeed
1111

@@ -36,30 +36,30 @@ def from_lims(cls, behavior_session_id: int) -> "BehaviorSession":
3636
@classmethod
3737
def from_nwb_path(
3838
cls, nwb_path: str, **api_kwargs: Any) -> "BehaviorSession":
39-
return NotImplementedError
39+
return cls(api=BehaviorNwbApi.from_path(path=nwb_path, **api_kwargs))
4040

4141
@property
4242
def behavior_session_id(self) -> int:
4343
"""Unique identifier for this experimental session.
4444
:rtype: int
4545
"""
46-
return self.api.behavior_session_id
46+
return self.api.get_behavior_session_id()
4747

4848
@property
4949
def ophys_session_id(self) -> Optional[int]:
5050
"""The unique identifier for the ophys session associated
5151
with this behavior session (if one exists)
5252
:rtype: int
5353
"""
54-
return self.api.ophys_session_id
54+
return self.api.get_ophys_session_id()
5555

5656
@property
5757
def ophys_experiment_ids(self) -> Optional[List[int]]:
5858
"""The unique identifiers for the ophys experiment(s) associated
5959
with this behavior session (if one exists)
6060
:rtype: int
6161
"""
62-
return self.api.ophys_experiment_ids
62+
return self.api.get_ophys_experiment_ids()
6363

6464
@property
6565
def licks(self) -> pd.DataFrame:

allensdk/brain_observatory/behavior/metadata_processing.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626
"previously trained, but with the lick-response "
2727
"sensor withdrawn (passive/open loop mode)."
2828
)
29+
TRAINING_DESCRIPTION = (
30+
"A training session where a mouse performs a visual change detection task "
31+
"with a set of natural scenes. Successfully completing the task delivers "
32+
"a water reward via a lick spout."
33+
)
2934

3035

3136
def get_expt_description(session_type: str) -> str:
@@ -55,8 +60,11 @@ def get_expt_description(session_type: str) -> str:
5560
ophys_4_6 = dict.fromkeys(["OPHYS_4", "OPHYS_6"], OPHYS_4_6_DESCRIPTION)
5661
ophys_2_5 = {"OPHYS_2": OPHYS_2_DESCRIPTION,
5762
"OPHYS_5": OPHYS_5_DESCRIPTION}
63+
training = dict.fromkeys(
64+
["TRAINING_1", "TRAINING_2", "TRAINING_3", "TRAINING_4", "TRAINING_5"],
65+
TRAINING_DESCRIPTION)
5866

59-
expt_description_dict = {**ophys_1_3, **ophys_2_5, **ophys_4_6}
67+
expt_description_dict = {**ophys_1_3, **ophys_2_5, **ophys_4_6, **training}
6068

6169
# Session type string will look something like: OPHYS_4_images_A
6270
truncated_session_type = "_".join(session_type.split("_")[:2])

allensdk/brain_observatory/behavior/project_apis/data_io/behavior_project_lims_api.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,6 @@ def _get_behavior_summary_table(self,
184184
SELECT
185185
bs.id AS behavior_session_id,
186186
bs.ophys_session_id,
187-
bs.behavior_training_id,
188187
equipment.name as equipment_name,
189188
bs.date_of_acquisition,
190189
d.id as donor_id,

allensdk/brain_observatory/behavior/schemas.py

Lines changed: 71 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ class SubjectMetadataSchema(RaisingSchema):
6161
class BehaviorMetadataSchema(RaisingSchema):
6262
"""This schema contains metadata pertaining to behavior.
6363
"""
64+
neurodata_type = 'BehaviorMetadata'
65+
neurodata_type_inc = 'LabMetaData'
66+
neurodata_doc = "Metadata for behavior and behavior + ophys experiments"
67+
neurodata_skip = {"experiment_datetime"}
6468

6569
behavior_session_uuid = fields.UUID(
6670
doc='MTrain record for session, also called foraging_id',
@@ -71,6 +75,21 @@ class BehaviorMetadataSchema(RaisingSchema):
7175
'visual_stimulus from the monitor'),
7276
required=True,
7377
)
78+
session_type = fields.String(
79+
doc='Experimental session description',
80+
allow_none=True,
81+
required=True,
82+
)
83+
# 'experiment_datetime' will be stored in
84+
# pynwb NWBFile 'session_start_time' attr
85+
experiment_datetime = fields.DateTime(
86+
doc='Date of the experiment (UTC, as string)',
87+
required=True,
88+
)
89+
rig_name = fields.String(
90+
doc='Name of behavior or optical physiology experiment rig',
91+
required=True,
92+
)
7493

7594

7695
class NwbOphysMetadataSchema(RaisingSchema):
@@ -123,10 +142,6 @@ class OphysMetadataSchema(NwbOphysMetadataSchema):
123142
doc='Id for this ophys session',
124143
required=True,
125144
)
126-
rig_name = fields.String(
127-
doc='Name of optical physiology experiment rig',
128-
required=True,
129-
)
130145
field_of_view_width = fields.Int(
131146
doc='Width of optical physiology imaging plane in pixels',
132147
required=True,
@@ -143,7 +158,7 @@ class OphysBehaviorMetadataSchema(BehaviorMetadataSchema, OphysMetadataSchema):
143158
"""
144159

145160
neurodata_type = 'OphysBehaviorMetadata'
146-
neurodata_type_inc = 'LabMetaData'
161+
neurodata_type_inc = 'BehaviorMetadata'
147162
neurodata_doc = "Metadata for behavior + ophys experiments"
148163
# Fields to skip converting to extension
149164
# They already exist as attributes for the following pyNWB classes:
@@ -152,18 +167,6 @@ class OphysBehaviorMetadataSchema(BehaviorMetadataSchema, OphysMetadataSchema):
152167
"targeted_structure", "experiment_datetime",
153168
"ophys_frame_rate"}
154169

155-
session_type = fields.String(
156-
doc='Experimental session description',
157-
allow_none=True,
158-
required=True,
159-
)
160-
# 'experiment_datetime' will be stored in
161-
# pynwb NWBFile 'session_start_time' attr
162-
experiment_datetime = fields.DateTime(
163-
doc='Date of the experiment (UTC, as string)',
164-
required=True,
165-
)
166-
167170

168171
class CompleteOphysBehaviorMetadataSchema(OphysBehaviorMetadataSchema,
169172
SubjectMetadataSchema):
@@ -230,3 +233,54 @@ class BehaviorTaskParametersSchema(RaisingSchema):
230233
doc='Total number of stimuli frames',
231234
required=True,
232235
)
236+
237+
238+
class EyeTrackingRigGeometry(RaisingSchema):
239+
"""Eye tracking rig geometry"""
240+
values = fields.Float(
241+
doc='position/rotation with respect to (x, y, z)',
242+
required=True,
243+
shape=(3,)
244+
)
245+
unit_of_measurement = fields.Str(
246+
doc='Unit of measurement for the data',
247+
required=True
248+
)
249+
250+
251+
class OphysEyeTrackingRigMetadataSchema(RaisingSchema):
252+
"""This schema encompasses metadata for ophys experiment rig
253+
"""
254+
neurodata_type = 'OphysEyeTrackingRigMetadata'
255+
neurodata_type_inc = 'NWBDataInterface'
256+
neurodata_doc = "Metadata for ophys experiment rig"
257+
258+
equipment = fields.Str(
259+
doc='Description of rig',
260+
required=True
261+
)
262+
monitor_position = fields.Nested(
263+
EyeTrackingRigGeometry,
264+
doc='position of monitor (x, y, z)',
265+
required=True
266+
)
267+
camera_position = fields.Nested(
268+
EyeTrackingRigGeometry,
269+
doc='position of camera (x, y, z)',
270+
required=True
271+
)
272+
led_position = fields.Nested(
273+
EyeTrackingRigGeometry,
274+
doc='position of LED (x, y, z)',
275+
required=True
276+
)
277+
monitor_rotation = fields.Nested(
278+
EyeTrackingRigGeometry,
279+
doc='rotation of monitor (x, y, z)',
280+
required=True
281+
)
282+
camera_rotation = fields.Nested(
283+
EyeTrackingRigGeometry,
284+
doc='rotation of camera (x, y, z)',
285+
required=True
286+
)

allensdk/brain_observatory/behavior/session_apis/abcs/behavior_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def get_licks(self) -> pd.DataFrame:
2727
2828
Returns
2929
-------
30-
np.ndarray
30+
pd.Dataframe
3131
A dataframe containing lick timestamps.
3232
"""
3333
raise NotImplementedError()

allensdk/brain_observatory/behavior/session_apis/abcs/behavior_ophys_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ def get_stimulus_presentations(self) -> pd.DataFrame:
152152
raise NotImplementedError()
153153

154154
@abc.abstractmethod
155-
def get_eye_tracking(self) -> pd.DataFrame:
155+
def get_eye_tracking(self) -> Optional[pd.DataFrame]:
156156
"""Get eye tracking data from behavior + ophys session.
157157
158158
Returns

allensdk/brain_observatory/behavior/session_apis/data_io/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# data_io classes for behavior only
2+
from allensdk.brain_observatory.behavior.session_apis.data_io.behavior_nwb_api import BehaviorNwbApi # noqa: F401, E501
23
from allensdk.brain_observatory.behavior.session_apis.data_io.behavior_lims_api import BehaviorLimsApi # noqa: F401, E501
4+
from allensdk.brain_observatory.behavior.session_apis.data_io.behavior_json_api import BehaviorJsonApi # noqa: F401, E501
35

46
# data_io classes for behavior + ophys
57
from allensdk.brain_observatory.behavior.session_apis.data_io.behavior_ophys_nwb_api import BehaviorOphysNwbApi # noqa: F401, E501

0 commit comments

Comments
 (0)