Skip to content

Commit

Permalink
Merge pull request #2277 from AllenInstitute/ticket/2257
Browse files Browse the repository at this point in the history
Updates to support MESO.2
  • Loading branch information
aamster authored Dec 8, 2021
2 parents e94632b + 0ac514b commit cb29a83
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 86 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.

## [2.13.2] = TBD
- Fixes bug that caused file paths on windows machines to be incorrect in Visual behavior user-facing classes
- Updates to support MESO.2

## [2.13.1] = 2021-10-04
- Fixes bug that was preventing the BehaviorSession from properly instantiating passive sessions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ def calculate_monitor_delay(sync_file: SyncFile,
'CAM2P.3': 0.021390,
'CAM2P.4': 0.021102,
'CAM2P.5': 0.021192,
'MESO.1': 0.03613}
'MESO.1': 0.03613,
# TODO update with actual monitor delay once calculated
'MESO.2': 0.03613}

if equipment_name not in delay_lookup:
msg = warning_msg
Expand Down
160 changes: 88 additions & 72 deletions allensdk/brain_observatory/behavior/sync/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,212 +3,226 @@
@author: marinag
"""
from itertools import chain
from typing import Dict, Any, Optional, List, Union
from allensdk.brain_observatory.behavior.sync.process_sync import (
filter_digital, calculate_delay) # NOQA: E402
from allensdk.brain_observatory.sync_dataset import Dataset as SyncDataset # NOQA: E402
from typing import Dict, Optional, List, Union
from allensdk.brain_observatory.sync_dataset import \
Dataset as SyncDataset
import numpy as np
import scipy.stats as sps


def get_raw_stimulus_frames(
dataset: SyncDataset,
permissive: bool = False
dataset: SyncDataset,
permissive: bool = False
) -> np.ndarray:
""" Report the raw timestamps of each stimulus frame. This corresponds to
the time at which the psychopy window's flip method returned, but not
""" Report the raw timestamps of each stimulus frame. This corresponds to
the time at which the psychopy window's flip method returned, but not
necessarily to the time at which the stimulus frame was displayed.
Parameters
----------
dataset : describes experiment timing
permissive : If True, None will be returned if timestamps are not found. If
False, a KeyError will be raised
permissive : If True, None will be returned if timestamps are not found.
If False, a KeyError will be raised
Returns
-------
array of timestamps (floating point; seconds; relative to experiment start).
array of timestamps (floating point; seconds; relative to experiment
start).
"""
try:
return dataset.get_edges("falling",'stim_vsync', "seconds")
return dataset.get_edges(kind="falling",
keys=["vsync_stim", "stim_vsync"],
units="seconds")
except KeyError:
if not permissive:
raise
return


def get_ophys_frames(
dataset: SyncDataset,
dataset: SyncDataset,
permissive: bool = False
) -> np.ndarray:
""" Report the timestamps of each optical physiology video frame
Parameters
----------
dataset : describes experiment timing
permissive : If True, None will be returned if timestamps are not found.
If False, a KeyError will be raised
Returns
-------
array of timestamps (floating point; seconds; relative to experiment start).
permissive : If True, None will be returned if timestamps are not found. If
False, a KeyError will be raised
array of timestamps (floating point; seconds; relative to experiment
start).
Notes
-----
use rising edge for Scientifica, falling edge for Nikon
use rising edge for Scientifica, falling edge for Nikon
http://confluence.corp.alleninstitute.org/display/IT/Ophys+Time+Sync
This function uses rising edges
"""
try:
return dataset.get_edges("rising", '2p_vsync', "seconds")
return dataset.get_edges(kind="rising",
keys=["vsync_2p", "2p_vsync"],
units="seconds")
except KeyError:
if not permissive:
raise
return


def get_lick_times(
dataset: SyncDataset,
dataset: SyncDataset,
permissive: bool = False
) -> Optional[np.ndarray]:
""" Report the timestamps of each detected lick
Parameters
----------
dataset : describes experiment timing
permissive : If True, None will be returned if timestamps are not found. If
False, a KeyError will be raised
permissive : If True, None will be returned if timestamps are not found.
If False, a KeyError will be raised
Returns
-------
array of timestamps (floating point; seconds; relative to experiment start)
or None. If None, no lick timestamps were found in this sync
array of timestamps (floating point; seconds; relative to experiment
start)
or None. If None, no lick timestamps were found in this sync
dataset.
"""
return dataset.get_edges(
"rising", ["lick_times", "lick_sensor"], "seconds", permissive)


def get_stim_photodiode(
dataset: SyncDataset,
dataset: SyncDataset,
permissive: bool = False
) -> Optional[List[float]]:
""" Report the timestamps of each detected sync square transition (both
""" Report the timestamps of each detected sync square transition (both
black -> white and white -> black) in this experiment.
Parameters
----------
dataset : describes experiment timing
permissive : If True, None will be returned if timestamps are not found. If
False, a KeyError will be raised
permissive : If True, None will be returned if timestamps are not found.
If False, a KeyError will be raised
Returns
-------
array of timestamps (floating point; seconds; relative to experiment start)
or None. If None, no photodiode timestamps were found in this sync
dataset.
array of timestamps (floating point; seconds; relative to experiment
start) or None. If None, no photodiode timestamps were found in this sync
dataset.
"""
return dataset.get_edges(
"all", ["stim_photodiode", "photodiode"], "seconds", permissive)


def get_trigger(
dataset: SyncDataset,
dataset: SyncDataset,
permissive: bool = False
) -> Optional[np.ndarray]:
""" Returns (as a 1-element array) the time at which optical physiology
""" Returns (as a 1-element array) the time at which optical physiology
acquisition was started.
Parameters
----------
dataset : describes experiment timing
permissive : If True, None will be returned if timestamps are not found. If
False, a KeyError will be raised
permissive : If True, None will be returned if timestamps are not found.
If False, a KeyError will be raised
Returns
-------
timestamps (floating point; seconds; relative to experiment start)
or None. If None, no timestamps were found in this sync dataset.
timestamps (floating point; seconds; relative to experiment start)
or None. If None, no timestamps were found in this sync dataset.
Notes
-----
Ophys frame timestamps can be recorded before acquisition start when
experimenters are setting up the recording session. These do not
correspond to acquired ophys frames.
Ophys frame timestamps can be recorded before acquisition start when
experimenters are setting up the recording session. These do not
correspond to acquired ophys frames.
"""
return dataset.get_edges(
"rising", ["2p_trigger", "acq_trigger"], "seconds", permissive)
keys = ["2p_trigger", "acq_trigger", "2p_acq_trigger", "2p_acquiring",
"stim_running"]
return dataset.get_edges(kind="rising",
keys=keys,
units="seconds",
permissive=permissive)


