API Documentation

Import EDF to Onda

OndaEDF.jl prefers "self-service" import over "automagic", and provides functionality to extract Onda.Samples and Onda.Annotations from an EDF.File. These can be written to disk (with Onda.store / Onda.write_annotations) or manipulated in memory as desired.

OndaEDF.edf_to_onda_samplesFunction
edf_to_onda_samples(edf::EDF.File; custom_extractors=())

Read signals from an EDF.File into a vector of Onda.Samples, which are returned along with a NamedTuple with diagnostic information (the same info returned by edf_header_to_onda_samples_info).

Collections of EDF.Signals are mapped as channels to Onda.Signals via simple "extractor" callbacks of the form:

edf::EDF.File -> (samples_info::Onda.SamplesInfo,
                  edf_signals::Vector{EDF.Signal})

edf_to_onda_samples automatically uses a variety of default extractors derived from the EDF standard texts; see src/standards.jl for details. The caller can also provide additional extractors via the custom_extractors keyword argument.

EDF.Signal labels that are converted into Onda channel names undergo the following transformations:

  • the label is whitespace-stripped, parens-stripped, and lowercased
  • trailing generic EDF references (e.g. "ref", "ref2", etc.) are dropped
  • any instance of + is replaced with _plus_ and / with _over_
  • all component names are converted to their "canonical names" when possible (e.g. "m1" in an EEG-matched channel name will be converted to "a1").

See the OndaEDF README for additional details regarding EDF formatting expectations.

OndaEDF.edf_to_onda_annotationsFunction
edf_to_onda_annotations(edf::EDF.File, uuid::UUID)

Extract EDF+ annotations from an EDF.File for recording with ID uuid and return them as a vector of Onda.Annotations. Each returned annotation has a value field that contains the string value of the corresponding EDF+ annotation.

If no EDF+ annotations are found in edf, then an empty Vector{Annotation} is returned.

Import utilities

OndaEDF.extract_channels_by_labelFunction
extract_channels_by_label(edf::EDF.File, signal_names, channel_names;
                          unit_alternatives=STANDARD_UNITS, preprocess_labels=(l,t) -> l)

For one or more signal names and one or more channel names, return a list of [(infos, errors)...] where errors is a vector of errors that occurred, and infos is a vector of (si::Onda.SamplesInfo, edf_signals::Vector{EDF.Signal}), where edf_signals align with si.channel. This list can have more than one pair if channels with the same signal kind/type have different sample rates or physical units.

(label, transducer_type) pairs will be transformed into labels by preprocess_labels (default preprocessor returns the original label). An alternate to STANDARD_UNITS for mapping different spellings of units to their canonical unit name can be passed in as unit_alternatives.

errors contains SamplesInfoErrors thrown if channels corresponding to a signal were extracted but an error occured while interpreting physical units, while promoting sample encodings, or otherwise constructing a SamplesInfo.

signal_names should be an iterable of Strings naming the signal types to extract (e.g., ["ecg", "ekg"]; ["eeg"]).

channel_names should be an iterable of channel specifications, each of which can be either a String giving the generated channel name, or a Pair mapping a canonical name to a list of alternatives that it should be substituted for (e.g., "canonical_name" => ["alt1", "alt2", ...]).

unit_alternatives lists standardized unit names and alternatives that map to them. See OndaEDF.STANDARD_UNITS for defaults.

preprocess_labels(label::String, transducer_type::String) is applied to raw edf signal header labels beforehand; defaults to returning label.

See OndaEDF.STANDARD_LABELS for the labels (signal_names => channel_namesPairs) that are used to extract EDF signals by default.

OndaEDF.edf_signals_to_samplesinfoFunction
edf_signals_to_samplesinfo(edf, edf_signals, kind, channel_names, samples_per_record; unit_alternatives=STANDARD_UNITS)

Generate a single Onda.SamplesInfo for the given collection of EDF.Signals corresponding to the channels of a single Onda signal. Sample units are converted to Onda units and checked for consistency, and a promoted encoding (resolution, offset, and sample type/rate) is generated.

No conversion of the actual signals is performed at this step.

Full-service import

For a more "full-service" experience, OndaEDF.jl also provides functionality to extract Onda.Samples and Onda.Annotations and then write them to disk:

OndaEDF.store_edf_as_ondaFunction
store_edf_as_onda(path, edf::EDF.File, uuid::UUID=uuid4();
                  custom_extractors=STANDARD_EXTRACTORS, import_annotations::Bool=true,
                  postprocess_samples=identity,
                  signals_prefix="edf", annotations_prefix=signals_prefix)

Convert an EDF.File to Onda.Samples and Onda.Annotations, store the samples in $path/samples/, and write the Onda signals and annotations tables to $path/$(signals_prefix).onda.signals.arrow and $path/$(annotations_prefix).onda.annotations.arrow. The default prefix is "edf", and if a prefix is provided for signals but not annotations both will use the signals prefix. The prefixes cannot reference (sub)directories.

Returns uuid => (signals, annotations).

Samples are extracted with edf_to_onda_samples, and EDF+ annotations are extracted with edf_to_onda_annotations if import_annotations==true (the default).

Collections of EDF.Signals are mapped as channels to Onda.Signals via simple "extractor" callbacks of the form:

edf::EDF.File -> (samples_info::Onda.SamplesInfo,
                  edf_signals::Vector{EDF.Signal})

store_edf_as_onda automatically uses a variety of default extractors derived from the EDF standard texts; see src/standards.jl and extract_channels_by_label for details. The caller can provide alternative extractors via the custom_extractors keyword argument, and the edf_signals_to_samplesinfo utility can be used to extract a common Onda.SamplesInfo from a collection of EDF.Signals.

EDF.Signal labels that are converted into Onda channel names undergo the following transformations:

  • the label's prepended signal type is matched against known types, if present
  • the remainder of the label is whitespace-stripped, parens-stripped, and lowercased
  • trailing generic EDF references (e.g. "ref", "ref2", etc.) are dropped
  • any instance of + is replaced with _plus_ and / with _over_
  • all component names are converted to their "canonical names" when possible (e.g. for an EOG matched channel, "eogl", "loc", "lefteye", etc. are converted to "left").

EDF.Signals which get extracted into more than one Onda.Samples are removed and an AmbiguousChannelError displayed as a warning.

See the OndaEDF README for additional details regarding EDF formatting expectations.

Export EDF from Onda

OndaEDF.onda_to_edfFunction
onda_to_edf(signals, annotations=[]; kwargs...)

Return an EDF.File containing signal data converted from the Onda signals table and (optionally) annotations from an annotations table.

Following the Onda v0.5 format, both signals and annotations can be any Tables.jl-compatible table (DataFrame, Arrow.Table, NamedTuple of vectors, vector of NamedTuples) which follow the signal and annotation schemas (respectively).

Each EDF.Signal in the returned EDF.File corresponds to a channel of an Onda.Signal.

The ordering of EDF.Signals in the output will match the order of the rows of the signals table (and within each channel grouping, the order of the signal's channels).