
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "generated/auto_examples/eeg2025/tutorial_eegdash_offline.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_generated_auto_examples_eeg2025_tutorial_eegdash_offline.py>`
        to download the full example code.

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_generated_auto_examples_eeg2025_tutorial_eegdash_offline.py:

============================
Working Offline with EEGDash
============================

Many HPC clusters restrict or block network access. It's common to have
dedicated queues for internet-enabled jobs that differ from GPU queues.
This tutorial shows how to use :doc:`EEGChallengeDataset
</api/dataset/eegdash.dataset.EEGChallengeDataset>` offline once a dataset is
present on disk.

.. GENERATED FROM PYTHON SOURCE LINES 11-29

.. code-block:: Python


    from pathlib import Path
    import platformdirs

    from eegdash.const import RELEASE_TO_OPENNEURO_DATASET_MAP
    from eegdash.dataset.dataset import EEGChallengeDataset


    # We'll use Release R2 as an example (HBN subset).
    # :doc:`EEGChallengeDataset </api/dataset/eegdash.dataset.EEGChallengeDataset>`
    # uses a suffixed cache folder for the competition data (e.g., "-bdf-mini").
    release = "R2"
    dataset_id = RELEASE_TO_OPENNEURO_DATASET_MAP[release]
    task = "RestingState"
    # Choose a cache directory. This should be on a fast local filesystem.
    cache_dir = Path(platformdirs.user_cache_dir("EEGDash"))
    cache_dir.mkdir(parents=True, exist_ok=True)


.. GENERATED FROM PYTHON SOURCE LINES 30-38

Step 1: Populate the local cache (Online)
-----------------------------------------
This block downloads the dataset from S3 to your local cache directory.
Run this part on a machine with internet access. If the dataset is already
on your disk at the specified ``cache_dir``, you can comment out or skip
this section.

To keep this example self-contained, we prefetch the data here.

.. GENERATED FROM PYTHON SOURCE LINES 38-52

.. code-block:: Python


    ds_online = EEGChallengeDataset(
        release=release,
        cache_dir=cache_dir,
        task=task,
        mini=True,
    )

    # Optional prefetch of all recordings (downloads everything to cache).
    from joblib import Parallel, delayed

    _ = Parallel(n_jobs=-1)(delayed(lambda d: d.raw)(d) for d in ds_online.datasets)



.. GENERATED FROM PYTHON SOURCE LINES 53-61

Step 2: Basic Offline Usage
---------------------------
Once the data is cached locally, you can interact with it without needing an
internet connection. The key is to instantiate your dataset object with the
``download=False`` flag. This tells :doc:`EEGChallengeDataset
</api/dataset/eegdash.dataset.EEGChallengeDataset>`
to look for data in the ``cache_dir`` instead of trying to connect to the
database or S3.

.. GENERATED FROM PYTHON SOURCE LINES 61-79

.. code-block:: Python



    # Here we check that the local cache folder exists
    offline_root = cache_dir / f"{dataset_id}-bdf-mini"
    print(f"Local dataset folder exists: {offline_root.exists()}\n{offline_root}")

    ds_offline = EEGChallengeDataset(
        release=release,
        cache_dir=cache_dir,
        task=task,
        download=False,
    )

    print(f"Found {len(ds_offline.datasets)} recording(s) offline.")
    if ds_offline.datasets:
        print("First record bidspath:", ds_offline.datasets[0].record["bidspath"])



.. GENERATED FROM PYTHON SOURCE LINES 80-87

Step 3: Filtering Entities Offline
----------------------------------
Even without a database connection, you can still filter your dataset by
BIDS entities like subject, session, or task. When ``download=False``,
:doc:`EEGChallengeDataset </api/dataset/eegdash.dataset.EEGChallengeDataset>`
uses the BIDS directory structure and filenames to apply these filters. This
example shows how to load data for a specific subject from the local cache.

.. GENERATED FROM PYTHON SOURCE LINES 87-105

.. code-block:: Python


    ds_offline_sub = EEGChallengeDataset(
        cache_dir=cache_dir,
        release=release,
        download=False,
        subject="NDARAB793GL3",
    )

    print(f"Filtered by subject=NDARAB793GL3: {len(ds_offline_sub.datasets)} recording(s).")
    if ds_offline_sub.datasets:
        keys = ("dataset", "subject", "task", "run")
        print("Records (dataset, subject, task, run):")
        for idx, base_ds in enumerate(ds_offline_sub.datasets, start=1):
            rec = base_ds.record
            summary = ", ".join(f"{k}={rec.get(k)}" for k in keys)
            print(f"  {idx:03d}: {summary}")



.. GENERATED FROM PYTHON SOURCE LINES 106-116

Step 4: Comparing Online vs. Offline Data
-----------------------------------------
As a sanity check, you can verify that the data loaded from your local cache
is identical to the data fetched from the online sources. This section
compares the shape of the raw data from the online and offline datasets to
ensure they match. This is a good way to confirm your local cache is complete
and correct.

If you have network access, you can uncomment the block below to download and
compare shapes.

.. GENERATED FROM PYTHON SOURCE LINES 116-123

.. code-block:: Python


    raw_online = ds_online.datasets[0].raw
    raw_offline = ds_offline.datasets[0].raw
    print("online shape:", raw_online.get_data().shape)
    print("offline shape:", raw_offline.get_data().shape)
    print("shapes equal:", raw_online.get_data().shape == raw_offline.get_data().shape)


.. GENERATED FROM PYTHON SOURCE LINES 124-129

Step 4.1: Comparing Descriptions, Online vs. Offline Data
---------------------------------------------------------

If you have network access, you can uncomment the block below to download and
compare shapes.

.. GENERATED FROM PYTHON SOURCE LINES 129-137

.. code-block:: Python

    description_online = ds_online.description
    description_offline = ds_offline.description
    print(description_offline)
    print(description_online)
    print("Online description shape:", description_online.shape)
    print("Offline description shape:", description_offline.shape)
    print("Descriptions equal:", description_online.equals(description_offline))


.. GENERATED FROM PYTHON SOURCE LINES 138-144

Notes and troubleshooting
-------------------------
- Working offline selects recordings by parsing BIDS filenames and directory
  structure. Some DB-only fields are unavailable; entity filters (subject,
  session, task, run) usually suffice.
- If you encounter issues, please open a GitHub issue so we can discuss.

**Estimated memory usage:**  0 MB


.. _sphx_glr_download_generated_auto_examples_eeg2025_tutorial_eegdash_offline.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: tutorial_eegdash_offline.ipynb <tutorial_eegdash_offline.ipynb>`

    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: tutorial_eegdash_offline.py <tutorial_eegdash_offline.py>`

    .. container:: sphx-glr-download sphx-glr-download-zip

      :download:`Download zipped: tutorial_eegdash_offline.zip <tutorial_eegdash_offline.zip>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_
