Lunapi Reference
This page describes the high-level interface to Luna functions.
This notebook
also contains a few further details. Below, we assume the lunapi
package will always be aliased as lp
, i.e.:
import lunapi as lp
Using the package generally involves first initiating a project class, which we'll call proj
:
proj = lp.proj()
The project is the primary "engine" that brings together various
Luna concepts including sample lists, output databases, special
variables, etc, alongside the ability to evaluate and execute Luna
functions. Given a project, you can create one or more data instances, that
represent signal and/or annotation data for a single observation. We'll generally assume the
instance is called p
:
p = proj.inst(x)
The sections below describe the suite of functions for a) manipulating projects, b) working with instances as well as c) other helper functions and d) the Moonbeam utility to pull NSRR data directly into Python. Below, we'll first tabulate all commands in the next section, and then give some more details on usage in the following sections.
Command tables
Major commands are described in bold text. Below:
-
the lunapi package is aliased as
lp
-
the
proj
class is assumed to also be calledproj
(i.e. fromproj = lp.proj()
) -
any
inst
class is assumed to be calledp
(i.e. fromp = proj.inst(x)
) -
any
moonbeam
class is assumed to be calledmb
Projects
Projects are singleton classes that organize Luna functions and objects within a single Python session.
Project/instance creation
Command | Description |
---|---|
lp.proj() |
Initiate/reference a lunapi project |
proj.inst() |
Create a new instance |
proj.empty_inst() |
Create an empty instance |
proj.retire() |
Retire a project |
Sample lists
Command | Description |
---|---|
proj.build() |
Traverses folders (recursively) to generate a lunapi sample-list |
proj.sample_list() |
Reads a sample-list from a file, or returns an existing sample-list |
proj.validate() |
Validate all files in a sample list |
proj.nobs() |
Returns of number of observations in the current sample-list |
proj.get_n() |
Returns of index (row) of an observations in the current sample-list |
proj.get_id() |
Returns the ID of a sample-list observation |
proj.get_edf() |
Returns the EDF filename of a sample-list observation |
proj.get_annots() |
Returns the annotation filename(s) of a sample-list observation |
proj.clear() |
Clears the current sample-list |
Executing Luna commands
Command | Description |
---|---|
proj.proc() |
Evaluate Luna commands on all sample-list individuals |
proj.strata() |
Return a list of command/strata pairs from a prior eval() run |
proj.table() |
Return a table as a dataframe from a prior eval() run |
proj.commands() |
Return a list of commands executed from a prior proc() run |
proj.variables() |
Return the variables (table header) for a specific command/strata pair from a prior eval() run |
proj.empty_result_set() |
Indicate whether there are any results in the project results cache |
Variables
Command | Description |
---|---|
proj.var() |
Get/set project-wide variable |
proj.varmap() |
Get/set project-wide variables (via a dict() ) |
proj.vars() |
Gets/sets project-wide options/variables |
proj.clear_var() |
Clears a project-wide option/variable |
proj.clear_vars() |
Clears all project-wide options/variables |
proj.clear_ivars() |
Clears all individual-specific variables (for all individuals) |
Models
Command | Description |
---|---|
proj.pops() |
A project-level wrapper for the POPS stager |
proj.predict_SUN2019() |
A project-level wrapper for the SUN2019 biological age model |
Misc.
Command | Description |
---|---|
proj.silence() |
Turns off the console/log echoing |
proj.is_silenced() |
Reports on whether the console/log is silenced |
proj.import_db() |
Imports a prior Luna output database from a file |
Instances
Instances are generally created by the proj.inst()
command; if the individual exists
in the project's sample list, then any EDF and annotation files are automatically attached.
Creation
Command | Description |
---|---|
inst.attach_edf() |
Explicitly attach an EDF |
inst.attach_annot() |
Attach an annotation file |
inst.refresh() |
Drop any changes made to the attached data |
Basic summaries
Command | Description |
---|---|
inst.headers() |
Returns a dataframe of channel-header information |
inst.annots() |
Returns a list of current annotation classes |
inst.channels() |
Returns a list of current channels |
inst.stat() |
Returns information on the attached data |
inst.has_channels() |
Returns a list of true/false values for whether certain channels exist |
inst.has_annots() |
Returns a list of true/false values for the presence of certain annotation classes |
inst.stages() |
Returns a list of current sleep stages |
inst.has_staging() |
Returns true/false for whether stage annotations are available |
Executing Luna commands
Command | Description |
---|---|
inst.eval() |
Evaluate arbitrary Luna commands |
inst.strata() |
Reports on the contents of the current result cache |
inst.table() |
Displays a table from the current result cache |
inst.proc() |
Evaluate arbitrary Luna commands and directly return all results |
inst.empty_result_set() |
Indicates whether the results cache is currently non-empty |
Individual-level variables
Command | Description |
---|---|
inst.ivar() |
Set or get an individual variable |
inst.ivars() |
Returns all individual variables |
Extracting signals & annotations
Command | Description |
---|---|
inst.data() |
Returns an array of signal/annotation data |
inst.slice() |
Returns an array of merged signal/annotation data based on selected intervals (slices) |
inst.slices() |
Returns an array of individual signal/annotation data based on selected intervals (slices) |
inst.e2i() |
Helper function to convert epochs to intervals |
inst.s2i() |
Helper function to convert epochs to intervals |
Updating signals & annotations
Command | Description |
---|---|
inst.insert_signal() |
Inserts a new signal into the in-memory EDF |
inst.update_signal() |
Updates an existing signal in the in-memory EDF |
inst.insert_annot() |
Insert/append annotation events |
Models
Command | Description |
---|---|
inst.pops() |
Run POPS stager for a single individual |
inst.predict_SUN2019() |
Fit Sun et al (2019) brain-age prediction model |
Plotting
Command | Description |
---|---|
inst.hypno() |
Plot a hypnogram given sleep stage data |
lp.hypno_density() |
Make a hypno-density (posterior stage probabilites) |
inst.psd() |
Calculate and plot a PSD curve |
inst.spec() |
Calculate and plot a spectrogram heatmap |
lp.topo_heat() |
Topo-plot |
Helpers
Utility functions
Command | Description |
---|---|
lp.cmdfile() |
Loads and parses a Luna command file |
lp.include() |
Reads and sets project variables based on a parameter file |
Scope
Command | Description |
---|---|
lp.scope() |
Initiate the Scope viewer |
Moonbeam
Command | Description |
---|---|
mb = lp.moonbeam() |
Initiate a Moonbeam object (mb ) |
mb.cohorts() |
List available cohorts |
mb.cohort() |
Set/list current cohort |
mb.inst() |
Beam/create an individual from the current cohort |
mb.pheno() |
Beam any phenotypes information for an individual |
mb.set_cache() |
Explicitly set cache |
mb.cached() |
Check whether a file is cached |
mb.pull() |
Pull (all files for) an individual |
mb.pull_file() |
Pull a single file |
Projects
lp.proj()
Constructor for proj class
proj()
Args:
none
Returns:
reference to a proj object
Example:
proj = lp.proj()
This calls lunapi.lunapi0.inaugurate()
, which constructs a singleton
instance of a Luna project. A session can only contain one
project: subsequent calls to proj()
will return a reference to
the same project.
proj.inst()
Creates a new instance (individual)
inst( x )
Args:
x (str) If there is an attached sample-list with individual ID 'x'
then this individual is attached (EDF & annotations)
Otherwise, an empty instance with ID 'x' is created
x (int) Assuming a sample-list is attached, generate a new
instance and attach the EDF/annotations; uses 1-based indexing
Returns:
reference to an inst object
Example:
p = proj.inst('id1')
This is the primary way to create a new instance in lunapi
.
If x
is a string that doesn't match an entry in the attached sample-list (from sample_list()
),
then a new, empty inst
object is created with that ID. Data can subsequently be attached
with the instance-level attach_edf()
and attach_annot()
functions.
Alternatively, if a sample-list exists within the project class and x
indexes (1-based) the entry in the list, then as well as creating an inst
with the ID
from the sample-list, this variant of inst()
will also automatically attach the specified
EDF (via attach_edf()
) and any annotation files also specified (via attach_annot()
). Likewise,
if x
is a string that matches an ID in the sample-list, the associated EDF/annotations will be attached.
Otherwise, an empty instance will be created, as above.
proj.empty_inst()
Create an empty EDF
This provides a means to create an empty EDF, similar to the command-line Luna interface as described here.
empty_inst( id , nr , rs ,
startdate = '01.01.00', starttime = '00.00.00' )
Args:
id (str) ID for the new (empty/zero-channel) instance
nr (int) number of EDF records
rs (float) duration of each EDF record (in seconds)
startdate (str) EDF format date-string for date
starttime (str) EDF format time-string for start
Returns:
reference to an empty inst object
Example:
p = proj.empty_inst('id1' , 3600 , 1 )
This creates an empty EDF with fixed duration of nr
* rs
seconds.
Signals can be added via using inst.eval()
and Luna commands (e.g. for
simulating signals), or directly from Python objects via
inst.insert_signal().
proj.retire()
Retire a project
proj()
Args:
none
Returns:
reference to a proj object
Example:
proj.retire()
This closes an existing project and frees all resources.
proj.build()
Traverses folders (recursively) to generate a lunapi sample-list
build( args )
Args:
args (list) a list of strings, either folders or special options
Returns:
nothing; it creates an internal sample-list
Example:
proj.build( [ '/tutorial/' , '/path/to/more/data' , '-ext=-profusion.xml' ] )
Internally, this function calls the same code used by the --build
option for the luna
command-line tool. If a specified folder does
not exist, this function returns a RuntimeError.
proj.sample_list()
Reads a sample-list from a file, or returns an existing sample-list
sample_list(x, path, df )
Args:
x (str, optional) filename of the sample-list
path (str, optional) path to prepend to all relative file paths when building the sample-list
df (boolean) return a pandas dataframe rather than python list (default=True)
Returns:
nothing, if reading a sample-list
a dataframe/list of (ID,EDF,set(annotation files))-tuples, if x is None
Example:
proj.sample_list( '/tutorial/s.lst' )
proj.sample_list()
If the sample list uses relative paths that are not appropriate for your current directory,
you can set the path
argument to add a prefix to all relative paths in the sample list. Alternatively
(and equivalently), you can set the project variable path
before calling sample_list(x)
to
acheve the same result: proj.var( 'path' , '/path/to/data/' )
. For example, if the current working folder
is /home/joe/work1/
and the data are in /data/proj1/
/data/proj1/
/data/proj1/s.lst
/data/proj1/edfs/
/data/proj1/annots/
s.lst
is in the form, e.g.:
id1 edfs/id1.edf annots/id1.annot
id2 edfs/id2.edf annots/id2.annot
id3 edfs/id3.edf annots/id3.annot
sample_list( '/data/proj1/s.lst' )
, Luna would look for the data (e.g. for id1
) in /home/joe/edfs/ed1.edf
, etc. Instead, running sample_list( '/data/proj1/s.lst' , '/data/proj1/' )
would create an internal sample-list as follows:
id1 /data/proj1/edfs/id1.edf /data/proj1/annots/id1.annot
id2 /data/proj1/edfs/id2.edf /data/proj1/annots/id2.annot
id3 /data/proj1/edfs/id3.edf /data/proj1/annots/id3.annot
proj.validate()
Validate all files in a sample list
nobs()
Args:
none
Returns:
a table of IDs, filenames and a flag for valid/invalid status
Example:
proj.sample_list( 's.lst' )
proj.validate()
This provides the same functionality as the --validate
option of
Luna, which is described here.
proj.nobs()
Returns of number of observations in the current sample-list
nobs()
Args:
none
Returns:
number of observations (int)
Example:
proj.nobs()
proj.get_n()
Returns of index (row) of an observations in the current sample-list
get_n(id)
Args:
id (str) ID corresponding to first field of the sample-list
Returns:
0-based index (int), it the ID exists in the sample-list
NoneType, if the ID does not exist in the sample-list
Example:
proj.nobs()
proj.get_id()
Returns the ID of a sample-list observation
get_id(n)
Args:
n (int) a 0-based index for the sample-list
Returns:
ID (str), if n is a valid index
NoneType, if n is not a valid index
Example:
proj.get_id(0)
proj.get_edf()
Returns the EDF filename of a sample-list observation
get_edf(x)
Args:
x (int) a 0-based index for the sample-list
x (str) an ID matching a sample-list observation
Returns:
EDF filename (str), if x is a valid index
NoneType, if x is not a valid index
Example:
proj.get_edf(0)
If x
is a str
, this calls the function is get_n(x)
.
proj.get_annots()
Returns the annotation filename(s) of a sample-list observation
get_annots(x)
Args:
x (int) a 0-based index for the sample-list
x (str) an ID matching a sample-list observation
Returns:
EDF filename (str), if x is a valid index
NoneType, if x is not a valid index
Example:
proj.get_edf(0)
If x
is a str
, this calls the function is get_n(x)
.
proj.clear()
Clears the current sample-list
clear()
Args:
none
Returns:
nothing; will only clear an existing sample-list
Example:
proj.clear()
proj.proc()
Evaluate Luna commands on all sample-list individuals
eval( cmdstr )
Args:
cmdstr (str) a valid Luna command script
Returns:
dict of command/strata (str) keys to dataframe values
Example:
proj.eval( 'HEADERS' )
eval()
also populates the proj
results cache, i.e. that can be subsequently queried with proj.strata()
, proj.table()
, etc.
The lp.cmdfile()
utility function can be used to pass a file-based Luna script to eval()
(i.e.
which will strip out comments, etc).
Multi-line scripts can be passed by using triple-quotes, e.g.:
proj.eval( """
MASK ifnot=N2
RE
STATS sig=${eeg}
""" )
Note that eval()
can used both project-wide and individual-specific
variables in scripts, e.g. as above (${eeg}
).
Note: a similar form of this command exists silent_eval()
which has identical syntax but suppresses any console/log output.
proj.strata()
Return a list of command/strata pairs from a prior eval()
run
strata()
Args:
none
Returns:
a dataframe of commands and strata pairs in the project-level results cache
Example:
proj.eval( 'HEADERS' )
proj.strata()
The project results cache stores the results of the last successful run of proj.eval()
proj.table()
Return a table as a dataframe from a prior eval()
run
table( cmd , strata = 'BL' )
Args:
cmd (str) case-sensitive command name in the project results cache
strata (str, optional, defaults to BL) case-sensitive stratum in the project results cache
Returns:
a dataframe of values associated with a specific command/strata pair in the project-level results cache
Example:
proj.eval( 'HEADERS' )
proj.table( 'HEADERS' )
proj.table( 'HEADERS' , 'CH' )
The project results cache stores the results of the last successful run of proj.eval()
. A list of available tables
is given by proj.strata()
. All individuals from the sample-list are combined as different rows of the same results
table.
proj.commands()
Return a list of commands executed from a prior eval()
run
commands()
Args:
none
Returns:
a dataframe of commands in the project-level results cache
Example:
proj.eval( 'HEADERS' )
proj.commands()
The project results cache stores the results of the last successful run of proj.eval()
proj.variables()
Return the variables (table header) for a specific command/strata pair from a prior eval()
run
table( cmd , strata = 'BL' )
Args:
cmd (str) case-sensitive command name in the project results cache
strata (str, optional, defaults to BL) case-sensitive stratum in the project results cache
Returns:
a dataframe of variable names from the table associated with a specific command/strata pair in the project-level results cache
Example:
proj.eval( 'HEADERS' )
proj.variables( 'HEADERS' )
proj.variables( 'HEADERS' , 'CH' )
This is similar to proj.table()
but only returns table headers (i.e. variable names).
proj.empty_result_set()
Indicate whether there are any results in the project results cache
proj.empty_result_set()
Args:
none
Returns:
bool, True if the project results cache is empty
Example:
proj.eval( 'HEADERS' )
proj.proj.empty_result_set()
The project results cache stores the results of the last successful run of proj.eval()
.
proj.var()
Sets or gets a project-wide option/variable
var(key=None,value=None)
Args:
key (str, optional) variable name
value (str, optional) value to set variable to
Returns:
nothing, if value is not None (it sets the option)
the value of the variable, if value is None but key is not
vars(), if key and value are both None
Example:
proj.var( 'path' , '/tutorial/')
proj.var( 'path' )
proj.varmap()
Sets project-wide options/variables
varmap(d)
Args:
d (dict) key/value pairs
Returns:
nothing, if value is not None (it sets the option)
Example:
proj.varmap( { 'path': '/tutorial/' , 'annot-file': '/path/to/a.annot' , 'ch': 'EEG1,EEG2' } )
proj.vars()
Special variables (i.e. above path
and annot-file
are enacted rather than set (i.e. only ch
above will appear in proj.vars()
).
Also note that some special project-wide variables may be automatically set (e.g. sleep
equals N1,N2,N3,R
).
proj.vars()
Gets/sets project-wide options/variables
vars( key = None , value = None )
Usage 1: return all variables
Args:
none
Returns:
a `dict` of `variable: value` pairs
Usage 2: return a specific variable
Args:
key (str)
Returns:
a `str` value for that variable (or `None` if it does not exist)
Usage 3: set a single key/value pair
Args:
key (str) variable name
value (str, int or float) variable value (scalar, that can be cast to a str)
Returns:
nothing
Usage 4: set multiple key/value pairs
Args:
key (dict) dictionary of key/value pairs to set
Returns:
nothing
Example:
proj.vars( 'a', 2 ) # sets ${a} to 2
proj.vars( { 'a': 2 , 'stage': 'N2' } )
proj.vars( 'stage' ) # returns 'N2'
proj.vars() # returns all variables (including presets)
proj.clear_var()
Clears a project-wide option/variable
clear_var(key)
Args:
key (str) name of the variable
Returns:
nothing
Example:
proj.clear_var( 'path' )
If the variable does not exist, this has no effect.
proj.clear_vars()
Clears all project-wide options/variables
clear_vars()
Args:
none
Returns:
nothing
Example:
proj.clear_vars()
proj.clear_ivars()
Clears all individual-specific variables (for all individuals)
clear_ivars()
Args:
none
Returns:
nothing
Example:
proj.clear_ivars()
This clears any previously attached individual-specific variables. Typically, these will be
attached through Luna's vars
special variable, i.e. proj.var( 'vars' , 'path/to/ivar.txt' )
.
(Note that although the Luna variable is vars
it would perhaps have been better called ivars
,
as lunapi
uses the vars
/ivars
nomenclature to distinguish betwen project-wide and individual-specific
variables.
proj.pops()
A project-level wrapper for the POPS stager
pops( s = None, s1 = None , s2 = None,
path = None , lib = None ,
do_edger = True ,
no_filter = False ,
do_reref = False ,
m = None , m1 = None , m2 = None )
Args:
s (str, optional) central EEG channel (in single-channel mode)
s1 (str, optional) first central EEG channel (in two-channel mode)
s2 (str, optional) second central EEG channel (in two-channel mode)
path (str,default = lp.resources.POPS_PATH ) path to POPS training model folder
lib (str,default = lp.resources.POPS_LIB ) library name of POPS training model
do_edger (bool, default=True) perform EDGER cleaning prior to POPS
no_filter (bool, default=False) assume EEG are pre-filtered, if True
do_reref (bool, default=False) perform re-referencing of the EEG before POPS
m (str, optional) mastoid reference (in single-channel mode, if do_reref == True )
m1 (str, optional) mastoid reference for s1 (in two-channel mode, if do_reref == True )
m2 (str, optional) mastoid reference for s2 (in two-channel mode, if do_reref == True )
Returns:
this command populates the project results cache with POPS results
explicitly returns proj.table( 'POPS' , 'E' )
Example:
# single channel example, all defaults
proj.pops( 'EEG' )
# two-channel, without filtering , and applying mastoid references
proj.pops( s1='C3', m1='M2', s2='C4',m2='M1', no_filter=True )
The default locations of lp.resources.POPS_PATH
and
lp.resources.POPS_LIB
are set to be appropriate for the
remnrem/lunapi docker image,
i.e. /build/nsrr/common/resources/pops/
. If you are running lunapi
outside of
the Docker context, you will need to edit these prior to running pops()
, e.g.:
lp.resources.POPS_PATH = '/home/george/data/pops/'
proj.pops( s='C3_M2' )
Currently, the default (and only) model is s2
; more models should be added soon.
More than two channels can be used (as equivalence channels) by
running POPS
via proj.eval()
directly. See the main Luna pages for details on POPS.
proj.predict_SUN2019()
A project-level wrapper for the SUN2019 biological age model
predict_SUN2019( cen , th = '3' , path = None )`
Args:
cen (str) comma-delimited list of central EEGs
th (float, default=3) SD threshold for missing-value imputation
path (str, default=None) path to resources for this model
Returns:
populates the project results cache with results
Example:
proj.silence() # turn off logging
proj.silence( False ) # turn it back on
resources.MODEL_PATH
is set to /build/luna-models/
(suitable for
the remnrem/lunapi
Docker image). If path
is None
, then it is
set to resources.MODEL_PATH
instead (i.e. this is the default).
For consistency across differnt lunapi commands, future releases will
allow Python lists as well as comma-delimited strings: i.e. cen = [
'C3' , 'C4' ]
as well as cen = 'C3,C4'
.
See the main Luna pages for details on the Sun et al (2019) model, and on the PREDICT command in general.
proj.silence()
Turns off the console/log echoing
silence( x = True , verbose = False )
Args:
x (bool, True by default) silence console output
verbose( bool, False by default) report action to console
Returns:
nothing
Example:
proj.silence() # turn off logging
proj.silence( False ) # turn it back on
proj.is_silenced()
Reports on whether the console/log is silenced
is_silenced()
Args:
none
Returns:
True if console/log is silenced, else False
Example:
proj.silence() # turn off logging
proj.is_silenced()
proj.import_db()
Imports a prior Luna output database from a file
import_db(f,s=None)
Args:
f (str) filename of luna database
s (set of str, optional) set of individual IDs to include
Returns:
a list of str, of the individual ID(s) imported
Example:
proj.import_db( 'out.db' )
proj.import_db( 'out.db' , s = { 'nsrr01', 'nsrr03' } )
proj.strata()
Note that lunapi
does not create destrat
-style databases - these are only generated
by the luna
command-line program. Any imported data are placed within the results cache of
the proj
class, and therefore accessible via proj.strata()
, proj.table()
, etc.
Instances
inst.attach_edf()
Attach an EDF
attach_edf( f )
Args:
f (str) EDF filename
Returns:
True if attachment was a success, else False
Example:
p = proj.inst( 'id1' )
p.attach_edf( '/path/to/id1.edf' )
You cannot attach a new EDF to an existing instance. If you want to reuse the same variable, you must first del
the instance: e.g.
p.attach_edf( 'f1.edf' )
del p
p.attach_edf( 'f2.edf' )
inst.attach_annot()
Attach an annotation file
attach_annot( f )
Args:
f (str) annotation filename
Returns:
True if attachment was a success, else False
Example:
p.attach_annot( '/path/to/id1.annot' )
inst.refresh()
Drop any changes made to the attached data
refresh()
Args:
none
Returns:
nothing
Example:
p.refresh()
This drops and then reattaches any currently attached EDFs and annotation files: i.e. all internal modifications to the attached instance are cleared.
inst.headers()
Returns a dataframe of channel-header information
headers()
Args:
none
Returns:
a Pandas dataframe of channel header information
Example:
p.headers()
inst.annots()
Returns a list of current annotation classes
annots()
Args:
none
Returns:
a Pandas dataframe of annotation classes
Example:
p.annots()
inst.stat()
Returns information on the attached data
stat()
Args:
none
Returns:
a Pandas dataframe of summary values (see below)
Example:
p.stat()
The key values that are returned are described in the total below:
Variable | Description |
---|---|
id |
EDF ID |
edf_file |
EDF filepath |
annotation_files |
Annotation filepath(s) |
ns |
Current number of signals |
nt |
Original, total number of signals in EDF header |
na |
Number of annotation classes |
duration |
EDF duration (hh:mm:ss) |
ne |
Number of epochs (if epoched) |
nem |
Number of masked epochs (if epoched ) |
elen |
Epoch duration (for standard, not generic, epochs) |
state |
Status flag: 1=attached, 0=empty, -1=problem |
inst.channels()
Returns a list of current channels
channels()
Args:
none
Returns:
a Pandas dataframe of channels
Example:
p.channels()
This function can also be called as chs()
instead of channels()
.
inst.has_channels()
Returns a list of true/false values for whether certain channels exist
has_channels(x)
Args:
x (str or list(str)) one or more channel labels to query
Returns:
a list of boolean values
Example:
p.has_channels( 'C3' )
p.has_channels( [ 'C3' , 'C4' , 'EMG' ] )
This function uses Luna channel aliasing when matching: i.e. if alternate labels have been specified, etc, when determining a match. Also, matches are case-insensitive.
inst.has_annots()
Returns a list of true/false values for the presence of certain annotation classes
has_annots(x)
Args:
x (str or list(str)) one or more annotation class labels
Returns:
a list of boolean values
Example:
p.has_annots('N2')
p.has_annots( [ 'N2','N3','R','REM','W','wake' ] )
inst.stages()
Returns a list of current sleep stages
stages()
Args:
none
Returns:
a list of sleep stages
Example:
ss = p.stages()
This is a wrapper around inst.eval( 'STAGE' )
.
inst.has_staging()
Returns true/false for whether stage annotations are available
has_staging()
Args:
none
Returns:
boolean
Example:
p.has_staging()
This tests whether annotations exist that can be mapped to Luna's generic forms (i.e. N1
, N2
, N3
, R
, W
, L
and ?
); also, valid staging requires that not all epochs have unknown (?
) stage assignments.
inst.eval()
Evaluate arbitrary Luna commands
eval( cmdstr )
Args:
cmdstr (str) a Luna command script
Returns:
inst.strata()
Examples:
p.eval( 'HEADERS' )
p.eval( lp.cmdfile( 'cmd/s1.txt' ) )
This populates the internal results cache which can be queried with strata()
, table()
, etc.
To turn off console logging use proj.silence()
. Alternatively, use silent_eval()
which is similar to eval()
but suppresses console output.
inst.strata()
Reports on the contents of the current result cache
strata()
Args:
none
Returns:
a Pandas dataframe of command/stratum pairs from the last command
Examples:
res = p.proc( 'HEADERS' )
p.strata()
This is returned by eval()
.
inst.table()
Displays a table from the current result cache
table( cmd , strata = 'BL' )
Args:
cmd (str) command name
strata (str, optional) if missing, defaults to BL (baseline)
Returns:
a Pandas dataframe of the results table
Examples:
res = p.proc( 'HEADERS' )
p.table( 'HEADERS' , 'CH' )
inst.proc()
Evaluate arbitrary Luna commands and directly return all results
proc( cmdstr )
Args:
cmdstr (str) a Luna command script
Returns:
dict of stratum->table pairs
Examples:
res = p.proc( 'HEADERS' )
lp.show( res )
This is effectively the same function as eval()
- it just varies in how it returns results: whereas eval()
returns a table summary of the results generated (command, factor/level), as generated by inst.strata()
; in contrast, proc()
returns an object representing all results directly. As with eval()
, this also populates the internal results cache. which can be queried with strata()
, table()
, etc.
To turn off console logging use proj.silence()
. Alternatively, use silent_proc()
which is similar to proc()
but suppresses console output.
inst.empty_result_set()
Indicates whether the results cache is currently non-empty
empty_result_set()
Args:
none
Returns:
True if the results cache is empty
Examples:
res = p.proc( 'HEADERS' )
if p.empty_result_set(): print( 'no results' )
The result cache may be empty is the previous command failed.
inst.ivar()
Set or get an individual variable
var( key = None , value = None )
Args:
key (str) variable name
value (str, optional) value (if setting)
Returns:
if key is None, returns all variables
if key is a dict, set key/value pairs
else, if value is None, returns the value of variable key
else, sets variable 'key' to 'value'
Example:
p.var( 'x' , 22 )
p.var( { 'a':22 , 'b':23 , 'c': 'abc' } )
p.var( 'x' ) # returns 22
Note, this may return automatically set individual-variables (i.e. ${eeg}
based on channel labels).
inst.ivars()
Returns all individual variables
ivars()
Args:
none
Returns:
a dict of key/value pairs for individual-variables set
Example:
p.ivars()
Note, this may include automatically set ivars
(i.e. ${eeg}
based on channel labels).
inst.data()
Returns an array of signal/annotation data
data( chs = None , annots = None , time = False )
Args:
chs (str or list[str] ) channel label(s)
annots (str ot list[str], optional) one or more annotation class labels
time (optional, default = False) add a time column to the output (seconds)
Returns:
a tuple of i) list[str] of labels, ii) numpy array of samples by signals
Examples:
d = p.data( ['EEG'] , ['N2'] , time = True)
All signals must have the same sample rate, as this returns a regular, i.e. rectangular array.
The presence/absence of annotations is represented as a 0/1 variable with the same sample rate.
inst.slice()
Returns an array of merged signal/annotation data based on selected intervals (slices)
slice( intervals, chs , annots , time = False )
Args:
intervals list of (start,stop)-tuples in time-points
chs (str or list[str] ) channel label(s)
annots (str ot list[str], optional) one or more annotation class labels
time (optional, default = False) add a time column to the output (seconds)
Returns:
a tuple of i) list[str] of labels, ii) numpy array of samples by signals
Examples:
d = p.slices( p.e2i( range(2,3) ), ['EEG'] , ['N2'] , time = True)
Intervals can be defined using convenience functions inst.e2i()
and inst.s2i()
to convert epochs or seconds to time-points (i.e. 1 time-point is 1e-9 seconds.
Unlike inst.slices()
, this function merges all requested samples into a single return array.
inst.slices()
Returns an array of individual signal/annotation data based on selected intervals (slices)
slices( intervals, chs , annots , time = False )
Args:
intervals list of (start,stop)-tuples in time-points
chs (str or list[str] ) channel label(s)
annots (str ot list[str], optional) one or more annotation class labels
time (optional, default = False) add a time column to the output (seconds)
Returns:
a list of tuples: i) list[str] of labels, ii) numpy array of samples by signals
Examples:
d = p.slices( p.e2i( range(2,3) ), ['EEG'] , ['N2'] , time = True)
Intervals can be defined using convenience functions inst.e2i()
and inst.s2i()
to convert epochs or seconds to time-points (i.e. 1 time-point is 1e-9 seconds.
Unlike inst.slice()
, this function does not merge all requested samples into a single return array,
but returns a list where each element is one interval from the intervals
input list.
inst.e2i()
Helper function to convert epochs to intervals
e2i( epochs )
Args:
epochs int or list[int] of base-1 epochs
Returns:
a list of (start,top)-tuples (time-points)
Examples:
p.e2i( range(1,5) )
Intervals are in time-points; 1 time-point is 1e-9 seconds. This is a member function of inst
as it supports generic epochs
(i.e. epochs need not be 30-second fixed intervals)
inst.s2i()
Helper function to convert epochs to intervals
e2i( secs )
Args:
secs list of (start,stop) float tuples (seconds)
Returns:
a list of (start,top)-tuples (time-points)
Examples:
p.s2i( range(1,5) )
Intervals are in time-points; 1 time-point is 1e-9 seconds.
This is a member function of inst
to provide a similar interface to inst.e2i()
-
it is a simple conversion from seconds to time-points that does not use inst
member data at all.
inst.insert_signal()
Inserts a new signal into the in-memory EDF
insert_signal( label , data , sr )
Args:
label (str) channel label (must be unique to EDF)
data (list[float]) signal data
sr (int) sample rate
Returns:
nothing
Examples:
p.insert_signal( 'P1' , x , sr = 200 )
This returns an error if the size of the signal does not match the EDF exactly. This is based on the current size of the in-memroy representation, i.e. which may differ from the on-disk file.
Also, the label
must not already exist in the EDF.
inst.update_signal()
Inserts a new signal into the in-memory EDF
update_signal( label , data )
Args:
label (str) channel label (must be unique to EDF)
data (list[float]) signal data
Returns:
nothing
Examples:
p.update_signal( 'P1' , x )
This returns an error if the size of the signal does not match the EDF exactly. This is based on the current size of the in-memroy representation, i.e. which may differ from the on-disk file.
label
must already exist in the EDF.
inst.insert_annot()
Insert/append annotation events
insert_annot( label , intervals, durcol2 = False )
Args:
label (str) annotation class
intervals (list[(start,stop)-tuples]) events (secs)
durcol2 (bool, optional ) if True, 2nd col. is duration, not stop
Returns:
nothing
Examples:
p.insert_annot( 'A1' , [ (10,12) , (45,46.5) ] )
Note, unlike slice()
and slices()
, intervals are input in seconds here, not time-points.
If the annotation class already exists, events are appended; otherwise, a new class is created.
inst.pops()
e for s1 (in two-channel mode, if do_reref == True ) m2 (str, optional) mastoid reference for s2 (in two-channel mode, if do_reref == True )
Returns:
this command populates the project results cache with POPS results
explicitly returns proj.table( 'POPS' , 'E' )
Example:
# single channel example, all defaults
p.pops( 'EEG' )
# two-channel, without filtering , and applying mastoid references
p.pops( s1='C3', m1='M2', s2='C4',m2='M1', no_filter=True )
```
This is the inst
-analog of proj.pops()
(i.e. fits to a
single individual rather than all individuals in the proj
sample-list).
The default locations of lp.resources.POPS_PATH
and
lp.resources.POPS_LIB
are set to be appropriate for the
remnrem/lunapi docker image,
i.e. /build/nsrr/common/resources/pops/
. If you are running lunapi
outside of
the Docker context, you will need to edit these prior to running pops()
, e.g.:
lp.resources.POPS_PATH = '/home/george/data/pops/'
p.pops( s='C3_M2' )
Currently, the default (and only) model is s2
; more models should be added soon.
More than two channels can be used (as equivalence channels) by
running POPS
via p.eval()
directly. See the main Luna pages for details on POPS.~
inst.predict_SUN2019()
Fit Sun et al (2019) brain-age prediction model
predict_SUN2019( cen , age = None , th = '3' , path = None )
Args:
cen (str or list[str]) comma-delimited list of central EEGs
th (float, default=3) SD threshold for missing-value imputation
path (str, default=None) path to resources for this model
Returns:
populates the project results cache with results
Example:
proj.silence() # turn off logging
proj.silence( False ) # turn it back on
This is the inst
-analog of proj.predict_SUN2019()
(i.e. fits to a
single individual rather than all individuals in the proj
sample-list).
resources.MODEL_PATH
is set to /build/luna-models/
(suitable for
the remnrem/lunapi
Docker image). If path
is None
, then it is
set to resources.MODEL_PATH
instead (i.e. this is the default).
Channels (cen
) can be specified as either Python lists as well as
comma-delimited strings: i.e. cen = [ 'C3' , 'C4' ]
as well as cen
= 'C3,C4'
.
See the main Luna pages for details on the Sun et al (2019) model, and on the PREDICT command in general.
inst.hypno()
Plot a hypnogram given sleep stage data
hypno()
Args:
none
Returns:
a hypnogram image
Example:
p.hypno()
This assumes that valid staging annotations exist for the attached individual (as can be queried by inst.has_staging()
). This function works by calling the project-level lp.hypno()
function, and is equivalent to calling lp.hypno( p.stages() )
lp.hypno()
Plot a hypnogram given sleep stage data
hypno( ss , e = None , xsize = 20 , ysize = 2 , title = None )
Args:
ss (list[str]) sleep stage annotations (per-epoch)
e (list[float]) optional epoch times (seconds)
xsize (float) size of figure (horiz.)
ysize(float) size if figure (vert.)
title (str) plot title
Returns:
a hypnogram plot
Example:
lp.hypno( p.stages() )
Stage labels are assumed to be N1
, N2
, N3
, R
, W
, ?
and L
. This function exists as well as inst.hypno()
as it allows for different sets of stages to be plotted (e.g. from manual versus automated staging), as the caller has to supply the stage data directly, unlike
inst.hypno()
(see above).
lp.hypno_density()
Make a hypno-density (posterior stage probabilites)
hypno_density( probs , e = None , xsize = 20 , ysize = 2 , title = None )
Args:
probs (array[float]) posterior probabilities
e (list[float]) optional epoch times (seconds)
xsize (float) size of figure (horiz.)
ysize(float) size if figure (vert.)
title (str) plot title
Returns:
a hypno-density plot
Example:
p.pops( 'EEG' )
stgs = p.table( 'POPS' , 'E' )
lp.hypno_density( stgs )
This function expects columns PP_N1
, PP_N2
, etc, as returned by
POPS
and SOAP
commands ( in the output stratifed by E
(epoch),
as above).
inst.psd()
Calculate and plot a PSD curve
psd( ch, minf = None, maxf = None, minp = None, maxp = None , xlines = None , ylines = None )
Args:
ch (str) a channel label
minf (float, optional) minimum frequency (x-axis)
maxf (float, optional) maximum frequency (x-axis)
minp (float, optional) minimum power (y-axis)
maxp (float, optional) maximum power (y-axis)
xlines (float) one or more x-axis lines
ylines (float) one or more y-axis lines
Returns:
a PSD plot
Example:
p.psd( 'C4' )
inst.spec()
Calculate and plot a spectrogram heatmap
spec( ch, mine = None , maxe = None , minf = None, maxf = None, w = 0.025 )
Args:
ch (str) a channel label
mine (int, optional) minimum epoch number (x-axis)
maxe (int, optional) maximum epoch number (x-axis)
minf (float, optional) minimum frequency (y-axis)
maxf (float, optional) maximum frequency (y-axis)
w (float, optional) winsorsize threshold (0-0.4)
Returns:
a spectrogram plot
Example:
p.spec( 'EEG' )
This is a wrapper to call the Luna PSD
command and the lp.spec()
to plot a spectrogram of results. Currently, it uses
the Welch method to generate a spectrogram.
lp.spec()
Plot a spectrogram heatmap given prior spectral resuts
spec(df , ch = None , var = 'PSD', mine = None , maxe = None , minf = None, maxf = None, w = 0.025 )`
Args:
df (dataframe) CH/E/F-level output from PSD or MTM
ch (str, optional) select output for this channel only
var (str, optional) power variable (default 'PSD')
mine (int, optional) minimum epoch number (x-axis)
maxe (int, optional) maximum epoch number (x-axis)
minf (float, optional) minimum frequency (y-axis)
maxf (float, optional) maximum frequency (y-axis)
w (float, optional) winsorsize threshold (0-0.4)
Returns:
a spectrogram
Example:
p.eval( 'PSD sig=EEG dB epoch-spectrum' )
df = p.table( 'PSD' , 'CH_E_F' )
lp.spec( df )
lp.topo_heat()
Make a topo-plot
topo_heat(chs, z,
ths = None, th=0.05,
topo = None, lmts= None ,
sz=70, colormap = "bwr", title = "",
rimcolor="black", lab = "dB")
Args:
chs (list[str]) channel labels (per channel)
z (list[float]) z-values to plot (per channel)
ths (list[float]) optional, threshold values (per channel)
th (float) threshold (default 0.05)
topo (dataframe) alternative channel locations
colormap (str) optional, default color-map (default: blue,white,red)
title (str) optional title
rimcolor (str) optional, color of rim (above threshold channels)
lab (str) optional, label (default 'dB')
Returns:
a topo-plot
Example:
p.eval( 'PSD sig=${eeg} dB ' )
df = p.table( 'PSD' , 'B_CH' )
df = p.table( 'PSD' , 'B_CH' )
df_sigma = df[ df[ 'B' ] == "SIGMA" ]
lp.topo_heat( df['CH'] , df['PSD' ] , title = 'Sigma', sz=200 )
The default channel locations are from lp.default_xy()
. You can
specify your own: see the format of lp.default_xy()
output for
details (i.e. a Pandas dataframe with three columns: CH
, with 2D
Cartesian co-ordinates X
and Y
scaled betwee -0.5 and +0.5,
i.e. head is a unit circle).
If ths
is not None
, then channels with a value for ths
below
th
(which is by default 0.05) are marked with a thicker rim (i.e. to
indicate significance).
lp.cmdfile()
Loads and parses a Luna command file
cmdfile( f )
lp.include()
Reads and sets project variables based on a parameter file
include( f )
N.b. lp.include( 'path/to/param' )
use the same function that the Luna command-line option @path/to/param
uses, e.g.
luna s.lst @param -o out.db < cmd.txt
lp.scope()
Initiates the scope viewer for a single instance
See the scope page for notes on using this tool in practice. Basic usuage is
lp.scope( p )
p
is an instance (i.e. a single recording).
Of the other options above, the most likely to be of immediate use is
chs
, which restricts the viewer to a subset of channels, e.g. :
lp.scope( p , chs = [ 'Fz', 'Cz', 'Pz' , 'Oz' ] )
This can be useful as scope performs some pre-processing of the
signals prior to creating the viewer window; for large datasets with
many channels and high sample rates, this can take a few seconds or
more, and so if you're only interested in a subset of channels, it can
be useful to add these options (or even for a single channel: e.g. in
the form lp.scope(p,'Cz')
.
The full set of options are given below (most are internal options that most users can ignore):
lp.scope(
p, chs=None,
bsigs=None, hsigs=None, anns=None,
stgs=['N1', 'N2', 'N3', 'R', 'W', '?', 'L'],
stgcols={'N1': 'blue', 'N2': 'blue', 'N3': 'navy', 'R': 'red', 'W': 'green', '?': 'gray', 'L': 'yellow'},
stgns={'N1': -1, 'N2': -2, 'N3': -3, 'R': 0, 'W': 1, '?': 2, 'L': 2},
sigcols=None, anncols=None,
throttle1_sr=100, throttle2_np=15000,
summary_mins=30, height=600, annot_height=0.15,
header_height=0.04, footer_height=0.01 )
Args:
p (lp.inst) lunapi instance
chs (list[str]) optional, list of channels to show (default: all)
bsigs (list[str]) optional, channels to calculate band power for (default, likely EEG)
hsigs (list[str]) optional, channels to calculate Hjorth parameters for (default, likely EEG)
anns (list[str]) optional, annotations to show (default:all)
stgs (list[str]) optional, stage labels (default: `['N1', 'N2', 'N3', 'R', 'W', '?', 'L']`)
stgcols (dict) optional, stage colors
stgns (dict) optional, stage y-axis values
sigcols (dict) optional, channel:color mappings
anncols (dict) optional, annotation:color mappings
throttle1_sr (int) optional, sample rate throttle (default: 100 Hz max)
throttle2_np (int) optional, number of points throttle (defautl: 15,000 max)
summary_mins (int) optional, duration of summary stats (currently not used)
height (int) optional, height of viewer in pixels
annot_height (float) optional, height of annotations as proportion (default: 0.15)
header_height (float)optional, height of header as proportion (default: 0.04)
footer_height (float)optional, height of footer as proportion (default: 0.01)
Returns:
an interactive scope viewer widget
Example:
proj.sample_list( 's.lst' )
p = proj.inst( 1 )
lp.scope( p )
lp.moonbeam()
Initiate a Moonbeam object
mb = lp.moonbeam( token )
where token
is your NSRR token, which
for NSRR users who are logged into the site is available from https://sleepdata.org/token.
Prototyping Moonbeam
Please note that the backend server support for Moonbeam is under flux and so this service may be temporarily unavailable: in future releases we'll try to make it more stable and performant.
mb.cohorts()
List available cohorts
mb.cohorts()
Returns a Pandas data-table of available cohorts for the logged-in user
mb.cohort()
Select a cohort and return available individuals
For example, to select cfs
(Cleveland Family Study) is that was listed as an available cohort:
mb.cohort( 'cfs' )
Returns of Pandas data-frame of individuals (ID and files).
mb.inst()
Pull an individual (EDF & annotations) from a selected cohort
p = mb.inst( id )
Generates and attaches an instance to p
(i.e. similar to p = proj.inst()
) assuming that id
is a string
that matches an ID in the attached cohort. If it exists locally (cached), that version will be used; otherwise,
Moonbeam will attempt to download it from the server.
mb.pheno()
Pull phenotypic data from the selected individual
mb.pheno()
Returns of Pandas data-frame of phenoytpes for the last pulled individual.
mb.set_cache()
Set the cache folder explicitly
mb.cached()
Internal function: check whether data are cached
mb.pull()
Internal function: pull an individual
mb.pull_file()
Interal function: pull a file