Visual Coding Ophys Dataset#

import pandas as pd 
import numpy as np
from datetime import datetime, date
from aind_data_access_api.document_db import MetadataDbClient

API_GATEWAY_HOST = "api.allenneuraldynamics.org"
DATABASE = 'metadata_index'
COLLECTION = 'data_assets'

docdb_api_client = MetadataDbClient(
   host=API_GATEWAY_HOST,
    version="v2",
   database=DATABASE,
   collection=COLLECTION,
)
print(docdb_api_client._base_url)
https://api.allenneuraldynamics.org/v2/metadata_index/data_assets

Dataset#

We will start exploring the parameters of the dataset to learn what data is available. We can query the database and create a dataframe of some of the key metadata fields:

aggregate = [
  {
    "$match": {
      "data_description.project_name": {
        "$regex": "Allen Brain Observatory - Visual Coding Ophys",
        "$options": "i"
      },
    }
  },
  {
    "$project": {
      "name": 1, 
      "subject_id": "$data_description.subject_id",
      "genotype": "$subject.subject_details.genotype", 
      "date_of_birth": "$subject.subject_details.date_of_birth", 
      "sex": "$subject.subject_details.sex", 
      "session_time": "$acquisition.acquisition_start_time",
      "project_name": "$data_description.project_name", 
      "modality": "$data_description.modalities.name",
      "depth": "$acquisition.data_streams.configurations.images.planes.depth",
      "targeted_structure": "$acquisition.data_streams.configurations.images.planes.targeted_structure.acronym",
      "session_type": "$acquisition.acquisition_type",
      "container_id": { "$arrayElemAt": ["$data_description.tags", 2] },
    }
  },
]
    
records = docdb_api_client.aggregate_docdb_records(
    pipeline = aggregate,
)
df = pd.DataFrame(records)

df['session_date'] = df.apply(lambda x: datetime.fromisoformat(x['session_time']).date(), axis=1)
df['session_time'] = df.apply(lambda x: datetime.fromisoformat(x['session_time']).time(), axis=1)
df['date_of_birth'] = df.apply(lambda x: datetime.strptime(x['date_of_birth'], '%Y-%m-%d').date(), axis=1)
df['age'] = df.apply(lambda x: (x['session_date'] - x['date_of_birth']).days, axis=1)

df['depth'] = df.apply(lambda x: list(np.array(x['depth']).flatten())[0], axis=1)
df['targeted_structure'] = df.apply(lambda x: str(np.array(x['targeted_structure']).flatten()[0]), axis=1)

df['container_id'] = df.apply(lambda x: int(x['container_id'].split(' ')[-1]), axis=1)

order = ['project_name','_id','name','subject_id','genotype','date_of_birth','sex','modality',
         'session_type','session_date','age','session_time','depth', 'targeted_structure','container_id']
df = df[order]

df.head()
project_name _id name subject_id genotype date_of_birth sex modality session_type session_date age session_time depth targeted_structure container_id
0 Allen Brain Observatory - Visual Coding Ophys c88f22d2-a6a5-42a8-805a-80869635cfba 261967_2016-11-08_11-29-45_nwb_2026-08-19_17-4... 261967 Nr5a1-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-GCaMP6f)/wt 2016-06-13 Female [Behavior videos, Planar optical physiology] three_session_B 2016-11-08 148 11:29:45 350 VISpm 555749366
1 Allen Brain Observatory - Visual Coding Ophys ae362a40-f97b-495e-96ec-fea98b19d753 280643_2016-12-22_11-09-41_nwb_2026-08-19_17-1... 280643 Emx1-IRES-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-GCaMP... 2016-09-17 Male [Planar optical physiology, Behavior videos] three_session_B 2016-12-22 96 11:09:41 175 VISal 560876149
2 Allen Brain Observatory - Visual Coding Ophys f1335249-f136-4b7b-a9f2-6b2b920d8c25 229105_2016-03-09_11-13-50_nwb_2026-08-19_18-1... 229105 Cux2-CreERT2/Cux2-CreERT2;Camk2a-tTA/wt;Ai93(T... 2015-12-14 Male [Planar optical physiology, Behavior videos] three_session_C 2016-03-09 86 11:13:50 175 VISal 511510998
3 Allen Brain Observatory - Visual Coding Ophys e556a3a4-edba-423e-a0eb-f239bf42e6cd 361635_2018-02-19_11-00-16_nwb_2026-08-19_18-1... 361635 Slc17a7-IRES2-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-G... 2017-10-12 Female [Planar optical physiology, Behavior videos] three_session_A 2018-02-19 130 11:00:16 375 VISpm 665413463
4 Allen Brain Observatory - Visual Coding Ophys 8a249c0b-ce8e-4b28-804b-e05755280db2 336246_2017-08-30_11-08-01_nwb_2026-08-19_17-2... 336246 Vip-IRES-Cre/wt;Ai148(TIT2L-GC6f-ICL-tTA2)/wt 2017-06-03 Female [Planar optical physiology, Behavior videos] three_session_A 2017-08-30 88 11:08:01 275 VISl 614556104

Targeted structures#

What brain regions were recorded across the dataset? Look at the unique targeted structures

df.targeted_structure.unique().tolist()
['VISpm', 'VISal', 'VISl', 'VISp', 'VISrl', 'VISam']

We see that data was collected in six different visual areas. VISp is the primary visual cortex, also known as V1. The others are higher visual areas (HVAs) that surround VISp. You can learn more about these areas and how we map them here.

Cre lines and reporters#

We used Cre lines to drive the expression of GCaMP6 in specific populations of neurons. We also use four different reporter lines for GCaMP6. The identity of both the driver and the reporter are contained within the genotype of the mouse. The genotype also conveys whether a given subject is homozygous or heterozygous (i.e. whether the subject has one or two copies of any element). So far, we see no significant differences between homozygous and heterozygous mice, and we recommend analyzing them together. But as a result, a list of unique genotypes is over complete

We can find a list of all the cre lines used in this dataset as follows

cre_lines = []
for item in df.genotype.unique():
    cre_lines.append(item.split('/')[0])
cre_lines = np.unique(cre_lines)
cre_lines.tolist()
['Cux2-CreERT2',
 'Emx1-IRES-Cre',
 'Fezf2-CreER',
 'Nr5a1-Cre',
 'Ntsr1-Cre_GN220',
 'Pvalb-IRES-Cre',
 'Rbp4-Cre_KL100',
 'Rorb-IRES2-Cre',
 'Scnn1a-Tg3-Cre',
 'Slc17a7-IRES2-Cre',
 'Sst-IRES-Cre',
 'Tlx3-Cre_PL56',
 'Vip-IRES-Cre']

See Transgenic tools to learn more about these Cre lines and reporters.

Note

Reporter lines: All the experiments in this dataset use GCaMP6. The large majority use GCaMP6f and only a few use GCaMP6s. However, you see four different reporters listed here. Why is this? Ai93 is the GCaMP6f reporter we used with the excitatory Cre lines. However, this reporter does not work well for inhibitory Cre lines. We used Ai148, another GCaMP6f reporter, with Vip-IRES-Cre and Sst-IRES-Cre. However, this didn’t work with the Pvalb-IRES-Cre. We use Ai162, a GCaMP6s reporter with Pvalb. Additionally, to have a GCaMP6f vs GCaMP6s comparison, we collected a small number of experiments using Ai94 with the Slc17a7-IRES2-Cre. This is a GCaMP6s reporter that complements Ai93. Slc17a7-IRES2-Cre is the only Cre line that was recorded using multiple reporter types.

Imaging depths#

Each experiment was collected at a single imaging depth.

df.depth.unique().tolist()
[350,
 175,
 375,
 275,
 300,
 276,
 550,
 625,
 285,
 250,
 400,
 390,
 265,
 325,
 320,
 335,
 185,
 570,
 205,
 365,
 435,
 225,
 200,
 195]

These values are in µm below the surface of the cortex. This is a long list and some of the values don’t differ by very much. How meaningful is it? We roughly consider depths less than 250 to be layer 2/3, 250-350 to be layer 4, 350-500 to be layer 5, and over 500 to be layer 6. Keep in mind, much of the imaging here was done with layer specific Cre lines, so for most purposes the best way to get layer specificity is to select appropriate Cre lines.

Experiment containers & sessions#

The experiment {term} container describes a set of 3 imaging sessions performed for the same field of view (ie. same targeted structure and imaging depth in the same mouse that targets the same set of neurons). Each experiment container has a unique ID number.

Let’s look at all of the sessions in one experiment container

df[df.container_id==df.container_id[0]]
project_name _id name subject_id genotype date_of_birth sex modality session_type session_date age session_time depth targeted_structure container_id
0 Allen Brain Observatory - Visual Coding Ophys c88f22d2-a6a5-42a8-805a-80869635cfba 261967_2016-11-08_11-29-45_nwb_2026-08-19_17-4... 261967 Nr5a1-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-GCaMP6f)/wt 2016-06-13 Female [Behavior videos, Planar optical physiology] three_session_B 2016-11-08 148 11:29:45 350 VISpm 555749366
174 Allen Brain Observatory - Visual Coding Ophys 4f8a2bc2-b805-463c-a8b4-f2cdb2d3ccd6 261967_2016-11-03_11-24-50_nwb_2026-08-19_17-5... 261967 Nr5a1-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-GCaMP6f)/wt 2016-06-13 Female [Planar optical physiology, Behavior videos] three_session_A 2016-11-03 143 11:24:50 350 VISpm 555749366
1277 Allen Brain Observatory - Visual Coding Ophys f90f0f7c-c149-454e-9817-7b480d3e832a 261967_2016-11-10_11-06-49_nwb_2026-08-19_17-5... 261967 Nr5a1-Cre/wt;Camk2a-tTA/wt;Ai93(TITL-GCaMP6f)/wt 2016-06-13 Female [Behavior videos, Planar optical physiology] three_session_C2 2016-11-10 150 11:06:49 350 VISpm 555749366

