Example behavior session¶

The following example shows how to access behavioral data for a given mouse across sessions

We will first install allensdk into your environment by running the appropriate commands below.

Install AllenSDK into your local environment¶

You can install AllenSDK with:

In [ ]:
pip install allensdk

Install AllenSDK into your notebook environment (good for Google Colab)¶

You can install AllenSDK into your notebook environment by executing the cell below.

If using Google Colab, click on the RESTART RUNTIME button that appears at the end of the output when this cell is complete,. Note that running this cell will produce a long list of outputs and some error messages. Clicking RESTART RUNTIME at the end will resolve these issues. You can minimize the cell after you are done to hide the output.

In [ ]:
!pip install --upgrade pip
!pip install allensdk

Imports¶

In [1]:
import matplotlib.pyplot as plt
import seaborn as sns
import os
import numpy as np
import pandas as pd
pd.set_option('display.max_columns', 500)

import allensdk.brain_observatory.behavior.behavior_project_cache as bpc

import allensdk
import pkg_resources
print('allensdk version 2.10.2 or higher is required, you have {} installed'.format(pkg_resources.get_distribution("allensdk").version))
allensdk version 2.10.2 or higher is required, you have 2.10.2 installed
In [2]:
%matplotlib notebook
In [3]:
from IPython.core.display import display, HTML
display(HTML("<style>.container { width:100% !important; }</style>"))

load cache, get behavior session table¶

This will set a location on your local drive to cache NWB files.
Then a table of all behavior sessions will be loaded.

In [4]:
# choose a location on your file system to cache NWB files as they are loaded:
my_cache_dir = A_PATH_TO_SOME_LOCAL_FOLDER

bc = bpc.VisualBehaviorOphysProjectCache.from_s3_cache(cache_dir=my_cache_dir)
          
behavior_session_table = bc.get_behavior_session_table()
ophys_session_table.csv: 100%|██████████| 165k/165k [00:00<00:00, 1.54MMB/s]
behavior_session_table.csv: 100%|██████████| 885k/885k [00:00<00:00, 4.96MMB/s]
ophys_experiment_table.csv: 100%|██████████| 336k/336k [00:00<00:00, 3.05MMB/s]

view a sample of the behavior session table¶

The behavior_session_table is a Pandas DataFrame with one row for every session and a collection of informative columns. We can view 10 randomly selected rows of the table using the Pandas sample command.
It's important to note that this table contains every session, including sessions performed on a two-photon imaging rig (session_type starts with OPHYS_) and pre-imaging (aka 'training') sessions, (session_type starts with TRAINING_).