def get_eye_tracking(
dataset: SyncDataset,
dataset: SyncDataset,
permissive: bool = False
) -> Optional[np.ndarray]:
""" Report the timestamps of each frame of the eye tracking video
Parameters
----------
dataset : describes experiment timing
permissive : If True, None will be returned if timestamps are not found. If
False, a KeyError will be raised
permissive : If True, None will be returned if timestamps are not found.
If False, a KeyError will be raised
Returns
-------
array of timestamps (floating point; seconds; relative to experiment start)
or None. If None, no eye tracking timestamps were found in this sync
dataset.
array of timestamps (floating point; seconds; relative to experiment
start) or None. If None, no eye tracking timestamps were found in this
sync dataset.
"""
return dataset.get_edges(
"rising", ["cam2_exposure", "eye_tracking"], "seconds", permissive)
keys = ["cam2_exposure", "eye_tracking", "eye_frame_received"]
return dataset.get_edges(kind="rising",
keys=keys,
units="seconds",
permissive=permissive)


def get_behavior_monitoring(
dataset: SyncDataset,
dataset: SyncDataset,
permissive: bool = False
) -> Optional[np.ndarray]:
""" Report the timestamps of each frame of the behavior
""" Report the timestamps of each frame of the behavior
monitoring video
Parameters
----------
dataset : describes experiment timing
permissive : If True, None will be returned if timestamps are not found. If
False, a KeyError will be raised
permissive : If True, None will be returned if timestamps are not found.
If False, a KeyError will be raised
Returns
-------
array of timestamps (floating point; seconds; relative to experiment start)
or None. If None, no behavior monitoring timestamps were found in this
sync dataset.
array of timestamps (floating point; seconds; relative to experiment
start) or None. If None, no behavior monitoring timestamps were found in
this sync dataset.
"""
return dataset.get_edges(
"rising", ["cam1_exposure", "behavior_monitoring"], "seconds",
permissive)
keys = ["cam1_exposure", "behavior_monitoring", "beh_frame_received"]
return dataset.get_edges(kind="rising",
keys=keys,
units="seconds",
permissive=permissive)


def get_sync_data(
sync_path: str,
permissive: bool = False
) -> Dict[str, Union[List, np.ndarray, None]]:
""" Convenience function for extracting several timestamp arrays from a
""" Convenience function for extracting several timestamp arrays from a
sync file.
Parameters
----------
sync_path : The hdf5 file here ought to be a Visual Behavior sync output
file. See allensdk.brain_observatory.sync_dataset for more details of
this format.
permissive : If True, None will be returned if timestamps are not found. If
False, a KeyError will be raised
sync_path : The hdf5 file here ought to be a Visual Behavior sync output
file. See allensdk.brain_observatory.sync_dataset for more details of
this format.
permissive : If True, None will be returned if timestamps are not found.
If False, a KeyError will be raised
Returns
-------
A dictionary with the following keys. All timestamps in seconds:
Expand All @@ -219,7 +233,7 @@ def get_sync_data(
behavior_monitoring : timestamps of behavior monitoring video frame
stim_photodiode : timestamps of each photodiode transition
stimulus_times_no_delay : raw stimulus frame timestamps
Some values may be None. This indicates that the corresponding timestamps
Some values may be None. This indicates that the corresponding timestamps
were not located in this sync file.
"""
Expand All @@ -230,7 +244,9 @@ def get_sync_data(
'lick_times': get_lick_times(sync_dataset, permissive),
'ophys_trigger': get_trigger(sync_dataset, permissive),
'eye_tracking': get_eye_tracking(sync_dataset, permissive),
'behavior_monitoring': get_behavior_monitoring(sync_dataset, permissive),
'behavior_monitoring': get_behavior_monitoring(sync_dataset,
permissive),
'stim_photodiode': get_stim_photodiode(sync_dataset, permissive),
'stimulus_times_no_delay': get_raw_stimulus_frames(sync_dataset, permissive)
'stimulus_times_no_delay': get_raw_stimulus_frames(sync_dataset,
permissive)
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,9 @@ def setup_method(self, method):
self.sync_file = SyncFile(filepath=str(test_data_dir / 'sync.h5'))
self.trials = TrialTable(trials=trials)

def test_monitor_delay(self, monkeypatch):
equipment = Equipment(equipment_name='CAM2P.1')
@pytest.mark.parametrize('equipment_name', ('CAMP2.1', 'MESO.2'))
def test_monitor_delay(self, monkeypatch, equipment_name):
equipment = Equipment(equipment_name=equipment_name)

def dummy_delay(self):
return 1.12
Expand Down
Loading

0 comments on commit cb29a83

Please sign in to comment.