Open In Colab

Installing requirements¶

The cell below installs every Python package needed to run this notebook, at fully pinned versions, using uv for fast resolution. In Colab the cell is collapsed by default — click the ▶ button to run it.

In [1]:
# install cell skipped during CI (deps preinstalled into system Python)

⚠️ Restart runtime after install

The install may upgrade packages already loaded in the kernel. Go to Runtime → Restart session, then Run all cells below (skip this install cell on re-run).

In [2]:
# This notebook compares the time taken to stream an NWB file from DANDI archive
# using lindi and fsspec. On my laptop on my home WiFi network, lindi streaming
# took 7.52 s and fsspec streaming took 141.01 s. This is expected to depend
# heavily on the network properties. For example on Dandihub, the times were
# ~3 s for lindi and ~12 s for fsspec.

import time
from pynwb import NWBHDF5IO
from dandi.dandiapi import DandiAPIClient
from fsspec import filesystem
from h5py import File
import lindi


def stream_nwbfile_lindi(DANDISET_ID, file_path):
    '''Stream NWB file from DANDI archive.

    Parameters
    ----------
    DANDISET_ID : str
        Dandiset ID
    file_path : str
        Path to NWB file in DANDI archive

    Returns
    -------
    nwbfile : NWBFile
        NWB file
    io : NWBHDF5IO
        NWB IO object (for closing)

    Notes
    -----
    The io object must be closed after use.
    '''
    with DandiAPIClient() as client:
        asset = client.get_dandiset(DANDISET_ID, 'draft').get_asset_by_path(file_path)
        asset_url = asset.get_content_url(follow_redirects=0, strip_query=True)
    file = lindi.LindiH5pyFile.from_hdf5_file(asset_url)
    io = NWBHDF5IO(file=file, load_namespaces=True)
    nwbfile = io.read()
    return nwbfile, io


def stream_nwbfile_fsspec(DANDISET_ID, file_path):
    '''Stream NWB file from DANDI archive.

    Parameters
    ----------
    DANDISET_ID : str
        Dandiset ID
    file_path : str
        Path to NWB file in DANDI archive

    Returns
    -------
    nwbfile : NWBFile
        NWB file
    io : NWBHDF5IO
        NWB IO object (for closing)

    Notes
    -----
    The io object must be closed after use.
    '''
    with DandiAPIClient() as client:
        asset = client.get_dandiset(DANDISET_ID, 'draft').get_asset_by_path(file_path)
        asset_url = asset.get_content_url(follow_redirects=0, strip_query=True)
    fs = filesystem("http")
    file_system = fs.open(asset_url, "rb")
    file = File(file_system, mode="r")
    io = NWBHDF5IO(file=file, load_namespaces=True)
    nwbfile = io.read()
    return nwbfile, io


DANDISET_ID = "000458"
file_path = "sub-586468/sub-586468_ses-20210819_behavior+ecephys.nwb"

timer = time.time()
nwbfile, io = stream_nwbfile_lindi(DANDISET_ID, file_path)
print(f"Elapsed time for lindi: {time.time() - timer:.2f} s")

timer = time.time()
nwbfile, io = stream_nwbfile_fsspec(DANDISET_ID, file_path)
print(f"Elapsed time for fsspec: {time.time() - timer:.2f} s")
Elapsed time for lindi: 7.10 s
Elapsed time for fsspec: 35.72 s
In [ ]: