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
-
Follow the example and lunapi tutorial notebooks from this repository
-
See the primary reference and scope viewer pages
- For a standalone desktop viewer built on top of lunapi, see LunaScope
Known issues
- Jupyter Lab is required for the
scopeviewer -
For most interactive signal viewing tasks, LunaScope is a better choice than the notebook-embedded
scopewidget -
Using
ctrl-Dorctrl-Cto 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.