{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# NWB Tutorial - Optical Physiology" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Introduction\n", "In this tutorial, we will create an NWB file for a hypothetical optical physiology experiment with a freely moving animal. The types of data we will convert are:\n", "* Subject (species, strain, age, etc.)\n", "* Animal position\n", "* Trials\n", "* Acquired two-photon images\n", "* Image segmentation (ROIs)\n", "* Fluorescence and dF/F responses" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Installing PyNWB\n", "First, install PyNWB using pip or conda. You will need Python 3.5+ installed.\n", "- `pip install pynwb`\n", "- `conda install -c conda-forge pynwb`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Set up the NWB file\n", "An NWB file represents a single session of an experiment. Each file must have a session description, identifier, and session start time. Importantly, the session start time is the reference time for all timestamps in the file. For example, an event with a timestamp of 0 in the file means the event occurred exactly at the session start time. \n", "\n", "Create a new `NWBFile` object with those and additional metadata. For all PyNWB constructors, we recommend using keyword arguments for clarity." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "root pynwb.file.NWBFile at 0x2069551235528\n", "Fields:\n", " experimenter: ['My Name']\n", " file_create_date: [datetime.datetime(2020, 9, 18, 3, 15, 30, 760259, tzinfo=tzlocal())]\n", " identifier: Mouse5_Day3\n", " institution: University of My Institution\n", " lab: My Lab Name\n", " related_publications: ['DOI:10.1016/j.neuron.2016.12.011']\n", " session_description: Mouse exploring an open field\n", " session_id: session_1234\n", " session_start_time: 2018-04-25 02:30:03-07:00\n", " timestamps_reference_time: 2018-04-25 02:30:03-07:00\n", "\n" ] } ], "source": [ "from pynwb import NWBFile\n", "from datetime import datetime\n", "from dateutil import tz\n", "\n", "session_start_time = datetime(2018, 4, 25, 2, 30, 3, tzinfo=tz.gettz('US/Pacific'))\n", "\n", "nwbfile = NWBFile(\n", " session_description='Mouse exploring an open field',\n", " identifier='Mouse5_Day3',\n", " session_start_time=session_start_time,\n", " session_id='session_1234', # optional\n", " experimenter='My Name', # optional\n", " lab='My Lab Name', # optional\n", " institution='University of My Institution', # optional\n", " related_publications='DOI:10.1016/j.neuron.2016.12.011' # optional\n", ")\n", "print(nwbfile)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Subject information\n", "Create a `Subject` object to store information about the experimental subject, such as age, species, genotype, sex, and a description. Then set `nwbfile.subject` to the new `Subject` object.\n", "\n", "\n", "\n", "Each of these fields is free-form text, so any values will be valid, but we recommend these values follow particular conventions to help software tools interpret the data:\n", "- 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", "- For species, we recommend using the formal latin binomal name, e.g., \"*Mus musculus*\", \"*Homo sapiens*\"\n", "- For sex, we recommend using \"F\" (female), \"M\" (male), \"U\" (unknown), and \"O\" (other)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "from pynwb.file import Subject\n", "\n", "nwbfile.subject = Subject(\n", " subject_id='001',\n", " age='P90D', \n", " description='mouse 5',\n", " species='Mus musculus', \n", " sex='M'\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## SpatialSeries and Position\n", "PyNWB contains classes that are specialized for different types of data. To store the spatial position of a subject, we will use the `SpatialSeries` and `Position` classes. \n", "\n", "`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", "\n", "\n", "\n", "Create a `SpatialSeries` object named `'SpatialSeries'` with some fake data." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from pynwb.behavior import SpatialSeries\n", "\n", "# create fake data with shape (50, 2)\n", "# the first dimension should always represent time\n", "position_data = np.array([np.linspace(0, 10, 50),\n", " np.linspace(0, 8, 50)]).T\n", "position_timestamps = np.linspace(0, 50) / 200\n", "\n", "spatial_series_obj = SpatialSeries(\n", " name='SpatialSeries', \n", " description='(x,y) position in open field',\n", " data=position_data,\n", " timestamps=position_timestamps,\n", " reference_frame='(0,0) is bottom left corner'\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can print the `SpatialSeries` object to view its contents." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "SpatialSeries pynwb.behavior.SpatialSeries at 0x2070073189192\n", "Fields:\n", " comments: no comments\n", " conversion: 1.0\n", " data: [[ 0. 0. ]\n", " [ 0.20408163 0.16326531]\n", " [ 0.40816327 0.32653061]\n", " [ 0.6122449 0.48979592]\n", " [ 0.81632653 0.65306122]\n", " [ 1.02040816 0.81632653]\n", " [ 1.2244898 0.97959184]\n", " [ 1.42857143 1.14285714]\n", " [ 1.63265306 1.30612245]\n", " [ 1.83673469 1.46938776]\n", " [ 2.04081633 1.63265306]\n", " [ 2.24489796 1.79591837]\n", " [ 2.44897959 1.95918367]\n", " [ 2.65306122 2.12244898]\n", " [ 2.85714286 2.28571429]\n", " [ 3.06122449 2.44897959]\n", " [ 3.26530612 2.6122449 ]\n", " [ 3.46938776 2.7755102 ]\n", " [ 3.67346939 2.93877551]\n", " [ 3.87755102 3.10204082]\n", " [ 4.08163265 3.26530612]\n", " [ 4.28571429 3.42857143]\n", " [ 4.48979592 3.59183673]\n", " [ 4.69387755 3.75510204]\n", " [ 4.89795918 3.91836735]\n", " [ 5.10204082 4.08163265]\n", " [ 5.30612245 4.24489796]\n", " [ 5.51020408 4.40816327]\n", " [ 5.71428571 4.57142857]\n", " [ 5.91836735 4.73469388]\n", " [ 6.12244898 4.89795918]\n", " [ 6.32653061 5.06122449]\n", " [ 6.53061224 5.2244898 ]\n", " [ 6.73469388 5.3877551 ]\n", " [ 6.93877551 5.55102041]\n", " [ 7.14285714 5.71428571]\n", " [ 7.34693878 5.87755102]\n", " [ 7.55102041 6.04081633]\n", " [ 7.75510204 6.20408163]\n", " [ 7.95918367 6.36734694]\n", " [ 8.16326531 6.53061224]\n", " [ 8.36734694 6.69387755]\n", " [ 8.57142857 6.85714286]\n", " [ 8.7755102 7.02040816]\n", " [ 8.97959184 7.18367347]\n", " [ 9.18367347 7.34693878]\n", " [ 9.3877551 7.51020408]\n", " [ 9.59183673 7.67346939]\n", " [ 9.79591837 7.83673469]\n", " [10. 8. ]]\n", " description: (x,y) position in open field\n", " interval: 1\n", " reference_frame: (0,0) is bottom left corner\n", " resolution: -1.0\n", " timestamps: [0. 0.00510204 0.01020408 0.01530612 0.02040816 0.0255102\n", " 0.03061224 0.03571429 0.04081633 0.04591837 0.05102041 0.05612245\n", " 0.06122449 0.06632653 0.07142857 0.07653061 0.08163265 0.08673469\n", " 0.09183673 0.09693878 0.10204082 0.10714286 0.1122449 0.11734694\n", " 0.12244898 0.12755102 0.13265306 0.1377551 0.14285714 0.14795918\n", " 0.15306122 0.15816327 0.16326531 0.16836735 0.17346939 0.17857143\n", " 0.18367347 0.18877551 0.19387755 0.19897959 0.20408163 0.20918367\n", " 0.21428571 0.21938776 0.2244898 0.22959184 0.23469388 0.23979592\n", " 0.24489796 0.25 ]\n", " timestamps_unit: seconds\n", " unit: meters\n", "\n" ] } ], "source": [ "print(spatial_series_obj)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To help data analysis and visualization tools know that this `SpatialSeries` object represents the position of the subject, store the `SpatialSeries` object inside of a `Position` object, which can hold one or more `SpatialSeries` objects.\n", "\n", "" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "from pynwb.behavior import Position\n", "\n", "position_obj = Position(spatial_series=spatial_series_obj) # name is set to 'Position' by default" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Behavior Processing Module\n", "\n", "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 subject's position was computed from a video tracking algorithm, so it would be classified as processed data. Since processed data can be diverse, NWB allows us to create processing modules, which are like folders, to store related processed data. \n", "\n", "Create a processing module called \"behavior\" for storing behavioral data in the `NWBFile` and add the `Position` object to the processing module." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Position pynwb.behavior.Position at 0x2070073215432\n", "Fields:\n", " spatial_series: {\n", " SpatialSeries \n", " }" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "behavior_module = nwbfile.create_processing_module(\n", " name='behavior', \n", " description='processed behavioral data'\n", ")\n", "behavior_module.add(position_obj)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Write to file" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, write the NWB file that we have built so far." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "from pynwb import NWBHDF5IO\n", "\n", "with NWBHDF5IO('ophys_tutorial.nwb', 'w') as io:\n", " io.write(nwbfile)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Read from an NWB file\n", "\n", "We can now read the file and print it to inspect its contents. \n", "\n", "We can also print the SpatialSeries data that we created by referencing the names of the objects in the hierarchy that contain it. We can access a processing module by indexing `nwbfile.processing` with the name of the processing module, which in our case is \"behavior\". \n", "\n", "Then, we can access the `Position` object inside of the \"behavior\" processing module by indexing it with the name of the `Position` object. The default name of `Position` objects is \"Position\". \n", "\n", "Finally, we can access the `SpatialSeries` object inside of the `Position` object by indexing it with the name of the `SpatialSeries` object, which we named `'SpatialSeries'`." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "behavior pynwb.base.ProcessingModule at 0x2069551037384\n", "Fields:\n", " data_interfaces: {\n", " Position \n", " }\n", " description: processed behavioral data\n", "\n", "Position pynwb.behavior.Position at 0x2069551010056\n", "Fields:\n", " spatial_series: {\n", " SpatialSeries \n", " }\n", "\n", "SpatialSeries pynwb.behavior.SpatialSeries at 0x2070078710664\n", "Fields:\n", " comments: no comments\n", " conversion: 1.0\n", " data: \n", " description: (x,y) position in open field\n", " interval: 1\n", " reference_frame: (0,0) is bottom left corner\n", " resolution: -1.0\n", " timestamps: \n", " timestamps_unit: seconds\n", " unit: meters\n", "\n" ] } ], "source": [ "with NWBHDF5IO('ophys_tutorial.nwb', 'r') as io:\n", " read_nwbfile = io.read()\n", " print(read_nwbfile.processing['behavior'])\n", " print(read_nwbfile.processing['behavior']['Position'])\n", " print(read_nwbfile.processing['behavior']['Position']['SpatialSeries'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also use the [HDFView](https://www.hdfgroup.org/downloads/hdfview/) tool to inspect the resulting NWB file.\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Trials\n", "\n", "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 not defined in the standard.\n", "\n", "\n", "\n", "The trials DynamicTable can be thought of as a table with this structure:\n", "\n", "\n", "\n", "We can add custom, user-defined columns to the trials table to hold data and metadata specific to this experiment or session. Continue adding to our `NWBFile` by creating a new column for the trials table named `'correct'`, which will be a boolean array." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "nwbfile.add_trial_column(name='correct', description='whether the trial was correct')\n", "nwbfile.add_trial(start_time=1.0, stop_time=5.0, correct=True)\n", "nwbfile.add_trial(start_time=6.0, stop_time=10.0, correct=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can view the trials table in tabular form by converting it to a pandas dataframe." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
start_timestop_timecorrect
id
01.05.0True
16.010.0False
\n", "
" ], "text/plain": [ " start_time stop_time correct\n", "id \n", "0 1.0 5.0 True\n", "1 6.0 10.0 False" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = nwbfile.trials.to_dataframe()\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Optical physiology\n", "Optical physiology results are written in four steps:\n", "1. Create imaging plane\n", "2. Add acquired two-photon images\n", "3. Add image segmentation\n", "4. Add fluorescence and dF/F responses" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Imaging Plane\n", "First, we must create an `ImagingPlane` object, which will hold information about the area and method used to collect the optical imaging data. This first requires creation of a `Device` object for the microscope and an `OpticalChannel` object. \n", "\n", "\n", "\n", "Create a `Device` named `'Microscope'` in the `NWBFile` object. Then create an `OpticalChannel` named `'OpticalChannel'` and an imaging plane named `'ImagingPlane'`, passing in the `OpticalChannel` object and the `Device` object." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "from pynwb.device import Device\n", "from pynwb.ophys import OpticalChannel\n", "\n", "device = nwbfile.create_device(\n", " name='Microscope', \n", " description='My two-photon microscope',\n", " manufacturer='The best microscope manufacturer'\n", ")\n", "optical_channel = OpticalChannel(\n", " name='OpticalChannel', \n", " description='an optical channel', \n", " emission_lambda=500.\n", ")\n", "imaging_plane = nwbfile.create_imaging_plane(\n", " name='ImagingPlane',\n", " optical_channel=optical_channel,\n", " imaging_rate=30.,\n", " description='a very interesting part of the brain',\n", " device=device,\n", " excitation_lambda=600.,\n", " indicator='GFP',\n", " location='V1',\n", " grid_spacing=[.01, .01],\n", " grid_spacing_unit='meters',\n", " origin_coords=[1., 2., 3.],\n", " origin_coords_unit='meters'\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Two Photon Series\n", "Now that we have our `ImagingPlane`, we can create a `TwoPhotonSeries` object to hold our raw 2-photon imaging data. Here, we have two options. The first option is to supply the raw image data to PyNWB, using the `data` argument. The other option is the provide a path to the image files. These two options have trade-offs, so it is worth spending time considering how you want to store this data.\n", "\n", "" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "from pynwb.ophys import TwoPhotonSeries\n", "\n", "# using internal data. this data will be stored inside the NWB file\n", "image_series1 = TwoPhotonSeries(\n", " name='TwoPhotonSeries1',\n", " data=np.ones((1000,100,100)),\n", " imaging_plane=imaging_plane,\n", " rate=1.0,\n", " unit='normalized amplitude'\n", ")\n", "\n", "# using external data. just the file paths will be stored inside the NWB file\n", "image_series2 = TwoPhotonSeries(\n", " name='TwoPhotonSeries2', \n", " dimension=[100,100],\n", " external_file=['images.tiff'], \n", " imaging_plane=imaging_plane,\n", " starting_frame=[0], \n", " format='external', \n", " starting_time=0.0, \n", " rate=1.0\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since these 2-photon data are raw, acquired data, rather than putting the `TwoPhotonSeries` objects in a `ProcessingModule` in the `NWBFile`, like for the computed spatial position data earlier, we will add them to the file as acquired data." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "nwbfile.add_acquisition(image_series1)\n", "nwbfile.add_acquisition(image_series2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Plane Segmentation\n", "The `PlaneSegmentation` class stores the detected regions of interest in the `TwoPhotonSeries` data. `PlaneSegmentation` is a subclass of `DynamicTable`, where each row represents a single region of interest (ROI). \n", "\n", "\n", "\n", "The `ImageSegmentation` class can contain multiple `PlaneSegmentation` tables so that we can store the results of different segmentation algorithms or different segmentation classes.\n", "\n", "\n", "\n", "Create an `ImageSegmentation` object, and from that object, create a `PlaneSegmentation` tables with a link to the `ImagingPlane` created earlier. Then create a `ProcessingModule` named `'ophys'` to store optical physiology data and add the `ImageSegmentation` to it. This is similar to how we stored the `SpatialSeries` object inside of a `Position` object and stored the `Position` object in a `ProcessingModule` named `'behavior'` earlier." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "ImageSegmentation pynwb.ophys.ImageSegmentation at 0x2070078693000\n", "Fields:\n", " plane_segmentations: {\n", " PlaneSegmentation \n", " }" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pynwb.ophys import ImageSegmentation\n", "\n", "img_seg = ImageSegmentation()\n", "ps = img_seg.create_plane_segmentation(\n", " name='PlaneSegmentation',\n", " description='output from segmenting my favorite imaging plane',\n", " imaging_plane=imaging_plane,\n", " reference_images=image_series1 # optional\n", ")\n", "ophys_module = nwbfile.create_processing_module(\n", " name='ophys', \n", " description='optical physiology processed data'\n", ")\n", "ophys_module.add(img_seg)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Regions Of Interest (ROIs)\n", "#### Image masks\n", "You may add ROIs to the `PlaneSegmentation` table using an image mask or a pixel mask. An image mask is an array that is the same size as a single frame of the `TwoPhotonSeries` that indicates the mask weight of each pixel in the image. Image mask values (weights) may be boolean or continuous between 0 and 1." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "for _ in range(30):\n", " image_mask = np.zeros((100, 100))\n", " \n", " # randomly generate example image masks\n", " x = np.random.randint(0, 95)\n", " y = np.random.randint(0, 95)\n", " image_mask[x:x+5, y:y+5] = 1\n", " \n", " # add image mask to plane segmentation\n", " ps.add_roi(image_mask=image_mask)\n", " \n", "# show one of the image masks\n", "import matplotlib.pyplot as plt\n", "plt.imshow(image_mask)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Pixel masks\n", "Alternatively, you could define ROIs using a pixel mask, which is an array of triplets (x, y, weight) that have a non-zero weight. All undefined pixels are assumed to be 0. Whichever method you choose to define ROIs -- image mask or pixel mask, you need to be consistent within a `PlaneSegmentation` table; you cannot add some ROIs using `image_mask` and some using `pixel_mask`." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "ps2 = img_seg.create_plane_segmentation(\n", " name='PlaneSegmentation2',\n", " description='output from segmenting my favorite imaging plane',\n", " imaging_plane=imaging_plane,\n", " reference_images=image_series1 # optional\n", ")\n", "\n", "for _ in range(30):\n", " # randomly generate example image masks\n", " x = np.random.randint(0, 95)\n", " y = np.random.randint(0, 95)\n", " \n", " pixel_mask = []\n", " for ix in range(x, x+5):\n", " for iy in range(y, y+5):\n", " pixel_mask.append((ix, iy, 1))\n", " \n", " # add pixel mask to plane segmentation\n", " ps2.add_roi(pixel_mask=pixel_mask)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can view the `PlaneSegmentation` table with pixel masks in tabular form by converting it to a pandas dataframe." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pixel_mask
id
0[(57, 24, 1), (57, 25, 1), (57, 26, 1), (57, 2...
1[(82, 51, 1), (82, 52, 1), (82, 53, 1), (82, 5...
2[(23, 5, 1), (23, 6, 1), (23, 7, 1), (23, 8, 1...
3[(51, 63, 1), (51, 64, 1), (51, 65, 1), (51, 6...
4[(18, 63, 1), (18, 64, 1), (18, 65, 1), (18, 6...
5[(58, 30, 1), (58, 31, 1), (58, 32, 1), (58, 3...
6[(54, 75, 1), (54, 76, 1), (54, 77, 1), (54, 7...
7[(32, 45, 1), (32, 46, 1), (32, 47, 1), (32, 4...
8[(77, 25, 1), (77, 26, 1), (77, 27, 1), (77, 2...
9[(81, 69, 1), (81, 70, 1), (81, 71, 1), (81, 7...
10[(81, 38, 1), (81, 39, 1), (81, 40, 1), (81, 4...
11[(77, 91, 1), (77, 92, 1), (77, 93, 1), (77, 9...
12[(19, 82, 1), (19, 83, 1), (19, 84, 1), (19, 8...
13[(39, 53, 1), (39, 54, 1), (39, 55, 1), (39, 5...
14[(12, 92, 1), (12, 93, 1), (12, 94, 1), (12, 9...
15[(81, 61, 1), (81, 62, 1), (81, 63, 1), (81, 6...
16[(58, 56, 1), (58, 57, 1), (58, 58, 1), (58, 5...
17[(63, 77, 1), (63, 78, 1), (63, 79, 1), (63, 8...
18[(41, 27, 1), (41, 28, 1), (41, 29, 1), (41, 3...
19[(12, 57, 1), (12, 58, 1), (12, 59, 1), (12, 6...
20[(66, 70, 1), (66, 71, 1), (66, 72, 1), (66, 7...
21[(84, 84, 1), (84, 85, 1), (84, 86, 1), (84, 8...
22[(72, 65, 1), (72, 66, 1), (72, 67, 1), (72, 6...
23[(74, 40, 1), (74, 41, 1), (74, 42, 1), (74, 4...
24[(32, 85, 1), (32, 86, 1), (32, 87, 1), (32, 8...
25[(33, 85, 1), (33, 86, 1), (33, 87, 1), (33, 8...
26[(51, 1, 1), (51, 2, 1), (51, 3, 1), (51, 4, 1...
27[(55, 46, 1), (55, 47, 1), (55, 48, 1), (55, 4...
28[(27, 9, 1), (27, 10, 1), (27, 11, 1), (27, 12...
29[(62, 37, 1), (62, 38, 1), (62, 39, 1), (62, 4...
\n", "
" ], "text/plain": [ " pixel_mask\n", "id \n", "0 [(57, 24, 1), (57, 25, 1), (57, 26, 1), (57, 2...\n", "1 [(82, 51, 1), (82, 52, 1), (82, 53, 1), (82, 5...\n", "2 [(23, 5, 1), (23, 6, 1), (23, 7, 1), (23, 8, 1...\n", "3 [(51, 63, 1), (51, 64, 1), (51, 65, 1), (51, 6...\n", "4 [(18, 63, 1), (18, 64, 1), (18, 65, 1), (18, 6...\n", "5 [(58, 30, 1), (58, 31, 1), (58, 32, 1), (58, 3...\n", "6 [(54, 75, 1), (54, 76, 1), (54, 77, 1), (54, 7...\n", "7 [(32, 45, 1), (32, 46, 1), (32, 47, 1), (32, 4...\n", "8 [(77, 25, 1), (77, 26, 1), (77, 27, 1), (77, 2...\n", "9 [(81, 69, 1), (81, 70, 1), (81, 71, 1), (81, 7...\n", "10 [(81, 38, 1), (81, 39, 1), (81, 40, 1), (81, 4...\n", "11 [(77, 91, 1), (77, 92, 1), (77, 93, 1), (77, 9...\n", "12 [(19, 82, 1), (19, 83, 1), (19, 84, 1), (19, 8...\n", "13 [(39, 53, 1), (39, 54, 1), (39, 55, 1), (39, 5...\n", "14 [(12, 92, 1), (12, 93, 1), (12, 94, 1), (12, 9...\n", "15 [(81, 61, 1), (81, 62, 1), (81, 63, 1), (81, 6...\n", "16 [(58, 56, 1), (58, 57, 1), (58, 58, 1), (58, 5...\n", "17 [(63, 77, 1), (63, 78, 1), (63, 79, 1), (63, 8...\n", "18 [(41, 27, 1), (41, 28, 1), (41, 29, 1), (41, 3...\n", "19 [(12, 57, 1), (12, 58, 1), (12, 59, 1), (12, 6...\n", "20 [(66, 70, 1), (66, 71, 1), (66, 72, 1), (66, 7...\n", "21 [(84, 84, 1), (84, 85, 1), (84, 86, 1), (84, 8...\n", "22 [(72, 65, 1), (72, 66, 1), (72, 67, 1), (72, 6...\n", "23 [(74, 40, 1), (74, 41, 1), (74, 42, 1), (74, 4...\n", "24 [(32, 85, 1), (32, 86, 1), (32, 87, 1), (32, 8...\n", "25 [(33, 85, 1), (33, 86, 1), (33, 87, 1), (33, 8...\n", "26 [(51, 1, 1), (51, 2, 1), (51, 3, 1), (51, 4, 1...\n", "27 [(55, 46, 1), (55, 47, 1), (55, 48, 1), (55, 4...\n", "28 [(27, 9, 1), (27, 10, 1), (27, 11, 1), (27, 12...\n", "29 [(62, 37, 1), (62, 38, 1), (62, 39, 1), (62, 4..." ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ps2.to_dataframe()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Storing fluorescence measurements" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now that ROIs are stored, you can store fluorescence data for these ROIs. These type of data are stored using the `RoiResponseSeries` and `Fluorescence` classes, which work similarly to the `SpatialSeries` and `Position` classes, except these are specialized for optical physiology data.\n", "\n", "\n", "\n", "To create an `RoiResponseSeries` object, we will need to reference a set of rows from a `PlaneSegmentation` table to indicate which ROIs correspond to which rows of your recorded data matrix. This is done using a `DynamicTableRegion`, which is a type of link that allows you to reference specific rows of a `DynamicTable`, such as a `PlaneSegmentation` table, by row indices. \n", "\n", "Create a `DynamicTableRegion` that references the first two ROIs of the `PlaneSegmentation` table." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "rt_region = ps.create_roi_table_region(\n", " region=[0,1],\n", " description='the first of two ROIs'\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then create a `RoiResponseSeries` object to hold fluorescence data for those two ROIs." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "from pynwb.ophys import RoiResponseSeries\n", "\n", "roi_resp_series = RoiResponseSeries(\n", " name='RoiResponseSeries',\n", " data=np.ones((50,2)), # 50 samples, 2 rois\n", " rois=rt_region,\n", " unit='lumens',\n", " rate=30.\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To help data analysis and visualization tools know that this `RoiResponseSeries` object represents fluorescence data, store the `RoiResponseSeries` object inside of a `Fluorescence` object. Then place the `Fluorescence` object into the same `ProcessingModule` named `'ophys'` that we created earlier. \n", "\n", "" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Fluorescence pynwb.ophys.Fluorescence at 0x2070072290248\n", "Fields:\n", " roi_response_series: {\n", " RoiResponseSeries \n", " }" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pynwb.ophys import Fluorescence\n", "\n", "fl = Fluorescence(roi_response_series=roi_resp_series)\n", "ophys_module.add(fl)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you want to store dF/F data instead of fluorescence data, then store the `RoiResponseSeries` object in a `DfOverF` object instead of a `Fluorescence` object. The `DfOverF` class works the same way as the `Fluorescence` class. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Write the file" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "c:\\users\\ryan\\miniconda3\\envs\\latest\\lib\\site-packages\\hdmf\\build\\objectmapper.py:239: DtypeConversionWarning: Spec 'ImagingPlane/origin_coords': Value with data type int32 is being converted to data type float32 as specified.\n", " warnings.warn(full_warning_msg, DtypeConversionWarning)\n" ] } ], "source": [ "with NWBHDF5IO('ophys_tutorial.nwb', 'w') as io:\n", " io.write(nwbfile)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Read the NWB file\n", "\n", "We can access the raw data by indexing `nwbfile.acquisition` with a name of the `TwoPhotonSeries`, e.g., `'TwoPhotonSeries1'`. \n", "\n", "We can also access the fluorescence responses by indexing `nwbfile.processing` with the name of the processing module, \"ophys\". Then, we can access the `Fluorescence` object inside of the \"ophys\" processing module by indexing it with the name of the `Fluorescence` object. The default name of `Fluorescence` objects is \"Fluorescence\". \n", "\n", "Finally, we can access the `RoiResponseSeries` object inside of the `Fluorescence` object by indexing it with the name of the `RoiResponseSeries` object, which we named `'RoiResponseSeries'`." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "TwoPhotonSeries1 pynwb.ophys.TwoPhotonSeries at 0x2068077051016\n", "Fields:\n", " comments: no comments\n", " conversion: 1.0\n", " data: \n", " description: no description\n", " imaging_plane: ImagingPlane pynwb.ophys.ImagingPlane at 0x2068080938952\n", "Fields:\n", " conversion: 1.0\n", " description: a very interesting part of the brain\n", " device: Microscope pynwb.device.Device at 0x2068077268808\n", "Fields:\n", " description: My two-photon microscope\n", " manufacturer: The best microscope manufacturer\n", "\n", " excitation_lambda: 600.0\n", " imaging_rate: 30.0\n", " indicator: GFP\n", " location: V1\n", " optical_channel: (\n", " OpticalChannel \n", " )\n", " unit: meters\n", "\n", " rate: 1.0\n", " resolution: -1.0\n", " starting_time: 0.0\n", " starting_time_unit: seconds\n", " unit: normalized amplitude\n", "\n", "ophys pynwb.base.ProcessingModule at 0x2068077038216\n", "Fields:\n", " data_interfaces: {\n", " Fluorescence ,\n", " ImageSegmentation \n", " }\n", " description: optical physiology processed data\n", "\n", "Fluorescence pynwb.ophys.Fluorescence at 0x2068079620680\n", "Fields:\n", " roi_response_series: {\n", " RoiResponseSeries \n", " }\n", "\n", "RoiResponseSeries pynwb.ophys.RoiResponseSeries at 0x2068079624008\n", "Fields:\n", " comments: no comments\n", " conversion: 1.0\n", " data: \n", " description: no description\n", " rate: 30.0\n", " resolution: -1.0\n", " rois: rois \n", " starting_time: 0.0\n", " starting_time_unit: seconds\n", " unit: lumens\n", "\n" ] } ], "source": [ "with NWBHDF5IO('ophys_tutorial.nwb', 'r') as io:\n", " read_nwbfile = io.read()\n", " print(read_nwbfile.acquisition['TwoPhotonSeries1'])\n", " print(read_nwbfile.processing['ophys'])\n", " print(read_nwbfile.processing['ophys']['Fluorescence'])\n", " print(read_nwbfile.processing['ophys']['Fluorescence']['RoiResponseSeries'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Reading NWB data\n", "\n", "Data arrays are read passively from the file. Calling the `data` attribute on a `TimeSeries` such as an `RoiResponseSeries` or `SpatialSeries` does not read the data values, but presents an `h5py` object that can be indexed to read data. You can use the `[:]` operator to read the entire data array into memory.\n", "\n", "Load and print all the `data` values of the `RoiResponseSeries` object representing the fluorescence data." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "TwoPhotonSeries1 pynwb.ophys.TwoPhotonSeries at 0x2068076932680\n", "Fields:\n", " comments: no comments\n", " conversion: 1.0\n", " data: \n", " description: no description\n", " imaging_plane: ImagingPlane pynwb.ophys.ImagingPlane at 0x2070172429064\n", "Fields:\n", " conversion: 1.0\n", " description: a very interesting part of the brain\n", " device: Microscope pynwb.device.Device at 0x2070172426632\n", "Fields:\n", " description: My two-photon microscope\n", " manufacturer: The best microscope manufacturer\n", "\n", " excitation_lambda: 600.0\n", " imaging_rate: 30.0\n", " indicator: GFP\n", " location: V1\n", " optical_channel: (\n", " OpticalChannel \n", " )\n", " unit: meters\n", "\n", " rate: 1.0\n", " resolution: -1.0\n", " starting_time: 0.0\n", " starting_time_unit: seconds\n", " unit: normalized amplitude\n", "\n", "[[1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]]\n" ] } ], "source": [ "with NWBHDF5IO('ophys_tutorial.nwb', 'r') as io:\n", " read_nwbfile = io.read()\n", "\n", " print(read_nwbfile.acquisition['TwoPhotonSeries1'])\n", " print(read_nwbfile.processing['ophys']['Fluorescence']['RoiResponseSeries'].data[:])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Accessing data regions\n", "It is often preferable to read only a portion of the data. To do this, index or slice into the `data` attribute just like if you were indexing or slicing a numpy array.\n", "\n", "The following code prints elements 0:10 in the first dimension (time) and 0:3 (ROIs) in the second dimension from the fluorescence data we have written." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "section of fluorescence responses:\n", "[[1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]\n", " [1. 1.]]\n" ] } ], "source": [ "with NWBHDF5IO('ophys_tutorial.nwb', 'r') as io:\n", " read_nwbfile = io.read()\n", "\n", " print('section of fluorescence responses:')\n", " print(read_nwbfile.processing['ophys']['Fluorescence']['RoiResponseSeries'].data[0:10, 0:3])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Learn more!\n", "\n", "## Python tutorials\n", "### See our tutorials for more details about your data type:\n", "* [Extracellular electrophysiology](https://pynwb.readthedocs.io/en/stable/tutorials/domain/ecephys.html#sphx-glr-tutorials-domain-ecephys-py)\n", "* [Calcium imaging](https://pynwb.readthedocs.io/en/stable/tutorials/domain/ophys.html#sphx-glr-tutorials-domain-ophys-py)\n", "* [Intracellular electrophysiology](https://pynwb.readthedocs.io/en/stable/tutorials/domain/icephys.html#sphx-glr-tutorials-domain-icephys-py)\n", "\n", "### Check out other tutorials that teach advanced NWB topics:\n", "* [Iterative data write](https://pynwb.readthedocs.io/en/stable/tutorials/general/iterative_write.html#sphx-glr-tutorials-general-iterative-write-py)\n", "* [Extensions](https://pynwb.readthedocs.io/en/stable/tutorials/general/extensions.html#sphx-glr-tutorials-general-extensions-py)\n", "* [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", "\n", "\n", "## MATLAB tutorials\n", "* [Extracellular electrophysiology](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ecephys.html)\n", "* [Calcium imaging](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ophys.html)\n", "* [Intracellular electrophysiology](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/icephys.html)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.7" } }, "nbformat": 4, "nbformat_minor": 4 }