Exploring an NWB File#

It can get cumbersome to manually dissect an NWB file with print statements. There are a few ways to view an NWB file graphically instead. A great way to do this in a Jupyter notebook is with NWBWidgets. Here, you can use NWBWidgets to view a file from a location on your machine. If you don’t want to download a file just to view it, you can still use NWBWidgets to view it remotely. Check out Streaming an NWB File with remfile to learn how to do this. Another way to explore an NWB file, that doesn’t require Jupyter, is with HDFView.

Environment Setup#

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

import warnings
warnings.filterwarnings('ignore')

try:
    from databook_utils.dandi_utils import dandi_stream_open
except:
    !git clone https://github.com/AllenInstitute/openscope_databook.git
    %cd openscope_databook
    %pip install -e .
from dandi import dandiapi
from nwbwidgets import nwb2widget
from pynwb import NWBHDF5IO
from nwbwidgets.view import default_neurodata_vis_spec
import pynwb

Downloading an NWB File#

To examine an NWB File locally, it must first be downloaded. dandiset_id and dandi_filepath may be changed to select a different file off of DANDI. If the file of interest already downloaded, you don’t need to run the download cell again. When trying to download an embargoed file, refer to the code from the Downloading an NWB File notebook. In the cells below, the DANDI API is used to facilitate the download. The get_dandiset() methods retrieves a specific dataset within DANDI while the get_asset_by_path() method retrieves a specific file within that dataset.

dandiset_id = "000021"
dandi_filepath = "sub-699733573/sub-699733573_ses-715093703.nwb"
download_loc = "."
filename = dandi_filepath.split("/")[-1]
filepath = f"{download_loc}/{filename}"

print(filename)
print(filepath)
sub-699733573_ses-715093703.nwb
./sub-699733573_ses-715093703.nwb
client = dandiapi.DandiAPIClient()
my_dandiset = client.get_dandiset(dandiset_id)
file = my_dandiset.get_asset_by_path(dandi_filepath)

# this may take awhile, especially if the file to download is large
file.download(filepath)

print(f"Downloaded file to {filepath}")
Downloaded file to ./sub-699733573_ses-715093703.nwb

Displaying an NWB file#

When passing in the NWB object, the nwb2widget function will display the NWB file embedded in the notebook with each of the fields and subfields as a widget. NWB Files can vary a lot in their specific structure, so it can be important to familiarize yourself with the structure of the data you’re working with.

io = NWBHDF5IO(filepath, mode="r", load_namespaces=True)
nwb = io.read()

print(nwb)
root pynwb.file.NWBFile at 0x1933891341664
Fields:
  acquisition: {
    raw_running_wheel_rotation <class 'pynwb.base.TimeSeries'>,
    running_wheel_signal_voltage <class 'pynwb.base.TimeSeries'>,
    running_wheel_supply_voltage <class 'pynwb.base.TimeSeries'>
  }
  devices: {
    probeA <class 'abc.EcephysProbe'>,
    probeB <class 'abc.EcephysProbe'>,
    probeC <class 'abc.EcephysProbe'>,
    probeD <class 'abc.EcephysProbe'>,
    probeE <class 'abc.EcephysProbe'>,
    probeF <class 'abc.EcephysProbe'>
  }
  electrode_groups: {
    probeA <class 'abc.EcephysElectrodeGroup'>,
    probeB <class 'abc.EcephysElectrodeGroup'>,
    probeC <class 'abc.EcephysElectrodeGroup'>,
    probeD <class 'abc.EcephysElectrodeGroup'>,
    probeE <class 'abc.EcephysElectrodeGroup'>,
    probeF <class 'abc.EcephysElectrodeGroup'>
  }
  electrodes: electrodes <class 'hdmf.common.table.DynamicTable'>
  file_create_date: [datetime.datetime(2020, 5, 26, 0, 53, 26, 986608, tzinfo=tzoffset(None, -25200))]
  identifier: 715093703
  institution: Allen Institute for Brain Science
  intervals: {
    drifting_gratings_presentations <class 'pynwb.epoch.TimeIntervals'>,
    flashes_presentations <class 'pynwb.epoch.TimeIntervals'>,
    gabors_presentations <class 'pynwb.epoch.TimeIntervals'>,
    invalid_times <class 'pynwb.epoch.TimeIntervals'>,
    natural_movie_one_presentations <class 'pynwb.epoch.TimeIntervals'>,
    natural_movie_three_presentations <class 'pynwb.epoch.TimeIntervals'>,
    natural_scenes_presentations <class 'pynwb.epoch.TimeIntervals'>,
    spontaneous_presentations <class 'pynwb.epoch.TimeIntervals'>,
    static_gratings_presentations <class 'pynwb.epoch.TimeIntervals'>
  }
  invalid_times: invalid_times <class 'pynwb.epoch.TimeIntervals'>
  processing: {
    eye_tracking_rig_metadata <class 'pynwb.base.ProcessingModule'>,
    optotagging <class 'pynwb.base.ProcessingModule'>,
    running <class 'pynwb.base.ProcessingModule'>,
    stimulus <class 'pynwb.base.ProcessingModule'>
  }
  session_description: Data and metadata for an Ecephys session
  session_id: 715093703
  session_start_time: 2019-01-19 00:54:18-08:00
  stimulus_notes: brain_observatory_1.1
  subject: subject abc.EcephysSpecimen at 0x1933891341856
Fields:
  age: P118D
  age_in_days: 118.0
  genotype: Sst-IRES-Cre/wt;Ai32(RCL-ChR2(H134R)_EYFP)/wt
  sex: M
  species: Mus musculus
  specimen_name: Sst-IRES-Cre;Ai32-386129
  subject_id: 699733573

  timestamps_reference_time: 2019-01-19 00:54:18-08:00
  units: units <class 'pynwb.misc.Units'>
# hide the error options in the nwbwidget
neurodata_vis_spec = default_neurodata_vis_spec
units_display = default_neurodata_vis_spec[pynwb.misc.Units] 
keys_to_delete = {'Raster Grid','Tuning Curves','Combined','Grouped PSTH'}
for key in keys_to_delete:
    if key in units_display:
        del units_display[key]
neurodata_vis_spec[pynwb.misc.Units] = units_display
nwb2widget(nwb, neurodata_vis_spec)