Skip to content

Manipulations

Commands to alter basic properties of the EDF and the signals therein

Command Description
SIGNALS Retain/remove specific EDF channels
COPY Duplicate one or more EDF channels
RESAMPLE Resample signal(s)
REFERENCE Re-reference signals
uV Rescale units to uV
mV Rescale units to mV
FLIP Flip polarity of signal
TIME-TRACK Add a time-track to an EDF
RECORD-SIZE Change EDF record size
ANON Strip ID information from EDF header

SIGNALS

The command requires one of two options: either keep or drop. Each expects a comma-delimited list of channel names (or aliases), which are either retained or removed from the in-memory dataset.

Parameters

Option Example Description
drop drop=EMG,ECG Drop channels EMG and ECG
keep keep=C3,C4 Drop all channels except C3 and C4

Outputs

Other than modifying the in-memory representation of the EDF, there is no further output (except some notes written to the log).

Example

For an EDF with 6 signals, including EMG, EOG-L and EOG-R, this command would drop these three signals:

luna s.lst -s "SIGNALS drop=EMG,EOG-L,EOG-R & DESC"
as shown by the relevant lines in the output from DESC:
Number of signals : 3
Signals           : EEG1[256] EEG2[256] EEG3[256]
In contrast, the keep option with the same arguments:
luna s.lst -s "SIGNALS keep=EMG,EOG-L,EOG-R & DESC"
yields the expected output:
Number of signals : 3
Signals           : EOG-L[256] EOG-R[256] EMG[256]

COPY

Duplicates one or more EDF channels

Because some Luna commands modify a channel (e.g. FILTER), it can be desirable to first make a copy of the original channel. New channels are written out with the WRITE command.

Although multiple signals can be duplicated at the same time (i.e. will all be given the same tag), only data channels (i.e. not EDF Annotation channels in EDF+) are duplicated.

Parameters

Parameter Example Description
sig sig=C3,C4 List of channels to duplicate
tag tag=DELTA A required option, this is added to make the new channel name, e.g. C3 becomes C3_DELTA

Output

One or more new channels are created in the in-memory representation of the EDF. Aside from a note in the log, there is no formal destrat-based output for this command.

Example

To extract one channel (EEG) from an original EDF, and then duplicate it:

luna s.lst 2 sig=EEG -s "DESC & COPY sig=EEG tag=V2 & DESC" 

As expected, the first DESC output shows a single channel:

EDF filename      : edfs/learn-nsrr02.edf
ID                : nsrr02
Clock time        : 21:18:06 - 07:15:36
Duration          : 09:57:30
# signals         : 1
Signals           : EEG[125]

After the COPY command has been executed, there are now two channels: EEG and EEG_V2:

EDF filename      : edfs/learn-nsrr02.edf
ID                : nsrr02
Clock time        : 21:18:06 - 07:15:36
Duration          : 09:57:30
# signals         : 2
Signals           : EEG[125] EEG_V2[125]

RESAMPLE

Changes the sampling rate of a signal

Uses functions from libsamplerate to upsample or downsample signals. Within a maximum upsampling/downsampling of 256, there are no constraints on the new sample rate (i.e. the ratio of old and new sample rates need not be a rational number).

Parameters

Parameter Example Description
sig sig=C3,C4 Signal list
sr sr=100 New sampling rate (Hz)

Output

No output other than a message to the log (and altering the in-memory signal).

Example

To create a new EDF with the EEG channel resampled to 100 Hz:

luna s.lst -s "RESAMPLE sig=EEG sr=100 & WRITE edf-tag=resample edf-dir=edfs/ sample-list=s2.lst"

REFERENCE

Re-references signals with respect to one or more other signals

Parameters

Parameter Example Description
sig sig=C3,C4 Signal(s) to re-reference
ref ref=A1,A2 Signal(s) to provide the reference

Both sig and ref are required parameters. If more than one channel is given as the reference (in a comma-delimited list), the average of those channels is used as the reference value.

Output

No output, other than a note to the log. In memory, the updated sig channels will contain the re-referenced values.

uV

Converts a signal to uV units

Check the unit field of the EDF header for either V, mV or uV and rescales the signal appropriately. If the header specifies some of unit, or none, then no action is taken.

Parameters

Parameter Example Description
sig sig=C3,C4 Signal(s) to convert

If sig is not specified, this command is applied to all channels.

Output

No output, other than updating the in-memory signal.

mV

Converts a signal to mV units

Check the unit field of the EDF header for either V, mV or uV and rescales the signal appropriately. If the header specifies some of unit, or none, then no action is taken.

Parameters

Parameter Example Description
sig sig=C3,C4 Signal(s) to convert

If sig is not specified, this command is applied to all channels.

Output

No output, other than updating the in-memory signal.

TIME-TRACK

Adds a time-track, which implicitly converts an EDF into an EDF+

This is an command only used internally, currently.

FLIP

Flips the polarity of a signal

Multiplies every sample value of a signal by -1.

Parameters
Parameter Example Description
sig sig=C3,C4 Signals to flip
Output

No output, other than message to the log and an updated in-memory signal.

Example

This next command takes the first 10 epochs of the C3 signal, outputs the original signal to a file (f1), then flips the signal, and re-outputs it (to f2):

luna me.lst sig=C3 -s "EPOCH & MASK epoch=1-10 & \
                       RESTRUCTURE & MATRIX file=f1 & \
                       FLIP & MATRIX file=f2"

Note

In the above, we used the end-of-line \ character (with no trailing whitespace) to continue the command on multiple lines, as many shells allow.

Comparing the original signals (looking at just the first 10 rows of output) ...

head f1
ID       E   S   SP T             C3
id001    1   0   0  0             3.43407
id001    1   0   1  0.00390625    2.06044
id001    1   0   2  0.0078125    -0.0763126
id001    1   0   3  0.0117188    -1.60256
id001    1   0   4  0.015625     -2.21306
id001    1   0   5  0.0195312    -2.21306
id001    1   0   6  0.0234375    -2.21306
id001    1   0   7  0.0273438    -2.06044
id001    1   0   8  0.03125      -2.06044

... to the new signals, we see the values have been flipped, albeit not as exactly as one might expect. (This is due to the encoding used by EDFs; see the note below for more details).

head f2
ID       E   S   SP T             C3
id001    1   0   0  0            -3.43865
id001    1   0   1  0.00390625   -2.06244
id001    1   0   2  0.0078125     0.0728122
id001    1   0   3  0.0117188     1.59799
id001    1   0   4  0.015625      2.20806
id001    1   0   5  0.0195312     2.20806
id001    1   0   6  0.0234375     2.20806
id001    1   0   7  0.0273438     2.05909
id001    1   0   8  0.03125       2.05909

Floating point accuracy

EDFs store data as 2-byte integers: in contrast, floating point numbers as used in Luna typically take up 4 or 8 bytes in memory. This relatively low resolution of EDF introduces slight numerical differences so that the values are clearly different from -1 times the original: i.e. 3.43407 is not minus -3.43865. As noted in the EDF spec, practically this limit on resolution is not a real issue for most biosignals, if they are recorded with sensible physical and digital min/max values to reflect the dynamic range of the signal.

RECORD-SIZE

Alters the record size of an EDF

This command changes the low-level encoding of data in an EDF, which is something that you should not normally need to change. Often, EDFs have a record size (i.e. the size of the blocks in which the data are stored) of 1 second or so. Why might you want to change this?

  • as the smallest EPOCH size is limited by the EDF record size, if the EDF record size is relatively large (e.g. 10 seconds), it will not be possible to specify smaller epochs (e.g. 5 seconds).

  • if the EDF record size is very small (e.g. 100 milliseconds), this can reduce performance when reading the EDF from disk

There are a number of points that should be borne in mind:

  • no subsequent commands can be issued after a RECORD-SIZE command; rather, a new EDF will be written to disk
  • you should ensure that the new record size contains an integer number of samples for all signals
  • currently, you can only change the record size of EDF, not EDF+ files
  • as only whole records are written to disk, the final part of an EDF (that is shorter than the new record size) may be truncated
Parameters
Parameter Example Description
dur dur=1 New EDF record/block size
edf-dir edf-dir=edfs/ Folder for writing new EDFs
edf-tag edf-tag=rec1 Tag added to new EDFs
sample-list sample-list=s2.lst Generate a sample-list pointing to the new EDFs

That is, while RECORD-SIZE itself only takes dur as the single option, one must also specify all options for WRITE, as RECORD-SIZE automatically triggers WRITE after changing the record size of the in-memory representation. (That is, as always, the original EDF file is left untouched.)

Output

No output, other than message to the log and an updated in-memory signal.

Example

Focusing only on the signals PR and EEG in the first tutorial EDF, we see that this EDF has a record size of 1 second:

luna s.lst 1 sig=PR,EEG -s "SUMMARY" 
# signals      : 2
# records      : 40920
Duration       : 1

That is, the EDF has 40,920 records, each of duration 1 second. Looking at the two signals, because the record duration is 1 second, this implies a sample rate of 1 Hz and 125 Hz respectively for PR and EEG.

Signal 1 : [PR]
       # samples per record : 1
...
Signal 2 : [EEG]
       # samples per record : 125
...

To generate a new EDF (which contains only these two signals) with an altered record size (in this example, 50 seconds):

luna s.lst 1 sig=PR,EEG -s "RECORD-SIZE dur=50 edf-tag=r50" 

(Note that setting a 50-second record size would be unusual, this is done here purely for illustrative purposes.) After running this command, you'll see the following messages in the log:

 saved new EDF, edfs/learn-nsrr01-r50.edf
 **warning: the PROBLEM flag was set, skipping to next EDF...

The warning message is expected, this is just Luna's way of ensuring that no further commands can be run after RECORD-SIZE command. Running SUMMARY on the new EDF, we see that the record size has been changed:

luna edfs/learn-nsrr01-r50.edf -s SUMMARY
# records      : 818
Duration       : 50
...
Signal 1 : [PR]
       # samples per record : 50
...
Signal 2 : [EEG]
       # samples per record : 6250
...

That is, instead of 40,920 records of 1 second we have 818 records of 50 seconds. Correspondingly, there are now 50 times the number of samples per record compared to the original EDF (the sample rate in Hz is obviously the same as before).

Note

Because 40,920 is not evenly divisible by 50, the last 20 seconds has been truncated (i.e. the log will indicate a total duration of 11:21:40 instead of the original 11:22:00).

ANON

Sets the in memory EDF header fields Patient ID and Start Date fields to missing (a . character). If a new EDF is generated with the WRITE command, it will have those fields blanked. As with all Luna commands, this does not alter the original EDF.

Note

This command does not alter the ID specified in the sample-list (i.e. the first column). That ID, which is used to track all output, etc, is distinct from the EDF header Patient ID field, and may or may not be similar.

Parameters

No parameters.

Output

No output other than message to the log, and altering the in-memory representation of the EDF header.

Example

A typical EDF with identifying information in the header (showing only relevant rows from the SUMMARY output):

luna my.edf -s "SUMMARY" | head 
EDF filename   : my.edf
Patient ID     : id00001
Recording info : 
Start date     : 07.06.16
Start time     : 23:07:56

... (cont'd) ...

Here we see how the ANON command effectively wipes this information:

luna my.edf -s "ANON & SUMMARY" | head 
EDF filename   : my.edf
Patient ID     : .
Recording info : 
Start date     : .
Start time     : 23:07:56

This next command takes all EDFs in a project (defined by s.lst) and creates a set of new EDFs with the WRITE command (in the folder edfs/, and with the new sample list s2.lst) that are identical except they have the Patient ID and Start Date fields set to missing:

luna s.lst -s "ANON & WRITE edf-dir=edfs/ edf-tag=anon sample-list=s2.lst"