diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index c4c1346..dd5297a 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -18,12 +18,12 @@ jobs:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Cache pip dependencies
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt', '**/pyproject.toml') }}
@@ -51,6 +51,12 @@ jobs:
# Test that the package can be imported after installation
python -c "from liveneuro import LiveNeuro, create_sample_brain_data; print('Package imports successful!')"
+ - name: Cache MNE datasets
+ uses: actions/cache@v4
+ with:
+ path: ~/mne_data
+ key: mne-data
+
- name: Run fast tests (Linux)
if: runner.os == 'Linux'
run: |
@@ -66,7 +72,7 @@ jobs:
- name: Upload coverage reports to Codecov
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.10'
- uses: codecov/codecov-action@v3
+ uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
flags: unittests
@@ -81,7 +87,7 @@ jobs:
- uses: actions/checkout@v4
- name: Set up Python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: "3.10"
diff --git a/docs/README.rst b/docs/README.rst
index 617cd98..7116b2a 100644
--- a/docs/README.rst
+++ b/docs/README.rst
@@ -30,7 +30,7 @@ Read the Docs
-------------
The documentation is automatically built and hosted on Read the Docs at:
-https://liveneuron.readthedocs.io
+https://liveneuro.readthedocs.io
The build is triggered automatically on every push to the main branch.
diff --git a/docs/api_reference.rst b/docs/api_reference.rst
index 48d475a..93c4fbd 100644
--- a/docs/api_reference.rst
+++ b/docs/api_reference.rst
@@ -1,7 +1,8 @@
API Reference
=============
-This page contains the complete API reference for LiveNeuro.
+This page documents the public LiveNeuro API. For guided examples, start with
+the :doc:`user_guide`.
Main Class
----------
@@ -11,51 +12,7 @@ Main Class
:exclude-members: __init__
:show-inheritance:
- The main visualization class for interactive 2D brain projections with activity time-course plots.
-
-Sample Data Module
-------------------
-
-.. autofunction:: liveneuro.create_sample_brain_data
-
-Data Format
+Sample Data
-----------
-Input Data Expectations
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-**Vector Data** (with direction and magnitude):
-
-* Eelbrain NDVar with dimensions: ``([case,] time, source, space)``
-* MNE ``VolVectorSourceEstimate`` with matching ``src`` SourceSpaces object
-* Built-in MNE sample data object returned by ``create_sample_brain_data()``
-
-**Scalar Data** (magnitude only):
-
-* Eelbrain NDVar with dimensions: ``([case,] time, source)``
-* Single value per source at each time point
-* Sample-data object returned by ``create_sample_brain_data(has_vector_data=False)``
-
-**Built-in Sample Data:**
-
-* 1589 sources in volumetric source space
-* 76 time points (-100ms to 400ms)
-* Vector data (3D current dipoles)
-
-Exceptions
-----------
-
-The library may raise the following exceptions:
-
-**ValueError**
- * Invalid ``display_mode`` string
- * Invalid ``layout_mode`` (not "vertical" or "horizontal" and not registered in LAYOUTS)
- * Invalid parameter values
-
-**ImportError**
- * Missing required dependencies
- * Eelbrain not installed when using eelbrain-specific features
-
-**RuntimeError**
- * Data processing errors
- * Visualization rendering errors
+.. autofunction:: liveneuro.create_sample_brain_data
diff --git a/docs/conf.py b/docs/conf.py
index db0f621..981d56f 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -26,7 +26,6 @@
"sphinx.ext.viewcode",
"sphinx.ext.intersphinx",
"sphinx.ext.autosummary",
- "myst_parser",
]
autodoc_mock_imports = [
@@ -44,24 +43,28 @@
]
templates_path = ["_templates"]
-exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
+exclude_patterns = [
+ "_build",
+ ".ipynb_checkpoints",
+ "README.rst",
+ "Thumbs.db",
+ ".DS_Store",
+]
# The suffix(es) of source filenames.
source_suffix = {
".rst": "restructuredtext",
- ".md": "markdown",
}
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme = "sphinx_rtd_theme"
-html_static_path = ["_static"]
+html_static_path = []
# Theme options
html_theme_options = {
"logo_only": False,
- "display_version": True,
"prev_next_buttons_location": "bottom",
"style_external_links": True,
"collapse_navigation": False,
@@ -99,19 +102,6 @@
"numpy": ("https://numpy.org/doc/stable/", None),
"matplotlib": ("https://matplotlib.org/stable/", None),
"plotly": ("https://plotly.com/python-api-reference/", None),
+ "mne": ("https://mne.tools/stable/", None),
+ "eelbrain": ("https://eelbrain.readthedocs.io/en/stable/", None),
}
-
-# MyST-Parser settings
-myst_enable_extensions = [
- "colon_fence",
- "deflist",
- "dollarmath",
- "fieldlist",
- "html_admonition",
- "html_image",
- "replacements",
- "smartquotes",
- "strikethrough",
- "substitution",
- "tasklist",
-]
diff --git a/docs/index.rst b/docs/index.rst
index 3961368..bf69b66 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,62 +1,41 @@
-Welcome to LiveNeuro's documentation!
-======================================
+.. raw:: html
-**LiveNeuro** is an interactive 2D brain visualization library using Plotly and Dash, designed for real-time exploration of neural activity data.
+
+
+
+
+
+
+LiveNeuro
+=========
.. image:: liveNeuron.png
:alt: LiveNeuro visualization overview
:align: center
:width: 720px
-.. image:: https://img.shields.io/badge/python-3.10%2B-blue
- :target: https://www.python.org/downloads/
- :alt: Python Version
-
-.. image:: https://img.shields.io/badge/license-MIT-green
- :target: https://opensource.org/licenses/MIT
- :alt: License
-
-.. image:: https://img.shields.io/badge/docs-ReadTheDocs-blue
- :target: https://liveneuron.readthedocs.io/en/latest/index.html
- :alt: Documentation
-
-Key Features
-------------
-
-* **Interactive 2D brain projections** - axial, sagittal, coronal, and hemisphere views
-* **Activity time-course plots** for time series visualization
-* **Optimized arrow rendering** for smoother interaction with dense vector fields
-* **Real-time controls** for time navigation and interaction
-* **Jupyter notebook support** for interactive development
-* **Customizable colormaps** and visualization options
-* **Export capabilities** for static images
-
-Quick Start
------------
-
-Installation
-^^^^^^^^^^^^
-
-**Install from GitHub**
-
-.. code-block:: bash
-
- pip install https://github.com/liang-bo96/LiveNeuro/archive/refs/heads/main.zip
-
-Basic Usage
-^^^^^^^^^^^
+**LiveNeuro** helps MNE-Python and Eelbrain users inspect volume source estimates
+as interactive 2D brain projections with linked time-course plots.
+It is built on Plotly and Dash, works in notebooks or a browser,
+and accepts MNE volume vector source estimates and :class:`eelbrain.NDVar` objects.
-.. code-block:: python
+Start Here
+----------
- from liveneuro import LiveNeuro
+* :ref:`installation`: create an environment and install LiveNeuro.
+* :ref:`quick-start`: open the built-in sample visualization.
+* :ref:`eelbrain-data-input`: plot an :class:`eelbrain.NDVar`.
+* :ref:`mne-data-input`: plot an :class:`mne.VolVectorSourceEstimate`.
+* :doc:`api_reference`: look up constructor parameters and public methods.
- # Create visualization with built-in MNE sample data
- viz = LiveNeuro()
-
- # Launch in interactive plot
- viz.run()
+Highlights
+----------
-For a full walkthrough of layouts and controls, start with the :doc:`user_guide`.
+* Linked activity time course with click-to-navigate updates.
+* Interactive sagittal, coronal, axial, and hemisphere projections.
+* Vector-field arrows with scale and threshold controls.
+* Notebook, JupyterLab, and external browser display modes.
+* Static export for figures and presentations.
.. toctree::
:maxdepth: 2
@@ -67,7 +46,7 @@ For a full walkthrough of layouts and controls, start with the :doc:`user_guide`
api_reference
Indices and tables
-==================
+------------------
* :ref:`genindex`
* :ref:`modindex`
diff --git a/docs/installation.rst b/docs/installation.rst
index 9e98f2b..dcf7a26 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -1,65 +1,75 @@
+.. _installation:
+
Installation
============
-Requirements
-------------
+LiveNeuro requires Python 3.10 or higher and the scientific Python stack used by
+MNE-Python and Eelbrain. For the most reliable setup, create an environment with
+``mamba`` or ``conda`` first, then install LiveNeuro with ``pip``.
+
+Create An Environment
+---------------------
+
+Follow the Eelbrain installation guide for platform-specific dependencies:
-LiveNeuro requires Python 3.10 or higher and an environment with Eelbrain
-available. The recommended procedure is to create an environment through
-``mamba`` following the official Eelbrain installation guide, then install
-LiveNeuro with ``pip``:
+* `Eelbrain installation guide `_
+
+For an existing conda-style environment, the minimum Eelbrain install is:
+
+.. code-block:: bash
-https://eelbrain.readthedocs.io/en/stable/installing.html
+ mamba install -c conda-forge eelbrain
-Install from GitHub
--------------------
+Install LiveNeuro
+-----------------
-Install directly from GitHub:
+Install the current development version directly from GitHub:
.. code-block:: bash
- pip install https://github.com/liang-bo96/LiveNeuro/archive/refs/heads/main.zip
+ pip install https://github.com/Eelbrain/LiveNeuro/archive/refs/heads/main.zip
-Verify Installation
--------------------
+Verify The Install
+------------------
-To verify the installation, run:
+Run a short import check:
.. code-block:: python
from liveneuro import LiveNeuro
- print("LiveNeuro installed successfully!")
-
-Troubleshooting
----------------
-Common Issues
-^^^^^^^^^^^^^
+ viz = LiveNeuro()
+ print("LiveNeuro is ready.")
-**ImportError: No module named 'liveneuro'**
+Then continue with :ref:`quick-start`.
-Make sure you have installed the package correctly. Try:
+.. _installation-troubleshooting:
-.. code-block:: bash
+Installation Troubleshooting
+----------------------------
- pip install --upgrade "https://github.com/liang-bo96/LiveNeuro/archive/refs/heads/main.zip"
+``ImportError: No module named 'liveneuro'``
+ Confirm that the environment running Python is the same one where LiveNeuro
+ was installed, then reinstall or upgrade:
-**Plotly/Dash version conflicts**
+ .. code-block:: bash
-If you encounter version conflicts, try:
+ pip install --upgrade "https://github.com/Eelbrain/LiveNeuro/archive/refs/heads/main.zip"
-.. code-block:: bash
+Missing Eelbrain or scientific dependencies
+ Revisit the Eelbrain installation guide, or install Eelbrain from
+ conda-forge:
- pip install --upgrade plotly dash
+ .. code-block:: bash
-**Missing dependencies**
+ mamba install -c conda-forge eelbrain
-If Eelbrain is missing or not importable, revisit the Eelbrain installation
-guide for platform-specific environment setup.
+Plotly or Dash version conflicts
+ Upgrade the interactive plotting dependencies inside the active environment:
-.. code-block:: bash
+ .. code-block:: bash
- mamba install -c conda-forge eelbrain
+ pip install --upgrade plotly dash
-For editable installs, test commands, and repository structure, see the
-repository ``README.md``.
+For editable installs, tests, and repository structure, see the repository
+``README.md``.
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 79e7c9c..3f3cda0 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -2,7 +2,5 @@
sphinx>=7.0.0
sphinx-rtd-theme>=1.3.0
sphinx-autodoc-typehints>=1.24.0
-myst-parser>=2.0.0
-
diff --git a/docs/user_guide.rst b/docs/user_guide.rst
index 5193a9b..c61437f 100644
--- a/docs/user_guide.rst
+++ b/docs/user_guide.rst
@@ -1,406 +1,44 @@
User Guide
==========
-This comprehensive guide covers all features and configuration options of LiveNeuro based on the actual implementation.
-
-Getting Started
----------------
-
-Basic Workflow
-^^^^^^^^^^^^^^
-
-1. **Create** visualization object with desired parameters
-2. **Launch** with ``run()``
-3. **Interact** with hover, click, and zoom
-4. **Export** static images if needed
-
-.. code-block:: python
-
- from liveneuro import LiveNeuro
-
- # Step 1: Create
- viz = LiveNeuro(display_mode="lyr")
-
- # Step 2: Launch
- viz.run() # Auto inline in Jupyter; external browser otherwise
-
- # Step 3: Interact (in browser/notebook)
- # Step 4: Export
- viz.export_images(output_dir="./plots", time_idx=30)
-
-Run Modes
----------
+LiveNeuro turns source-space time series into an interactive Dash application:
+a time-course plot controls one or more 2D brain projections, and each
+projection updates as you move through time.
.. note::
- In IPython shells (outside notebooks), explicitly pass ``mode="external"`` to
- ``run()`` to start a visualization that can be accessed in a browser.
-* **Interpreter / shell**: uses built-in MNE sample data if ``y`` is omitted; launches a server on a random port (explicit ``mode="external"`` recommended).
-
- .. code-block:: python
-
- viz = LiveNeuro()
- viz.run(mode="external")
-
-* **Notebook**: auto-selects ``mode="inline"`` (embedded IFrame). Choose explicitly if you want a browser or a Lab tab.
-
- .. code-block:: python
-
- viz = LiveNeuro()
- viz.run() # inline by default in notebooks; use mode="external" for shells
- # viz.run(mode="jupyterlab") # open in JupyterLab tab
- # viz.run(mode="external") # force external browser
-
-Understanding Display Modes
-----------------------------
-
-Display modes control which anatomical views are shown and in what order.
-
-Anatomical Coordinate System
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-* **X-axis (Sagittal)**: Side view, left-right through brain
-* **Y-axis (Coronal)**: Front view, front-back through brain
-* **Z-axis (Axial)**: Top view, top-bottom through brain
-* **L**: Left hemisphere lateral view
-* **R**: Right hemisphere lateral view
-
-Single View Modes
-^^^^^^^^^^^^^^^^^
-
-Use single letters for individual views:
-
-.. code-block:: python
-
- viz = LiveNeuro(display_mode="x") # Sagittal only
- viz = LiveNeuro(display_mode="y") # Coronal only
- viz = LiveNeuro(display_mode="z") # Axial only
- viz = LiveNeuro(display_mode="l") # Left hemisphere only
- viz = LiveNeuro(display_mode="r") # Right hemisphere only
-
-Multi-View Modes
-^^^^^^^^^^^^^^^^
-
-Combine letters for multiple views:
-
-.. code-block:: python
-
- # Orthogonal views (special keyword)
- viz = LiveNeuro(display_mode="ortho") # x + y + z
-
- # Hemisphere combinations
- viz = LiveNeuro(display_mode="lr") # Left + Right
- viz = LiveNeuro(display_mode="lyr") # Left + Coronal + Right (default)
- viz = LiveNeuro(display_mode="lzr") # Left + Axial + Right
-
- # Axis combinations
- viz = LiveNeuro(display_mode="xz") # Sagittal + Axial
- viz = LiveNeuro(display_mode="yx") # Coronal + Sagittal
- viz = LiveNeuro(display_mode="yz") # Coronal + Axial
-
-Four-View Modes
-^^^^^^^^^^^^^^^
-
-For comprehensive anatomical coverage:
-
-.. code-block:: python
-
- # Four views in different orders
- viz = LiveNeuro(display_mode="lyrz") # L + Coronal + R + Axial
- viz = LiveNeuro(display_mode="lzry") # L + Axial + R + Coronal
-
-**Note:** Order of letters determines display order of anatomical projections (left-to-right).
-
-Layout Modes
-------------
-
-Vertical Layout (Default)
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-**When to use:**
-
-* General use, including 1–4 projections
-* When the detailed activity time course should be prominent
-* When you want more horizontal space per projection
-
-**Characteristics:**
-
-* Detailed activity time course on top
-* Brain projections arranged beneath
-* Good for multiple projections while preserving horizontal space
-
-.. code-block:: python
-
- viz = LiveNeuro(
- display_mode="lyr",
- layout_mode="vertical" # Default
- )
-
-Horizontal Layout
-^^^^^^^^^^^^^^^^^
-
-**When to use:**
-
-* Wide screens or presentations
-* When spatial layout (left-to-right comparison) is the focus
-
-**Characteristics:**
-
-* Detailed activity time course on the left
-* Brain projections arranged to the right
-
-
-.. code-block:: python
-
- viz = LiveNeuro(
- display_mode="lyrz",
- layout_mode="horizontal"
- )
-
-Arrow Visualization
--------------------
-
-Understanding Arrows
-^^^^^^^^^^^^^^^^^^^^
-
-Arrows represent vector fields in brain data:
-
-* **Direction**: Shows orientation of activity (e.g., current flow)
-* **Length**: Indicates magnitude (controlled by ``arrow_scale``)
-* **Visibility**: Filtered by ``arrow_threshold``
-
-Arrow Scale Parameter
-^^^^^^^^^^^^^^^^^^^^^
-
-The ``arrow_scale`` parameter (default: 1.0) controls arrow length:
-
-.. code-block:: python
-
- # Short arrows for dense data
- viz = LiveNeuro(arrow_scale=0.5)
-
- # Default balanced length
- viz = LiveNeuro(arrow_scale=1.0)
-
- # Long arrows for sparse data
- viz = LiveNeuro(arrow_scale=2.0)
-
-**Recommendations:**
-
-* Dense vector fields: 0.5 - 0.8
-* Moderate density: 1.0 (default)
-* Sparse fields: 1.2 - 2.0
-
-Arrow Threshold Parameter
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The ``arrow_threshold`` parameter filters arrows by magnitude:
-
-.. code-block:: python
-
- # Show all arrows
- viz = LiveNeuro(arrow_threshold=None)
-
- # Auto threshold (10% of maximum magnitude)
- viz = LiveNeuro(arrow_threshold='auto')
-
- # Custom threshold
- viz = LiveNeuro(arrow_threshold=0.15)
-
-**When to use:**
-
-* ``None``: Small datasets or when all vectors are important
-* ``'auto'``: Good default for most cases
-* *float*: Fine-tune based on data characteristics
-
-Combined Arrow Optimization
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-For best results, combine both parameters:
-
-.. code-block:: python
-
- # Dense data with many small vectors
- viz = LiveNeuro(
- arrow_scale=0.7,
- arrow_threshold='auto'
- )
-
- # Sparse data with clear patterns
- viz = LiveNeuro(
- arrow_scale=1.5,
- arrow_threshold=0.05
- )
-
-Color Mapping
--------------
-
-Built-in Colormaps
-^^^^^^^^^^^^^^^^^^
-
-LiveNeuro supports Plotly's built-in colorscales:
-
-.. code-block:: python
-
- # Sequential colormaps
- viz = LiveNeuro(cmap='YlOrRd') # Yellow-Orange-Red (default)
- viz = LiveNeuro(cmap='Hot') # Hot (red/orange/yellow)
- viz = LiveNeuro(cmap='Viridis') # Perceptually uniform
- viz = LiveNeuro(cmap='OrRd') # Orange-Red
- viz = LiveNeuro(cmap='Reds') # Red scale
-
-See https://plotly.com/python/builtin-colorscales/ for all options.
-
-Custom Colormaps
-^^^^^^^^^^^^^^^^
-
-Create custom colorscales with transparency:
-
-.. code-block:: python
-
- # Custom gradient with transparency
- custom_cmap = [
- [0, 'rgba(255,255,0,0.5)'], # Yellow, 50% transparent
- [0.5, 'rgba(255,165,0,0.8)'], # Orange, 80% opaque
- [1, 'rgba(255,0,0,1.0)'] # Red, fully opaque
- ]
-
- viz = LiveNeuro(cmap=custom_cmap)
-
-**Color Range:**
-
-* Automatically scaled to data range (min to max)
-* Consistent across all views and time points
-* Unified colorbar shows current scaling
-* Override manually with ``vmin`` / ``vmax`` to lock the range
-
-.. code-block:: python
-
- viz = LiveNeuro(vmin=-2.0, vmax=2.0)
+ Examples in this guide assume notebook use, where
+ :meth:`liveneuro.LiveNeuro.run` displays the app inline. See
+ :ref:`run-modes` for browser, JupyterLab, and fixed-port options.
-Activity Time Course Plot Modes
---------------------
+.. _quick-start:
-Full Mode (Default)
-^^^^^^^^^^^^^^^^^^^
+Quick Start
+-----------
-Shows a sampled set of source traces plus statistics (random subset for readability):
+Start with the built-in sample data to check that the app opens correctly:
.. code-block:: python
- viz = LiveNeuro(show_max_only=False)
-
-**Displays:**
-
-* Random subset of source activity traces
-* Mean activity
-* Maximum activity across all sources
-
-Simplified Mode
-^^^^^^^^^^^^^^^
-
-Shows only summary statistics:
-
-.. code-block:: python
-
- viz = LiveNeuro(show_max_only=True)
-
-**Displays:**
-
-* Mean activity
-* Maximum activity
-
-**When to use:**
-
-* You want a clean summary without individual traces
-* Presentations or screenshots where mean/max is enough
-
-Interactive Features
---------------------
-
-Hover Information
-^^^^^^^^^^^^^^^^^
-
-**Brain Plots:**
-
-* Hover over any voxel to see activity value
-* Shows magnitude at current time point
-
-**Detailed activity time course:**
-
-* Hover over time axis to see max and min activity
-* Displays values for all visible traces
-
-Time Navigation
-^^^^^^^^^^^^^^^
-
-**Click to Navigate:**
-
-* Click anywhere on the time-course axis
-* Brain views instantly update to that time point
-* Precise time selection with spike indicator
-
-
-Zoom and Pan
-^^^^^^^^^^^^
-
-**Mouse Controls:**
-
-* **Mouse Wheel**: Zoom in/out
-* **Click + Drag**: Box zoom (default drag mode)
-* **Pan**: Select the pan tool in the toolbar, then drag to move the view
-* **Double-click**: Reset to original view
-
-
-Data Input
-----------
-
-Using Built-in MNE Sample Data
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Simplest option for testing and learning:
-
-.. code-block:: python
-
- # Use built-in MNE sample data
- viz = LiveNeuro(y=None)
-
-**Characteristics:**
-
-* 1589 sources in volumetric source space
-* 76 time points (-100ms to 400ms)
-* Vector data (3D current dipoles)
-* Requires Eelbrain installed
+ from liveneuro import LiveNeuro
-Using Eelbrain NDVar
-^^^^^^^^^^^^^^^^^^^^^
+ viz = LiveNeuro()
+ viz.run()
-For your own data:
+Use :meth:`liveneuro.LiveNeuro.export_images` when you want static output:
.. code-block:: python
- from eelbrain import datasets
- from liveneuro import LiveNeuro
-
- # Load Eelbrain data
- data_ds = datasets.get_mne_sample(src='vol', ori='vector')
- y = data_ds['src'] # NDVar with dimensions (case, time, source, space)
-
- # Visualize
- viz = LiveNeuro(y=y)
-
-**Expected Dimensions:**
+ viz.export_images(output_dir="./plots", time_idx=30)
-* Vector data: ``([case,] time, source, space)``
-* Scalar data: ``([case,] time, source)``
-* If case dimension present: mean is computed automatically
+.. _mne-data-input:
-Using MNE VolVectorSourceEstimate
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Using MNE Data
+--------------
-For MNE volume vector source estimates, pass the source estimate together with
-the matching source space. The source estimate provides vector data and time
-values; the source space provides the 3D coordinates needed for projections.
+For MNE users, the most direct input is a volume vector source estimate together
+with the matching source space. The source estimate supplies the data and time
+values; the source space supplies the 3D coordinates needed for projection.
.. code-block:: python
@@ -421,7 +59,6 @@ values; the source space provides the 3D coordinates needed for projections.
baseline=(None, 0),
proj=True,
)
-
inverse_operator = read_inverse_operator(
data_dir / "sample_audvis-meg-vol-7-meg-inv.fif"
)
@@ -437,239 +74,287 @@ values; the source space provides the 3D coordinates needed for projections.
)
viz = LiveNeuro(y=stc, src=src)
+ viz.run()
+``src`` is required for MNE source estimates. LiveNeuro needs source-space
+coordinates for the 2D projections, while the MNE source estimate stores vertex
+ids and data values. Scalar MNE :class:`mne.VolSourceEstimate` objects are not
+currently accepted directly; use a vector
+:class:`mne.VolVectorSourceEstimate` or convert scalar source data to an
+Eelbrain :class:`eelbrain.NDVar`.
-Running the Application
------------------------
+.. _eelbrain-data-input:
-Browser Mode
-^^^^^^^^^^^^^^^^^^^^^^^
+Using Eelbrain Data
+-------------------
-Opens in external browser:
+LiveNeuro also accepts Eelbrain :class:`eelbrain.NDVar` objects:
.. code-block:: python
- viz = LiveNeuro()
- viz.run(mode="external") # Random port; defaults to inline in notebooks, external browser otherwise
-
- # Or specify port
- viz.run(port=8888, mode="external") # Force browser if inline is detected
-
-
-Jupyter Modes (Default)
-^^^^^^^^^^^^^
+ from eelbrain import datasets
+ from liveneuro import LiveNeuro
-Multiple options for Jupyter notebooks:
+ data = datasets.get_mne_sample(src="vol", ori="vector")
+ y = data["src"]
-.. code-block:: python
-
- # Inline display (embedded in notebook) - auto size
+ viz = LiveNeuro(y=y)
viz.run()
- # JupyterLab tab (opens in separate tab)
- viz.run(mode='jupyterlab')
+Expected dimensions are ``([case,] time, source, space)`` for vector data and
+``([case,] time, source)`` for scalar data. If a case dimension is present,
+LiveNeuro plots the case average.
+Concepts
+--------
-Exporting Images
-----------------
+Source estimates
+ LiveNeuro visualizes source activity over time. For MNE inputs, pass a
+ volume vector source estimate such as
+ :class:`mne.VolVectorSourceEstimate`.
-Basic Export
-^^^^^^^^^^^^
+Source spaces
+ The matching MNE :class:`mne.SourceSpaces` object provides the source
+ coordinates. This is why MNE inputs use ``LiveNeuro(y=stc, src=src)``.
-Export current view as static image:
+Vector and scalar data
+ Vector data has a 3D orientation at each source and time point. LiveNeuro
+ shows its magnitude as color and its orientation as arrows. Supported scalar
+ :class:`eelbrain.NDVar` data is shown as magnitude only.
-.. code-block:: python
+Time course and projections
+ The time-course plot summarizes activity across sources. Clicking a time
+ point updates each brain projection to that time.
- result = viz.export_images(
- output_dir="./images",
- time_idx=30,
- format="png"
- )
+.. _run-modes:
- if result["status"] == "success":
- for plot_type, filepath in result["files"].items():
- print(f"{plot_type}: {filepath}")
+Running The Application
+-----------------------
-**Exports:**
+:meth:`liveneuro.LiveNeuro.run` starts the Dash application. The common modes are:
-* All brain projection views
-* Activity Time Course plot
-* Separate files for each
+.. list-table::
+ :header-rows: 1
-Supported Formats
-^^^^^^^^^^^^^^^^^
+ * - Mode
+ - Use
+ - Example
+ * - ``external``
+ - Browser tab from a script, shell, or notebook.
+ - ``viz.run(mode="external")``
+ * - ``inline``
+ - Embedded output in a notebook.
+ - ``viz.run(mode="inline")``
+ * - ``jupyterlab``
+ - Separate JupyterLab tab.
+ - ``viz.run(mode="jupyterlab")``
-.. code-block:: python
+Use a fixed port when you need a predictable URL:
- # PNG (default, best for presentations)
- viz.export_images(format="png")
+.. code-block:: python
- # JPEG (smaller file size)
- viz.export_images(format="jpg")
+ viz.run(port=8888, mode="external")
- # SVG (vector, scalable)
- viz.export_images(format="svg")
+.. _display-modes:
- # PDF (publication quality)
- viz.export_images(format="pdf")
+Display Modes
+-------------
-Performance Optimization
-------------------------
+``display_mode`` controls which anatomical projections are shown and in what
+order. The default is ``"lyr"``: left hemisphere, coronal, right hemisphere.
+
+.. list-table::
+ :header-rows: 1
+
+ * - Value
+ - Views
+ - Typical use
+ * - ``"lyr"``
+ - Left, coronal, right
+ - Default hemisphere comparison.
+ * - ``"lr"``
+ - Left and right
+ - Compact hemisphere view.
+ * - ``"ortho"``
+ - Sagittal, coronal, axial
+ - MNE-style orthogonal overview.
+ * - ``"x"``, ``"y"``, ``"z"``
+ - One sagittal, coronal, or axial view
+ - Focused inspection.
+ * - ``"lyrz"`` or ``"lzry"``
+ - Four views
+ - Broader anatomical coverage.
+
+Letters determine display order, so ``"xz"`` and ``"zx"`` use the same two
+views in a different order.
+
+.. _layout-modes:
-For Large Datasets
-^^^^^^^^^^^^^^^^^^
+Layout Modes
+------------
-1. **Use arrow threshold**:
+``layout_mode`` controls where the time course appears relative to the brain
+views. The implementation default is ``"horizontal"``.
- .. code-block:: python
+.. list-table::
+ :header-rows: 1
- viz = LiveNeuro(arrow_threshold='auto')
+ * - Value
+ - Layout
+ - Good for
+ * - ``"horizontal"``
+ - Time course on the left, brain views on the right.
+ - Wide screens, notebooks, and side-by-side comparison.
+ * - ``"vertical"``
+ - Time course above the brain views.
+ - More horizontal space per brain projection.
-2. **Simplify detailed activity time course**:
+Example:
- .. code-block:: python
+.. code-block:: python
- viz = LiveNeuro(show_max_only=True)
+ viz = LiveNeuro(display_mode="lyrz", layout_mode="horizontal")
-3. **Use focused display modes**:
+.. _visual-controls:
- .. code-block:: python
+Visual Controls
+---------------
- viz = LiveNeuro(display_mode="lr") # Fewer views
+Arrow controls
+^^^^^^^^^^^^^^
-Combined Optimization
-^^^^^^^^^^^^^^^^^^^^^
+For vector data, arrows show orientation and color shows magnitude.
+``arrow_scale`` changes arrow length; ``arrow_threshold`` hides lower-magnitude
+vectors.
.. code-block:: python
- # Optimized for large dataset
viz = LiveNeuro(
- display_mode="lr", # Only 2 views
- layout_mode="horizontal", # Better layout
- arrow_scale=0.7, # Smaller arrows
- arrow_threshold='auto', # Filter weak vectors
- show_max_only=True, # Simplified time course
- cmap='Hot'
+ arrow_scale=0.7,
+ arrow_threshold="auto",
)
-Best Practices
---------------
+Use ``arrow_threshold="auto"`` to hide vectors below 10% of the maximum
+magnitude. Use ``None`` when you want to see every vector.
-For Presentations
-^^^^^^^^^^^^^^^^^
+Color mapping
+^^^^^^^^^^^^^
-.. code-block:: python
+``cmap`` accepts Plotly colorscale names or custom colorscale lists:
- viz = LiveNeuro(
- display_mode="lyr", # Standard comparison view
- layout_mode="horizontal", # Wide screen friendly
- arrow_scale=1.2, # Slightly larger arrows
- arrow_threshold='auto', # Clean visualization
- show_max_only=True, # Focus on patterns
- cmap='Hot' # High contrast
- )
+.. code-block:: python
- viz.run(mode='external') # Full screen
+ viz = LiveNeuro(cmap="Viridis")
-For Publications
-^^^^^^^^^^^^^^^^
+LiveNeuro uses a consistent color range across views and time points. Set
+``vmin`` and ``vmax`` when you need fixed limits across figures:
.. code-block:: python
- viz = LiveNeuro(
- display_mode="lyr",
- arrow_scale=1.0,
- arrow_threshold='auto',
- cmap='YlOrRd' # Publication-friendly
- )
+ viz = LiveNeuro(vmin=-2.0, vmax=2.0)
- # Export high-quality images
- viz.export_images(
- output_dir="./publication_figures",
- time_idx=30,
- format="pdf" # Vector format for publications
- )
+See `Plotly built-in colorscales `_
+for available color names.
+
+Time-course detail
+^^^^^^^^^^^^^^^^^^
-For Interactive Exploration
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+By default, the time-course plot shows a sampled set of source traces plus mean
+and maximum activity. Use ``show_max_only=True`` for a cleaner summary:
.. code-block:: python
- viz = LiveNeuro(
- display_mode="lyrz", # Comprehensive views
- layout_mode="horizontal", # Better for exploration
- arrow_scale=1.0,
- arrow_threshold=None, # See all vectors initially
- show_max_only=False, # Full time-course information
- cmap='Viridis'
- )
+ viz = LiveNeuro(show_max_only=True)
- viz.run() # Enable debug with debug=True when troubleshooting
+Interacting With The Visualization
+----------------------------------
-Troubleshooting
----------------
+* Hover over brain projections to inspect activity at the current time point.
+* Click the time-course plot to update all brain views.
+* Use mouse wheel zoom, box zoom, pan, and double-click reset from the Plotly
+ toolbar.
-Common Issues
-^^^^^^^^^^^^^
+.. _export-images:
-**Issue: Random port is inconvenient**
+Exporting Images
+----------------
-Solution:
+:meth:`liveneuro.LiveNeuro.export_images` saves each brain projection and the
+time-course plot as separate image files:
.. code-block:: python
- viz.run(port=8888) # Use fixed port
+ result = viz.export_images(
+ output_dir="./images",
+ time_idx=30,
+ format="png",
+ )
-**Issue: Arrows too dense or unclear**
+Supported formats include ``"png"``, ``"jpg"``, ``"svg"``, and ``"pdf"``.
+Kaleido is required for static export and is included in the package
+dependencies.
-Solution:
+.. _performance:
+
+Performance
+-----------
+
+For larger datasets, reduce the number of rendered traces and arrows before
+reducing the data itself:
.. code-block:: python
viz = LiveNeuro(
- arrow_scale=0.7, # Reduce size
- arrow_threshold='auto' # Filter weak ones
+ display_mode="lr",
+ arrow_scale=0.7,
+ arrow_threshold="auto",
+ show_max_only=True,
)
-**Issue: Detailed activity time course too cluttered**
-
-Solution:
+These settings render fewer brain views, hide low-magnitude arrows, and keep the
+time course focused on summary traces.
-.. code-block:: python
-
- viz = LiveNeuro(show_max_only=True)
+.. _troubleshooting:
-**Issue: Slow performance**
+Troubleshooting
+---------------
-Solution:
+Installation problems
+ See :ref:`installation-troubleshooting`.
-.. code-block:: python
+Missing or invalid ``src`` with MNE data
+ MNE source estimates store data and vertex ids, but LiveNeuro also needs the
+ matching source-space coordinates. Pass the source space used to create the
+ estimate: ``LiveNeuro(y=stc, src=src)``. See :ref:`mne-data-input`.
- viz = LiveNeuro(
- display_mode="lr", # Fewer views
- arrow_threshold='auto', # Fewer arrows
- show_max_only=True # Simpler time course
- )
+Scalar MNE :class:`mne.VolSourceEstimate` input fails
+ LiveNeuro currently accepts MNE :class:`mne.VolVectorSourceEstimate` objects
+ directly, not scalar :class:`mne.VolSourceEstimate` objects. Convert scalar
+ source data to an Eelbrain :class:`eelbrain.NDVar` or use a vector source
+ estimate.
-**Issue: Export fails**
+Invalid ``display_mode`` or ``layout_mode``
+ Check :ref:`display-modes` and :ref:`layout-modes` for supported values.
-Check:
+The browser URL changes on each run
+ Pass a fixed port, for example ``viz.run(port=8888, mode="external")``.
-1. Output directory exists or can be created
-2. Kaleido is installed (included in dependencies, upgrade if needed): ``pip install -U kaleido``
-3. Sufficient disk space
+Arrows are too dense
+ Use ``arrow_threshold="auto"`` and reduce ``arrow_scale``.
-Debug Mode
-^^^^^^^^^^
+The time-course plot is too cluttered
+ Use ``show_max_only=True``.
-Debug mode is off by default for a clean UI. Enable it when troubleshooting:
+Export fails
+ Confirm that the output directory is writable and that Kaleido is installed
+ in the active environment.
-.. code-block:: python
+More diagnostic output
+ Run with ``debug=True``:
- viz.run(debug=True)
+ .. code-block:: python
-This provides:
+ viz.run(debug=True)
-* Detailed console output
-* Error tracebacks
-* Performance information
+For constructor parameters and method signatures, see
+:class:`liveneuro.LiveNeuro` in the :doc:`api_reference`.
diff --git a/src/liveneuro/_liveneuro.py b/src/liveneuro/_liveneuro.py
index 0b9c47e..8b02248 100644
--- a/src/liveneuro/_liveneuro.py
+++ b/src/liveneuro/_liveneuro.py
@@ -2,8 +2,9 @@
LiveNeuro core module.
This module provides the core LiveNeuro class, an interactive 2D visualization
-interface for Eelbrain's NDVar and MNE source estimate data structures. It
-transforms neuroscience data into explorable brain maps and time-series plots.
+interface for Eelbrain's :class:`eelbrain.NDVar` and MNE source estimate data
+structures. It transforms neuroscience data into explorable brain maps and
+time-series plots.
"""
from __future__ import annotations
@@ -33,8 +34,9 @@ class LiveNeuro:
If ``y`` has a case dimension, the mean is plotted.
If ``y`` has a space dimension, the norm is plotted.
If None, uses MNE sample data for demonstration.
- Pass an Eelbrain NDVar, an MNE ``VolVectorSourceEstimate`` with
- ``src``, or the sample data object returned by
+ Pass an Eelbrain :class:`eelbrain.NDVar`, an MNE
+ :class:`mne.VolVectorSourceEstimate` with ``src``, or the sample data
+ object returned by
:func:`liveneuro.create_sample_brain_data`.
cmap
Plotly colorscale for heatmaps. Can be:
@@ -91,22 +93,25 @@ class LiveNeuro:
'Source 0', 'Source 1', etc.). If False, hides all titles and legends for a
cleaner visualization. Default is False.
src
- Matching MNE SourceSpaces object when ``y`` is an
- ``mne.VolVectorSourceEstimate``. Required for MNE source estimates because
- the source estimate stores vertex ids while LiveNeuro needs 3D source
- coordinates.
+ Matching MNE :class:`mne.SourceSpaces` object when ``y`` is an
+ :class:`mne.VolVectorSourceEstimate`. Required for MNE source estimates
+ because the source estimate stores vertex ids while LiveNeuro needs 3D
+ source coordinates.
Notes
-----
Expected input format
- - For vector data: NDVar with dimensions ([case,] time, source, space)
- - For scalar data: NDVar with dimensions ([case,] time, source)
- - For MNE vector volume data: VolVectorSourceEstimate plus matching ``src``
+ - For vector data: :class:`eelbrain.NDVar` with dimensions
+ ([case,] time, source, space)
+ - For scalar data: :class:`eelbrain.NDVar` with dimensions
+ ([case,] time, source)
+ - For MNE vector volume data: :class:`mne.VolVectorSourceEstimate` plus
+ matching ``src``
- If case dimension present: mean across cases is plotted
- If space dimension present: norm across space is plotted for butterfly plot
- - ``create_sample_brain_data`` returns a minimal NDVar-like object compatible
- with the ``y`` parameter for quick demos
+ - :func:`liveneuro.create_sample_brain_data` returns a minimal NDVar-like
+ object compatible with the ``y`` parameter for quick demos
"""
def __init__(