Skip to content

Luna + Python = lunapi

lunapi is a Python module that provides an interface to Luna. It accesses the C/C++ Luna library directly, meaning all core Luna commands described here have similar syntax and performance; many of the fundamental concepts described here apply here too.

LunaScope

LunaScope is a standalone desktop viewer built on top of lunapi. For interactive visual review, it is generally the better and more full-featured tool; the scope utility described here is a smaller embedded viewer intended for use inside JupyterLab notebooks.

Installation

To obtain lunapi (macOS, Linux or Windows), use pip:

pip install lunapi

lunapi supports Python 3.9 through 3.14. For an isolated installation, create and activate a virtual environment with:

python3 -m venv .venv
source .venv/bin/activate              # macOS/Linux
# .venv\Scripts\Activate.ps1             # Windows PowerShell

Then install lunapi inside the environment:

python -m pip install --upgrade pip
pip install lunapi

To leave the virtual environment, use deactivate.

Using lunapi as a Python module

The primary way to use lunapi is as a Python module for programmatic analysis. Import it using the conventional alias:

import lunapi as lp

This interface provides access to Luna operations from Python scripts, notebooks, and other applications.

Command-line use

The lunapi package also provides luna.py, a Python command-line variant for the standard sample-list processing workflow. It uses the same underlying Luna implementation as the Python API and accepts a sample list or a single EDF, Luna variables, parameter files, and a command string. It is intended as a drop-in replacement for common lunaC jobs; use lunaC for standalone options that are not part of this interface (for example, --xml, --merge, or --append).

luna.py s.lst -o out.db sig=EEG @params.txt -s "EPOCH len=30 PSD"

The command string can be read from standard input instead of using -s:

cat commands.txt | luna.py s.lst -o out.db

To process one EDF directly:

luna.py recording.edf -o out.db -s "HEADERS"

Rows can be selected by 1-based row number, inclusive range, Luna-style slice, or sample-list ID:

luna.py s.lst 3 -o out.db -s "HEADERS"
luna.py s.lst 10-20 -o out.db -s "STATS"
luna.py s.lst 2/5 subject_001 -o out.db -s "DESC"

The helper modes --build and --validate use Luna's native sample-list builder and validator:

luna.py --build /data/study > s.lst
luna.py --validate s.lst

Run luna.py --help for the complete list of supported options. The command is installed alongside lunapi by pip install lunapi and is named luna.py so that it does not conflict with the native lunaC executable.

The package also installs destrat.py, a Python/SQLite reader for Luna output databases. It accepts one or more database paths, glob patterns, a command selector, row and column stratifiers, variable and individual filters, and level restrictions. For example:

destrat.py out.db
destrat.py out.db +PSD -r CH F -v PSD
destrat.py out/run-*.db +PSD -r F/11,15 CH -c B -v PSD

Results are written as tab-delimited text to standard output. Use lp.destrat() when the same queries should be performed inside Python and returned as pandas dataframes.

Alternatively, you can pull the lunapi Docker image which also provides a Jupyter lab environment (as well as the command-line Luna and R-based lunaR tools) in a single package.

Getting started

Known issues

  • Jupyter Lab is required for the scope viewer
  • For most interactive signal viewing tasks, LunaScope is a better choice than the notebook-embedded scope widget

  • Using ctrl-D or ctrl-C to escape from long-running Luna processes may be slow

  • On some platforms, commands may run more slowly under the Jupyter Lab environment compared to a plain Python environment (which gives comparable performance to the command-line Luna). This may be due to suboptimal configuration settings, but it is beyond the scope of this documentation to advise for specific cases. In general, the notebooks are best suited for smaller, interactive jobs rather than more intensive processing.