Notice that the subject_id, genotype, targeted structure, depth are all the same. What differs are the session_type, the session_date, and age.

Each session_type has a different set of visual stimuli.

As you see, each experiment container has three different session types. For the data published in June 2016 and October 2016, the last session is three_session_C</b<> while the data published after this were collected using three_session_C2. The key difference between these sessions is a change in the locally sparse noise stimulus. This is described more here.

containers

Exercise: How many sessions were collected in each cortical visual area for each Cre line?#

# we made a list of cre_lines above
areas = df.targeted_structure.unique().tolist() #list of areas

df2 = pd.DataFrame(columns=areas, index=cre_lines)
for cre in cre_lines:
  for area in areas:
    df2.loc[cre, area] = len(df[(df.targeted_structure==area)&(df['genotype'].str.contains(cre))])
df2
VISpm VISal VISl VISp VISrl VISam
Cux2-CreERT2 51 39 45 63 36 33
Emx1-IRES-Cre 12 21 24 60 27 9
Fezf2-CreER 0 0 15 12 0 0
Nr5a1-Cre 21 24 24 36 21 21
Ntsr1-Cre_GN220 15 0 21 18 0 0
Pvalb-IRES-Cre 0 0 15 48 0 0
Rbp4-Cre_KL100 21 24 27 33 12 27
Rorb-IRES2-Cre 27 21 21 33 15 24
Scnn1a-Tg3-Cre 0 0 0 27 0 0
Slc17a7-IRES2-Cre 45 6 48 60 6 6
Sst-IRES-Cre 42 3 45 51 6 0
Tlx3-Cre_PL56 0 0 9 18 0 0
Vip-IRES-Cre 48 0 51 51 0 0