In [5]:
behavior_session_table.sample(10)
Out[5]:
equipment_name full_genotype mouse_id reporter_line driver_line sex age_in_days session_type cre_line indicator session_number prior_exposures_to_session_type prior_exposures_to_image_set prior_exposures_to_omissions ophys_session_id ophys_experiment_id ophys_container_id project_code date_of_acquisition file_id
behavior_session_id
974330793 BEH.F-Box1 Sst-IRES-Cre/wt;Ai148(TIT2L-GC6f-ICL-tTA2)/wt 477202 Ai148(TIT2L-GC6f-ICL-tTA2) [Sst-IRES-Cre] M 150.0 OPHYS_0_images_B_habituation Sst-IRES-Cre GCaMP6f 0.0 0 39.0 0 NaN NaN NaN NaN 2019-10-30 14:18:09.393 1.081760e+09
1030893060 BEH.G-Box4 Sst-IRES-Cre/wt;Ai148(TIT2L-GC6f-ICL-tTA2)/wt 524274 Ai148(TIT2L-GC6f-ICL-tTA2) [Sst-IRES-Cre] M 93.0 TRAINING_0_gratings_autorewards_15min Sst-IRES-Cre GCaMP6f NaN 0 NaN 0 NaN NaN NaN NaN 2020-06-19 12:03:18.947 1.085379e+09
825012995 BEH.G Vip-IRES-Cre/wt;Ai148(TIT2L-GC6f-ICL-tTA2)/wt 429952 Ai148(TIT2L-GC6f-ICL-tTA2) [Vip-IRES-Cre] M 129.0 TRAINING_4_images_A_handoff_ready Vip-IRES-Cre GCaMP6f NaN 5 9.0 0 NaN NaN NaN NaN 2019-02-18 14:58:21.851 1.081581e+09
881315895 CAM2P.4 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai94(TITL-G... 456564 Ai94(TITL-GCaMP6s) [Slc17a7-IRES2-Cre, Camk2a-tTA] F 105.0 OPHYS_0_images_A_habituation Slc17a7-IRES2-Cre GCaMP6s 0.0 0 16.0 0 NaN NaN NaN NaN 2019-06-05 10:38:55.714 1.085367e+09
1038132332 BEH.G-Box1 Vip-IRES-Cre/wt;Ai148(TIT2L-GC6f-ICL-tTA2)/wt 523927 Ai148(TIT2L-GC6f-ICL-tTA2) [Vip-IRES-Cre] F 129.0 TRAINING_5_images_A_epilogue Vip-IRES-Cre GCaMP6f NaN 3 11.0 0 NaN NaN NaN NaN 2020-07-23 13:13:25.926 1.081778e+09
1055031004 BEH.F-Box3 Vip-IRES-Cre/wt;Ai148(TIT2L-GC6f-ICL-tTA2)/wt 538219 Ai148(TIT2L-GC6f-ICL-tTA2) [Vip-IRES-Cre] F 117.0 TRAINING_1_gratings Vip-IRES-Cre GCaMP6f NaN 11 NaN 0 NaN NaN NaN NaN 2020-10-06 13:47:11.772 1.085381e+09
917506393 BEH.G-Box6 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 459777 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] F 150.0 TRAINING_5_images_A_handoff_ready Slc17a7-IRES2-Cre GCaMP6f NaN 31 39.0 0 NaN NaN NaN NaN 2019-08-05 12:25:59.198 1.081713e+09
918900907 BEH.F-Box3 Vip-IRES-Cre/wt;Ai148(TIT2L-GC6f-ICL-tTA2)/wt 453988 Ai148(TIT2L-GC6f-ICL-tTA2) [Vip-IRES-Cre] M 180.0 TRAINING_5_images_A_handoff_ready Vip-IRES-Cre GCaMP6f NaN 28 43.0 0 NaN NaN NaN NaN 2019-08-07 09:31:30.837 1.081714e+09
976558967 MESO.1 Sst-IRES-Cre/wt;Ai148(TIT2L-GC6f-ICL-tTA2)/wt 482853 Ai148(TIT2L-GC6f-ICL-tTA2) [Sst-IRES-Cre] M 128.0 OPHYS_2_images_A_passive Sst-IRES-Cre GCaMP6f 2.0 0 27.0 2 976382032.0 [977247466, 977247468, 977247472, 977247474, 9... [1018028199, 1018028202, 1018028212, 101802821... VisualBehaviorMultiscope 2019-11-05 08:53:47.241 NaN
902135840 CAM2P.5 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 461946 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] F 112.0 OPHYS_2_images_B_passive Slc17a7-IRES2-Cre GCaMP6f 2.0 0 13.0 2 901759468.0 [902487182] [895259496] VisualBehaviorTask1B 2019-07-09 11:01:23.316 NaN

Select one mouse¶

We'll choose one mouse id from the full list of unique mouse IDs in the dataset

In [6]:
mouse_id = behavior_session_table['mouse_id'].unique()[76]
mouse_id
Out[6]:
445002

query the full behavior sessions table for all sessions that this mouse performed¶

This will return a subset of the full behavior_session_table in which the mouse_id matches our mouse_id variable (mouse 445002). The table should be returned in order of date of acquisition, but we'll use the Pandas command sort_values(by = 'date_of_acquisition') just to be sure.

What we then see is a table that has metadata for every session performed by this mouse, in sequential order. The equipment_name column tells us where the session was run on that day and the session_type column tells us the name of the session type. See the technical white paper for a description of the progression of stages.

For this mouse, we can see that it progressed through a series of training stages starting on 3/15/2019 in behavior training boxes BEH.B-Box3 and BEH.B-Box1.

On 4/1/2019, it reached the TRAINING_5_images_A_handoff_ready, which meant that it was ready for transition to an imaging rig as soon as space became available.

On 4/4/2019, it was transitioned to ophys rig CAM2P.3, where it then underwent three days of habituation without imaging. This is evidenced by the fact that the session type for 4/4/2019, 4/5/2019, and 4/8/2019 was OPHYS_0_images_A_habituation and there was no associated ophys_session_id.

The first day of imaging for this mouse was on 4/9/2019, with session_type = OPHYS_1_images_A.

Note that this mouse has two OPHYS_5_images_B_passive sessions, the first taken in order (immediately after OPHYS_4_images_B), and second taken at the end of the sequence. The first OPHYS_5_images_B_passive does not have an ophys_session_id associated with it. This is likely due to that first session failing to meet quality control standards and being excluded from the dataset. The second OPHYS_5_images_B_passive was likely a retake, taken after the first was identified as having been failed.

In general, ophys behavior sessions that do not have associated ophys_session_ids are sessions for which the ophys data has been removed do to failure to meet quality control standards.

In [7]:
this_mouse_table = behavior_session_table.query('mouse_id == @mouse_id').sort_values(by = 'date_of_acquisition')
# note that the following is functionally equivalent if you find the syntax easier to read: 
# this_mouse_table = behavior_session_table[behavior_session_table['mouse_id'] == mouse_id]
this_mouse_table
Out[7]:
equipment_name full_genotype mouse_id reporter_line driver_line sex age_in_days session_type cre_line indicator session_number prior_exposures_to_session_type prior_exposures_to_image_set prior_exposures_to_omissions ophys_session_id ophys_experiment_id ophys_container_id project_code date_of_acquisition file_id
behavior_session_id
837658854 BEH.B-Box3 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 72.0 TRAINING_0_gratings_autorewards_15min Slc17a7-IRES2-Cre GCaMP6f NaN 0 NaN 0 NaN NaN NaN NaN 2019-03-15 14:49:24.015 1.085362e+09
838515247 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 75.0 TRAINING_1_gratings Slc17a7-IRES2-Cre GCaMP6f NaN 0 NaN 0 NaN NaN NaN NaN 2019-03-18 13:44:01.474 1.085362e+09
839219841 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 76.0 TRAINING_1_gratings Slc17a7-IRES2-Cre GCaMP6f NaN 1 NaN 0 NaN NaN NaN NaN 2019-03-19 12:50:12.068 1.085362e+09
839565422 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 77.0 TRAINING_1_gratings Slc17a7-IRES2-Cre GCaMP6f NaN 2 NaN 0 NaN NaN NaN NaN 2019-03-20 13:16:44.461 1.085362e+09
839912316 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 78.0 TRAINING_2_gratings_flashed Slc17a7-IRES2-Cre GCaMP6f NaN 0 NaN 0 NaN NaN NaN NaN 2019-03-21 12:54:25.388 1.081589e+09
840581827 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 79.0 TRAINING_2_gratings_flashed Slc17a7-IRES2-Cre GCaMP6f NaN 1 NaN 0 NaN NaN NaN NaN 2019-03-22 12:56:37.162 1.081589e+09
841426832 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 82.0 TRAINING_3_images_A_10uL_reward Slc17a7-IRES2-Cre GCaMP6f NaN 0 0.0 0 NaN NaN NaN NaN 2019-03-25 13:33:53.275 1.081589e+09
841827774 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 83.0 TRAINING_3_images_A_10uL_reward Slc17a7-IRES2-Cre GCaMP6f NaN 1 1.0 0 NaN NaN NaN NaN 2019-03-26 12:43:01.470 1.081590e+09
842385277 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 84.0 TRAINING_3_images_A_10uL_reward Slc17a7-IRES2-Cre GCaMP6f NaN 2 2.0 0 NaN NaN NaN NaN 2019-03-27 12:13:04.923 1.081591e+09
842819933 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 85.0 TRAINING_4_images_A_training Slc17a7-IRES2-Cre GCaMP6f NaN 0 3.0 0 NaN NaN NaN NaN 2019-03-28 12:11:36.413 1.081591e+09
843400453 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 86.0 TRAINING_5_images_A_epilogue Slc17a7-IRES2-Cre GCaMP6f NaN 0 4.0 0 NaN NaN NaN NaN 2019-03-29 13:03:16.029 1.081592e+09
844199758 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 89.0 TRAINING_5_images_A_handoff_ready Slc17a7-IRES2-Cre GCaMP6f NaN 0 5.0 0 NaN NaN NaN NaN 2019-04-01 11:59:06.026 1.081591e+09
844908261 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 90.0 TRAINING_5_images_A_handoff_ready Slc17a7-IRES2-Cre GCaMP6f NaN 1 6.0 0 NaN NaN NaN NaN 2019-04-02 12:34:16.170 1.081592e+09
845572044 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 91.0 TRAINING_5_images_A_handoff_ready Slc17a7-IRES2-Cre GCaMP6f NaN 2 7.0 0 NaN NaN NaN NaN 2019-04-03 12:16:13.522 1.081592e+09
846331423 CAM2P.3 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 92.0 OPHYS_0_images_A_habituation Slc17a7-IRES2-Cre GCaMP6f 0.0 0 8.0 0 NaN NaN NaN NaN 2019-04-04 13:13:13.399 1.085362e+09
847036328 CAM2P.3 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 93.0 OPHYS_0_images_A_habituation Slc17a7-IRES2-Cre GCaMP6f 0.0 1 9.0 0 NaN NaN NaN NaN 2019-04-05 12:47:32.422 1.085362e+09
847874940 CAM2P.3 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 96.0 OPHYS_0_images_A_habituation Slc17a7-IRES2-Cre GCaMP6f 0.0 2 10.0 0 NaN NaN NaN NaN 2019-04-08 13:27:21.095 1.085362e+09
848613406 CAM2P.3 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 97.0 OPHYS_1_images_A Slc17a7-IRES2-Cre GCaMP6f 1.0 0 11.0 0 848264483.0 [848697625] [846215539] VisualBehavior 2019-04-09 13:26:26.372 NaN
849147676 CAM2P.3 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 98.0 OPHYS_2_images_A_passive Slc17a7-IRES2-Cre GCaMP6f 2.0 0 12.0 1 848894137.0 [849203565] [846215539] VisualBehavior 2019-04-10 13:34:39.264 NaN
849651275 CAM2P.3 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 99.0 OPHYS_3_images_A Slc17a7-IRES2-Cre GCaMP6f 3.0 0 13.0 2 849597937.0 [850479305] [846215539] VisualBehavior 2019-04-11 12:31:50.074 NaN
850989832 CAM2P.3 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 100.0 OPHYS_4_images_B Slc17a7-IRES2-Cre GCaMP6f 4.0 0 0.0 3 850959102.0 [851060467] [846215539] VisualBehavior 2019-04-12 13:30:27.946 NaN
851773928 CAM2P.3 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 103.0 OPHYS_5_images_B_passive Slc17a7-IRES2-Cre GCaMP6f 5.0 0 1.0 4 NaN NaN NaN NaN 2019-04-15 12:20:00.123 1.081596e+09
852451567 CAM2P.3 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 104.0 OPHYS_6_images_B Slc17a7-IRES2-Cre GCaMP6f 6.0 0 2.0 5 852326785.0 [852691524] [846215539] VisualBehavior 2019-04-16 12:24:46.804 NaN
855200229 CAM2P.3 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 110.0 OPHYS_5_images_B_passive Slc17a7-IRES2-Cre GCaMP6f 5.0 1 3.0 6 855083235.0 [855582961] [846215539] VisualBehavior 2019-04-22 09:01:33.022 NaN

iterate over all sessions for this mouse, build a behavior_session_dict which will have one behavior session object for every session that this mouse performed, with the key being the behavior_session_id¶

Note that this could take many minutes to complete. For each session in our new table, this_mouse_table, we are pulling the behavior session NWB file from AWS, opening it as a BehaviorSession object using the AllenSDK, and also caching a copy of the NWB file in the directory specified above as my_cache_dir. When the below cell completes, all behavior sessions for this mouse will be held in memory in the behavior_session_dict dictionary.

If you were to re-run this cell a second time, it would access your cached NWB files instead of downloading them from AWS, allowing it to run substantially faster.

It is important to note that we will only be loading the behavior data here, even for sessions that had corresponding imaging data. The get_behavior_ophys_experiment method would be used to get behavior and ophys data for ophys sessions. See additional sample notebooks for details.

In [8]:
behavior_session_ids = this_mouse_table.index.values
behavior_session_dict = {}
for behavior_session_id in behavior_session_ids:
    behavior_session_dict[behavior_session_id] = bc.get_behavior_session(behavior_session_id)
behavior_session_837658854.nwb: 100%|██████████| 51.7M/51.7M [00:04<00:00, 11.3MMB/s]  
behavior_session_838515247.nwb: 100%|██████████| 66.9M/66.9M [00:05<00:00, 12.1MMB/s]  
behavior_session_839219841.nwb: 100%|██████████| 66.7M/66.7M [00:06<00:00, 10.1MMB/s]  
behavior_session_839565422.nwb: 100%|██████████| 66.7M/66.7M [00:06<00:00, 11.0MMB/s]  
behavior_session_839912316.nwb: 100%|██████████| 68.0M/68.0M [00:05<00:00, 11.4MMB/s]  
behavior_session_840581827.nwb: 100%|██████████| 68.0M/68.0M [00:06<00:00, 11.1MMB/s]  
behavior_session_841426832.nwb: 100%|██████████| 188M/188M [00:15<00:00, 12.0MMB/s]   
behavior_session_841827774.nwb: 100%|██████████| 188M/188M [00:14<00:00, 13.1MMB/s]   
behavior_session_842385277.nwb: 100%|██████████| 188M/188M [00:16<00:00, 11.5MMB/s]   
behavior_session_842819933.nwb: 100%|██████████| 188M/188M [00:15<00:00, 12.1MMB/s]    
behavior_session_843400453.nwb: 100%|██████████| 193M/193M [00:17<00:00, 11.1MMB/s]   
behavior_session_844199758.nwb: 100%|██████████| 193M/193M [00:18<00:00, 10.5MMB/s]   
behavior_session_844908261.nwb: 100%|██████████| 193M/193M [00:15<00:00, 12.8MMB/s]   
behavior_session_845572044.nwb: 100%|██████████| 193M/193M [00:15<00:00, 12.3MMB/s]   
behavior_session_846331423.nwb: 100%|██████████| 193M/193M [00:16<00:00, 11.8MMB/s]   
behavior_session_847036328.nwb: 100%|██████████| 193M/193M [00:16<00:00, 11.8MMB/s]   
behavior_session_847874940.nwb: 100%|██████████| 193M/193M [00:15<00:00, 12.5MMB/s]    
behavior_ophys_experiment_848697625.nwb: 100%|██████████| 819M/819M [01:04<00:00, 12.7MMB/s]    
behavior_ophys_experiment_849203565.nwb: 100%|██████████| 950M/950M [01:14<00:00, 12.7MMB/s]    
behavior_ophys_experiment_850479305.nwb: 100%|██████████| 898M/898M [01:12<00:00, 12.3MMB/s]    
behavior_ophys_experiment_851060467.nwb: 100%|██████████| 877M/877M [01:07<00:00, 12.9MMB/s]    
behavior_session_851773928.nwb: 100%|██████████| 192M/192M [00:14<00:00, 13.4MMB/s]   
behavior_ophys_experiment_852691524.nwb: 100%|██████████| 926M/926M [01:09<00:00, 13.4MMB/s]    
behavior_ophys_experiment_855582961.nwb: 100%|██████████| 1.04G/1.04G [01:17<00:00, 13.4MMB/s]   

We can view all attributes of the behavior session object¶

These are all of the methods and attributes available on the BehaviorSession object. Not all are explored in this notebook.

In [9]:
behavior_session_id = behavior_session_ids[-1]
behavior_session_dict[behavior_session_id].list_data_attributes_and_methods()
Out[9]:
['behavior_session_id',
 'get_performance_metrics',
 'get_reward_rate',
 'get_rolling_performance_df',
 'licks',
 'metadata',
 'raw_running_speed',
 'rewards',
 'running_speed',
 'stimulus_presentations',
 'stimulus_templates',
 'stimulus_timestamps',
 'task_parameters',
 'trials']

Note that any attribute can be followed by a ? in a Jupyter Notebook to see the docstring. For example, running the cell below will make a frame appear at the bottom of your browser with the docstring for the running_speed attribute.

In [10]:
behavior_session = behavior_session_dict[behavior_session_id]
behavior_session.running_speed?

here are some basic task parameters¶

We can see the session_type, which is OPHYS_5_images_B_passive and a number of other task parameters.

In [11]:
behavior_session_dict[behavior_session_id].task_parameters
Out[11]:
{'n_stimulus_frames': 69255,
 'response_window_sec': [0.15, 0.75],
 'auto_reward_volume': 0.005,
 'session_type': 'OPHYS_5_images_B_passive',
 'stimulus_distribution': 'geometric',
 'task': 'change detection',
 'stimulus': 'images',
 'omitted_flash_fraction': 0.05,
 'reward_volume': 0.007,
 'stimulus_duration_sec': 0.25,
 'blank_duration_sec': [0.5, 0.5]}

Look at some of the attributes of the last 'handoff ready session'¶

We can filter the full table to get the last TRAINING_5_images_A_handoff_ready session. This would have been the last training session before the animal was subsequently handed off to the imaging team, after which all sessions were performed on a two-photon imaging rig.

In [12]:
behavior_session_id = this_mouse_table.query('session_type == "TRAINING_5_images_A_handoff_ready"').index[-1]
# note that the following is functionally equivalent if you find the syntax easier to read: 
# behavior_session_id = this_mouse_table[this_mouse_table['session_type'] == "TRAINING_5_images_A_handoff_ready"].index[-1]
dataset = behavior_session_dict[behavior_session_id]

stimuli¶

One entry for every distinct stimulus. Includes onset and offset time/frame.

In [13]:
dataset.stimulus_presentations.head(5)
Out[13]:
duration end_frame image_index image_name image_set index omitted start_frame start_time stop_time is_change
stimulus_presentations_id
0 0.250208 18000.0 0 im065 Natural_Images_Lum_Matched_set_training_2017.0... 0 False 17985.0 300.001180 300.251388 False
1 0.250228 18045.0 0 im065 Natural_Images_Lum_Matched_set_training_2017.0... 1 False 18030.0 300.751814 301.002042 False
2 0.250259 18090.0 0 im065 Natural_Images_Lum_Matched_set_training_2017.0... 2 False 18075.0 301.502388 301.752647 False
3 0.250277 18136.0 0 im065 Natural_Images_Lum_Matched_set_training_2017.0... 3 False 18121.0 302.269753 302.520030 False
4 0.250199 18181.0 0 im065 Natural_Images_Lum_Matched_set_training_2017.0... 4 False 18166.0 303.020392 303.270591 False

licks¶

One entry for every detected lick onset time, assigned the time of the corresponding visual stimulus frame.

In [14]:
dataset.licks.sample(5)
Out[14]:
timestamps frame
1240 1570.283190 94138
470 722.889309 43337
503 780.270804 46777
1252 1580.992166 94780
1257 1581.726111 94824

rewards¶

One entry for every reward that was delivered, assigned the time of the corresponding visual stimulus frame. Autorewarded is True if the reward was delivered without requiring a preceding lick.

In [15]:
dataset.rewards.sample(5)
Out[15]:
volume timestamps autorewarded
100 0.007 2041.578365 False
29 0.007 813.631992 False
6 0.007 401.736694 False
24 0.007 720.820943 False
25 0.007 761.721954 False

running data¶

One entry for each read of the analog input line monitoring the encoder voltage, polled at ~60 Hz

In [16]:
dataset.running_speed.head()
Out[16]:
timestamps speed
0 0.000000 0.010719
1 0.016554 -0.034077
2 0.033231 -0.079193
3 0.049912 -0.121338
4 0.067623 -0.156735

we can make a simple plot where we combine together running, licking and stimuli¶

First, add a column to the stimulus_presentations table that assigns a unique color to every stimulus¶

In [17]:
unique_stimuli = [stimulus for stimulus in dataset.stimulus_presentations['image_name'].unique()]
colormap = {image_name: sns.color_palette()[image_number] for image_number, image_name in enumerate(np.sort(unique_stimuli))}
dataset.stimulus_presentations['color'] = dataset.stimulus_presentations['image_name'].map(lambda image_name: colormap[image_name])

now make some simple plotting functions to plot these datastreams¶

In [18]:
def plot_running(ax, initial_time, final_time):
    '''
    a simple function to plot running speed between two specified times on a specified axis
    inputs:
        ax: axis on which to plot
        intial_time: initial time to plot from
        final_time: final time to plot to
    '''
    running_sample = dataset.running_speed.query('timestamps >= @initial_time and timestamps <= @final_time')
    ax.plot(
        running_sample['timestamps'],
        running_sample['speed']
    )

def plot_licks(ax, initial_time, final_time):
    '''
    a simple function to plot licks as dots between two specified times on a specified axis
    inputs:
        ax: axis on which to plot
        intial_time: initial time to plot from
        final_time: final time to plot to
    '''
    licking_sample = dataset.licks.query('timestamps >= @initial_time and timestamps <= @final_time')
    ax.plot(
        licking_sample['timestamps'],
        np.zeros_like(licking_sample['timestamps']),
        marker = 'o',
        color = 'black',
        linestyle = 'none'
    )
    
def plot_rewards(ax, initial_time, final_time):
    '''
    a simple function to plot rewards between two specified times as blue diamonds on a specified axis
    inputs:
        ax: axis on which to plot
        intial_time: initial time to plot from
        final_time: final time to plot to
    '''
    rewards_sample = dataset.rewards.query('timestamps >= @initial_time and timestamps <= @final_time')
    ax.plot(
        rewards_sample['timestamps'],
        np.zeros_like(rewards_sample['timestamps']),
        marker = 'd',
        color = 'blue',
        linestyle = 'none',
        markersize = 12,
        alpha = 0.5
    )
    
def plot_stimuli(ax, ti, tf):
    '''
    a simple function to plot stimuli as colored vertical spans on a s
    inputs:
        ax: axis on which to plot
        intial_time: initial time to plot from
        final_time: final time to plot to
    '''
    stimulus_presentations_sample = dataset.stimulus_presentations.query('stop_time >= @initial_time and start_time <= @final_time')
    for idx, stimulus in stimulus_presentations_sample.iterrows():
        ax.axvspan(stimulus['start_time'], stimulus['stop_time'], color=stimulus['color'], alpha=0.25)

now make the plot¶

In [19]:
initial_time = 775 # initial time for plot, in seconds
final_time = 800 # final time for plot, in seconds
fig, ax = plt.subplots(figsize = (15,5))
plot_running(ax, initial_time, final_time)
plot_licks(ax, initial_time, final_time)
plot_rewards(ax, initial_time, final_time)
plot_stimuli(ax, initial_time, final_time)

ax.legend(['running speed', 'licks', 'rewards'])

ax.set_ylabel('running speed (cm/s)')
ax.set_xlabel('time in session (s)')
ax.set_xlim(initial_time, final_time)
ax.set_title('a short section of the session');

Above, we can see that stimuli were being delivered at a regular cadence (250 ms on, 500 ms off). There were changes to new stimuli at t = 778.6 and t = 793.7, as indicated by the change in the color of the bars. The mouse licked inside of the required response window following both stimulus changes and received a reward coincident with the first lick following the change. The subsequent licks are likely a result of the mouse consuming the water reward. There was also a brief bout of two licks, likely representing impulsivity, at t = 786.9.

trials¶

We can view attributes of every trial here. Below is a random sample of 5 trials

In [20]:
dataset.trials.sample(5)
Out[20]:
start_time stop_time lick_times reward_time reward_volume hit false_alarm miss stimulus_change aborted go catch auto_rewarded correct_reject trial_length response_time change_frame change_time response_latency initial_image_name change_image_name
trials_id
133 1145.777254 1148.362823 [1147.8956996658817, 1148.0458577824757] NaN 0.0 False False False False True False False False False 2.585569 NaN NaN NaN NaN im065 im065
62 650.712128 658.018251 [] NaN 0.0 False False True True False True False False False 7.306123 NaN 39191.0 653.752495 inf im063 im061
239 1768.766277 1771.885580 [1771.5686300797388] NaN 0.0 False False False False True False False False False 3.119302 NaN NaN NaN NaN im066 im066
497 3736.683052 3743.972490 [] NaN 0.0 False False True True False True False False False 7.289437 NaN 224193.0 3739.723400 inf im061 im063
463 3443.887593 3451.193661 [] NaN 0.0 False False True True False True False False False 7.306068 NaN 206640.0 3446.927890 inf im062 im065

we can examine one trial in some detail. Let's randomly select a hit trial.¶

Some things to note:

  • The trial started at 831.2635398912244 seconds (start_time) relative to the start of the session.
  • The stimulus changed from 'im063' (intial_image_name) to 'im069' (change_image_name) at t = 834.287206646593 seconds (change_time) relative to the start of the session.
  • The animal's first lick (lick_times[0]) and response_time was at t = 834.69975263 seconds relative to the start of the session.
  • The response_latency, which is response_time - change_time, was 0.41254598174464263 seconds.
  • A reward (reward_time) was delivered at 834.6997526283376 seconds relative to the start of the session. This was coincident with the first lick.
In [21]:
dataset.trials.query('hit').sample(random_state=0).to_dict('records')
Out[21]:
[{'start_time': 831.2635398912244,
  'stop_time': 838.5529783256352,
  'lick_times': array([834.69975263, 834.81651755, 835.1001309 , 835.25021287,
         835.40033855, 835.53378616, 835.68391515, 835.83403254,
         836.01752922, 836.16765357, 836.33444306, 836.51795332,
         836.6513857 ]),
  'reward_time': 834.6997526283376,
  'reward_volume': 0.007,
  'hit': True,
  'false_alarm': False,
  'miss': False,
  'stimulus_change': True,
  'aborted': False,
  'go': True,
  'catch': False,
  'auto_rewarded': False,
  'correct_reject': False,
  'trial_length': 7.28943843441084,
  'response_time': 834.6997526283376,
  'change_frame': 50014.0,
  'change_time': 834.287206646593,
  'response_latency': 0.41254598174464263,
  'initial_image_name': 'im063',
  'change_image_name': 'im069'}]

One useful method is the get_performance_metrics method, which returns some summary metrics on the session, derived from the 'rolling_performance_df'¶

In [22]:
behavior_session_dict[behavior_session_id].get_performance_metrics()
Out[22]:
{'trial_count': 516,
 'go_trial_count': 285,
 'catch_trial_count': 41,
 'hit_trial_count': 112,
 'miss_trial_count': 173,
 'false_alarm_trial_count': 4,
 'correct_reject_trial_count': 37,
 'auto_reward_count': 5,
 'earned_reward_count': 112,
 'total_reward_count': 117,
 'total_reward_volume': 0.8090000000000003,
 'maximum_reward_rate': 4.538096320942588,
 'engaged_trial_count': 286,
 'mean_hit_rate': 0.5083809219533421,
 'mean_hit_rate_uncorrected': 0.5117040303378002,
 'mean_hit_rate_engaged': 0.8257788159919642,
 'mean_false_alarm_rate': 0.149303880370626,
 'mean_false_alarm_rate_uncorrected': 0.14679636896218598,
 'mean_false_alarm_rate_engaged': 0.26905802530802525,
 'mean_dprime': 1.1510474492903153,
 'mean_dprime_engaged': 1.6017817039091797,
 'max_dprime': 2.1577849816633154,
 'max_dprime_engaged': 2.1577849816633154}

we can build out a new table that has all performance data for every session as follows:¶

This might take a minute or so. The AllenSDK will be extracting the performance data from the NWB file for every session individually.

In [23]:
behavior_performance_table = pd.DataFrame(
    [behavior_session_dict[behavior_session_id].get_performance_metrics() for behavior_session_id in behavior_session_ids]
).set_index(behavior_session_ids)
In [24]:
behavior_performance_table.head()
Out[24]:
trial_count go_trial_count catch_trial_count hit_trial_count miss_trial_count false_alarm_trial_count correct_reject_trial_count auto_reward_count earned_reward_count total_reward_count total_reward_volume maximum_reward_rate engaged_trial_count mean_hit_rate mean_hit_rate_uncorrected mean_hit_rate_engaged mean_false_alarm_rate mean_false_alarm_rate_uncorrected mean_false_alarm_rate_engaged mean_dprime mean_dprime_engaged max_dprime max_dprime_engaged
837658854 118 0 0 0 0 0 0 118 0 118 0.590 4.852157 101 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
838515247 1405 133 13 106 27 6 7 5 106 111 1.085 5.294545 346 0.808946 0.819726 0.822212 0.574381 0.624039 0.421906 0.662053 1.145407 1.832280 1.832280
839219841 451 335 61 48 287 1 60 29 48 77 0.625 5.015095 49 0.231115 0.233778 0.809956 0.059502 0.025165 0.176463 0.452645 1.875796 2.288211 2.288211
839565422 683 269 41 107 162 4 37 15 107 122 1.145 5.393113 403 0.523621 0.529213 0.877314 0.192331 0.169870 0.377171 1.208391 1.599180 2.201408 2.201408
839912316 966 174 20 103 71 6 14 10 103 113 1.080 3.833645 583 0.778670 0.785813 0.919466 0.439618 0.511879 0.586558 1.164035 1.240594 1.679661 1.644854

for convenience, we should merge this with the existing table we built for this mouse¶

In [25]:
this_mouse_table = this_mouse_table.merge(
    behavior_performance_table,
    left_index = True,
    right_index = True,
)
this_mouse_table.head()
Out[25]:
equipment_name full_genotype mouse_id reporter_line driver_line sex age_in_days session_type cre_line indicator session_number prior_exposures_to_session_type prior_exposures_to_image_set prior_exposures_to_omissions ophys_session_id ophys_experiment_id ophys_container_id project_code date_of_acquisition file_id trial_count go_trial_count catch_trial_count hit_trial_count miss_trial_count false_alarm_trial_count correct_reject_trial_count auto_reward_count earned_reward_count total_reward_count total_reward_volume maximum_reward_rate engaged_trial_count mean_hit_rate mean_hit_rate_uncorrected mean_hit_rate_engaged mean_false_alarm_rate mean_false_alarm_rate_uncorrected mean_false_alarm_rate_engaged mean_dprime mean_dprime_engaged max_dprime max_dprime_engaged
behavior_session_id
837658854 BEH.B-Box3 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 72.0 TRAINING_0_gratings_autorewards_15min Slc17a7-IRES2-Cre GCaMP6f NaN 0 NaN 0 NaN NaN NaN NaN 2019-03-15 14:49:24.015 1.085362e+09 118 0 0 0 0 0 0 118 0 118 0.590 4.852157 101 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
838515247 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 75.0 TRAINING_1_gratings Slc17a7-IRES2-Cre GCaMP6f NaN 0 NaN 0 NaN NaN NaN NaN 2019-03-18 13:44:01.474 1.085362e+09 1405 133 13 106 27 6 7 5 106 111 1.085 5.294545 346 0.808946 0.819726 0.822212 0.574381 0.624039 0.421906 0.662053 1.145407 1.832280 1.832280
839219841 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 76.0 TRAINING_1_gratings Slc17a7-IRES2-Cre GCaMP6f NaN 1 NaN 0 NaN NaN NaN NaN 2019-03-19 12:50:12.068 1.085362e+09 451 335 61 48 287 1 60 29 48 77 0.625 5.015095 49 0.231115 0.233778 0.809956 0.059502 0.025165 0.176463 0.452645 1.875796 2.288211 2.288211
839565422 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 77.0 TRAINING_1_gratings Slc17a7-IRES2-Cre GCaMP6f NaN 2 NaN 0 NaN NaN NaN NaN 2019-03-20 13:16:44.461 1.085362e+09 683 269 41 107 162 4 37 15 107 122 1.145 5.393113 403 0.523621 0.529213 0.877314 0.192331 0.169870 0.377171 1.208391 1.599180 2.201408 2.201408
839912316 BEH.B-Box1 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 445002 Ai93(TITL-GCaMP6f) [Slc17a7-IRES2-Cre, Camk2a-tTA] M 78.0 TRAINING_2_gratings_flashed Slc17a7-IRES2-Cre GCaMP6f NaN 0 NaN 0 NaN NaN NaN NaN 2019-03-21 12:54:25.388 1.081589e+09 966 174 20 103 71 6 14 10 103 113 1.080 3.833645 583 0.778670 0.785813 0.919466 0.439618 0.511879 0.586558 1.164035 1.240594 1.679661 1.644854

Now we can plot the max_dprime value for every session¶

We can see that this particular mouse performed relatively consistently for every session as it progressed through training.

In [27]:
fig, ax = plt.subplots(figsize = (15,5))

ax.plot(
    np.arange(len(this_mouse_table)),
    this_mouse_table['max_dprime'],
    marker = 'o'
)
ax.set_xticks(range(len(this_mouse_table)))
ax.set_xticklabels(list(this_mouse_table['session_type'].values),rotation = 30, ha='right')

# make alternating black/gray vspans for visual clarity
colors = ['black', 'gray']
for ii in range(len(this_mouse_table)):
    ax.axvspan(ii - 0.5, ii + 0.5, color = colors[ii%2], alpha=0.25)

ax.set_xlim(-0.5, len(this_mouse_table) - 0.5)
ax.set_ylabel('dprime')
ax.set_xlabel('session type')
ax.set_title("Max of rolling d' for every session for mouse {}".format(mouse_id))
fig.tight_layout()
In [ ]: