OpenScope’s Dendritic Coupling Dataset#

Predictive coding hypotheses posit that perception is an active process whereby brain regions predict incoming sensory inputs, against which they are compared by other neural populations. Mismatches between predictions and inputs result in error signals that can then be used to update the predictive model encoded in synaptic weights, thereby driving plasticity. Although increasing amounts of evidence are consistent with the general framework, many different algorithmic implementations have been proposed, requiring further experiments to test specific corollaries of these varied approaches. One important, testable implication distinguishing some current theories involves the coupling strength in L2/3 and L5 pyramidal neurons between distal apical dendrites, which tend to receive top-down inputs that may include sensory prediction data, and their conjoined somata, which are often driven by bottom-up inputs. In particular, error signals are computed or else collocated in apical dendrites in some implementations, resulting in a quiescent subunit when the prediction matches inputs—zero error—and, thus, reduced dendro-somatic coupling during such times. In contrast, a separate proposal implies the opposite: Since many apical dendritic voltage signals can only reach their electrotonically segregated soma when facilitated by bursting induced by concurrent somatic sensory inputs, dendro-somatic coupling would instead be strongest when top-down predictions match bottom-up signals.

Our experiment seeks to test these hypotheses by near-simultaneously imaging L2/3 and L5 somata and distal apical dendrites in mouse V1, LM, PM, and AM in transgenic lines that express GCaMP6f. Imaging four distinct areas allows us to also examine the consistency of the coupling rules, further putting the notion of a cortical canonical microcircuit to the test. By habituating animals to sets of visual stimuli with spatiotemporal patterns that are subsequently violated, we can evaluate the neural responses across the visual cortical hierarchy to help in adjudicating these important neuroscientific questions.

dendritic_coupling_fig3

Environment Setup#

⚠️Note: If running on a new environment, run this cell once and then restart the kernel⚠️

import warnings
warnings.filterwarnings('ignore')

try:
    from databook_utils.dandi_utils import dandi_download_open
except:
    !git clone https://github.com/AllenInstitute/openscope_databook.git
    %cd openscope_databook
    %pip install -e .
    %cd docs/projects
import os

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

from mpl_interactions import hyperslicer
from scipy import interpolate
from scipy.stats import ttest_ind

%matplotlib inline

The Experiment#

For this release of Dendritic Coupling, Openscope has pre-released just 2 mice on the DANDI Archive. The following table gives a summary of all the files from those two mice in this dataset. Eight files are produced from each experimental session, one for each imaging plane, and six sessions are conducted with each mouse, totalling 96 files for this dandiset. This table was generated from Getting Experimental Metadata from DANDI.

