├── .gitignore ├── Cosyne 2020 ├── NWB_tutorial_2020.ipynb ├── NWB_tutorial_2020.mlx ├── README.md ├── images │ ├── electrodes_table.png │ ├── lfp.png │ ├── position.png │ ├── ragged_array.png │ ├── spatial_series.png │ ├── subject_diagram.png │ ├── trials.png │ └── trials_example.png └── nwbwidgets.ipynb ├── HCK08 ├── ICEphys_basic_hck8.ipynb ├── ICEphys_basic_hck8.mlx ├── ecephys_tutorial.ipynb ├── ecephys_tutorial.mlx ├── images │ ├── Behavior.png │ ├── Behavior.svg │ ├── ElectricalSeries.png │ ├── ElectricalSeries.svg │ ├── Electrodes.png │ ├── Electrodes.svg │ ├── Fluorescence.png │ ├── Fluorescence.svg │ ├── IC Ephys NWB Classes.svg │ ├── ImageSegmentation.png │ ├── ImageSegmentation.svg │ ├── ImagingPlane.png │ ├── ImagingPlane.svg │ ├── IntracellularElectrode.svg │ ├── LFP.svg │ ├── PlaneSegmentation.png │ ├── PlaneSegmentation2.png │ ├── PlaneSegmentation2.svg │ ├── Position.svg │ ├── Position2.png │ ├── Position2.svg │ ├── RoiResponseSeries.png │ ├── RoiResponseSeries2.png │ ├── RoiResponseSeries2.svg │ ├── SpatialSeries.png │ ├── SpatialSeries.svg │ ├── Subject.png │ ├── TwoPhotonSeries.png │ ├── TwoPhotonSeries.svg │ ├── VCClampSeries_no_TS.svg │ ├── VCStimSeries.svg │ ├── VCStimSeries_no_TS.svg │ ├── ecephys.png │ ├── ecephys.svg │ ├── lfp.png │ ├── ophys.png │ ├── ophys.svg │ ├── planesegmentation.svg │ ├── position.png │ ├── position_hdfview.png │ ├── position_hdfview1.png │ ├── ragged_array.png │ ├── roiresponseseries.svg │ ├── subject.svg │ ├── trials.png │ ├── trials.svg │ └── trials_example.png ├── ophys_tutorial.ipynb └── ophys_tutorial.mlx ├── HCK09 ├── ecephys_tutorial.ipynb ├── ecephys_tutorial.mlx ├── icephys_tutorial.ipynb ├── icephys_tutorial.mlx ├── images │ ├── Behavior.png │ ├── Behavior.svg │ ├── ElectricalSeries.png │ ├── ElectricalSeries.svg │ ├── Electrodes.png │ ├── Electrodes.svg │ ├── Fluorescence.png │ ├── Fluorescence.svg │ ├── IC Ephys NWB Classes.svg │ ├── ImageSegmentation.png │ ├── ImageSegmentation.svg │ ├── ImagingPlane.png │ ├── ImagingPlane.svg │ ├── IntracellularElectrode.svg │ ├── LFP.png │ ├── LFP.svg │ ├── Ophys.svg │ ├── PlaneSegmentation.png │ ├── PlaneSegmentation.svg │ ├── Position.png │ ├── Position.svg │ ├── RoiResponseSeries.png │ ├── RoiResponseSeries.svg │ ├── SpatialSeries.png │ ├── SpatialSeries.svg │ ├── Subject.png │ ├── Subject.svg │ ├── Trials.png │ ├── Trials.svg │ ├── TwoPhotonSeries.png │ ├── TwoPhotonSeries.svg │ ├── VCClampSeries_no_TS.svg │ ├── VCStimSeries.svg │ ├── VCStimSeries_no_TS.svg │ ├── dandi_download1.png │ ├── dandi_download2.png │ ├── dandi_download3.png │ ├── ecephys.png │ ├── ecephys.svg │ ├── ophys.png │ ├── position_hdfview.png │ ├── ragged_array.png │ └── trials_example.png ├── matnwb_read_demo.mlx ├── ophys_tutorial.ipynb ├── ophys_tutorial.mlx └── pynwb_read_demo.ipynb ├── HCK11 ├── ecephys_tutorial.ipynb ├── ecephys_tutorial.mlx ├── icephys_tutorial.ipynb ├── icephys_tutorial.mlx ├── images │ ├── Behavior.png │ ├── Behavior.svg │ ├── ElectricalSeries.png │ ├── ElectricalSeries.svg │ ├── Electrodes.png │ ├── Electrodes.svg │ ├── Fluorescence.png │ ├── Fluorescence.svg │ ├── IC Ephys NWB Classes.svg │ ├── ImageSegmentation.png │ ├── ImageSegmentation.svg │ ├── ImagingPlane.png │ ├── ImagingPlane.svg │ ├── IntracellularElectrode.svg │ ├── LFP.png │ ├── LFP.svg │ ├── Ophys.svg │ ├── PlaneSegmentation.png │ ├── PlaneSegmentation.svg │ ├── Position.png │ ├── Position.svg │ ├── RoiResponseSeries.png │ ├── RoiResponseSeries.svg │ ├── SpatialSeries.png │ ├── SpatialSeries.svg │ ├── Subject.png │ ├── Subject.svg │ ├── Trials.png │ ├── Trials.svg │ ├── TwoPhotonSeries.png │ ├── TwoPhotonSeries.svg │ ├── VCClampSeries_no_TS.svg │ ├── VCStimSeries.svg │ ├── VCStimSeries_no_TS.svg │ ├── dandi_download1.png │ ├── dandi_download2.png │ ├── dandi_download3.png │ ├── ecephys.png │ ├── ecephys.svg │ ├── ophys.png │ ├── position_hdfview.png │ ├── ragged_array.png │ └── trials_example.png ├── matnwb_read_demo.mlx ├── ophys_tutorial.ipynb ├── ophys_tutorial.mlx └── pynwb_read_demo.ipynb ├── HCK13 ├── ecephys_tutorial.ipynb ├── ecephys_tutorial.mlx ├── icephys_tutorial.ipynb ├── icephys_tutorial.mlx ├── images │ ├── Behavior.png │ ├── Behavior.svg │ ├── ElectricalSeries.png │ ├── ElectricalSeries.svg │ ├── Electrodes.png │ ├── Electrodes.svg │ ├── Fluorescence.png │ ├── Fluorescence.svg │ ├── IC Ephys NWB Classes.svg │ ├── ImageSegmentation.png │ ├── ImageSegmentation.svg │ ├── ImagingPlane.png │ ├── ImagingPlane.svg │ ├── IntracellularElectrode.svg │ ├── LFP.png │ ├── LFP.svg │ ├── Ophys.svg │ ├── PlaneSegmentation.png │ ├── PlaneSegmentation.svg │ ├── Position.png │ ├── Position.svg │ ├── RoiResponseSeries.png │ ├── RoiResponseSeries.svg │ ├── SpatialSeries.png │ ├── SpatialSeries.svg │ ├── Subject.png │ ├── Subject.svg │ ├── Trials.png │ ├── Trials.svg │ ├── TwoPhotonSeries.png │ ├── TwoPhotonSeries.svg │ ├── VCClampSeries_no_TS.svg │ ├── VCStimSeries.svg │ ├── VCStimSeries_no_TS.svg │ ├── dandi_download1.png │ ├── dandi_download2.png │ ├── dandi_download3.png │ ├── ecephys.png │ ├── ecephys.svg │ ├── ophys.png │ ├── position_hdfview.png │ ├── ragged_array.png │ └── trials_example.png ├── matnwb_read_demo.mlx ├── ophys_tutorial.ipynb ├── ophys_tutorial.mlx └── pynwb_read_demo.ipynb ├── Neuromatch2021 ├── ecephys_tutorial.ipynb ├── ecephys_tutorial.mlx ├── icephys_tutorial.ipynb ├── icephys_tutorial.mlx ├── images │ ├── Behavior.png │ ├── Behavior.svg │ ├── ElectricalSeries.png │ ├── ElectricalSeries.svg │ ├── Electrodes.png │ ├── Electrodes.svg │ ├── Fluorescence.png │ ├── Fluorescence.svg │ ├── IC Ephys NWB Classes.svg │ ├── ImageSegmentation.png │ ├── ImageSegmentation.svg │ ├── ImagingPlane.png │ ├── ImagingPlane.svg │ ├── IntracellularElectrode.svg │ ├── LFP.png │ ├── LFP.svg │ ├── Ophys.svg │ ├── PlaneSegmentation.png │ ├── PlaneSegmentation.svg │ ├── Position.png │ ├── Position.svg │ ├── RoiResponseSeries.png │ ├── RoiResponseSeries.svg │ ├── SpatialSeries.png │ ├── SpatialSeries.svg │ ├── Subject.png │ ├── Subject.svg │ ├── Trials.png │ ├── Trials.svg │ ├── TwoPhotonSeries.png │ ├── TwoPhotonSeries.svg │ ├── VCClampSeries_no_TS.svg │ ├── VCStimSeries.svg │ ├── VCStimSeries_no_TS.svg │ ├── dandi_download1.png │ ├── dandi_download2.png │ ├── dandi_download3.png │ ├── ecephys.png │ ├── ecephys.svg │ ├── ophys.png │ ├── position_hdfview.png │ ├── ragged_array.png │ └── trials_example.png ├── matnwb_read_demo.mlx ├── ophys_tutorial.ipynb ├── ophys_tutorial.mlx └── pynwb_read_demo.ipynb └── images ├── electrodes_table.png ├── lfp.png ├── position.png └── ragged_array.png /.gitignore: -------------------------------------------------------------------------------- 1 | # NWB Tutorial 2 | *.nwb 3 | 4 | ### VisualStudioCode ### 5 | .vscode/* 6 | !.vscode/settings.json 7 | !.vscode/tasks.json 8 | !.vscode/extensions.json 9 | .history 10 | 11 | ### Python ### 12 | # Byte-compiled / optimized / DLL files 13 | __pycache__/ 14 | *.py[cod] 15 | *$py.class 16 | 17 | # Jupyter Notebook 18 | .ipynb_checkpoints 19 | 20 | # PyCharm 21 | .idea/ 22 | 23 | # shell scripts (e.g. used with fswatch) 24 | *.sh 25 | 26 | # vscode 27 | .vscode/ 28 | 29 | #mypy 30 | .mypy_cache/ 31 | -------------------------------------------------------------------------------- /Cosyne 2020/NWB_tutorial_2020.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Cosyne 2020/NWB_tutorial_2020.mlx -------------------------------------------------------------------------------- /Cosyne 2020/README.md: -------------------------------------------------------------------------------- 1 | # nwb_tutorial: NWB tutorials made for Cosyne 2020 2 | 3 | Use `NWB_tutorial_2020.ipynb` to following along with **Part 2** of the tutorial. 4 | 5 | **Part 3** will include a demonstration of the NWBWidgets project. 6 | We have included two small NWB files recently released by the Svoboda Lab. 7 | These files have been placed in `/opt/data/Cosyne2020_NWB_tutorial/`. 8 | You can load these files yourself and explore them with the `nwbwidgets.ipynb` notebook. 9 | 10 | Thank you to the DANDI team for hosting these tutorials on the dandihub. 11 | DANDI is a new platform for sharing neurophysiology data. Learn more about the project 12 | [here](www.dandiarchive.org). This Jupyter Hub instace will be shut down shortly after 13 | the tutorial (so make sure to save anything you want to keep locally). You will be able 14 | to do similar things with dandihub once it launches. 15 | -------------------------------------------------------------------------------- /Cosyne 2020/images/electrodes_table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Cosyne 2020/images/electrodes_table.png -------------------------------------------------------------------------------- /Cosyne 2020/images/lfp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Cosyne 2020/images/lfp.png -------------------------------------------------------------------------------- /Cosyne 2020/images/position.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Cosyne 2020/images/position.png -------------------------------------------------------------------------------- /Cosyne 2020/images/ragged_array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Cosyne 2020/images/ragged_array.png -------------------------------------------------------------------------------- /Cosyne 2020/images/spatial_series.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Cosyne 2020/images/spatial_series.png -------------------------------------------------------------------------------- /Cosyne 2020/images/subject_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Cosyne 2020/images/subject_diagram.png -------------------------------------------------------------------------------- /Cosyne 2020/images/trials.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Cosyne 2020/images/trials.png -------------------------------------------------------------------------------- /Cosyne 2020/images/trials_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Cosyne 2020/images/trials_example.png -------------------------------------------------------------------------------- /HCK08/ICEphys_basic_hck8.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/ICEphys_basic_hck8.mlx -------------------------------------------------------------------------------- /HCK08/ecephys_tutorial.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# NWB Tutorial - Extracellular Electrophysiology" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Introduction\n", 15 | "In this tutorial, we will create an NWB file for a hypothetical extracellular electrophysiology experiment with a freely moving animal. The types of data we will convert are:\n", 16 | "- Subject information (species, strain, age, etc.) \n", 17 | "- Animal position\n", 18 | "- Trials\n", 19 | "- LFP\n", 20 | "- Spike times" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "## Installing PyNWB\n", 28 | "First, install PyNWB using pip or conda. You will need Python 3.5+ installed.\n", 29 | "- `pip install pynwb`\n", 30 | "- `conda install -c conda-forge pynwb`" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "## Set up the NWB file\n", 38 | "An NWB file represents a single session of an experiment. Each file must have a session description, identifier, and session start time. Create a new `NWBFile` object with those and additional metadata. For all PyNWB constructors, we recommend using keyword arguments." 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": null, 44 | "metadata": {}, 45 | "outputs": [], 46 | "source": [ 47 | "from pynwb import NWBFile\n", 48 | "from datetime import datetime\n", 49 | "from dateutil import tz\n", 50 | "\n", 51 | "start_time = datetime(2018, 4, 25, 2, 30, 3, tzinfo=tz.gettz('US/Pacific'))\n", 52 | "\n", 53 | "nwbfile = NWBFile(\n", 54 | " session_description='Mouse exploring an open field',\n", 55 | " identifier='Mouse5_Day3',\n", 56 | " session_start_time=start_time,\n", 57 | " session_id='session_1234', # optional\n", 58 | " experimenter='My Name', # optional\n", 59 | " lab='My Lab Name', # optional\n", 60 | " institution='University of My Institution', # optional\n", 61 | " related_publications='DOI:10.1016/j.neuron.2016.12.011' # optional\n", 62 | ")\n", 63 | "print(nwbfile)" 64 | ] 65 | }, 66 | { 67 | "cell_type": "markdown", 68 | "metadata": {}, 69 | "source": [ 70 | "## Subject information\n", 71 | "Create a `Subject` object to store information about the experimental subject, such as age, species, genotype, sex, and a freeform description. Then set `nwbfile.subject` to the `Subject` object.\n", 72 | "\n", 73 | "\n", 74 | "\n", 75 | "Each of these fields is free-form text, so any values will be valid, but here are our recommendations:\n", 76 | "- For age, we recommend using the [ISO 8601 Duration format](https://en.wikipedia.org/wiki/ISO_8601#Durations), e.g., P90D for 90 days old\n", 77 | "- For species, we recommend using the formal latin binomal name (e.g., mouse: *Mus musculus*, human: *Homo sapiens*)\n", 78 | "- For sex, we recommend using F (female), M (male), U (unknown), and O (other)" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": null, 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [ 87 | "from pynwb.file import Subject\n", 88 | "\n", 89 | "nwbfile.subject = Subject(\n", 90 | " subject_id='001',\n", 91 | " age='P90D', \n", 92 | " description='mouse 5',\n", 93 | " species='Mus musculus', \n", 94 | " sex='M'\n", 95 | ")" 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "metadata": {}, 101 | "source": [ 102 | "## SpatialSeries and Position\n", 103 | "Many types of data can be stored in specialized classes in NWB. To store the spatial position of an animal, use the `SpatialSeries` and `Position` classes. \n", 104 | "\n", 105 | "`SpatialSeries` is a subclass of `TimeSeries`. `TimeSeries` is a common base class for measurements sampled over time, and provides fields for data and time (regularly or irregularly sampled).\n", 106 | "\n", 107 | "\n", 108 | "\n", 109 | "Create a `SpatialSeries` object named `'SpatialSeries'` with some fake data." 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": null, 115 | "metadata": {}, 116 | "outputs": [], 117 | "source": [ 118 | "import numpy as np\n", 119 | "from pynwb.behavior import SpatialSeries\n", 120 | "\n", 121 | "# create fake data with shape (50, 2)\n", 122 | "# the first dimension should always represent time\n", 123 | "position_data = np.array([np.linspace(0, 10, 50),\n", 124 | " np.linspace(0, 8, 50)]).T\n", 125 | "position_timestamps = np.linspace(0, 50) / 200\n", 126 | "\n", 127 | "spatial_series_obj = SpatialSeries(\n", 128 | " name='SpatialSeries', \n", 129 | " description='(x,y) position in open field',\n", 130 | " data=position_data,\n", 131 | " timestamps=position_timestamps,\n", 132 | " reference_frame='(0,0) is bottom left corner'\n", 133 | ")" 134 | ] 135 | }, 136 | { 137 | "cell_type": "markdown", 138 | "metadata": {}, 139 | "source": [ 140 | "You can print the `SpatialSeries` object to view its contents." 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": null, 146 | "metadata": {}, 147 | "outputs": [], 148 | "source": [ 149 | "print(spatial_series_obj)" 150 | ] 151 | }, 152 | { 153 | "cell_type": "markdown", 154 | "metadata": {}, 155 | "source": [ 156 | "To help data analysis and visualization tools know that this `SpatialSeries` object represents the position of the animal, store the `SpatialSeries` object inside of a `Position` object, which can hold one or more `SpatialSeries` objects.\n", 157 | "\n", 158 | "" 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "execution_count": null, 164 | "metadata": {}, 165 | "outputs": [], 166 | "source": [ 167 | "from pynwb.behavior import Position\n", 168 | "\n", 169 | "position_obj = Position(spatial_series=spatial_series_obj)" 170 | ] 171 | }, 172 | { 173 | "cell_type": "markdown", 174 | "metadata": {}, 175 | "source": [ 176 | "NWB differentiates between raw, *acquired data*, which should never change, and *processed data*, which are the results of preprocessing algorithms and could change. Let's assume that the animal's position was computed from a video tracking algorithm, so it would be classified as processed data. Since processed data can be very diverse, NWB allows us to create processing modules, which are like folders, to store related processed data or data that comes from a single algorithm. \n", 177 | "\n", 178 | "Create a processing module called \"behavior\" for storing behavioral data in the `NWBFile` and add the `Position` object to the module." 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": null, 184 | "metadata": {}, 185 | "outputs": [], 186 | "source": [ 187 | "behavior_module = nwbfile.create_processing_module(\n", 188 | " name='behavior', \n", 189 | " description='processed behavioral data'\n", 190 | ")\n", 191 | "behavior_module.add(position_obj)" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "" 199 | ] 200 | }, 201 | { 202 | "cell_type": "markdown", 203 | "metadata": {}, 204 | "source": [ 205 | "## Write to file" 206 | ] 207 | }, 208 | { 209 | "cell_type": "markdown", 210 | "metadata": {}, 211 | "source": [ 212 | "Now, write the NWB file that we have built so far." 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "execution_count": null, 218 | "metadata": {}, 219 | "outputs": [], 220 | "source": [ 221 | "from pynwb import NWBHDF5IO\n", 222 | "\n", 223 | "with NWBHDF5IO('ecephys_tutorial.nwb', 'w') as io:\n", 224 | " io.write(nwbfile)" 225 | ] 226 | }, 227 | { 228 | "cell_type": "markdown", 229 | "metadata": {}, 230 | "source": [ 231 | "We can then read the file and print it to inspect its contents. We can also print the `SpatialSeries` data that we created by referencing the names of the objects in the hierarchy that contain it. The processing module called `'behavior'` contains our `Position` object. By default, the `Position` object is named `'Position'`. The `Position` object contains our `SpatialSeries` object named `'SpatialSeries'`." 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": null, 237 | "metadata": {}, 238 | "outputs": [], 239 | "source": [ 240 | "with NWBHDF5IO('ecephys_tutorial.nwb', 'r') as io:\n", 241 | " read_nwbfile = io.read()\n", 242 | " print(read_nwbfile.processing['behavior']['Position']['SpatialSeries'])" 243 | ] 244 | }, 245 | { 246 | "cell_type": "markdown", 247 | "metadata": {}, 248 | "source": [ 249 | "We can also use the HDFView tool to inspect the resulting NWB file.\n", 250 | "\n", 251 | "" 252 | ] 253 | }, 254 | { 255 | "cell_type": "markdown", 256 | "metadata": {}, 257 | "source": [ 258 | "## Trials\n", 259 | "\n", 260 | "Trials are stored in a `TimeIntervals` object which is a subclass of `DynamicTable`. `DynamicTable` objects are used to store tabular metadata throughout NWB, including for trials, electrodes, and sorted units. They offer flexibility for tabular data by allowing required columns, optional columns, and custom columns.\n", 261 | "\n", 262 | "\n", 263 | "\n", 264 | "The trials DynamicTable can be thought of as a table with this structure:\n", 265 | "\n", 266 | "\n", 267 | "\n", 268 | "Continue adding to our `NWBFile` by creating a new column for the trials table named `'correct'`, which will be a boolean array." 269 | ] 270 | }, 271 | { 272 | "cell_type": "code", 273 | "execution_count": null, 274 | "metadata": {}, 275 | "outputs": [], 276 | "source": [ 277 | "nwbfile.add_trial_column(name='correct', description='whether the trial was correct')\n", 278 | "nwbfile.add_trial(start_time=1.0, stop_time=5.0, correct=True)\n", 279 | "nwbfile.add_trial(start_time=6.0, stop_time=10.0, correct=False)" 280 | ] 281 | }, 282 | { 283 | "cell_type": "markdown", 284 | "metadata": {}, 285 | "source": [ 286 | "We can view the trials table in tabular form by converting it to a pandas dataframe." 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": null, 292 | "metadata": {}, 293 | "outputs": [], 294 | "source": [ 295 | "nwbfile.trials.to_dataframe()" 296 | ] 297 | }, 298 | { 299 | "cell_type": "markdown", 300 | "metadata": {}, 301 | "source": [ 302 | "## Electrodes table\n", 303 | "Extracellular electrodes are stored in a `electrodes` table, which is also a `DynamicTable`. `electrodes` has several required fields: x, y, z, impedence, location, filtering, and electrode group.\n", 304 | "\n", 305 | "\n", 306 | "\n", 307 | "Use the following code to add electrodes for a multi-shank probe with 4 shanks, each with 3 electrodes. We will also add a custom column named `'label'` to a table." 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": null, 313 | "metadata": {}, 314 | "outputs": [], 315 | "source": [ 316 | "nwbfile.add_electrode_column(name='label', description='label of electrode')\n", 317 | "shank_channels = [4, 3] # set up two shanks, the first with 4 electrodes and the second with 3 electrodes\n", 318 | "\n", 319 | "electrode_counter = 0\n", 320 | "device = nwbfile.create_device('array')\n", 321 | "for shankn, nelecs in enumerate(shank_channels):\n", 322 | " # create an electrode group for this shank\n", 323 | " electrode_group = nwbfile.create_electrode_group(\n", 324 | " name='shank{}'.format(shankn),\n", 325 | " description='electrode group for shank {}'.format(shankn),\n", 326 | " device=device,\n", 327 | " location='brain area'\n", 328 | " )\n", 329 | " # add electrodes to the electrode table\n", 330 | " for ielec in range(nelecs):\n", 331 | " nwbfile.add_electrode(\n", 332 | " x=5.3, y=1.5, z=8.5, imp=np.nan,\n", 333 | " location='unknown', \n", 334 | " filtering='unknown',\n", 335 | " group=electrode_group,\n", 336 | " label='shank{}elec{}'.format(shankn, ielec)\n", 337 | " )\n", 338 | " electrode_counter += 1" 339 | ] 340 | }, 341 | { 342 | "cell_type": "markdown", 343 | "metadata": {}, 344 | "source": [ 345 | "Like for the trials table, we can view the electrodes table in tabular form by converting it to a pandas dataframe." 346 | ] 347 | }, 348 | { 349 | "cell_type": "code", 350 | "execution_count": null, 351 | "metadata": {}, 352 | "outputs": [], 353 | "source": [ 354 | "nwbfile.electrodes.to_dataframe()" 355 | ] 356 | }, 357 | { 358 | "cell_type": "markdown", 359 | "metadata": {}, 360 | "source": [ 361 | "## Links\n", 362 | "In the above loop, we created `ElectrodeGroup` objects in the `NWBFile`, and when we added an electrode to the `NWBFile`, we passed in the `ElectrodeGroup` object for the required `'group'` argument. This creates a reference from the `electrodes` table to individual `ElectrodeGroup` objects, one per row (electrode).\n", 363 | "\n", 364 | "## ElectricalSeries and DynamicTableRegion\n", 365 | "\n", 366 | "Voltage data are stored in `ElectricalSeries` objects. `ElectricalSeries` is a subclass of `TimeSeries` specialized for voltage data. In order to create our `ElectricalSeries` object, we will need to reference a set of rows in the `electrodes` table to indicate which electrodes were recorded. We will do this by creating a `DynamicTableRegion`, which is a type of link that allows you to reference specific rows of a `DynamicTable`, such as the `electrodes` table, by row indices.\n", 367 | "\n", 368 | "Create a `DynamicTableRegion` that references all rows of the `electrodes` table." 369 | ] 370 | }, 371 | { 372 | "cell_type": "code", 373 | "execution_count": null, 374 | "metadata": {}, 375 | "outputs": [], 376 | "source": [ 377 | "all_table_region = nwbfile.create_electrode_table_region(\n", 378 | " region=list(range(electrode_counter)), \n", 379 | " description='all electrodes'\n", 380 | ")" 381 | ] 382 | }, 383 | { 384 | "cell_type": "markdown", 385 | "metadata": {}, 386 | "source": [ 387 | "Now create an `ElectricalSeries` object to hold LFP data collected during the experiment.\n", 388 | "\n", 389 | "" 390 | ] 391 | }, 392 | { 393 | "cell_type": "code", 394 | "execution_count": null, 395 | "metadata": {}, 396 | "outputs": [], 397 | "source": [ 398 | "from pynwb.ecephys import ElectricalSeries\n", 399 | "\n", 400 | "lfp_data = np.random.randn(50, 4)\n", 401 | "lfp_elec_series = ElectricalSeries(\n", 402 | " name='ElectricalSeries', \n", 403 | " data=lfp_data, \n", 404 | " electrodes=all_table_region, \n", 405 | " rate=200.\n", 406 | ")" 407 | ] 408 | }, 409 | { 410 | "cell_type": "markdown", 411 | "metadata": {}, 412 | "source": [ 413 | "## LFP\n", 414 | "To help data analysis and visualization tools know that this `ElectricalSeries` object represents LFP data, store the `ElectricalSeries` object inside of an `LFP` object. Then place the `LFP` object in a `ProcessingModule` named `'ecephys'`. This is analogous to how we stored the `SpatialSeries` object inside of a `Position` object and stored the `Position` object in a `ProcessingModule` named `'behavior'` earlier.\n", 415 | "\n", 416 | "" 417 | ] 418 | }, 419 | { 420 | "cell_type": "code", 421 | "execution_count": null, 422 | "metadata": {}, 423 | "outputs": [], 424 | "source": [ 425 | "from pynwb.ecephys import LFP\n", 426 | "\n", 427 | "lfp = LFP(electrical_series=lfp_elec_series)\n", 428 | "\n", 429 | "ecephys_module = nwbfile.create_processing_module(\n", 430 | " name='ecephys', \n", 431 | " description='extracellular electrophysiology data'\n", 432 | ")\n", 433 | "ecephys_module.add(lfp)" 434 | ] 435 | }, 436 | { 437 | "cell_type": "markdown", 438 | "metadata": {}, 439 | "source": [ 440 | "## Spike Times\n", 441 | "Spike times are stored in the `Units` table, which is another subclass of `DynamicTable`. We can add columns to the `Units` table just like we did for the electrodes and trials tables. \n", 442 | "\n", 443 | "Generate some random spike data and populate the `Units` table using `nwbfile.add_unit`. Then display the `Units` table as a pandas dataframe." 444 | ] 445 | }, 446 | { 447 | "cell_type": "code", 448 | "execution_count": null, 449 | "metadata": {}, 450 | "outputs": [], 451 | "source": [ 452 | "nwbfile.add_unit_column(name='quality', description='sorting quality')\n", 453 | "\n", 454 | "poisson_lambda = 20\n", 455 | "firing_rate = 20\n", 456 | "n_units = 10\n", 457 | "for n_units_per_shank in range(n_units):\n", 458 | " n_spikes = np.random.poisson(lam=poisson_lambda)\n", 459 | " spike_times = np.round(np.cumsum(np.random.exponential(1/firing_rate, n_spikes)), 5)\n", 460 | " nwbfile.add_unit(spike_times=spike_times, quality='good', waveform_mean=[1, 2, 3, 4, 5])\n", 461 | "\n", 462 | "nwbfile.units.to_dataframe()" 463 | ] 464 | }, 465 | { 466 | "cell_type": "markdown", 467 | "metadata": {}, 468 | "source": [ 469 | "## Write the file" 470 | ] 471 | }, 472 | { 473 | "cell_type": "code", 474 | "execution_count": null, 475 | "metadata": {}, 476 | "outputs": [], 477 | "source": [ 478 | "with NWBHDF5IO('ecephys_tutorial.nwb', 'w') as io:\n", 479 | " io.write(nwbfile)" 480 | ] 481 | }, 482 | { 483 | "cell_type": "markdown", 484 | "metadata": {}, 485 | "source": [ 486 | "## Reading NWB data\n", 487 | "Data arrays are read passively from the file. Calling `TimeSeries.data` does not read the data values, but presents an `h5py` object that can be indexed to read data. Index this array just like a numpy array to read only a specific section of the array, or use the `[:]` operator to read the entire thing." 488 | ] 489 | }, 490 | { 491 | "cell_type": "code", 492 | "execution_count": null, 493 | "metadata": {}, 494 | "outputs": [], 495 | "source": [ 496 | "with NWBHDF5IO('ecephys_tutorial.nwb', 'r') as io:\n", 497 | " read_nwbfile = io.read()\n", 498 | "\n", 499 | " print(read_nwbfile.processing['ecephys']['LFP']['ElectricalSeries'].data[:])" 500 | ] 501 | }, 502 | { 503 | "cell_type": "markdown", 504 | "metadata": {}, 505 | "source": [ 506 | "## Accessing data regions\n", 507 | "It is often preferable to read only a portion of the data. To do this, index or slice into the `'data'` property. The following prints elements 0:10 in the first dimension and 0:3 in the second dimension from the LFP data we have written.\n", 508 | "\n", 509 | "Accessing data from a `DynamicTable` is similar: `read_nwbfile.units['spike_times'][0]` only reads the times from the 0th unit." 510 | ] 511 | }, 512 | { 513 | "cell_type": "code", 514 | "execution_count": null, 515 | "metadata": {}, 516 | "outputs": [], 517 | "source": [ 518 | "with NWBHDF5IO('ecephys_tutorial.nwb', 'r') as io:\n", 519 | " read_nwbfile = io.read()\n", 520 | "\n", 521 | " print('section of lfp:')\n", 522 | " print(read_nwbfile.processing['ecephys']['LFP']['ElectricalSeries'].data[:10,:3])\n", 523 | " print('')\n", 524 | " print('spike times from 0th unit:')\n", 525 | " print(read_nwbfile.units['spike_times'][0])" 526 | ] 527 | }, 528 | { 529 | "cell_type": "markdown", 530 | "metadata": {}, 531 | "source": [ 532 | "# Learn more!\n", 533 | "\n", 534 | "## Python tutorials\n", 535 | "### See our tutorials for more details about your data type:\n", 536 | "* [Extracellular electrophysiology](https://pynwb.readthedocs.io/en/stable/tutorials/domain/ecephys.html#sphx-glr-tutorials-domain-ecephys-py)\n", 537 | "* [Calcium imaging](https://pynwb.readthedocs.io/en/stable/tutorials/domain/ophys.html#sphx-glr-tutorials-domain-ophys-py)\n", 538 | "* [Intracellular electrophysiology](https://pynwb.readthedocs.io/en/stable/tutorials/domain/icephys.html#sphx-glr-tutorials-domain-icephys-py)\n", 539 | "\n", 540 | "### Check out other tutorials that teach advanced NWB topics:\n", 541 | "* [Iterative data write](https://pynwb.readthedocs.io/en/stable/tutorials/general/iterative_write.html#sphx-glr-tutorials-general-iterative-write-py)\n", 542 | "* [Extensions](https://pynwb.readthedocs.io/en/stable/tutorials/general/extensions.html#sphx-glr-tutorials-general-extensions-py)\n", 543 | "* [Advanced HDF5 I/O](https://pynwb.readthedocs.io/en/stable/tutorials/general/advanced_hdf5_io.html#sphx-glr-tutorials-general-advanced-hdf5-io-py)\n", 544 | "\n", 545 | "\n", 546 | "## MATLAB tutorials\n", 547 | "* [Extracellular electrophysiology](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ecephys.html)\n", 548 | "* [Calcium imaging](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ophys.html)\n", 549 | "* [Intracellular electrophysiology](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/icephys.html)\n" 550 | ] 551 | } 552 | ], 553 | "metadata": { 554 | "kernelspec": { 555 | "display_name": "Python 3", 556 | "language": "python", 557 | "name": "python3" 558 | }, 559 | "language_info": { 560 | "codemirror_mode": { 561 | "name": "ipython", 562 | "version": 3 563 | }, 564 | "file_extension": ".py", 565 | "mimetype": "text/x-python", 566 | "name": "python", 567 | "nbconvert_exporter": "python", 568 | "pygments_lexer": "ipython3", 569 | "version": "3.7.7" 570 | } 571 | }, 572 | "nbformat": 4, 573 | "nbformat_minor": 4 574 | } 575 | -------------------------------------------------------------------------------- /HCK08/ecephys_tutorial.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/ecephys_tutorial.mlx -------------------------------------------------------------------------------- /HCK08/images/Behavior.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/Behavior.png -------------------------------------------------------------------------------- /HCK08/images/ElectricalSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/ElectricalSeries.png -------------------------------------------------------------------------------- /HCK08/images/Electrodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/Electrodes.png -------------------------------------------------------------------------------- /HCK08/images/Fluorescence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/Fluorescence.png -------------------------------------------------------------------------------- /HCK08/images/ImageSegmentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/ImageSegmentation.png -------------------------------------------------------------------------------- /HCK08/images/ImagingPlane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/ImagingPlane.png -------------------------------------------------------------------------------- /HCK08/images/IntracellularElectrode.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /HCK08/images/PlaneSegmentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/PlaneSegmentation.png -------------------------------------------------------------------------------- /HCK08/images/PlaneSegmentation2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/PlaneSegmentation2.png -------------------------------------------------------------------------------- /HCK08/images/Position2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/Position2.png -------------------------------------------------------------------------------- /HCK08/images/RoiResponseSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/RoiResponseSeries.png -------------------------------------------------------------------------------- /HCK08/images/RoiResponseSeries2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/RoiResponseSeries2.png -------------------------------------------------------------------------------- /HCK08/images/SpatialSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/SpatialSeries.png -------------------------------------------------------------------------------- /HCK08/images/Subject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/Subject.png -------------------------------------------------------------------------------- /HCK08/images/TwoPhotonSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/TwoPhotonSeries.png -------------------------------------------------------------------------------- /HCK08/images/ecephys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/ecephys.png -------------------------------------------------------------------------------- /HCK08/images/lfp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/lfp.png -------------------------------------------------------------------------------- /HCK08/images/ophys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/ophys.png -------------------------------------------------------------------------------- /HCK08/images/position.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/position.png -------------------------------------------------------------------------------- /HCK08/images/position_hdfview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/position_hdfview.png -------------------------------------------------------------------------------- /HCK08/images/position_hdfview1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/position_hdfview1.png -------------------------------------------------------------------------------- /HCK08/images/ragged_array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/ragged_array.png -------------------------------------------------------------------------------- /HCK08/images/subject.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /HCK08/images/trials.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/trials.png -------------------------------------------------------------------------------- /HCK08/images/trials_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/images/trials_example.png -------------------------------------------------------------------------------- /HCK08/ophys_tutorial.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK08/ophys_tutorial.mlx -------------------------------------------------------------------------------- /HCK09/ecephys_tutorial.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/ecephys_tutorial.mlx -------------------------------------------------------------------------------- /HCK09/icephys_tutorial.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/icephys_tutorial.mlx -------------------------------------------------------------------------------- /HCK09/images/Behavior.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/Behavior.png -------------------------------------------------------------------------------- /HCK09/images/ElectricalSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/ElectricalSeries.png -------------------------------------------------------------------------------- /HCK09/images/Electrodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/Electrodes.png -------------------------------------------------------------------------------- /HCK09/images/Fluorescence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/Fluorescence.png -------------------------------------------------------------------------------- /HCK09/images/ImageSegmentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/ImageSegmentation.png -------------------------------------------------------------------------------- /HCK09/images/ImagingPlane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/ImagingPlane.png -------------------------------------------------------------------------------- /HCK09/images/LFP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/LFP.png -------------------------------------------------------------------------------- /HCK09/images/PlaneSegmentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/PlaneSegmentation.png -------------------------------------------------------------------------------- /HCK09/images/Position.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/Position.png -------------------------------------------------------------------------------- /HCK09/images/RoiResponseSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/RoiResponseSeries.png -------------------------------------------------------------------------------- /HCK09/images/SpatialSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/SpatialSeries.png -------------------------------------------------------------------------------- /HCK09/images/Subject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/Subject.png -------------------------------------------------------------------------------- /HCK09/images/Subject.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /HCK09/images/Trials.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/Trials.png -------------------------------------------------------------------------------- /HCK09/images/TwoPhotonSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/TwoPhotonSeries.png -------------------------------------------------------------------------------- /HCK09/images/dandi_download1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/dandi_download1.png -------------------------------------------------------------------------------- /HCK09/images/dandi_download2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/dandi_download2.png -------------------------------------------------------------------------------- /HCK09/images/dandi_download3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/dandi_download3.png -------------------------------------------------------------------------------- /HCK09/images/ecephys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/ecephys.png -------------------------------------------------------------------------------- /HCK09/images/ophys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/ophys.png -------------------------------------------------------------------------------- /HCK09/images/position_hdfview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/position_hdfview.png -------------------------------------------------------------------------------- /HCK09/images/ragged_array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/ragged_array.png -------------------------------------------------------------------------------- /HCK09/images/trials_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/images/trials_example.png -------------------------------------------------------------------------------- /HCK09/matnwb_read_demo.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/matnwb_read_demo.mlx -------------------------------------------------------------------------------- /HCK09/ophys_tutorial.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK09/ophys_tutorial.mlx -------------------------------------------------------------------------------- /HCK09/pynwb_read_demo.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# NWB Tutorial - Reading NWB Data in Python\n", 8 | "\n", 9 | "## Introduction\n", 10 | "\n", 11 | "In this tutorial, we will read single neuron spiking data that is in the NWB standard format and do a basic visualization of the data." 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## Download the data\n", 19 | "\n", 20 | "First, let's download an NWB data file from the [DANDI neurophysiology data archive](https://dandiarchive.org/). \n", 21 | "\n", 22 | "An NWB file represents a single session of an experiment. It contains all the data of that session and the metadata required to understand the data. \n", 23 | "\n", 24 | "We will use data from one session of an experiment by [Chandravadia et al. (2020)](https://www.nature.com/articles/s41597-020-0415-9), where the authors recorded single neuron activity from the medial temporal lobes of human subjects while they performed a recognition memory task.\n", 25 | "\n", 26 | "1. Go to the DANDI page for this dataset: https://dandiarchive.org/dandiset/000004/draft\n", 27 | "2. Toward the top middle of the page, click the \"View Data\" button. \n", 28 | "\n", 29 | "\n", 30 | "3. Click on the folder \"sub-P11MHM\" (click the folder name, not the checkbox).\n", 31 | "\n", 32 | "\n", 33 | "4. Then click on the download symbol to the right of the filename \"sub-P11HMH_ses-20061101_ecephys+image.nwb\" to download the data file (69 MB) to your computer.\n", 34 | "" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "## Installing PyNWB\n", 42 | "\n", 43 | "To read data in the NWB format in Python, we recommend using the [PyNWB](https://pynwb.readthedocs.io/) package created by the NWB development team.\n", 44 | "\n", 45 | "First, install PyNWB using `pip` or `conda`. You will need Python 3.5+ installed.\n", 46 | "- `pip install -U pynwb`\n", 47 | "- `conda install -c conda-forge pynwb`\n", 48 | "\n", 49 | "In addition you will need `matplotlib` later on for the generation of plots. This can also be installed via `pip` or `conda`\n", 50 | "- `pip install -U matplotlib`\n", 51 | "- `conda install matplotlib`" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "## Using NWBHDF5IO\n", 59 | "\n", 60 | "To read and write data in NWB, we will use the `NWBHDF5IO` class. You can read this as \"NWB\" \"HDF5\" \"IO\". This class reads NWB data that is in the HDF5 storage format, a popular, hierarchical format for storing large-scale scientific data. \"IO\" stands for Input/Output which means reading/writing data." 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": null, 66 | "metadata": {}, 67 | "outputs": [], 68 | "source": [ 69 | "from pynwb import NWBHDF5IO\n", 70 | "\n", 71 | "# Change the string below to the path of the file on your computer\n", 72 | "filepath = 'C:/Users/Ryan/Downloads/sub-P11HMH_ses-20061101_ecephys+image.nwb'\n", 73 | "io = NWBHDF5IO(filepath, 'r') # open the file in read mode 'r'" 74 | ] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "metadata": {}, 79 | "source": [ 80 | "Call the `NWBHDF5IO.read()` method to read the NWB data into an `NWBFile` object. Print the `NWBFile` object to inspect its contents." 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": null, 86 | "metadata": {}, 87 | "outputs": [], 88 | "source": [ 89 | "nwb = io.read()\n", 90 | "nwb" 91 | ] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "metadata": {}, 96 | "source": [ 97 | "## Access stimulus data in NWB\n", 98 | "\n", 99 | "Data representing stimuli that were presented to the experimental subject are stored in `NWBFile.stimulus`." 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": null, 105 | "metadata": {}, 106 | "outputs": [], 107 | "source": [ 108 | "nwb.stimulus" 109 | ] 110 | }, 111 | { 112 | "cell_type": "markdown", 113 | "metadata": {}, 114 | "source": [ 115 | "`NWBFile.stimulus` is a dictionary that can contain PyNWB objects representing different types of data, such as images or time series of images. In this file, `NWBFile.stimulus` contains a single key `'StimulusPresentation'` with an `OpticalSeries` object representing what images were shown to the subject and at what times." 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": null, 121 | "metadata": {}, 122 | "outputs": [], 123 | "source": [ 124 | "stim = nwb.stimulus['StimulusPresentation']" 125 | ] 126 | }, 127 | { 128 | "cell_type": "markdown", 129 | "metadata": {}, 130 | "source": [ 131 | "## Lazy loading of datasets\n", 132 | "\n", 133 | "Data arrays are read passively from the NWB file. Calling the `data` attribute on a `TimeSeries` such as an `OpticalSeries` does not read the data values, but presents an `h5py` object that can be indexed to read the data. You can use the `[:]` operator to read the entire data array into memory." 134 | ] 135 | }, 136 | { 137 | "cell_type": "code", 138 | "execution_count": null, 139 | "metadata": {}, 140 | "outputs": [], 141 | "source": [ 142 | "stim = nwb.stimulus['StimulusPresentation']\n", 143 | "\n", 144 | "print(stim.data.shape)\n", 145 | "all_stim_data = stim.data[:]" 146 | ] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "metadata": {}, 151 | "source": [ 152 | "Time series data in NWB can have multiple dimensions, and the first dimension always represents time. So this dataset has 200 images of size 400x300 pixels with three channels (red, green, and blue)." 153 | ] 154 | }, 155 | { 156 | "cell_type": "markdown", 157 | "metadata": {}, 158 | "source": [ 159 | "## Slicing datasets\n", 160 | "It is often preferable to read only a portion of the data, e.g., because the full data array is too large to fit into your computer's RAM. To do this, index or slice into the `data` attribute just like if you were indexing or slicing a numpy array." 161 | ] 162 | }, 163 | { 164 | "cell_type": "code", 165 | "execution_count": null, 166 | "metadata": {}, 167 | "outputs": [], 168 | "source": [ 169 | "pic_index = 31\n", 170 | "img = stim.data[pic_index]\n", 171 | "\n", 172 | "import matplotlib.pyplot as plt\n", 173 | "img = img[...,::-1] # reverse the last dimension because the data were stored in BGR instead of RGB\n", 174 | "plt.imshow(img, aspect='auto')" 175 | ] 176 | }, 177 | { 178 | "cell_type": "markdown", 179 | "metadata": {}, 180 | "source": [ 181 | "## Access single unit data in NWB\n", 182 | "Data and metadata about sorted single units are stored in `NWBFile.units`. `NWBFile.units` is a `Units` object that stores metadata about each single unit in a tabular form, where each row represents a unit and has spike times and additional metadata. Printing the `Units` object shows the column names and basic metadata associated with each unit." 183 | ] 184 | }, 185 | { 186 | "cell_type": "code", 187 | "execution_count": null, 188 | "metadata": {}, 189 | "outputs": [], 190 | "source": [ 191 | "nwb.units" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "We can also view the single unit data as a [pandas DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html)." 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": null, 204 | "metadata": {}, 205 | "outputs": [], 206 | "source": [ 207 | "units_df = nwb.units.to_dataframe()\n", 208 | "units_df" 209 | ] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "metadata": {}, 214 | "source": [ 215 | "To access the spike times of the first single unit, index `nwb.units` with the column name 'spike_times' and then the row index, 0. All times in NWB are stored in seconds relative to the session start time." 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": null, 221 | "metadata": {}, 222 | "outputs": [], 223 | "source": [ 224 | "nwb.units['spike_times'][0]" 225 | ] 226 | }, 227 | { 228 | "cell_type": "markdown", 229 | "metadata": {}, 230 | "source": [ 231 | "## Visualize spiking activity relative to stimulus onset\n", 232 | "\n", 233 | "Now we can look at when these single units spike relative to when image stimuli were presented to the subject.\n", 234 | "\n", 235 | "Let's loop through the first 10 units and get their spike times. For each unit, loop through each stimulus onset time and compute the spike times relative to stimulus onset. Finally, create a raster plot and histogram of these aligned spike times." 236 | ] 237 | }, 238 | { 239 | "cell_type": "code", 240 | "execution_count": null, 241 | "metadata": {}, 242 | "outputs": [], 243 | "source": [ 244 | "import numpy as np\n", 245 | "\n", 246 | "before = 1. # in seconds\n", 247 | "after = 3.\n", 248 | "\n", 249 | "stim_on_times = stim.timestamps[:] # get the stimulus times for all stimuli\n", 250 | "\n", 251 | "for unit in range(10):\n", 252 | " unit_spike_times = nwb.units['spike_times'][unit]\n", 253 | " trial_spikes = []\n", 254 | " for time in stim_on_times:\n", 255 | " # compute spike times relative to stimulus onset\n", 256 | " aligned_spikes = unit_spike_times - time\n", 257 | " # keep only spike times in a given time window around the stimulus onset\n", 258 | " aligned_spikes = aligned_spikes[(-before < aligned_spikes) & (aligned_spikes < after)]\n", 259 | " trial_spikes.append(aligned_spikes)\n", 260 | " fig, axs = plt.subplots(2, 1, sharex=True)\n", 261 | " plt.xlabel('time (s)')\n", 262 | " axs[0].eventplot(trial_spikes)\n", 263 | " \n", 264 | " axs[0].set_ylabel('trial')\n", 265 | " axs[0].set_title('unit {}'.format(unit))\n", 266 | " axs[0].axvline(0, color=[.5,.5,.5])\n", 267 | " \n", 268 | " axs[1].hist(np.hstack(trial_spikes), 30)\n", 269 | " axs[1].axvline(0, color=[.5,.5,.5])" 270 | ] 271 | }, 272 | { 273 | "cell_type": "markdown", 274 | "metadata": {}, 275 | "source": [ 276 | "## Accessing trial information in NWB\n", 277 | "\n", 278 | "Trial data are stored in `NWBFile.trials`. `NWBFile.trials` is a `TimeIntervals` object that stores metadata about each trial in a tabular form, where each row represents a trial and has a start time, stop time, and additional metadata. Like for the `Units` table, you can also view the trial data as a pandas DataFrame." 279 | ] 280 | }, 281 | { 282 | "cell_type": "code", 283 | "execution_count": null, 284 | "metadata": {}, 285 | "outputs": [], 286 | "source": [ 287 | "trials_df = nwb.trials.to_dataframe()\n", 288 | "trials_df" 289 | ] 290 | }, 291 | { 292 | "cell_type": "markdown", 293 | "metadata": {}, 294 | "source": [ 295 | "The stimuli are stored in `nwb.stimuli` and can be mapped one to one to each row (trial) of `nwb.trials` based on the `stim_on_time` column. Let's visualize the first 10 images that were categorized as landscapes in the session. We can interact with the trial data as a PyNWB `TimeIntervals` type or as a pandas DataFrame. Here, let's use pandas functions." 296 | ] 297 | }, 298 | { 299 | "cell_type": "code", 300 | "execution_count": null, 301 | "metadata": {}, 302 | "outputs": [], 303 | "source": [ 304 | "assert np.all(stim.timestamps[:] == trials_df.stim_on_time[:])\n", 305 | "\n", 306 | "stim_on_times_landscapes = trials_df[trials_df.category_name == 'landscapes'].stim_on_time\n", 307 | "for time in stim_on_times_landscapes[:10]:\n", 308 | " img = np.squeeze(stim.data[np.where(stim.timestamps[:] == time)])\n", 309 | " img = img[...,::-1] # reverse the last dimension because the data were stored in BGR instead of RGB\n", 310 | " plt.figure()\n", 311 | " plt.imshow(img, aspect='auto')" 312 | ] 313 | }, 314 | { 315 | "cell_type": "markdown", 316 | "metadata": {}, 317 | "source": [ 318 | "## Exploring the NWB file\n", 319 | "\n", 320 | "You can explore the NWB file by printing the `NWBFile` object and accessing its attributes, but it may be useful to explore the data in a less programmatic, more visual way. You can use NWBWidgets, a package containing interactive widgets for visualizing NWB data, or you can use the HDFView tool, which can open any generic HDF5 file, which an NWB file is.\n", 321 | "\n", 322 | "### NWBWidgets\n", 323 | "\n", 324 | "To use NWBWidgets, first install NWBWidgets:\n", 325 | "- `pip install -U nwbwidgets`\n", 326 | "\n", 327 | "Then import and run the `nwb2widget` function on the `NWBFile` object." 328 | ] 329 | }, 330 | { 331 | "cell_type": "code", 332 | "execution_count": null, 333 | "metadata": {}, 334 | "outputs": [], 335 | "source": [ 336 | "from nwbwidgets import nwb2widget\n", 337 | "\n", 338 | "nwb2widget(nwb)" 339 | ] 340 | }, 341 | { 342 | "cell_type": "markdown", 343 | "metadata": {}, 344 | "source": [ 345 | "### HDFView\n", 346 | "\n", 347 | "To use HDFView to inspect and explore the NWB file, download and install HDFView from here: https://www.hdfgroup.org/downloads/hdfview/ and then open the NWB file using the program." 348 | ] 349 | }, 350 | { 351 | "cell_type": "markdown", 352 | "metadata": {}, 353 | "source": [ 354 | "## Conclusion\n", 355 | "\n", 356 | "This is an example of how to get started with understanding and analyzing public NWB datasets. This particular dataset was published with an extensive open analysis in both MATLAB and Python, which you can find [here](https://github.com/rutishauserlab/recogmem-release-NWB). For more datasets, or to publish your own NWB data for free, check out the DANDI archive. Also, make sure to check out the DANDI breakout session later in this event." 357 | ] 358 | }, 359 | { 360 | "cell_type": "markdown", 361 | "metadata": {}, 362 | "source": [ 363 | "# Learn more!\n", 364 | "\n", 365 | "## Python tutorials\n", 366 | "### See our tutorials for more details about your data type:\n", 367 | "* [Extracellular electrophysiology](https://pynwb.readthedocs.io/en/stable/tutorials/domain/ecephys.html#sphx-glr-tutorials-domain-ecephys-py)\n", 368 | "* [Calcium imaging](https://pynwb.readthedocs.io/en/stable/tutorials/domain/ophys.html#sphx-glr-tutorials-domain-ophys-py)\n", 369 | "* [Intracellular electrophysiology](https://pynwb.readthedocs.io/en/stable/tutorials/domain/icephys.html#sphx-glr-tutorials-domain-icephys-py)\n", 370 | "\n", 371 | "### Check out other tutorials that teach advanced NWB topics:\n", 372 | "* [Iterative data write](https://pynwb.readthedocs.io/en/stable/tutorials/general/iterative_write.html#sphx-glr-tutorials-general-iterative-write-py)\n", 373 | "* [Extensions](https://pynwb.readthedocs.io/en/stable/tutorials/general/extensions.html#sphx-glr-tutorials-general-extensions-py)\n", 374 | "* [Advanced HDF5 I/O](https://pynwb.readthedocs.io/en/stable/tutorials/general/advanced_hdf5_io.html#sphx-glr-tutorials-general-advanced-hdf5-io-py)\n", 375 | "\n", 376 | "\n", 377 | "## MATLAB tutorials\n", 378 | "* [Extracellular electrophysiology](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ecephys.html)\n", 379 | "* [Calcium imaging](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ophys.html)\n", 380 | "* [Intracellular electrophysiology](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/icephys.html)" 381 | ] 382 | } 383 | ], 384 | "metadata": { 385 | "kernelspec": { 386 | "display_name": "Python 3", 387 | "language": "python", 388 | "name": "python3" 389 | }, 390 | "language_info": { 391 | "codemirror_mode": { 392 | "name": "ipython", 393 | "version": 3 394 | }, 395 | "file_extension": ".py", 396 | "mimetype": "text/x-python", 397 | "name": "python", 398 | "nbconvert_exporter": "python", 399 | "pygments_lexer": "ipython3", 400 | "version": "3.7.7" 401 | } 402 | }, 403 | "nbformat": 4, 404 | "nbformat_minor": 4 405 | } 406 | -------------------------------------------------------------------------------- /HCK11/ecephys_tutorial.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/ecephys_tutorial.mlx -------------------------------------------------------------------------------- /HCK11/icephys_tutorial.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/icephys_tutorial.mlx -------------------------------------------------------------------------------- /HCK11/images/Behavior.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/Behavior.png -------------------------------------------------------------------------------- /HCK11/images/ElectricalSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/ElectricalSeries.png -------------------------------------------------------------------------------- /HCK11/images/Electrodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/Electrodes.png -------------------------------------------------------------------------------- /HCK11/images/Fluorescence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/Fluorescence.png -------------------------------------------------------------------------------- /HCK11/images/ImageSegmentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/ImageSegmentation.png -------------------------------------------------------------------------------- /HCK11/images/ImagingPlane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/ImagingPlane.png -------------------------------------------------------------------------------- /HCK11/images/LFP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/LFP.png -------------------------------------------------------------------------------- /HCK11/images/PlaneSegmentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/PlaneSegmentation.png -------------------------------------------------------------------------------- /HCK11/images/Position.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/Position.png -------------------------------------------------------------------------------- /HCK11/images/RoiResponseSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/RoiResponseSeries.png -------------------------------------------------------------------------------- /HCK11/images/SpatialSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/SpatialSeries.png -------------------------------------------------------------------------------- /HCK11/images/Subject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/Subject.png -------------------------------------------------------------------------------- /HCK11/images/Subject.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /HCK11/images/Trials.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/Trials.png -------------------------------------------------------------------------------- /HCK11/images/TwoPhotonSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/TwoPhotonSeries.png -------------------------------------------------------------------------------- /HCK11/images/dandi_download1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/dandi_download1.png -------------------------------------------------------------------------------- /HCK11/images/dandi_download2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/dandi_download2.png -------------------------------------------------------------------------------- /HCK11/images/dandi_download3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/dandi_download3.png -------------------------------------------------------------------------------- /HCK11/images/ecephys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/ecephys.png -------------------------------------------------------------------------------- /HCK11/images/ophys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/ophys.png -------------------------------------------------------------------------------- /HCK11/images/position_hdfview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/position_hdfview.png -------------------------------------------------------------------------------- /HCK11/images/ragged_array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/ragged_array.png -------------------------------------------------------------------------------- /HCK11/images/trials_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/images/trials_example.png -------------------------------------------------------------------------------- /HCK11/matnwb_read_demo.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/matnwb_read_demo.mlx -------------------------------------------------------------------------------- /HCK11/ophys_tutorial.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK11/ophys_tutorial.mlx -------------------------------------------------------------------------------- /HCK11/pynwb_read_demo.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# NWB Tutorial - Reading NWB Data in Python\n", 8 | "\n", 9 | "## Introduction\n", 10 | "\n", 11 | "In this tutorial, we will read single neuron spiking data that is in the NWB standard format and do a basic visualization of the data." 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## Download the data\n", 19 | "\n", 20 | "First, let's download an NWB data file from the [DANDI neurophysiology data archive](https://dandiarchive.org/). \n", 21 | "\n", 22 | "An NWB file represents a single session of an experiment. It contains all the data of that session and the metadata required to understand the data. \n", 23 | "\n", 24 | "We will use data from one session of an experiment by [Chandravadia et al. (2020)](https://www.nature.com/articles/s41597-020-0415-9), where the authors recorded single neuron activity from the medial temporal lobes of human subjects while they performed a recognition memory task.\n", 25 | "\n", 26 | "1. Go to the DANDI page for this dataset: https://dandiarchive.org/dandiset/000004/draft\n", 27 | "2. Toward the top middle of the page, click the \"View Data\" button. \n", 28 | "\n", 29 | "\n", 30 | "3. Click on the folder \"sub-P11MHM\" (click the folder name, not the checkbox).\n", 31 | "\n", 32 | "\n", 33 | "4. Then click on the download symbol to the right of the filename \"sub-P11HMH_ses-20061101_ecephys+image.nwb\" to download the data file (69 MB) to your computer.\n", 34 | "" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "## Installing PyNWB\n", 42 | "\n", 43 | "To read data in the NWB format in Python, we recommend using the [PyNWB](https://pynwb.readthedocs.io/) package created by the NWB development team.\n", 44 | "\n", 45 | "First, install PyNWB using `pip` or `conda`. You will need Python 3.5+ installed.\n", 46 | "- `pip install -U pynwb`\n", 47 | "- `conda install -c conda-forge pynwb` " 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": {}, 53 | "source": [ 54 | "## Using NWBHDF5IO\n", 55 | "\n", 56 | "To read and write data in NWB, we will use the `NWBHDF5IO` class. You can read this as \"NWB\" \"HDF5\" \"IO\". This class reads NWB data that is in the HDF5 storage format, a popular, hierarchical format for storing large-scale scientific data. \"IO\" stands for Input/Output which means reading/writing data." 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": {}, 63 | "outputs": [], 64 | "source": [ 65 | "from pynwb import NWBHDF5IO\n", 66 | "\n", 67 | "# Change the string below to the path of the file on your computer\n", 68 | "filepath = 'C:/Users/Ryan/Downloads/sub-P11HMH_ses-20061101_ecephys+image.nwb'\n", 69 | "io = NWBHDF5IO(filepath, 'r') # open the file in read mode 'r'" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "Call the `NWBHDF5IO.read()` method to read the NWB data into an `NWBFile` object. Print the `NWBFile` object to inspect its contents." 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": null, 82 | "metadata": {}, 83 | "outputs": [], 84 | "source": [ 85 | "nwb = io.read()\n", 86 | "nwb" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "## Access stimulus data in NWB\n", 94 | "\n", 95 | "Data representing stimuli that were presented to the experimental subject are stored in `NWBFile.stimulus`." 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": null, 101 | "metadata": {}, 102 | "outputs": [], 103 | "source": [ 104 | "nwb.stimulus" 105 | ] 106 | }, 107 | { 108 | "cell_type": "markdown", 109 | "metadata": {}, 110 | "source": [ 111 | "`NWBFile.stimulus` is a dictionary that can contain PyNWB objects representing different types of data, such as images or time series of images. In this file, `NWBFile.stimulus` contains a single key `'StimulusPresentation'` with an `OpticalSeries` object representing what images were shown to the subject and at what times." 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": null, 117 | "metadata": {}, 118 | "outputs": [], 119 | "source": [ 120 | "stim = nwb.stimulus['StimulusPresentation']" 121 | ] 122 | }, 123 | { 124 | "cell_type": "markdown", 125 | "metadata": {}, 126 | "source": [ 127 | "## Lazy loading of datasets\n", 128 | "\n", 129 | "Data arrays are read passively from the NWB file. Calling the `data` attribute on a `TimeSeries` such as an `OpticalSeries` does not read the data values, but presents an `h5py` object that can be indexed to read the data. You can use the `[:]` operator to read the entire data array into memory." 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": null, 135 | "metadata": {}, 136 | "outputs": [], 137 | "source": [ 138 | "stim = nwb.stimulus['StimulusPresentation']\n", 139 | "\n", 140 | "print(stim.data.shape)\n", 141 | "all_stim_data = stim.data[:]" 142 | ] 143 | }, 144 | { 145 | "cell_type": "markdown", 146 | "metadata": {}, 147 | "source": [ 148 | "Time series data in NWB can have multiple dimensions, and the first dimension always represents time. So this dataset has 200 images of size 400x300 pixels with three channels (red, green, and blue)." 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "metadata": {}, 154 | "source": [ 155 | "## Slicing datasets\n", 156 | "It is often preferable to read only a portion of the data, e.g., because the full data array is too large to fit into your computer's RAM. To do this, index or slice into the `data` attribute just like if you were indexing or slicing a numpy array." 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": null, 162 | "metadata": {}, 163 | "outputs": [], 164 | "source": [ 165 | "pic_index = 31\n", 166 | "img = stim.data[pic_index]\n", 167 | "\n", 168 | "import matplotlib.pyplot as plt\n", 169 | "img = img[...,::-1] # reverse the last dimension because the data were stored in BGR instead of RGB\n", 170 | "plt.imshow(img, aspect='auto')" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": {}, 176 | "source": [ 177 | "## Access single unit data in NWB\n", 178 | "Data and metadata about sorted single units are stored in `NWBFile.units`. `NWBFile.units` is a `Units` object that stores metadata about each single unit in a tabular form, where each row represents a unit and has spike times and additional metadata. Printing the `Units` object shows the column names and basic metadata associated with each unit." 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": null, 184 | "metadata": {}, 185 | "outputs": [], 186 | "source": [ 187 | "nwb.units" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "We can also view the single unit data as a [pandas DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html)." 195 | ] 196 | }, 197 | { 198 | "cell_type": "code", 199 | "execution_count": null, 200 | "metadata": {}, 201 | "outputs": [], 202 | "source": [ 203 | "units_df = nwb.units.to_dataframe()\n", 204 | "units_df" 205 | ] 206 | }, 207 | { 208 | "cell_type": "markdown", 209 | "metadata": {}, 210 | "source": [ 211 | "To access the spike times of the first single unit, index `nwb.units` with the column name 'spike_times' and then the row index, 0. All times in NWB are stored in seconds relative to the session start time." 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": null, 217 | "metadata": {}, 218 | "outputs": [], 219 | "source": [ 220 | "nwb.units['spike_times'][0]" 221 | ] 222 | }, 223 | { 224 | "cell_type": "markdown", 225 | "metadata": {}, 226 | "source": [ 227 | "## Visualize spiking activity relative to stimulus onset\n", 228 | "\n", 229 | "Now we can look at when these single units spike relative to when image stimuli were presented to the subject.\n", 230 | "\n", 231 | "Let's loop through the first 10 units and get their spike times. For each unit, loop through each stimulus onset time and compute the spike times relative to stimulus onset. Finally, create a raster plot and histogram of these aligned spike times." 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": null, 237 | "metadata": {}, 238 | "outputs": [], 239 | "source": [ 240 | "import numpy as np\n", 241 | "\n", 242 | "before = 1. # in seconds\n", 243 | "after = 3.\n", 244 | "\n", 245 | "stim_on_times = stim.timestamps[:] # get the stimulus times for all stimuli\n", 246 | "\n", 247 | "for unit in range(10):\n", 248 | " unit_spike_times = nwb.units['spike_times'][unit]\n", 249 | " trial_spikes = []\n", 250 | " for time in stim_on_times:\n", 251 | " # compute spike times relative to stimulus onset\n", 252 | " aligned_spikes = unit_spike_times - time\n", 253 | " # keep only spike times in a given time window around the stimulus onset\n", 254 | " aligned_spikes = aligned_spikes[(-before < aligned_spikes) & (aligned_spikes < after)]\n", 255 | " trial_spikes.append(aligned_spikes)\n", 256 | " fig, axs = plt.subplots(2, 1, sharex=True)\n", 257 | " plt.xlabel('time (s)')\n", 258 | " axs[0].eventplot(trial_spikes)\n", 259 | " \n", 260 | " axs[0].set_ylabel('trial')\n", 261 | " axs[0].set_title('unit {}'.format(unit))\n", 262 | " axs[0].axvline(0, color=[.5,.5,.5])\n", 263 | " \n", 264 | " axs[1].hist(np.hstack(trial_spikes), 30)\n", 265 | " axs[1].axvline(0, color=[.5,.5,.5])" 266 | ] 267 | }, 268 | { 269 | "cell_type": "markdown", 270 | "metadata": {}, 271 | "source": [ 272 | "## Accessing trial information in NWB\n", 273 | "\n", 274 | "Trial data are stored in `NWBFile.trials`. `NWBFile.trials` is a `TimeIntervals` object that stores metadata about each trial in a tabular form, where each row represents a trial and has a start time, stop time, and additional metadata. Like for the `Units` table, you can also view the trial data as a pandas DataFrame." 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": null, 280 | "metadata": {}, 281 | "outputs": [], 282 | "source": [ 283 | "trials_df = nwb.trials.to_dataframe()\n", 284 | "trials_df" 285 | ] 286 | }, 287 | { 288 | "cell_type": "markdown", 289 | "metadata": {}, 290 | "source": [ 291 | "The stimuli are stored in `nwb.stimuli` and can be mapped one to one to each row (trial) of `nwb.trials` based on the `stim_on_time` column. Let's visualize the first 10 images that were categorized as landscapes in the session. We can interact with the trial data as a PyNWB `TimeIntervals` type or as a pandas DataFrame. Here, let's use pandas functions." 292 | ] 293 | }, 294 | { 295 | "cell_type": "code", 296 | "execution_count": null, 297 | "metadata": {}, 298 | "outputs": [], 299 | "source": [ 300 | "assert np.all(stim.timestamps[:] == trials_df.stim_on_time[:])\n", 301 | "\n", 302 | "stim_on_times_landscapes = trials_df[trials_df.category_name == 'landscapes'].stim_on_time\n", 303 | "for time in stim_on_times_landscapes[:10]:\n", 304 | " img = np.squeeze(stim.data[np.where(stim.timestamps[:] == time)])\n", 305 | " img = img[...,::-1] # reverse the last dimension because the data were stored in BGR instead of RGB\n", 306 | " plt.figure()\n", 307 | " plt.imshow(img, aspect='auto')" 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "metadata": {}, 313 | "source": [ 314 | "## Exploring the NWB file\n", 315 | "\n", 316 | "You can explore the NWB file by printing the `NWBFile` object and accessing its attributes, but it may be useful to explore the data in a less programmatic, more visual way. You can use NWBWidgets, a package containing interactive widgets for visualizing NWB data, or you can use the HDFView tool, which can open any generic HDF5 file, which an NWB file is.\n", 317 | "\n", 318 | "### NWBWidgets\n", 319 | "\n", 320 | "To use NWBWidgets, first install NWBWidgets:\n", 321 | "- `pip install -U nwbwidgets`\n", 322 | "\n", 323 | "Then import and run the `nwb2widget` function on the `NWBFile` object." 324 | ] 325 | }, 326 | { 327 | "cell_type": "code", 328 | "execution_count": null, 329 | "metadata": {}, 330 | "outputs": [], 331 | "source": [ 332 | "from nwbwidgets import nwb2widget\n", 333 | "\n", 334 | "nwb2widget(nwb)" 335 | ] 336 | }, 337 | { 338 | "cell_type": "markdown", 339 | "metadata": {}, 340 | "source": [ 341 | "### HDFView\n", 342 | "\n", 343 | "To use HDFView to inspect and explore the NWB file, download and install HDFView from here: https://www.hdfgroup.org/downloads/hdfview/ and then open the NWB file using the program." 344 | ] 345 | }, 346 | { 347 | "cell_type": "markdown", 348 | "metadata": {}, 349 | "source": [ 350 | "## Conclusion\n", 351 | "\n", 352 | "This is an example of how to get started with understanding and analyzing public NWB datasets. This particular dataset was published with an extensive open analysis in both MATLAB and Python, which you can find [here](https://github.com/rutishauserlab/recogmem-release-NWB). For more datasets, or to publish your own NWB data for free, check out the DANDI archive. Also, make sure to check out the DANDI breakout session later in this event." 353 | ] 354 | }, 355 | { 356 | "cell_type": "markdown", 357 | "metadata": {}, 358 | "source": [ 359 | "# Learn more!\n", 360 | "\n", 361 | "## Python tutorials\n", 362 | "### See our tutorials for more details about your data type:\n", 363 | "* [Extracellular electrophysiology](https://pynwb.readthedocs.io/en/stable/tutorials/domain/ecephys.html#sphx-glr-tutorials-domain-ecephys-py)\n", 364 | "* [Calcium imaging](https://pynwb.readthedocs.io/en/stable/tutorials/domain/ophys.html#sphx-glr-tutorials-domain-ophys-py)\n", 365 | "* [Intracellular electrophysiology](https://pynwb.readthedocs.io/en/stable/tutorials/domain/icephys.html#sphx-glr-tutorials-domain-icephys-py)\n", 366 | "\n", 367 | "### Check out other tutorials that teach advanced NWB topics:\n", 368 | "* [Iterative data write](https://pynwb.readthedocs.io/en/stable/tutorials/general/iterative_write.html#sphx-glr-tutorials-general-iterative-write-py)\n", 369 | "* [Extensions](https://pynwb.readthedocs.io/en/stable/tutorials/general/extensions.html#sphx-glr-tutorials-general-extensions-py)\n", 370 | "* [Advanced HDF5 I/O](https://pynwb.readthedocs.io/en/stable/tutorials/general/advanced_hdf5_io.html#sphx-glr-tutorials-general-advanced-hdf5-io-py)\n", 371 | "\n", 372 | "\n", 373 | "## MATLAB tutorials\n", 374 | "* [Extracellular electrophysiology](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ecephys.html)\n", 375 | "* [Calcium imaging](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ophys.html)\n", 376 | "* [Intracellular electrophysiology](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/icephys.html)" 377 | ] 378 | } 379 | ], 380 | "metadata": { 381 | "kernelspec": { 382 | "display_name": "Python 3", 383 | "language": "python", 384 | "name": "python3" 385 | }, 386 | "language_info": { 387 | "codemirror_mode": { 388 | "name": "ipython", 389 | "version": 3 390 | }, 391 | "file_extension": ".py", 392 | "mimetype": "text/x-python", 393 | "name": "python", 394 | "nbconvert_exporter": "python", 395 | "pygments_lexer": "ipython3", 396 | "version": "3.7.7" 397 | } 398 | }, 399 | "nbformat": 4, 400 | "nbformat_minor": 4 401 | } 402 | -------------------------------------------------------------------------------- /HCK13/ecephys_tutorial.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/ecephys_tutorial.mlx -------------------------------------------------------------------------------- /HCK13/icephys_tutorial.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/icephys_tutorial.mlx -------------------------------------------------------------------------------- /HCK13/images/Behavior.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/Behavior.png -------------------------------------------------------------------------------- /HCK13/images/ElectricalSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/ElectricalSeries.png -------------------------------------------------------------------------------- /HCK13/images/Electrodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/Electrodes.png -------------------------------------------------------------------------------- /HCK13/images/Fluorescence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/Fluorescence.png -------------------------------------------------------------------------------- /HCK13/images/ImageSegmentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/ImageSegmentation.png -------------------------------------------------------------------------------- /HCK13/images/ImagingPlane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/ImagingPlane.png -------------------------------------------------------------------------------- /HCK13/images/LFP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/LFP.png -------------------------------------------------------------------------------- /HCK13/images/PlaneSegmentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/PlaneSegmentation.png -------------------------------------------------------------------------------- /HCK13/images/Position.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/Position.png -------------------------------------------------------------------------------- /HCK13/images/RoiResponseSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/RoiResponseSeries.png -------------------------------------------------------------------------------- /HCK13/images/SpatialSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/SpatialSeries.png -------------------------------------------------------------------------------- /HCK13/images/Subject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/Subject.png -------------------------------------------------------------------------------- /HCK13/images/Subject.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /HCK13/images/Trials.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/Trials.png -------------------------------------------------------------------------------- /HCK13/images/TwoPhotonSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/TwoPhotonSeries.png -------------------------------------------------------------------------------- /HCK13/images/dandi_download1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/dandi_download1.png -------------------------------------------------------------------------------- /HCK13/images/dandi_download2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/dandi_download2.png -------------------------------------------------------------------------------- /HCK13/images/dandi_download3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/dandi_download3.png -------------------------------------------------------------------------------- /HCK13/images/ecephys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/ecephys.png -------------------------------------------------------------------------------- /HCK13/images/ophys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/ophys.png -------------------------------------------------------------------------------- /HCK13/images/position_hdfview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/position_hdfview.png -------------------------------------------------------------------------------- /HCK13/images/ragged_array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/ragged_array.png -------------------------------------------------------------------------------- /HCK13/images/trials_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/images/trials_example.png -------------------------------------------------------------------------------- /HCK13/matnwb_read_demo.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/matnwb_read_demo.mlx -------------------------------------------------------------------------------- /HCK13/ophys_tutorial.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/HCK13/ophys_tutorial.mlx -------------------------------------------------------------------------------- /HCK13/pynwb_read_demo.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# NWB Tutorial - Reading NWB Data in Python\n", 8 | "\n", 9 | "## Introduction\n", 10 | "\n", 11 | "In this tutorial, we will read single neuron spiking data that is in the NWB standard format and do a basic visualization of the data." 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## Download the data\n", 19 | "\n", 20 | "First, let's download an NWB data file from the [DANDI neurophysiology data archive](https://dandiarchive.org/). \n", 21 | "\n", 22 | "An NWB file represents a single session of an experiment. It contains all the data of that session and the metadata required to understand the data. \n", 23 | "\n", 24 | "We will use data from one session of an experiment by [Chandravadia et al. (2020)](https://www.nature.com/articles/s41597-020-0415-9), where the authors recorded single neuron activity from the medial temporal lobes of human subjects while they performed a recognition memory task.\n", 25 | "\n", 26 | "1. Go to the DANDI page for this dataset: https://dandiarchive.org/dandiset/000004/draft\n", 27 | "2. Toward the top middle of the page, click the \"View Data\" button. \n", 28 | "\n", 29 | "\n", 30 | "3. Click on the folder \"sub-P11MHM\" (click the folder name, not the checkbox).\n", 31 | "\n", 32 | "\n", 33 | "4. Then click on the download symbol to the right of the filename \"sub-P11HMH_ses-20061101_ecephys+image.nwb\" to download the data file (69 MB) to your computer.\n", 34 | "" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "## Installing PyNWB\n", 42 | "\n", 43 | "To read data in the NWB format in Python, we recommend using the [PyNWB](https://pynwb.readthedocs.io/) package created by the NWB development team.\n", 44 | "\n", 45 | "First, install PyNWB using `pip` or `conda`. You will need Python 3.5+ installed.\n", 46 | "- `pip install -U pynwb`\n", 47 | "- `conda install -c conda-forge pynwb` " 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": {}, 53 | "source": [ 54 | "## Using NWBHDF5IO\n", 55 | "\n", 56 | "To read and write data in NWB, we will use the `NWBHDF5IO` class. You can read this as \"NWB\" \"HDF5\" \"IO\". This class reads NWB data that is in the HDF5 storage format, a popular, hierarchical format for storing large-scale scientific data. \"IO\" stands for Input/Output which means reading/writing data." 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": {}, 63 | "outputs": [], 64 | "source": [ 65 | "from pynwb import NWBHDF5IO\n", 66 | "\n", 67 | "# Change the string below to the path of the file on your computer\n", 68 | "filepath = 'C:/Users/Ryan/Downloads/sub-P11HMH_ses-20061101_ecephys+image.nwb'\n", 69 | "io = NWBHDF5IO(filepath, 'r') # open the file in read mode 'r'" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "Call the `NWBHDF5IO.read()` method to read the NWB data into an `NWBFile` object. Print the `NWBFile` object to inspect its contents." 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": null, 82 | "metadata": {}, 83 | "outputs": [], 84 | "source": [ 85 | "nwb = io.read()\n", 86 | "nwb" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "## Access stimulus data in NWB\n", 94 | "\n", 95 | "Data representing stimuli that were presented to the experimental subject are stored in `NWBFile.stimulus`." 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": null, 101 | "metadata": {}, 102 | "outputs": [], 103 | "source": [ 104 | "nwb.stimulus" 105 | ] 106 | }, 107 | { 108 | "cell_type": "markdown", 109 | "metadata": {}, 110 | "source": [ 111 | "`NWBFile.stimulus` is a dictionary that can contain PyNWB objects representing different types of data, such as images or time series of images. In this file, `NWBFile.stimulus` contains a single key `'StimulusPresentation'` with an `OpticalSeries` object representing what images were shown to the subject and at what times." 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": null, 117 | "metadata": {}, 118 | "outputs": [], 119 | "source": [ 120 | "stim = nwb.stimulus['StimulusPresentation']" 121 | ] 122 | }, 123 | { 124 | "cell_type": "markdown", 125 | "metadata": {}, 126 | "source": [ 127 | "## Lazy loading of datasets\n", 128 | "\n", 129 | "Data arrays are read passively from the NWB file. Calling the `data` attribute on a `TimeSeries` such as an `OpticalSeries` does not read the data values, but presents an `h5py` object that can be indexed to read the data. You can use the `[:]` operator to read the entire data array into memory." 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": null, 135 | "metadata": {}, 136 | "outputs": [], 137 | "source": [ 138 | "stim = nwb.stimulus['StimulusPresentation']\n", 139 | "\n", 140 | "print(stim.data.shape)\n", 141 | "all_stim_data = stim.data[:]" 142 | ] 143 | }, 144 | { 145 | "cell_type": "markdown", 146 | "metadata": {}, 147 | "source": [ 148 | "Time series data in NWB can have multiple dimensions, and the first dimension always represents time. So this dataset has 200 images of size 400x300 pixels with three channels (red, green, and blue)." 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "metadata": {}, 154 | "source": [ 155 | "## Slicing datasets\n", 156 | "It is often preferable to read only a portion of the data, e.g., because the full data array is too large to fit into your computer's RAM. To do this, index or slice into the `data` attribute just like if you were indexing or slicing a numpy array." 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": null, 162 | "metadata": {}, 163 | "outputs": [], 164 | "source": [ 165 | "pic_index = 31\n", 166 | "img = stim.data[pic_index]\n", 167 | "\n", 168 | "import matplotlib.pyplot as plt\n", 169 | "img = img[...,::-1] # reverse the last dimension because the data were stored in BGR instead of RGB\n", 170 | "plt.imshow(img, aspect='auto')" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": {}, 176 | "source": [ 177 | "## Access single unit data in NWB\n", 178 | "Data and metadata about sorted single units are stored in `NWBFile.units`. `NWBFile.units` is a `Units` object that stores metadata about each single unit in a tabular form, where each row represents a unit and has spike times and additional metadata. Printing the `Units` object shows the column names and basic metadata associated with each unit." 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": null, 184 | "metadata": {}, 185 | "outputs": [], 186 | "source": [ 187 | "nwb.units" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "We can also view the single unit data as a [pandas DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html)." 195 | ] 196 | }, 197 | { 198 | "cell_type": "code", 199 | "execution_count": null, 200 | "metadata": {}, 201 | "outputs": [], 202 | "source": [ 203 | "units_df = nwb.units.to_dataframe()\n", 204 | "units_df" 205 | ] 206 | }, 207 | { 208 | "cell_type": "markdown", 209 | "metadata": {}, 210 | "source": [ 211 | "To access the spike times of the first single unit, index `nwb.units` with the column name 'spike_times' and then the row index, 0. All times in NWB are stored in seconds relative to the session start time." 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": null, 217 | "metadata": {}, 218 | "outputs": [], 219 | "source": [ 220 | "nwb.units['spike_times'][0]" 221 | ] 222 | }, 223 | { 224 | "cell_type": "markdown", 225 | "metadata": {}, 226 | "source": [ 227 | "## Visualize spiking activity relative to stimulus onset\n", 228 | "\n", 229 | "Now we can look at when these single units spike relative to when image stimuli were presented to the subject.\n", 230 | "\n", 231 | "Let's loop through the first 10 units and get their spike times. For each unit, loop through each stimulus onset time and compute the spike times relative to stimulus onset. Finally, create a raster plot and histogram of these aligned spike times." 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": null, 237 | "metadata": {}, 238 | "outputs": [], 239 | "source": [ 240 | "import numpy as np\n", 241 | "\n", 242 | "before = 1. # in seconds\n", 243 | "after = 3.\n", 244 | "\n", 245 | "stim_on_times = stim.timestamps[:] # get the stimulus times for all stimuli\n", 246 | "\n", 247 | "for unit in range(10):\n", 248 | " unit_spike_times = nwb.units['spike_times'][unit]\n", 249 | " trial_spikes = []\n", 250 | " for time in stim_on_times:\n", 251 | " # compute spike times relative to stimulus onset\n", 252 | " aligned_spikes = unit_spike_times - time\n", 253 | " # keep only spike times in a given time window around the stimulus onset\n", 254 | " aligned_spikes = aligned_spikes[(-before < aligned_spikes) & (aligned_spikes < after)]\n", 255 | " trial_spikes.append(aligned_spikes)\n", 256 | " fig, axs = plt.subplots(2, 1, sharex=True)\n", 257 | " plt.xlabel('time (s)')\n", 258 | " axs[0].eventplot(trial_spikes)\n", 259 | " \n", 260 | " axs[0].set_ylabel('trial')\n", 261 | " axs[0].set_title('unit {}'.format(unit))\n", 262 | " axs[0].axvline(0, color=[.5,.5,.5])\n", 263 | " \n", 264 | " axs[1].hist(np.hstack(trial_spikes), 30)\n", 265 | " axs[1].axvline(0, color=[.5,.5,.5])" 266 | ] 267 | }, 268 | { 269 | "cell_type": "markdown", 270 | "metadata": {}, 271 | "source": [ 272 | "## Accessing trial information in NWB\n", 273 | "\n", 274 | "Trial data are stored in `NWBFile.trials`. `NWBFile.trials` is a `TimeIntervals` object that stores metadata about each trial in a tabular form, where each row represents a trial and has a start time, stop time, and additional metadata. Like for the `Units` table, you can also view the trial data as a pandas DataFrame." 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": null, 280 | "metadata": {}, 281 | "outputs": [], 282 | "source": [ 283 | "trials_df = nwb.trials.to_dataframe()\n", 284 | "trials_df" 285 | ] 286 | }, 287 | { 288 | "cell_type": "markdown", 289 | "metadata": {}, 290 | "source": [ 291 | "The stimuli are stored in `nwb.stimuli` and can be mapped one to one to each row (trial) of `nwb.trials` based on the `stim_on_time` column. Let's visualize the first 10 images that were categorized as landscapes in the session. We can interact with the trial data as a PyNWB `TimeIntervals` type or as a pandas DataFrame. Here, let's use pandas functions." 292 | ] 293 | }, 294 | { 295 | "cell_type": "code", 296 | "execution_count": null, 297 | "metadata": {}, 298 | "outputs": [], 299 | "source": [ 300 | "assert np.all(stim.timestamps[:] == trials_df.stim_on_time[:])\n", 301 | "\n", 302 | "stim_on_times_landscapes = trials_df[trials_df.category_name == 'landscapes'].stim_on_time\n", 303 | "for time in stim_on_times_landscapes[:10]:\n", 304 | " img = np.squeeze(stim.data[np.where(stim.timestamps[:] == time)])\n", 305 | " img = img[...,::-1] # reverse the last dimension because the data were stored in BGR instead of RGB\n", 306 | " plt.figure()\n", 307 | " plt.imshow(img, aspect='auto')" 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "metadata": {}, 313 | "source": [ 314 | "## Exploring the NWB file\n", 315 | "\n", 316 | "You can explore the NWB file by printing the `NWBFile` object and accessing its attributes, but it may be useful to explore the data in a less programmatic, more visual way. You can use NWBWidgets, a package containing interactive widgets for visualizing NWB data, or you can use the HDFView tool, which can open any generic HDF5 file, which an NWB file is.\n", 317 | "\n", 318 | "### NWBWidgets\n", 319 | "\n", 320 | "To use NWBWidgets, first install NWBWidgets:\n", 321 | "- `pip install -U nwbwidgets`\n", 322 | "\n", 323 | "Then import and run the `nwb2widget` function on the `NWBFile` object." 324 | ] 325 | }, 326 | { 327 | "cell_type": "code", 328 | "execution_count": null, 329 | "metadata": {}, 330 | "outputs": [], 331 | "source": [ 332 | "from nwbwidgets import nwb2widget\n", 333 | "\n", 334 | "nwb2widget(nwb)" 335 | ] 336 | }, 337 | { 338 | "cell_type": "markdown", 339 | "metadata": {}, 340 | "source": [ 341 | "### HDFView\n", 342 | "\n", 343 | "To use HDFView to inspect and explore the NWB file, download and install HDFView from here: https://www.hdfgroup.org/downloads/hdfview/ and then open the NWB file using the program." 344 | ] 345 | }, 346 | { 347 | "cell_type": "markdown", 348 | "metadata": {}, 349 | "source": [ 350 | "## Conclusion\n", 351 | "\n", 352 | "This is an example of how to get started with understanding and analyzing public NWB datasets. This particular dataset was published with an extensive open analysis in both MATLAB and Python, which you can find [here](https://github.com/rutishauserlab/recogmem-release-NWB). For more datasets, or to publish your own NWB data for free, check out the DANDI archive. Also, make sure to check out the DANDI breakout session later in this event." 353 | ] 354 | }, 355 | { 356 | "cell_type": "markdown", 357 | "metadata": {}, 358 | "source": [ 359 | "# Learn more!\n", 360 | "\n", 361 | "## Python tutorials\n", 362 | "### See our tutorials for more details about your data type:\n", 363 | "* [Extracellular electrophysiology](https://pynwb.readthedocs.io/en/stable/tutorials/domain/ecephys.html#sphx-glr-tutorials-domain-ecephys-py)\n", 364 | "* [Calcium imaging](https://pynwb.readthedocs.io/en/stable/tutorials/domain/ophys.html#sphx-glr-tutorials-domain-ophys-py)\n", 365 | "* [Intracellular electrophysiology](https://pynwb.readthedocs.io/en/stable/tutorials/domain/icephys.html#sphx-glr-tutorials-domain-icephys-py)\n", 366 | "\n", 367 | "### Check out other tutorials that teach advanced NWB topics:\n", 368 | "* [Iterative data write](https://pynwb.readthedocs.io/en/stable/tutorials/general/iterative_write.html#sphx-glr-tutorials-general-iterative-write-py)\n", 369 | "* [Extensions](https://pynwb.readthedocs.io/en/stable/tutorials/general/extensions.html#sphx-glr-tutorials-general-extensions-py)\n", 370 | "* [Advanced HDF5 I/O](https://pynwb.readthedocs.io/en/stable/tutorials/general/advanced_hdf5_io.html#sphx-glr-tutorials-general-advanced-hdf5-io-py)\n", 371 | "\n", 372 | "\n", 373 | "## MATLAB tutorials\n", 374 | "* [Extracellular electrophysiology](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ecephys.html)\n", 375 | "* [Calcium imaging](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ophys.html)\n", 376 | "* [Intracellular electrophysiology](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/icephys.html)" 377 | ] 378 | } 379 | ], 380 | "metadata": { 381 | "kernelspec": { 382 | "display_name": "Python 3", 383 | "language": "python", 384 | "name": "python3" 385 | }, 386 | "language_info": { 387 | "codemirror_mode": { 388 | "name": "ipython", 389 | "version": 3 390 | }, 391 | "file_extension": ".py", 392 | "mimetype": "text/x-python", 393 | "name": "python", 394 | "nbconvert_exporter": "python", 395 | "pygments_lexer": "ipython3", 396 | "version": "3.7.7" 397 | } 398 | }, 399 | "nbformat": 4, 400 | "nbformat_minor": 4 401 | } 402 | -------------------------------------------------------------------------------- /Neuromatch2021/ecephys_tutorial.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/ecephys_tutorial.mlx -------------------------------------------------------------------------------- /Neuromatch2021/icephys_tutorial.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/icephys_tutorial.mlx -------------------------------------------------------------------------------- /Neuromatch2021/images/Behavior.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/Behavior.png -------------------------------------------------------------------------------- /Neuromatch2021/images/ElectricalSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/ElectricalSeries.png -------------------------------------------------------------------------------- /Neuromatch2021/images/Electrodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/Electrodes.png -------------------------------------------------------------------------------- /Neuromatch2021/images/Fluorescence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/Fluorescence.png -------------------------------------------------------------------------------- /Neuromatch2021/images/ImageSegmentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/ImageSegmentation.png -------------------------------------------------------------------------------- /Neuromatch2021/images/ImagingPlane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/ImagingPlane.png -------------------------------------------------------------------------------- /Neuromatch2021/images/LFP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/LFP.png -------------------------------------------------------------------------------- /Neuromatch2021/images/PlaneSegmentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/PlaneSegmentation.png -------------------------------------------------------------------------------- /Neuromatch2021/images/Position.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/Position.png -------------------------------------------------------------------------------- /Neuromatch2021/images/RoiResponseSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/RoiResponseSeries.png -------------------------------------------------------------------------------- /Neuromatch2021/images/SpatialSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/SpatialSeries.png -------------------------------------------------------------------------------- /Neuromatch2021/images/Subject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/Subject.png -------------------------------------------------------------------------------- /Neuromatch2021/images/Subject.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Neuromatch2021/images/Trials.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/Trials.png -------------------------------------------------------------------------------- /Neuromatch2021/images/TwoPhotonSeries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/TwoPhotonSeries.png -------------------------------------------------------------------------------- /Neuromatch2021/images/dandi_download1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/dandi_download1.png -------------------------------------------------------------------------------- /Neuromatch2021/images/dandi_download2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/dandi_download2.png -------------------------------------------------------------------------------- /Neuromatch2021/images/dandi_download3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/dandi_download3.png -------------------------------------------------------------------------------- /Neuromatch2021/images/ecephys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/ecephys.png -------------------------------------------------------------------------------- /Neuromatch2021/images/ophys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/ophys.png -------------------------------------------------------------------------------- /Neuromatch2021/images/position_hdfview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/position_hdfview.png -------------------------------------------------------------------------------- /Neuromatch2021/images/ragged_array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/ragged_array.png -------------------------------------------------------------------------------- /Neuromatch2021/images/trials_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/images/trials_example.png -------------------------------------------------------------------------------- /Neuromatch2021/matnwb_read_demo.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/matnwb_read_demo.mlx -------------------------------------------------------------------------------- /Neuromatch2021/ophys_tutorial.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/Neuromatch2021/ophys_tutorial.mlx -------------------------------------------------------------------------------- /Neuromatch2021/pynwb_read_demo.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# NWB Tutorial - Reading NWB Data in Python\n", 8 | "\n", 9 | "## Introduction\n", 10 | "\n", 11 | "In this tutorial, we will read single neuron spiking data that is in the NWB standard format and do a basic visualization of the data." 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## Download the data\n", 19 | "\n", 20 | "First, let's download an NWB data file from the [DANDI neurophysiology data archive](https://dandiarchive.org/). \n", 21 | "\n", 22 | "An NWB file represents a single session of an experiment. It contains all the data of that session and the metadata required to understand the data. \n", 23 | "\n", 24 | "We will use data from one session of an experiment by [Chandravadia et al. (2020)](https://www.nature.com/articles/s41597-020-0415-9), where the authors recorded single neuron activity from the medial temporal lobes of human subjects while they performed a recognition memory task.\n", 25 | "\n", 26 | "1. Go to the DANDI page for this dataset: https://dandiarchive.org/dandiset/000004/draft\n", 27 | "2. Toward the top middle of the page, click the \"View Data\" button. \n", 28 | "\n", 29 | "\n", 30 | "3. Click on the folder \"sub-P11MHM\" (click the folder name, not the checkbox).\n", 31 | "\n", 32 | "\n", 33 | "4. Then click on the download symbol to the right of the filename \"sub-P11HMH_ses-20061101_ecephys+image.nwb\" to download the data file (69 MB) to your computer.\n", 34 | "" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "## Installing PyNWB\n", 42 | "\n", 43 | "To read data in the NWB format in Python, we recommend using the [PyNWB](https://pynwb.readthedocs.io/) package created by the NWB development team.\n", 44 | "\n", 45 | "First, install PyNWB using `pip` or `conda`. You will need Python 3.5+ installed.\n", 46 | "- `pip install -U pynwb`\n", 47 | "- `conda install -c conda-forge pynwb` " 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": {}, 53 | "source": [ 54 | "## Using NWBHDF5IO\n", 55 | "\n", 56 | "To read and write data in NWB, we will use the `NWBHDF5IO` class. You can read this as \"NWB\" \"HDF5\" \"IO\". This class reads NWB data that is in the HDF5 storage format, a popular, hierarchical format for storing large-scale scientific data. \"IO\" stands for Input/Output which means reading/writing data." 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": {}, 63 | "outputs": [], 64 | "source": [ 65 | "from pynwb import NWBHDF5IO\n", 66 | "\n", 67 | "# Change the string below to the path of the file on your computer\n", 68 | "filepath = 'C:/Users/Ryan/Downloads/sub-P11HMH_ses-20061101_ecephys+image.nwb'\n", 69 | "io = NWBHDF5IO(filepath, 'r') # open the file in read mode 'r'" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "Call the `NWBHDF5IO.read()` method to read the NWB data into an `NWBFile` object. Print the `NWBFile` object to inspect its contents." 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": null, 82 | "metadata": {}, 83 | "outputs": [], 84 | "source": [ 85 | "nwb = io.read()\n", 86 | "nwb" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "## Access stimulus data in NWB\n", 94 | "\n", 95 | "Data representing stimuli that were presented to the experimental subject are stored in `NWBFile.stimulus`." 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": null, 101 | "metadata": {}, 102 | "outputs": [], 103 | "source": [ 104 | "nwb.stimulus" 105 | ] 106 | }, 107 | { 108 | "cell_type": "markdown", 109 | "metadata": {}, 110 | "source": [ 111 | "`NWBFile.stimulus` is a dictionary that can contain PyNWB objects representing different types of data, such as images or time series of images. In this file, `NWBFile.stimulus` contains a single key `'StimulusPresentation'` with an `OpticalSeries` object representing what images were shown to the subject and at what times." 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": null, 117 | "metadata": {}, 118 | "outputs": [], 119 | "source": [ 120 | "stim = nwb.stimulus['StimulusPresentation']" 121 | ] 122 | }, 123 | { 124 | "cell_type": "markdown", 125 | "metadata": {}, 126 | "source": [ 127 | "## Lazy loading of datasets\n", 128 | "\n", 129 | "Data arrays are read passively from the NWB file. Calling the `data` attribute on a `TimeSeries` such as an `OpticalSeries` does not read the data values, but presents an `h5py` object that can be indexed to read the data. You can use the `[:]` operator to read the entire data array into memory." 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": null, 135 | "metadata": {}, 136 | "outputs": [], 137 | "source": [ 138 | "stim = nwb.stimulus['StimulusPresentation']\n", 139 | "\n", 140 | "print(stim.data.shape)\n", 141 | "all_stim_data = stim.data[:]" 142 | ] 143 | }, 144 | { 145 | "cell_type": "markdown", 146 | "metadata": {}, 147 | "source": [ 148 | "Time series data in NWB can have multiple dimensions, and the first dimension always represents time. So this dataset has 200 images of size 400x300 pixels with three channels (red, green, and blue)." 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "metadata": {}, 154 | "source": [ 155 | "## Slicing datasets\n", 156 | "It is often preferable to read only a portion of the data, e.g., because the full data array is too large to fit into your computer's RAM. To do this, index or slice into the `data` attribute just like if you were indexing or slicing a numpy array." 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": null, 162 | "metadata": {}, 163 | "outputs": [], 164 | "source": [ 165 | "pic_index = 31\n", 166 | "img = stim.data[pic_index]\n", 167 | "\n", 168 | "import matplotlib.pyplot as plt\n", 169 | "img = img[...,::-1] # reverse the last dimension because the data were stored in BGR instead of RGB\n", 170 | "plt.imshow(img, aspect='auto')" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": {}, 176 | "source": [ 177 | "## Access single unit data in NWB\n", 178 | "Data and metadata about sorted single units are stored in `NWBFile.units`. `NWBFile.units` is a `Units` object that stores metadata about each single unit in a tabular form, where each row represents a unit and has spike times and additional metadata. Printing the `Units` object shows the column names and basic metadata associated with each unit." 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": null, 184 | "metadata": {}, 185 | "outputs": [], 186 | "source": [ 187 | "nwb.units" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "We can also view the single unit data as a [pandas DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html)." 195 | ] 196 | }, 197 | { 198 | "cell_type": "code", 199 | "execution_count": null, 200 | "metadata": {}, 201 | "outputs": [], 202 | "source": [ 203 | "units_df = nwb.units.to_dataframe()\n", 204 | "units_df" 205 | ] 206 | }, 207 | { 208 | "cell_type": "markdown", 209 | "metadata": {}, 210 | "source": [ 211 | "To access the spike times of the first single unit, index `nwb.units` with the column name 'spike_times' and then the row index, 0. All times in NWB are stored in seconds relative to the session start time." 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": null, 217 | "metadata": {}, 218 | "outputs": [], 219 | "source": [ 220 | "nwb.units['spike_times'][0]" 221 | ] 222 | }, 223 | { 224 | "cell_type": "markdown", 225 | "metadata": {}, 226 | "source": [ 227 | "## Visualize spiking activity relative to stimulus onset\n", 228 | "\n", 229 | "Now we can look at when these single units spike relative to when image stimuli were presented to the subject.\n", 230 | "\n", 231 | "Let's loop through the first 10 units and get their spike times. For each unit, loop through each stimulus onset time and compute the spike times relative to stimulus onset. Finally, create a raster plot and histogram of these aligned spike times." 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": null, 237 | "metadata": {}, 238 | "outputs": [], 239 | "source": [ 240 | "import numpy as np\n", 241 | "\n", 242 | "before = 1. # in seconds\n", 243 | "after = 3.\n", 244 | "\n", 245 | "stim_on_times = stim.timestamps[:] # get the stimulus times for all stimuli\n", 246 | "\n", 247 | "for unit in range(10):\n", 248 | " unit_spike_times = nwb.units['spike_times'][unit]\n", 249 | " trial_spikes = []\n", 250 | " for time in stim_on_times:\n", 251 | " # compute spike times relative to stimulus onset\n", 252 | " aligned_spikes = unit_spike_times - time\n", 253 | " # keep only spike times in a given time window around the stimulus onset\n", 254 | " aligned_spikes = aligned_spikes[(-before < aligned_spikes) & (aligned_spikes < after)]\n", 255 | " trial_spikes.append(aligned_spikes)\n", 256 | " fig, axs = plt.subplots(2, 1, sharex=True)\n", 257 | " plt.xlabel('time (s)')\n", 258 | " axs[0].eventplot(trial_spikes)\n", 259 | " \n", 260 | " axs[0].set_ylabel('trial')\n", 261 | " axs[0].set_title('unit {}'.format(unit))\n", 262 | " axs[0].axvline(0, color=[.5,.5,.5])\n", 263 | " \n", 264 | " axs[1].hist(np.hstack(trial_spikes), 30)\n", 265 | " axs[1].axvline(0, color=[.5,.5,.5])" 266 | ] 267 | }, 268 | { 269 | "cell_type": "markdown", 270 | "metadata": {}, 271 | "source": [ 272 | "## Accessing trial information in NWB\n", 273 | "\n", 274 | "Trial data are stored in `NWBFile.trials`. `NWBFile.trials` is a `TimeIntervals` object that stores metadata about each trial in a tabular form, where each row represents a trial and has a start time, stop time, and additional metadata. Like for the `Units` table, you can also view the trial data as a pandas DataFrame." 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": null, 280 | "metadata": {}, 281 | "outputs": [], 282 | "source": [ 283 | "trials_df = nwb.trials.to_dataframe()\n", 284 | "trials_df" 285 | ] 286 | }, 287 | { 288 | "cell_type": "markdown", 289 | "metadata": {}, 290 | "source": [ 291 | "The stimuli are stored in `nwb.stimuli` and can be mapped one to one to each row (trial) of `nwb.trials` based on the `stim_on_time` column. Let's visualize the first 10 images that were categorized as landscapes in the session. We can interact with the trial data as a PyNWB `TimeIntervals` type or as a pandas DataFrame. Here, let's use pandas functions." 292 | ] 293 | }, 294 | { 295 | "cell_type": "code", 296 | "execution_count": null, 297 | "metadata": {}, 298 | "outputs": [], 299 | "source": [ 300 | "assert np.all(stim.timestamps[:] == trials_df.stim_on_time[:])\n", 301 | "\n", 302 | "stim_on_times_landscapes = trials_df[trials_df.category_name == 'landscapes'].stim_on_time\n", 303 | "for time in stim_on_times_landscapes[:10]:\n", 304 | " img = np.squeeze(stim.data[np.where(stim.timestamps[:] == time)])\n", 305 | " img = img[...,::-1] # reverse the last dimension because the data were stored in BGR instead of RGB\n", 306 | " plt.figure()\n", 307 | " plt.imshow(img, aspect='auto')" 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "metadata": {}, 313 | "source": [ 314 | "## Exploring the NWB file\n", 315 | "\n", 316 | "You can explore the NWB file by printing the `NWBFile` object and accessing its attributes, but it may be useful to explore the data in a less programmatic, more visual way. You can use NWBWidgets, a package containing interactive widgets for visualizing NWB data, or you can use the HDFView tool, which can open any generic HDF5 file, which an NWB file is.\n", 317 | "\n", 318 | "### NWBWidgets\n", 319 | "\n", 320 | "To use NWBWidgets, first install NWBWidgets:\n", 321 | "- `pip install -U nwbwidgets`\n", 322 | "\n", 323 | "Then import and run the `nwb2widget` function on the `NWBFile` object." 324 | ] 325 | }, 326 | { 327 | "cell_type": "code", 328 | "execution_count": null, 329 | "metadata": {}, 330 | "outputs": [], 331 | "source": [ 332 | "from nwbwidgets import nwb2widget\n", 333 | "\n", 334 | "nwb2widget(nwb)" 335 | ] 336 | }, 337 | { 338 | "cell_type": "markdown", 339 | "metadata": {}, 340 | "source": [ 341 | "### HDFView\n", 342 | "\n", 343 | "To use HDFView to inspect and explore the NWB file, download and install HDFView from here: https://www.hdfgroup.org/downloads/hdfview/ and then open the NWB file using the program." 344 | ] 345 | }, 346 | { 347 | "cell_type": "markdown", 348 | "metadata": {}, 349 | "source": [ 350 | "## Conclusion\n", 351 | "\n", 352 | "This is an example of how to get started with understanding and analyzing public NWB datasets. This particular dataset was published with an extensive open analysis in both MATLAB and Python, which you can find [here](https://github.com/rutishauserlab/recogmem-release-NWB). For more datasets, or to publish your own NWB data for free, check out the DANDI archive. Also, make sure to check out the DANDI breakout session later in this event." 353 | ] 354 | }, 355 | { 356 | "cell_type": "markdown", 357 | "metadata": {}, 358 | "source": [ 359 | "# Learn more!\n", 360 | "\n", 361 | "## Python tutorials\n", 362 | "### See our tutorials for more details about your data type:\n", 363 | "* [Extracellular electrophysiology](https://pynwb.readthedocs.io/en/stable/tutorials/domain/ecephys.html#sphx-glr-tutorials-domain-ecephys-py)\n", 364 | "* [Calcium imaging](https://pynwb.readthedocs.io/en/stable/tutorials/domain/ophys.html#sphx-glr-tutorials-domain-ophys-py)\n", 365 | "* [Intracellular electrophysiology](https://pynwb.readthedocs.io/en/stable/tutorials/domain/icephys.html#sphx-glr-tutorials-domain-icephys-py)\n", 366 | "\n", 367 | "### Check out other tutorials that teach advanced NWB topics:\n", 368 | "* [Iterative data write](https://pynwb.readthedocs.io/en/stable/tutorials/advanced_io/iterative_write.html#sphx-glr-tutorials-advanced-io-iterative-write-py)\n", 369 | "* [Extensions](https://pynwb.readthedocs.io/en/stable/tutorials/general/extensions.html#sphx-glr-tutorials-general-extensions-py)\n", 370 | "* [Advanced HDF5 I/O](https://pynwb.readthedocs.io/en/stable/tutorials/advanced_io/h5dataio.html#sphx-glr-tutorials-advanced-io-h5dataio-py)\n", 371 | "\n", 372 | "\n", 373 | "## MATLAB tutorials\n", 374 | "* [Extracellular electrophysiology](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ecephys.html)\n", 375 | "* [Calcium imaging](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ophys.html)\n", 376 | "* [Intracellular electrophysiology](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/icephys.html)" 377 | ] 378 | } 379 | ], 380 | "metadata": { 381 | "kernelspec": { 382 | "display_name": "Python 3", 383 | "language": "python", 384 | "name": "python3" 385 | }, 386 | "language_info": { 387 | "codemirror_mode": { 388 | "name": "ipython", 389 | "version": 3 390 | }, 391 | "file_extension": ".py", 392 | "mimetype": "text/x-python", 393 | "name": "python", 394 | "nbconvert_exporter": "python", 395 | "pygments_lexer": "ipython3", 396 | "version": "3.7.7" 397 | } 398 | }, 399 | "nbformat": 4, 400 | "nbformat_minor": 4 401 | } 402 | -------------------------------------------------------------------------------- /images/electrodes_table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/images/electrodes_table.png -------------------------------------------------------------------------------- /images/lfp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/images/lfp.png -------------------------------------------------------------------------------- /images/position.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/images/position.png -------------------------------------------------------------------------------- /images/ragged_array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeurodataWithoutBorders/nwb_tutorial/eeb9c1ee23ee28ac26e5c32d9eedcc95ae000e4d/images/ragged_array.png --------------------------------------------------------------------------------