includes some visualizations
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import zscore
from sklearn.decomposition import PCA
# @title Figure settings
from matplotlib import rcParams
rcParams['figure.figsize'] = [20, 4]
rcParams['font.size'] = 15
rcParams['axes.spines.top'] = False
rcParams['axes.spines.right'] = False
rcParams['figure.autolayout'] = True
# @title Data retrieval
import os, requests
fname = []
for j in range(3):
fname.append('steinmetz_part%d.npz'%j)
url = ["https://osf.io/agvxh/download"]
url.append("https://osf.io/uv3mw/download")
url.append("https://osf.io/ehmw2/download")
for j in range(len(url)):
if not os.path.isfile(fname[j]):
try:
r = requests.get(url[j])
except requests.ConnectionError:
print("!!! Failed to download data !!!")
else:
if r.status_code != requests.codes.ok:
print("!!! Failed to download data !!!")
else:
with open(fname[j], "wb") as fid:
fid.write(r.content)
# @title Data loading
alldat = np.array([])
for j in range(len(fname)):
alldat = np.hstack((alldat,
np.load('steinmetz_part%d.npz'%j,
allow_pickle=True)['dat']))
alldat
contains 39 sessions from 10 mice, data from Steinmetz et al, 2019. Time bins for all measurements are 10ms, starting 500ms before stimulus onset. The mouse had to determine which side has the highest contrast. For each dat = alldat[k]
, you have the fields below. For extra variables, check out the extra notebook and extra data files (lfp, waveforms and exact spike times, non-binned).
dat['mouse_name']
: mouse namedat['date_exp']
: when a session was performeddat['spks']
: neurons by trials by time bins.dat['brain_area']
: brain area for each neuron recorded.dat['ccf']
: Allen Institute brain atlas coordinates for each neuron.dat['ccf_axes']
: axes names for the Allen CCF.dat['contrast_right']
: contrast level for the right stimulus, which is always contralateral to the recorded brain areas.dat['contrast_left']
: contrast level for left stimulus.dat['gocue']
: when the go cue sound was played.dat['response_time']
: when the response was registered, which has to be after the go cue. The mouse can turn the wheel before the go cue (and nearly always does!), but the stimulus on the screen won't move before the go cue.dat['response']
: which side the response was (-1
, 0
, 1
). When the right-side stimulus had higher contrast, the correct choice was -1
. 0
is a no go response.dat['feedback_time']
: when feedback was provided.dat['feedback_type']
: if the feedback was positive (+1
, reward) or negative (-1
, white noise burst).dat['wheel']
: turning speed of the wheel that the mice uses to make a response, sampled at 10ms
.dat['pupil']
: pupil area (noisy, because pupil is very small) + pupil horizontal and vertical position.dat['face']
: average face motion energy from a video camera.dat['licks']
: lick detections, 0 or 1.dat['trough_to_peak']
: measures the width of the action potential waveform for each neuron. Widths <=10
samples are "putative fast spiking neurons".dat['%X%_passive']
: same as above for X
= {spks
, pupil
, wheel
, contrast_left
, contrast_right
} but for passive trials at the end of the recording when the mouse was no longer engaged and stopped making responses.dat['prev_reward']
: time of the feedback (reward/white noise) on the previous trial in relation to the current stimulus time.dat['reaction_time']
: ntrials by 2. First column: reaction time computed from the wheel movement as the first sample above 5
ticks/10ms bin. Second column: direction of the wheel movement (0
= no move detected).The original dataset is here: https://figshare.com/articles/dataset/Dataset_from_Steinmetz_et_al_2019/9598406
# Make a plot of which brain areas are present in each dataset
# note that region 4 ("other ctx" are neurons that were not able to be classified)
# region 4 does not correspond to brain_group 4, which are all cortical neurons outside of visual cortex
regions = ["vis ctx", "thal", "hipp", "other ctx", "midbrain", "basal ganglia", "cortical subplate", "other"]
region_colors = ['blue', 'red', 'green', 'darkblue', 'violet', 'lightblue', 'orange', 'gray']
brain_groups = [["VISa", "VISam", "VISl", "VISp", "VISpm", "VISrl"], # visual cortex
["CL", "LD", "LGd", "LH", "LP", "MD", "MG", "PO", "POL", "PT", "RT", "SPF", "TH", "VAL", "VPL", "VPM"], # thalamus
["CA", "CA1", "CA2", "CA3", "DG", "SUB", "POST"], # hippocampal
["ACA", "AUD", "COA", "DP", "ILA", "MOp", "MOs", "OLF", "ORB", "ORBm", "PIR", "PL", "SSp", "SSs", "RSP","TT"], # non-visual cortex
["APN", "IC", "MB", "MRN", "NB", "PAG", "RN", "SCs", "SCm", "SCig", "SCsg", "ZI"], # midbrain
["ACB", "CP", "GPe", "LS", "LSc", "LSr", "MS", "OT", "SNr", "SI"], # basal ganglia
["BLA", "BMA", "EP", "EPd", "MEA"] # cortical subplate
]
# Assign each area an index
area_to_index = dict(root=0)
counter = 1
for group in brain_groups:
for area in group:
area_to_index[area] = counter
counter += 1
# Figure out which areas are in each dataset
areas_by_dataset = np.zeros((counter, len(alldat)), dtype=bool)
for j, d in enumerate(alldat):
for area in np.unique(d['brain_area']):
i = area_to_index[area]
areas_by_dataset[i, j] = True
# Show the binary matrix
plt.figure(figsize=(8, 10))
plt.imshow(areas_by_dataset, cmap="Greys", aspect="auto", interpolation="none")
# Label the axes
plt.xlabel("dataset")
plt.ylabel("area")
# Add tick labels
yticklabels = ["root"]
for group in brain_groups:
yticklabels.extend(group)
plt.yticks(np.arange(counter), yticklabels, fontsize=8)
plt.xticks(np.arange(len(alldat)), fontsize=9)
# Color the tick labels by region
ytickobjs = plt.gca().get_yticklabels()
ytickobjs[0].set_color("black")
counter = 1
for group, color in zip(brain_groups, region_colors):
for area in group:
ytickobjs[counter].set_color(color)
counter += 1
plt.title("Brain areas present in each dataset")
plt.grid(True)
plt.show()
# @title Basic plots of population average
# select just one of the recordings here. 11 is nice because it has some neurons in vis ctx.
dat = alldat[11]
print(dat.keys())
dt = dat['bin_size'] # binning at 10 ms
NT = dat['spks'].shape[-1]
ax = plt.subplot(1, 5, 1)
response = dat['response'] # right - nogo - left (-1, 0, 1)
vis_right = dat['contrast_right'] # 0 - low - high
vis_left = dat['contrast_left'] # 0 - low - high
plt.plot(dt * np.arange(NT), 1/dt * dat['spks'][:, response >= 0].mean(axis=(0, 1))) # left responses
plt.plot(dt * np.arange(NT), 1/dt * dat['spks'][:, response < 0].mean(axis=(0, 1))) # right responses
plt.plot(dt * np.arange(NT), 1/dt * dat['spks'][:, vis_right > 0].mean(axis=(0, 1))) # stimulus on the right
plt.plot(dt * np.arange(NT), 1/dt * dat['spks'][:, vis_right == 0].mean(axis=(0, 1))) # no stimulus on the right
plt.legend(['left resp', 'right resp', 'right stim', 'no right stim'], fontsize=12)
ax.set(xlabel='time (sec)', ylabel='firing rate (Hz)')
plt.show()
dict_keys(['spks', 'wheel', 'pupil', 'response', 'response_time', 'bin_size', 'stim_onset', 'contrast_right', 'contrast_left', 'brain_area', 'feedback_time', 'feedback_type', 'gocue', 'mouse_name', 'date_exp', 'trough_to_peak', 'active_trials', 'contrast_left_passive', 'contrast_right_passive', 'spks_passive', 'pupil_passive', 'wheel_passive', 'prev_reward', 'ccf', 'ccf_axes', 'cellid_orig', 'reaction_time', 'face', 'face_passive', 'licks', 'licks_passive'])
nareas = 4 # only the top 4 regions are in this particular mouse
NN = len(dat['brain_area']) # number of neurons
barea = nareas * np.ones(NN, ) # last one is "other"
for j in range(nareas):
barea[np.isin(dat['brain_area'], brain_groups[j])] = j # assign a number to each region
# @title plots by brain region and visual conditions
for j in range(nareas):
ax = plt.subplot(1, nareas, j + 1)
plt.plot(1/dt * dat['spks'][barea==j][:, np.logical_and(vis_left == 0, vis_right > 0)].mean(axis=(0, 1)))
plt.plot(1/dt * dat['spks'][barea==j][:, np.logical_and(vis_left > 0, vis_right == 0)].mean(axis=(0, 1)))
plt.plot(1/dt * dat['spks'][barea==j][:, np.logical_and(vis_left == 0, vis_right == 0)].mean(axis=(0, 1)))
plt.plot(1/dt * dat['spks'][barea==j][:, np.logical_and(vis_left > 0, vis_right > 0)].mean(axis=(0, 1)))
plt.text(.25, .92, 'n=%d'%np.sum(barea == j), transform=ax.transAxes)
if j==0:
plt.legend(['right only', 'left only', 'neither', 'both'], fontsize=12)
ax.set(xlabel='binned time', ylabel='mean firing rate (Hz)', title=regions[j])
plt.show()
# @title plots by brain region and response type
for j in range(nareas):
ax = plt.subplot(1, nareas, j + 1)
plt.title(regions[j])
if np.sum(barea == j) == 0:
continue
plt.plot(1/dt * dat['spks'][barea == j][:, response < 0].mean(axis=(0, 1)))
plt.plot(1/dt * dat['spks'][barea == j][:, response > 0].mean(axis=(0, 1)))
plt.plot(1/dt * dat['spks'][barea == j][:, response == 0].mean(axis=(0, 1)))
if j == 0:
plt.legend(['resp = left', 'resp = right', 'resp = none'], fontsize=12)
ax.set(xlabel='time', ylabel='mean firing rate (Hz)')
plt.show()