session_files = pd.read_csv("../../data/dc_sessions.csv")
session_files
identifier size path session_time session_id experiment_id container_id group group_count imaging_depth location fov_height fov_width specimen_name sex age genotype stim_types n_rois session_end
0 2b16c329-a2f2-44c0-917f-d2485eca5fb7 4008765509 sub-644972/sub-644972_ses-1238929581-acq-12391... 2023-01-11 16:33:05.503000+00:00 1238929581 1239101628 0 3 4 288 VISpm 512 512 644972 M P162.0D Rbp4-Cre_KL100/wt;Camk2a-tTA/wt;Ai93(TITL-GCaM... {'movie_flower_rev_fwd_presentations', 'movie_... None 3937.19637
1 c1a7d88e-2a7d-463e-a73d-b46eaea61593 1079474009 sub-644972/sub-644972_ses-1237338784-acq-12378... 2023-01-04 16:58:58.862000+00:00 1237338784 1237809217 0 0 4 20 VISp 512 512 644972 M P155.0D Rbp4-Cre_KL100/wt;Camk2a-tTA/wt;Ai93(TITL-GCaM... {'spontaneous_presentations', 'rotate_gabors_p... 6 3941.94600
2 dff85610-18b0-4d72-8ebd-5639516fe0b7 1073642857 sub-644972/sub-644972_ses-1237338784-acq-12378... 2023-01-04 16:58:58.862000+00:00 1237338784 1237809220 0 1 4 25 VISam 512 512 644972 M P155.0D Rbp4-Cre_KL100/wt;Camk2a-tTA/wt;Ai93(TITL-GCaM... {'spontaneous_presentations', 'rotate_gabors_p... 1 3941.94600
3 ee3b7520-6ac7-49ea-88b3-022d5be7816b 1069138065 sub-644972/sub-644972_ses-1237338784-acq-12378... 2023-01-04 16:58:58.862000+00:00 1237338784 1237809223 0 2 4 30 VISl 512 512 644972 M P155.0D Rbp4-Cre_KL100/wt;Camk2a-tTA/wt;Ai93(TITL-GCaM... {'spontaneous_presentations', 'rotate_gabors_p... None 3941.94600
4 a81fd01e-36be-4eff-a3f1-379201a95bf4 1144934234 sub-644972/sub-644972_ses-1237338784-acq-12378... 2023-01-04 16:58:58.862000+00:00 1237338784 1237809219 0 0 4 295 VISp 512 512 644972 M P155.0D Rbp4-Cre_KL100/wt;Camk2a-tTA/wt;Ai93(TITL-GCaM... {'spontaneous_presentations', 'rotate_gabors_p... 62 3941.94600
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
91 42b35234-d4dd-49cb-85c2-08a201ce826e 4041517083 sub-656228/sub-656228_ses-1247233186-acq-12473... 2023-02-14 21:44:00.768000+00:00 1247233186 1247385130 0 0 4 152 VISp 512 512 656228 M P109.0D Cux2-CreERT2/wt;Camk2a-tTA/wt;Ai93(TITL-GCaMP6... {'movie_flower_rev_fwd_presentations', 'movie_... 25 3943.08654
92 9661ce3c-372a-4f00-8db8-a68184fbc607 4014625264 sub-656228/sub-656228_ses-1247233186-acq-12473... 2023-02-14 21:44:00.768000+00:00 1247233186 1247385137 0 3 4 46 VISpm 512 512 656228 M P109.0D Cux2-CreERT2/wt;Camk2a-tTA/wt;Ai93(TITL-GCaMP6... {'movie_flower_rev_fwd_presentations', 'movie_... 2 3943.08654
93 aace7ef8-742f-4382-b53d-938e30c25fc9 4014619723 sub-656228/sub-656228_ses-1247233186-acq-12473... 2023-02-14 21:44:00.768000+00:00 1247233186 1247385131 0 1 4 50 VISam 512 512 656228 M P109.0D Cux2-CreERT2/wt;Camk2a-tTA/wt;Ai93(TITL-GCaMP6... {'movie_flower_rev_fwd_presentations', 'movie_... 2 3943.08654
94 667eb4f7-88ab-4d19-bfc1-3f9e789f5c20 4043804172 sub-656228/sub-656228_ses-1247233186-acq-12473... 2023-02-14 21:44:00.768000+00:00 1247233186 1247385136 0 2 4 144 VISl 512 512 656228 M P109.0D Cux2-CreERT2/wt;Camk2a-tTA/wt;Ai93(TITL-GCaMP6... {'gratings_presentations', 'movie_touch_of_evi... 27 3943.08654
95 8f9bd3ef-120d-4f5c-9498-ec79d477d447 4016954448 sub-656228/sub-656228_ses-1247233186-acq-12473... 2023-02-14 21:44:00.768000+00:00 1247233186 1247385128 0 0 4 42 VISp 512 512 656228 M P109.0D Cux2-CreERT2/wt;Camk2a-tTA/wt;Ai93(TITL-GCaMP6... {'gratings_presentations', 'movie_touch_of_evi... 4 3943.08654

96 rows × 20 columns

n_sessions = len(session_files["session_id"].value_counts())
subjects_info = session_files.groupby(["specimen_name", "sex"]).size().reset_index().to_dict()
m_count = len([sex for sex in subjects_info["sex"].values() if sex == "M"])
f_count = len([sex for sex in subjects_info["sex"].values() if sex == "F"])

print("Dandiset Overview:")
print(len(session_files), "files")
print(len(subjects_info["specimen_name"]), "subjects", m_count, "males", f_count,"females")
Dandiset Overview:
96 files
2 subjects 2 males 0 females

Downloading Ophys File#

dandiset_id = "000871"
dandi_filepath = "sub-656228/sub-656228_ses-1245548523-acq-1245937736_image+ophys.nwb"
download_loc = "."
# This can sometimes take a while depending on the size of the file
io = dandi_download_open(dandiset_id, dandi_filepath, download_loc)
nwb = io.read()
PATH                                                     SIZE   DONE            DONE% CHECKSUM STATUS          MESSAGE
sub-656228_ses-1245548523-acq-1245937736_image+ophys.nwb 4.0 GB 4.0 GB           100%    ok    done                   
Summary:                                                 4.0 GB 4.0 GB                         1 done                 
                                                                100.00%                                               
Downloaded file to ./sub-656228_ses-1245548523-acq-1245937736_image+ophys.nwb
Opening file

Imaging Data#

Our Ophys files include lab metadata and imaging_planes objects which ential the information about the location being imaged, shown below.

nwb.lab_meta_data
{'metadata': metadata abc.OphysMetadata at 0x1696900265824
 Fields:
   experiment_container_id: 0
   field_of_view_height: 512
   field_of_view_width: 512
   imaging_depth: 144
   imaging_plane_group: 3
   imaging_plane_group_count: 4
   ophys_experiment_id: 1245937736
   ophys_session_id: 1245548523}
nwb.imaging_planes
{'imaging_plane_1': imaging_plane_1 pynwb.ophys.ImagingPlane at 0x1696900258672
 Fields:
   conversion: 1.0
   description: (512, 512) field of view in VISpm at depth 144 um
   device: MESO.2 pynwb.device.Device at 0x1696900258000
 Fields:
   description: Allen Brain Observatory - Mesoscope 2P Rig
 
   excitation_lambda: 910.0
   imaging_rate: 10.0
   indicator: GCaMP6f
   location: VISpm
   optical_channel: (
     channel_1 <class 'pynwb.ophys.OpticalChannel'>
   )
   unit: meters}

Stimulus Templates#

The files for the Dendritic Coupling project contain the movies used as visual stimulus, referred to as stim templates. The project contain three main stimulus movies with regular forward playback. Some files in the project, such as this one, have reverse, forward-reverse, and reverse-forward versions as well. Below, screenshots from each of the movies are displayed, and one of the movies can be played embedded within this notebook. The key used can be changed to view different stim templates.

nwb.stimulus_template.keys()
dict_keys(['flower_fwd', 'flower_fwd_rev', 'flower_rev', 'flower_rev_fwd', 'touch_of_evil_fwd', 'touch_of_evil_fwd_rev', 'touch_of_evil_rev', 'touch_of_evil_rev_fwd', 'worms_fwd', 'worms_fwd_rev', 'worms_rev', 'worms_rev_fwd'])
n_cols = 4
n_rows = 3
fig, axes = plt.subplots(n_rows, n_cols, figsize=(n_cols*8, n_rows*4))

if len(axes.shape) == 1:
    axes = axes.reshape((1, axes.shape[0]))

for i, template_name in enumerate(nwb.stimulus_template.keys()):
    template_img = nwb.stimulus_template[template_name].data[:,:,0]
    template_img = np.rot90(template_img, k=3)

    ax_row = int(i / n_cols)
    ax_col = i % n_cols
    axes[ax_row][ax_col].imshow(template_img, cmap="gray")
    axes[ax_row][ax_col].set_title(template_name, fontsize=8)

for ax in axes.flat:
    ax.xaxis.set_ticks([])
    ax.yaxis.set_ticks([])

fig.tight_layout()
../_images/d620ce0da42fb3aa070841f7c6b58839bf2a61b63f6d19b402160612139d2963.png
%matplotlib ipympl
plt.tick_params(left=False, bottom=False, labelleft=False, labelbottom=False)

# change this key to view other stim template movies
template_key = "flower_fwd_rev"
template = nwb.stimulus_template[template_key].data
template = np.transpose(template)
view = hyperslicer(template, play_buttons=True, cmap="gray")

Selecting Stimulus Times#

nwb.intervals.keys()
dict_keys(['fixed_gabors_presentations', 'gratings_presentations', 'movie_flower_fwd_presentations', 'movie_flower_fwd_rev_presentations', 'movie_flower_rev_fwd_presentations', 'movie_flower_rev_presentations', 'movie_touch_of_evil_fwd_presentations', 'movie_touch_of_evil_fwd_rev_presentations', 'movie_touch_of_evil_rev_fwd_presentations', 'movie_touch_of_evil_rev_presentations', 'movie_worms_fwd_presentations', 'movie_worms_fwd_rev_presentations', 'movie_worms_rev_fwd_presentations', 'movie_worms_rev_presentations', 'rotate_gabors_presentations', 'spontaneous_presentations'])
stim_table = nwb.intervals["movie_worms_fwd_rev_presentations"]
print(stim_table.colnames)
stim_table[:10]
('start_time', 'stop_time', 'stimulus_name', 'stimulus_block', 'frame', 'color', 'contrast', 'opacity', 'orientation', 'size', 'units', 'stimulus_index', 'tags', 'timeseries')
start_time stop_time stimulus_name stimulus_block frame color contrast opacity orientation size units stimulus_index tags timeseries
id
0 133.87838 133.91170 movie_worms_fwd_rev 7.0 0.0 [1.0, 1.0, 1.0] 1.0 1.0 0.0 [1920.0, 1080.0] pix 10.0 [stimulus_time_interval] [(6000, 2, timestamps pynwb.base.TimeSeries at...
1 133.91170 133.94513 movie_worms_fwd_rev 7.0 1.0 [1.0, 1.0, 1.0] 1.0 1.0 0.0 [1920.0, 1080.0] pix 10.0 [stimulus_time_interval] [(6002, 2, timestamps pynwb.base.TimeSeries at...
2 133.94513 133.97842 movie_worms_fwd_rev 7.0 2.0 [1.0, 1.0, 1.0] 1.0 1.0 0.0 [1920.0, 1080.0] pix 10.0 [stimulus_time_interval] [(6004, 2, timestamps pynwb.base.TimeSeries at...
3 133.97842 134.01179 movie_worms_fwd_rev 7.0 3.0 [1.0, 1.0, 1.0] 1.0 1.0 0.0 [1920.0, 1080.0] pix 10.0 [stimulus_time_interval] [(6006, 2, timestamps pynwb.base.TimeSeries at...
4 134.01179 134.04522 movie_worms_fwd_rev 7.0 4.0 [1.0, 1.0, 1.0] 1.0 1.0 0.0 [1920.0, 1080.0] pix 10.0 [stimulus_time_interval] [(6008, 2, timestamps pynwb.base.TimeSeries at...
5 134.04522 134.07857 movie_worms_fwd_rev 7.0 5.0 [1.0, 1.0, 1.0] 1.0 1.0 0.0 [1920.0, 1080.0] pix 10.0 [stimulus_time_interval] [(6010, 2, timestamps pynwb.base.TimeSeries at...
6 134.07857 134.11187 movie_worms_fwd_rev 7.0 6.0 [1.0, 1.0, 1.0] 1.0 1.0 0.0 [1920.0, 1080.0] pix 10.0 [stimulus_time_interval] [(6012, 2, timestamps pynwb.base.TimeSeries at...
7 134.11187 134.14529 movie_worms_fwd_rev 7.0 7.0 [1.0, 1.0, 1.0] 1.0 1.0 0.0 [1920.0, 1080.0] pix 10.0 [stimulus_time_interval] [(6014, 2, timestamps pynwb.base.TimeSeries at...
8 134.14529 134.17865 movie_worms_fwd_rev 7.0 8.0 [1.0, 1.0, 1.0] 1.0 1.0 0.0 [1920.0, 1080.0] pix 10.0 [stimulus_time_interval] [(6016, 2, timestamps pynwb.base.TimeSeries at...
9 134.17865 134.21195 movie_worms_fwd_rev 7.0 9.0 [1.0, 1.0, 1.0] 1.0 1.0 0.0 [1920.0, 1080.0] pix 10.0 [stimulus_time_interval] [(6018, 2, timestamps pynwb.base.TimeSeries at...
print(np.mean(np.diff(stim_table.start_time)))
print(set(stim_table.frame))
0.4026468757717955
{0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0, 81.0, 82.0, 83.0, 84.0, 85.0, 86.0, 87.0, 88.0, 89.0, 90.0, 91.0, 92.0, 93.0, 94.0, 95.0, 96.0, 97.0, 98.0, 99.0, 100.0, 101.0, 102.0, 103.0, 104.0, 105.0, 106.0, 107.0, 108.0, 109.0, 110.0, 111.0, 112.0, 113.0, 114.0, 115.0, 116.0, 117.0, 118.0, 119.0, 120.0, 121.0, 122.0, 123.0, 124.0, 125.0, 126.0, 127.0, 128.0, 129.0, 130.0, 131.0, 132.0, 133.0, 134.0, 135.0, 136.0, 137.0, 138.0, 139.0, 140.0, 141.0, 142.0, 143.0, 144.0, 145.0, 146.0, 147.0, 148.0, 149.0, 150.0, 151.0, 152.0, 153.0, 154.0, 155.0, 156.0, 157.0, 158.0, 159.0, 160.0, 161.0, 162.0, 163.0, 164.0, 165.0, 166.0, 167.0, 168.0, 169.0, 170.0, 171.0, 172.0, 173.0, 174.0, 175.0, 176.0, 177.0, 178.0, 179.0, 180.0, 181.0, 182.0, 183.0, 184.0, 185.0, 186.0, 187.0, 188.0, 189.0, 190.0, 191.0, 192.0, 193.0, 194.0, 195.0, 196.0, 197.0, 198.0, 199.0, 200.0, 201.0, 202.0, 203.0, 204.0, 205.0, 206.0, 207.0, 208.0, 209.0, 210.0, 211.0, 212.0, 213.0, 214.0, 215.0, 216.0, 217.0, 218.0, 219.0, 220.0, 221.0, 222.0, 223.0, 224.0, 225.0, 226.0, 227.0, 228.0, 229.0, 230.0, 231.0, 232.0, 233.0, 234.0, 235.0, 236.0, 237.0, 238.0, 239.0, 240.0, 241.0, 242.0, 243.0, 244.0, 245.0, 246.0, 247.0, 248.0, 249.0, 250.0, 251.0, 252.0, 253.0, 254.0, 255.0, 256.0, 257.0, 258.0, 259.0, 260.0, 261.0, 262.0, 263.0, 264.0, 265.0, 266.0, 267.0, 268.0, 269.0}
# flower video reverses around frame 190
rev_stim_select = lambda row: row.frame.item() == 190
rev_stim_times = [float(stim_table[i].start_time) for i in range(len(stim_table)) if rev_stim_select(stim_table[i])]
print(len(rev_stim_times))
15

Extracting ROI Fluorescence#

dff = nwb.processing["ophys"]["dff"]
dff_trace = dff.roi_response_series["traces"].data
dff_timestamps = dff.roi_response_series["traces"].timestamps

print(dff_trace.shape)
print(dff_timestamps.shape)

avg_dff_trace = np.average(dff_trace, axis=1)
(37515, 27)
(37515,)

Session Timeline#

To get a good idea of the order and the way stimulus is shown throughout the session, the code below generates a timeline of the various ‘epochs’ of stimulus. It can be seen that there are many small epochs showing the various stimulus movies in the first half of the session, followed by a long epoch of rotating gabors and then a long epoch of fixed gabors.

# extract epoch times from stim table where stimulus rows have a different 'block' than following row
# returns list of epochs, where an epoch is of the form (stimulus name, stimulus block, start time, stop time)
def extract_epochs(stim_name, stim_table, epochs):
    
    # specify a current epoch stop and start time
    epoch_start = stim_table.start_time[0]
    epoch_stop = stim_table.stop_time[0]

    # for each row, try to extend current epoch stop_time
    for i in range(len(stim_table)):
        this_block = stim_table.stimulus_block[i]
        # if end of table, end the current epoch
        if i+1 >= len(stim_table):
            epochs.append((stim_name, this_block, epoch_start, epoch_stop))
            break
            
        next_block = stim_table.stimulus_block[i+1]
        # if next row is the same stim block, push back epoch_stop time
        if next_block == this_block:
            epoch_stop = stim_table.stop_time[i+1]
        # otherwise, end the current epoch, start new epoch
        else:
            epochs.append((stim_name, this_block, epoch_start, epoch_stop))
            epoch_start = stim_table.start_time[i+1]
            epoch_stop = stim_table.stop_time[i+1]
    
    return epochs
# extract epochs from all valid stimulus tables
epochs = []
for stim_name in nwb.intervals.keys():
    stim_table = nwb.intervals[stim_name]
    try:
        epochs = extract_epochs(stim_name, stim_table, epochs)
    except:
        continue

# epochs take the form (stimulus name, stimulus block, start time, stop time)
print(len(epochs))
epochs.sort(key=lambda x: x[2])
for epoch in epochs:
    print(epoch)
185
('movie_worms_fwd_presentations', 0.0, 63.82019, 72.82766)
('movie_flower_fwd_presentations', 1.0, 73.82849, 82.83596)
('movie_worms_rev_fwd_presentations', 2.0, 83.83679, 92.84427)
('movie_worms_rev_presentations', 3.0, 93.84511, 102.8526)
('movie_touch_of_evil_rev_fwd_presentations', 4.0, 103.85349, 112.8609)
('movie_flower_fwd_rev_presentations', 5.0, 113.86172, 122.8692)
('movie_touch_of_evil_rev_presentations', 6.0, 123.8701, 132.87751)
('movie_worms_fwd_rev_presentations', 7.0, 133.87838, 142.88589)
('movie_flower_rev_presentations', 8.0, 143.8867, 152.89421)
('movie_flower_rev_fwd_presentations', 9.0, 153.89504, 162.90245)
('movie_touch_of_evil_fwd_presentations', 10.0, 163.90335, 172.91077)
('movie_touch_of_evil_fwd_rev_presentations', 11.0, 173.91166, 182.91914)
('movie_flower_fwd_rev_presentations', 12.0, 183.91991, 192.92746)
('movie_flower_fwd_presentations', 13.0, 193.92822, 202.93571)
('movie_worms_rev_fwd_presentations', 14.0, 203.93658, 212.94401)
('movie_touch_of_evil_rev_presentations', 15.0, 213.94489, 222.95238)
('movie_touch_of_evil_rev_fwd_presentations', 16.0, 223.95321, 232.96067)
('movie_touch_of_evil_fwd_presentations', 17.0, 233.96147, 242.96905)
('movie_worms_rev_presentations', 18.0, 243.96973, 252.97727)
('movie_flower_rev_fwd_presentations', 19.0, 253.97802, 262.98549)
('movie_worms_fwd_presentations', 20.0, 263.98637, 272.99384)
('movie_touch_of_evil_fwd_rev_presentations', 21.0, 273.99461, 283.00207)
('movie_worms_fwd_rev_presentations', 22.0, 284.00291, 293.01036)
('movie_flower_rev_presentations', 23.0, 294.01118, 303.01871)
('movie_touch_of_evil_rev_fwd_presentations', 24.0, 304.01951, 313.02696)
('movie_touch_of_evil_fwd_rev_presentations', 25.0, 314.02777, 323.03522)
('movie_touch_of_evil_fwd_presentations', 26.0, 324.03606, 333.04357)
('movie_touch_of_evil_rev_presentations', 27.0, 334.04441, 343.05179)
('movie_worms_fwd_rev_presentations', 28.0, 344.05262, 353.06008)
('movie_worms_rev_presentations', 29.0, 354.06099, 363.06836)
('movie_flower_fwd_rev_presentations', 30.0, 364.06927, 373.07673)
('movie_flower_rev_fwd_presentations', 31.0, 374.07749, 383.08503)
('movie_worms_rev_fwd_presentations', 32.0, 384.08584, 393.09323)
('movie_flower_rev_presentations', 33.0, 394.09411, 403.10155)
('movie_worms_fwd_presentations', 34.0, 404.10234, 413.10986)
('movie_flower_fwd_presentations', 35.0, 414.11063, 423.11815)
('movie_flower_rev_presentations', 36.0, 424.11892, 433.12645)
('movie_flower_fwd_presentations', 37.0, 434.12729, 443.1347)
('movie_worms_fwd_rev_presentations', 38.0, 444.13552, 453.14303)
('movie_worms_rev_presentations', 39.0, 454.14386, 463.15132)
('movie_touch_of_evil_fwd_rev_presentations', 40.0, 464.15207, 473.15954)
('movie_touch_of_evil_rev_fwd_presentations', 41.0, 474.16038, 483.16782)
('movie_touch_of_evil_fwd_presentations', 42.0, 484.16866, 493.17616)
('movie_worms_fwd_presentations', 43.0, 494.17697, 503.18447)
('movie_touch_of_evil_rev_presentations', 44.0, 504.18523, 513.19278)
('movie_flower_fwd_rev_presentations', 45.0, 514.19359, 523.20098)
('movie_worms_rev_fwd_presentations', 46.0, 524.20188, 533.20935)
('movie_flower_rev_fwd_presentations', 47.0, 534.21017, 543.21763)
('movie_worms_fwd_rev_presentations', 48.0, 544.21846, 553.22592)
('movie_flower_fwd_presentations', 49.0, 554.22667, 563.23422)
('movie_touch_of_evil_fwd_rev_presentations', 50.0, 564.23505, 573.24243)
('movie_touch_of_evil_fwd_presentations', 51.0, 574.24333, 583.25071)
('movie_worms_fwd_presentations', 52.0, 584.25162, 593.259)
('movie_flower_rev_presentations', 53.0, 594.25991, 603.2673)
('movie_worms_rev_presentations', 54.0, 604.26813, 613.2756)
('movie_touch_of_evil_rev_presentations', 55.0, 614.27641, 623.28387)
('movie_touch_of_evil_rev_fwd_presentations', 56.0, 624.28478, 633.29224)
('movie_flower_rev_fwd_presentations', 57.0, 634.29302, 643.30053)
('movie_flower_fwd_rev_presentations', 58.0, 644.30136, 653.30874)
('movie_worms_rev_fwd_presentations', 59.0, 654.30959, 663.31713)
('movie_flower_fwd_presentations', 60.0, 664.31794, 673.3254)
('movie_worms_fwd_presentations', 61.0, 674.3262, 683.33361)
('movie_touch_of_evil_fwd_rev_presentations', 62.0, 684.33444, 693.34198)
('movie_touch_of_evil_rev_fwd_presentations', 63.0, 694.34284, 703.35019)
('movie_worms_rev_fwd_presentations', 64.0, 704.35102, 713.35855)
('movie_flower_rev_fwd_presentations', 65.0, 714.35934, 723.36684)
('movie_worms_fwd_rev_presentations', 66.0, 724.36768, 733.37515)
('movie_touch_of_evil_rev_presentations', 67.0, 734.37589, 743.38341)
('movie_flower_fwd_rev_presentations', 68.0, 744.38424, 753.39164)
('movie_touch_of_evil_fwd_presentations', 69.0, 754.39254, 763.39993)
('movie_worms_rev_presentations', 70.0, 764.40076, 773.40829)
('movie_flower_rev_presentations', 71.0, 774.40912, 783.41651)
('movie_flower_fwd_presentations', 72.0, 784.41734, 793.42487)
('movie_touch_of_evil_rev_presentations', 73.0, 794.42562, 803.43311)
('movie_flower_rev_presentations', 74.0, 804.43393, 813.44144)
('movie_worms_rev_fwd_presentations', 75.0, 814.4423, 823.44974)
('movie_flower_rev_fwd_presentations', 76.0, 824.45057, 833.45798)
('movie_touch_of_evil_rev_fwd_presentations', 77.0, 834.45886, 843.46628)
('movie_touch_of_evil_fwd_rev_presentations', 78.0, 844.46715, 853.47461)
('movie_worms_rev_presentations', 79.0, 854.47544, 863.4829)
('movie_worms_fwd_presentations', 80.0, 864.48366, 873.49119)
('movie_flower_fwd_rev_presentations', 81.0, 874.49202, 883.49943)
('movie_worms_fwd_rev_presentations', 82.0, 884.50026, 893.5077)
('movie_touch_of_evil_fwd_presentations', 83.0, 894.5086, 903.51606)
('movie_worms_rev_fwd_presentations', 84.0, 904.51688, 913.52428)
('movie_flower_fwd_presentations', 85.0, 914.52511, 923.53263)
('movie_touch_of_evil_rev_fwd_presentations', 86.0, 924.53346, 933.54088)
('movie_touch_of_evil_rev_presentations', 87.0, 934.54171, 943.54921)
('movie_worms_fwd_rev_presentations', 88.0, 944.55006, 953.55751)
('movie_worms_fwd_presentations', 89.0, 954.55827, 963.56573)
('movie_touch_of_evil_fwd_rev_presentations', 90.0, 964.56656, 973.57403)
('movie_worms_rev_presentations', 91.0, 974.57493, 983.58232)
('movie_flower_rev_presentations', 92.0, 984.58321, 993.59067)
('movie_flower_fwd_rev_presentations', 93.0, 994.59142, 1003.59895)
('movie_flower_rev_fwd_presentations', 94.0, 1004.59978, 1013.60718)
('movie_touch_of_evil_fwd_presentations', 95.0, 1014.608, 1023.61551)
('movie_touch_of_evil_rev_fwd_presentations', 96.0, 1024.6163, 1033.62383)
('movie_worms_fwd_rev_presentations', 97.0, 1034.62465, 1043.63211)
('movie_touch_of_evil_fwd_presentations', 98.0, 1044.63288, 1053.64041)
('movie_worms_fwd_presentations', 99.0, 1054.64124, 1063.64863)
('movie_flower_fwd_rev_presentations', 100.0, 1064.64954, 1073.65698)
('movie_flower_rev_presentations', 101.0, 1074.65783, 1083.66528)
('movie_worms_rev_presentations', 102.0, 1084.6661, 1093.67357)
('movie_worms_rev_fwd_presentations', 103.0, 1094.67433, 1103.6819)
('movie_flower_rev_fwd_presentations', 104.0, 1104.68268, 1113.69008)
('movie_touch_of_evil_rev_presentations', 105.0, 1114.69097, 1123.69841)
('movie_flower_fwd_presentations', 106.0, 1124.69933, 1133.70673)
('movie_touch_of_evil_fwd_rev_presentations', 107.0, 1134.70755, 1143.71494)
('movie_worms_rev_fwd_presentations', 108.0, 1144.71577, 1153.72324)
('movie_flower_rev_fwd_presentations', 109.0, 1154.72406, 1163.73158)
('movie_worms_fwd_rev_presentations', 110.0, 1164.73242, 1173.73986)
('movie_touch_of_evil_fwd_rev_presentations', 111.0, 1174.74064, 1183.74818)
('movie_touch_of_evil_rev_fwd_presentations', 112.0, 1184.749, 1193.75639)
('movie_touch_of_evil_rev_presentations', 113.0, 1194.75726, 1203.76475)
('movie_worms_rev_presentations', 114.0, 1204.76557, 1213.77304)
('movie_flower_rev_presentations', 115.0, 1214.77387, 1223.78133)
('movie_worms_fwd_presentations', 116.0, 1224.78209, 1233.78963)
('movie_flower_fwd_presentations', 117.0, 1234.79044, 1243.79785)
('movie_touch_of_evil_fwd_presentations', 118.0, 1244.79867, 1253.8062)
('movie_flower_fwd_rev_presentations', 119.0, 1254.80704, 1263.81449)
('movie_flower_rev_fwd_presentations', 120.0, 1264.81532, 1273.82281)
('movie_worms_rev_presentations', 121.0, 1274.82354, 1283.83107)
('movie_touch_of_evil_rev_fwd_presentations', 122.0, 1284.8319, 1293.83931)
('movie_touch_of_evil_rev_presentations', 123.0, 1294.8402, 1303.84758)
('movie_touch_of_evil_fwd_presentations', 124.0, 1304.84847, 1313.85594)
('movie_touch_of_evil_fwd_rev_presentations', 125.0, 1314.85679, 1323.8642)
('movie_worms_rev_fwd_presentations', 126.0, 1324.865, 1333.87249)
('movie_flower_rev_presentations', 127.0, 1334.87332, 1343.88074)
('movie_worms_fwd_rev_presentations', 128.0, 1344.88161, 1353.8891)
('movie_worms_fwd_presentations', 129.0, 1354.88986, 1363.89732)
('movie_flower_fwd_rev_presentations', 130.0, 1364.89822, 1373.90561)
('movie_flower_fwd_presentations', 131.0, 1374.90651, 1383.9139)
('movie_flower_fwd_presentations', 132.0, 1384.9148, 1393.92226)
('movie_touch_of_evil_fwd_presentations', 133.0, 1394.9231, 1403.93054)
('movie_touch_of_evil_fwd_rev_presentations', 134.0, 1404.93133, 1413.93885)
('movie_flower_rev_fwd_presentations', 135.0, 1414.9396, 1423.94711)
('movie_flower_fwd_rev_presentations', 136.0, 1424.94796, 1433.95542)
('movie_touch_of_evil_rev_fwd_presentations', 137.0, 1434.95626, 1443.96367)
('movie_worms_fwd_rev_presentations', 138.0, 1444.96448, 1453.972)
('movie_worms_rev_presentations', 139.0, 1454.97276, 1463.9803)
('movie_touch_of_evil_rev_presentations', 140.0, 1464.98112, 1473.98856)
('movie_worms_fwd_presentations', 141.0, 1474.98941, 1483.99687)
('movie_worms_rev_fwd_presentations', 142.0, 1484.99779, 1494.00509)
('movie_flower_rev_presentations', 143.0, 1495.00599, 1504.01338)
('movie_touch_of_evil_fwd_presentations', 144.0, 1505.01425, 1514.02174)
('movie_touch_of_evil_rev_presentations', 145.0, 1515.0225, 1524.03)
('movie_touch_of_evil_rev_fwd_presentations', 146.0, 1525.03086, 1534.03832)
('movie_flower_rev_presentations', 147.0, 1535.03908, 1544.04654)
('movie_worms_fwd_presentations', 148.0, 1545.04744, 1554.05483)
('movie_flower_fwd_rev_presentations', 149.0, 1555.05573, 1564.06316)
('movie_worms_rev_presentations', 150.0, 1565.06403, 1574.07149)
('movie_worms_fwd_rev_presentations', 151.0, 1575.07232, 1584.07971)
('movie_worms_rev_fwd_presentations', 152.0, 1585.08053, 1594.08806)
('movie_touch_of_evil_fwd_rev_presentations', 153.0, 1595.08889, 1604.09628)
('movie_flower_rev_fwd_presentations', 154.0, 1605.09711, 1614.10464)
('movie_flower_fwd_presentations', 155.0, 1615.10547, 1624.11293)
('movie_worms_rev_presentations', 156.0, 1625.11374, 1634.12124)
('movie_flower_fwd_presentations', 157.0, 1635.12198, 1644.12951)
('movie_worms_fwd_rev_presentations', 158.0, 1645.13034, 1654.13773)
('movie_worms_fwd_presentations', 159.0, 1655.13863, 1664.14609)
('movie_flower_fwd_rev_presentations', 160.0, 1665.14693, 1674.15433)
('movie_flower_rev_presentations', 161.0, 1675.1552, 1684.16259)
('movie_touch_of_evil_fwd_rev_presentations', 162.0, 1685.16342, 1694.17095)
('movie_touch_of_evil_fwd_presentations', 163.0, 1695.17171, 1704.17924)
('movie_touch_of_evil_rev_presentations', 164.0, 1705.18009, 1714.18754)
('movie_flower_rev_fwd_presentations', 165.0, 1715.1883, 1724.19577)
('movie_touch_of_evil_rev_fwd_presentations', 166.0, 1725.1966, 1734.20404)
('movie_worms_rev_fwd_presentations', 167.0, 1735.20494, 1744.2124)
('movie_worms_fwd_presentations', 168.0, 1745.21317, 1754.22062)
('movie_worms_fwd_rev_presentations', 169.0, 1755.22145, 1764.22891)
('movie_touch_of_evil_fwd_rev_presentations', 170.0, 1765.22976, 1774.2372)
('movie_flower_rev_fwd_presentations', 171.0, 1775.2381, 1784.24549)
('movie_worms_rev_presentations', 172.0, 1785.24639, 1794.25385)
('movie_worms_rev_fwd_presentations', 173.0, 1795.25461, 1804.26214)
('movie_touch_of_evil_rev_fwd_presentations', 174.0, 1805.2629, 1814.27036)
('movie_flower_fwd_presentations', 175.0, 1815.27119, 1824.27866)
('movie_flower_fwd_rev_presentations', 176.0, 1825.27948, 1834.28702)
('movie_touch_of_evil_rev_presentations', 177.0, 1835.28777, 1844.29531)
('movie_touch_of_evil_fwd_presentations', 178.0, 1845.29606, 1854.30359)
('movie_flower_rev_presentations', 179.0, 1855.30436, 1864.31181)
('rotate_gabors_presentations', 180.0, 1895.33751, 2345.71065)
('rotate_gabors_presentations', 181.0, 2345.71065, 2796.08381)
('fixed_gabors_presentations', 182.0, 2826.1088, 3276.48193)
('fixed_gabors_presentations', 183.0, 3276.48193, 3726.85508)
('gratings_presentations', 184.0, 3756.87998, 3944.23512)
# can set these manually to get a closer look at the timeline
time_start = min(epochs, key=lambda epoch: epoch[1])[1]
time_end = max(epochs, key=lambda epoch:epoch[2])[2]
# time_start = 3000
# time_end = 3100

# can set this to change what trace is displayed alongside epochs
display_trace = avg_dff_trace * 100 # to yield percentage
# unit_idx = 30
# display_trace = dff_trace[:,unit_idx] * 100
%matplotlib inline
### make plot of chosen fluorescence trace over time with colored epoch sections

fig, ax = plt.subplots(figsize=(15,5))

# filter epochs which aren't at least partially in the time window
bounded_epochs = {epoch for epoch in epochs if epoch[2] < time_end and epoch[3] > time_start}

# assign unique color to each stimulus name
stim_names = list({epoch[0] for epoch in bounded_epochs})
colors = plt.cm.rainbow(np.linspace(0,1,len(stim_names)))
stim_color_map = {stim_names[i]:colors[i] for i in range(len(stim_names))}

epoch_key = {}
y_hi = np.amax(display_trace) # change these to manually set height of the plot
y_lo = np.amin(display_trace)
# draw colored rectangles for each epoch
for epoch in bounded_epochs:
    stim_name, stim_block, epoch_start, epoch_end = epoch
    color = stim_color_map[stim_name]
    rec = ax.add_patch(mpl.patches.Rectangle((epoch_start, y_lo), epoch_end-epoch_start, y_hi, alpha=0.3, facecolor=color))
    epoch_key[(stim_name)] = rec

ax.set_xlim(time_start, time_end)
ax.set_ylim(y_lo, y_hi)
ax.set_xlabel("Time (s)")
ax.set_ylabel("Average DF/F (%)")
ax.set_title("Average DFF throughout session")

fig.legend(epoch_key.values(), epoch_key.keys(), loc="lower right", bbox_to_anchor=(1.25, 0.25))
ax.plot(dff_timestamps[:], display_trace)

print(np.amax(avg_dff_trace))
plt.tight_layout()
plt.show()
1.8759732163094385
../_images/a6236987e8040a4381b37da6e15455c847676787c2b65acad39e0b5826c09b55.png

Viewing Behavioral Data#

Our NWB files also come with several metrics of animal behavior during the session, including running speed and eye tracking. Below is plotted the angle of the eye of the subject over time. The plot can be tailored to create the best view, as there are frequently large outliers in the eye tracking.

eye_tracking = nwb.acquisition["EyeTracking"]
# extract coords from eye tracking array
xs = np.array([point[0] for point in eye_tracking.eye_tracking.data])
ys = np.array([point[1] for point in eye_tracking.eye_tracking.data])

et_start_idx = 0
et_end_idx = len(eye_tracking.eye_tracking.data)
print("Min X:", np.nanmin(xs), "Max X:", np.nanmax(xs))
print("Min Y:", np.nanmin(ys), "Max Y:", np.nanmax(ys))
Min X: -2133.6747116929796 Max X: 380.65425645594405
Min Y: -5975.965894691784 Max Y: 460.3917121054316
fig, ax = plt.subplots()
colors = plt.cm.viridis(np.linspace(0, 1, et_end_idx-et_start_idx))
ax.plot(xs[et_start_idx:et_end_idx], ys[et_start_idx:et_end_idx], zorder=0, linewidth=0.25)
ax.scatter(xs[et_start_idx:et_end_idx], ys[et_start_idx:et_end_idx], s=5, c=colors, zorder=1)

# change these to set the plot limits (there are sometimes unusual outliers)
ax.set_xlim(0,500)
ax.set_ylim(0,500)

ax.set_xlabel("x pixel")
ax.set_ylabel("y pixel")
ax.set_title("Eye Trace Through Time")
plt.show()
../_images/45ff0fb94df95353b8a4b24a24ccaa7328c5bc96a142bd99c82a04cca1bbb97f.png

Generating Response Windows#

window_start_time = -2
window_end_time = 3
interp_hz = 10
# generate regularly-space x values and interpolate along it
time_axis = np.arange(dff_timestamps[0], dff_timestamps[-1], step=(1/interp_hz))
interp_dff = []

# interpolate channel by channel to save RAM
for channel in range(dff_trace.shape[1]):
    f = interpolate.interp1d(dff_timestamps, dff_trace[:,channel], axis=0, kind="nearest", fill_value="extrapolate")
    interp_dff.append(f(time_axis))

interp_dff = np.array(interp_dff)

print(interp_dff.shape)
(27, 39414)
# validate window bounds
if window_start_time > 0:
    raise ValueError("start time must be non-positive number")
if window_end_time <= 0:
    raise ValueError("end time must be positive number")
    
# get event windows
windows = []
window_length = int((window_end_time-window_start_time) * interp_hz)

for stim_ts in rev_stim_times:
    # convert time to index
    start_idx = int( (stim_ts + window_start_time - dff_timestamps[0]) * interp_hz )
    end_idx = start_idx + window_length
 
    # bounds checking
    if start_idx < 0 or end_idx > interp_dff.shape[1]:
        continue
        
    windows.append(interp_dff[:,start_idx:end_idx])
    
if len(windows) == 0:
    raise ValueError("There are no windows for these timestamps")

windows = np.array(windows) * 100 # x100 to convert values to dF/F percentage
neuronwise_windows = np.swapaxes(windows,0,1)

print(neuronwise_windows.shape)
(27, 15, 50)

Showing Response Windows#

%matplotlib inline
def show_dff_response(ax, dff, window_start_time, window_end_time, aspect="auto", vmin=None, vmax=None, yticklabels=[], skipticks=1, xlabel="Time (s)", ylabel="ROI", cbar=True, cbar_label=None):
    if len(dff) == 0:
        print("Input data has length 0; Nothing to display")
        return

    img = ax.imshow(dff, aspect=aspect, extent=[window_start_time, window_end_time, 0, len(dff)], vmin=vmin, vmax=vmax)
    if cbar:
        ax.colorbar(img, shrink=0.5, label=cbar_label)

    ax.plot([0,0],[0, len(dff)], ":", color="white", linewidth=1.0)

    if len(yticklabels) != 0:
        ax.set_yticks(range(len(yticklabels)))
        ax.set_yticklabels(yticklabels, fontsize=8)

        n_ticks = len(yticklabels[::skipticks])
        ax.yaxis.set_major_locator(plt.MaxNLocator(n_ticks))

    ax.set_xlabel(xlabel)
    ax.set_ylabel(ylabel)
def show_many_responses(windows, rows, cols, window_idxs=None, title=None, subplot_title="", xlabel=None, ylabel=None, cbar_label=None, vmin=0, vmax=100):
    if window_idxs is None:
        window_idxs = range(len(windows))
    windows = windows[window_idxs]
    
    # handle case with no input data
    if len(windows) == 0:
        print("Input data has length 0; Nothing to display")
        return
    # handle cases when there aren't enough windows for number of rows
    if len(windows) < rows*cols:
        rows = (len(windows) // cols) + 1

    fig, axes = plt.subplots(rows, cols, figsize=(2*cols+2, 2*rows+2), layout="constrained")
    # handle case when there's only one row
    if len(axes.shape) == 1:
        axes = axes.reshape((1, axes.shape[0]))
    
    for i in range(rows*cols):
        ax_row = int(i // cols)
        ax_col = i % cols
        ax = axes[ax_row][ax_col]
        
        if i > len(windows)-1:
            ax.set_visible(False)
            continue

        window = windows[i]
        show_dff_response(ax, window, window_start_time, window_end_time, xlabel=xlabel, ylabel=ylabel, cbar=False, vmin=vmin, vmax=vmax)
        ax.set_title(f"{subplot_title} {window_idxs[i]}")
        if ax_row != rows-1:
            ax.get_xaxis().set_visible(False)
        if ax_col != 0:
            ax.get_yaxis().set_visible(False)

    fig.suptitle(title)
    norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax)
    colorbar = fig.colorbar(mpl.cm.ScalarMappable(norm=norm), ax=axes, shrink=1.5/rows, label=cbar_label)
show_many_responses(neuronwise_windows,
                    6,
                    15,
                    title="Response of Some ROIs across trials",
                    subplot_title="ROI",
                    xlabel="time (s)",
                    ylabel="trial",
                    cbar_label="$\Delta$F/F (%)")
../_images/a3a3f89aa2da86f374461002b19901a1fac435253a588d9cc08463b44fc8ce27.png

Selecting Cells#

# get the index within the window that stimulus occurs (time 0)
stimulus_onset_idx = int(-window_start_time * interp_hz)
baseline = windows[:,:,0:stimulus_onset_idx]
evoked_responses = windows[:,:,stimulus_onset_idx:]

print(stimulus_onset_idx)
print(baseline.shape)
print(evoked_responses.shape)
20
(15, 27, 20)
(15, 27, 30)
mean_trial_responses = np.mean(evoked_responses, axis=2)
mean_trial_baselines = np.mean(baseline, axis=2)

n = mean_trial_responses.shape[0]
t,p = ttest_ind(mean_trial_responses, mean_trial_baselines)
IC3_selected_rois = np.where(p < 0.05 / n)[0]
print(f"Selected ROIs {IC3_selected_rois}")
Selected ROIs [ 8 17]
show_many_responses(neuronwise_windows[IC3_selected_rois],
                    6,
                    15,
                    title="Response of Some ROIs across trials",
                    subplot_title="ROI",
                    xlabel="time (s)",
                    ylabel="trial",
                    cbar_label="$\Delta$F/F (%)")
../_images/20380ff019b5be90911219fb1f4641273959ab4d2cc6567bd320ffa4769e5533.png

Viewing Raw Movie#

Although not shown in the metadata table shown above, each one of our session files comes with a copy on DANDI that also includes the actual movies from the brain.

# raw
dandi_movie_filepath = "sub-656228/sub-656228_ses-1245548523-acq-1245937736-raw-movies_image+ophys.nwb"
# denoised
# dandi_movie_filepath = "sub-656228/sub-656228_ses-1245548523-acq-1245937736-denoised-movies_ophys.nwb"
# This can sometimes take a while depending on the size of the file
io = dandi_download_open(dandiset_id, dandi_movie_filepath, download_loc)
nwb = io.read()
PATH                                                                SIZE    DONE            DONE% CHECKSUM STATUS          MESSAGE
sub-656228_ses-1245548523-acq-1245937736-raw-movies_image+ophys.nwb 23.7 GB 23.7 GB          100%    ok    done                   
Summary:                                                            23.7 GB 23.7 GB                        1 done                 
                                                                            100.00%                                               
Downloaded file to ./sub-656228_ses-1245548523-acq-1245937736-raw-movies_image+ophys.nwb
Opening file
# start_time = flr_timestamps[0]
start_time = 540
# end_time = flr_timestamps[-1]
end_time = 600
start_idx, end_idx = np.searchsorted(dff_timestamps, [start_time, end_time])
print(start_idx)
print(end_idx)
4823
5394
raw_movie = nwb.acquisition["raw_suite2p_motion_corrected"].data
flr_timestamps = np.array(dff.roi_response_series["traces"].timestamps)

print(raw_movie.shape)
print(flr_timestamps.shape)
(37515, 512, 512)
(37515,)
%matplotlib ipympl
plt.tick_params(left=False, bottom=False, labelleft=False, labelbottom=False)
view = hyperslicer(raw_movie[start_idx:end_idx], play_buttons=True)