import re
from nnsa.edfreadpy.io.config import BASIC_UNITS, UNIT_PREFIXES, \
EEG_LABELS, EEG_SENSORS, EEG_TYPE, \
ECG_TYPE, ECG_SENSORS, ECG_LABELS
[docs]def check_unit(unit):
"""
Check if the unit is a valid standardized unit.
Args:
unit (str): a unit (physical dimension).
Returns:
(bool): True if the unit is a valid standardzied unit, False if not.
"""
if unit == 'a.u.':
return True
# Ignore the 'NOS' unit in some files.
if unit == 'NOS':
return True
# Split unit at locations of /, *, ^, or a positive integer.
for unit_part in re.split('/|\*|\^|[0-9]+', unit):
# Check if part is not empty.
if unit_part:
# Check if current part is invalid.
if not (unit_part in BASIC_UNITS) and not (unit_part[0] in UNIT_PREFIXES and unit_part[1:] in BASIC_UNITS):
# Invalid unit.
return False
# If we did not return by now, the unit is valid.
return True
[docs]def standardize_and_check_ecg_label(label):
"""
Check if the label is a valid signal label for ECG signals and convert a non-standardazied, but valid ECG label
to a standardized ECG label.
Args:
label (str): a label for an ECG signal.
Returns:
label (str): the (standardized) ECG signal label. If valid is True, this is the valid standardized label.
If valid is False, this is the unchanged, original (invalid) label.
valid (bool): True if the specified label is a valid label, False if not.
"""
# Label is not case-sensitive and not sensitive to leading or trailing spaces.
label_lower = label.lower().strip()
ecg_labels = [lab.lower() for lab in ECG_LABELS]
ecg_sensors = [sens.lower() for sens in ECG_SENSORS]
# Initialize valid bool to False and start testing whether label is valid.
valid = False
# Labels like 'ECG II' are standardized labels, hence valid.
if label_lower in ecg_labels:
label = ECG_LABELS[ecg_labels.index(label_lower)]
valid = True
# Labels like 'II' are valid, but need to be converted to standardized labels.
elif label_lower in ecg_sensors:
label = ' '.join([ECG_TYPE, ECG_SENSORS[ecg_sensors.index(label_lower)]]) # ECG II.
valid = True
# Labels like 'ECG' are valid, but need to be converted to standardized labels.
elif label_lower == 'ecg':
label = ECG_TYPE # ECG.
valid = True
return label, valid
[docs]def standardize_and_check_eeg_label(label):
"""
Check if the label is a valid signal label for EEG signals and convert a non-standardazied, but valid EEG label
to a standardized EEG label.
Args:
label (str): a label for an EEG signal.
Returns:
label (str): the (standardized) EEG signal label. If valid is True, this is the valid standardized label.
If valid is False, this is the unchanged, original (invalid) label.
valid (bool): True if the specified label is a valid label, False if not.
"""
# Label is not case-sensitive and not sensitive to leading or trailing spaces.
label_lower = label.lower().strip()
eeg_labels = [lab.lower() for lab in EEG_LABELS]
eeg_sensors = [sens.lower() for sens in EEG_SENSORS]
# Initialize valid bool to False and start testing whether label is valid.
valid = False
# Labels like 'EEG Cz' are standardized labels, hence valid.
if label_lower in eeg_labels:
label = EEG_LABELS[eeg_labels.index(label_lower)]
valid = True
# Labels like 'Cz' are valid, but need to be converted to standardized labels.
elif label_lower in eeg_sensors:
label = ' '.join([EEG_TYPE, EEG_SENSORS[eeg_sensors.index(label_lower)]]) # EEG C4
valid = True
# Labels like 'EEG C4-Cz' are valid.
elif all([lab in eeg_sensors for lab in label_lower.replace('eeg ', '').split('-')]):
label = label
valid = True
# Labels like 'EEG C4-EEG Cz' are valid.
elif all([lab in eeg_labels for lab in label_lower.split('-')]):
label = ' '.join([EEG_TYPE, label.replace('EEG ', '')]) # EEG C4-Cz
valid = True
# Labels like 'C4-Cz' are valid.
elif all([lab in eeg_sensors for lab in label_lower.split('-')]):
label = ' '.join([EEG_TYPE, label]) # EEG C4-Cz
valid = True
return label, valid
[docs]def standardize_and_check_label(label):
"""
Check if the label is a valid standardized signal label according to EDF+ standards.
If not, tries to convert a non-standardazied, but valid label to a standardized label.
Args:
label (str): a label for an arbitrary signal.
Returns:
label (str): the (standardized) signal label. If valid is True, this is the valid standardized label.
If valid is False, this is the unchanged, original (invalid) label.
valid (bool): True if the specified label is a valid label, False if not.
"""
# Initialize valid bool to False and start testing whether label is valid.
valid = False
# ECG.
if not valid:
label, valid = standardize_and_check_ecg_label(label)
# EEG.
if not valid:
label, valid = standardize_and_check_eeg_label(label)
# Oxygen.
if not valid and label.lower().strip() in [
'sao2', 'spo2', 'pleth',
'rsco2', 'rso2', 'rso2-1', 'rso2-2', 'sao2 rso.-1', 'sao2 rso.-1', 'sao2 rso2-1', 'sao2 rso2-2'
'tfoe', 'toi',
]:
if len(label.strip().split(' ')) == 1 or not label.lower().startswith('sao2'):
label = 'SaO2 {}'.format(label)
valid = True
# Respiration.
if not valid and ((label.lower().strip() in ['abdomen', 'thorax']) or ('resp' in label.lower())):
if not label.lower().startswith('resp'):
label = 'Resp {}'.format(label)
valid = True
# Random.
# Labels like 'Random channel 1' are valid.
if not valid and ('random' in label.lower() or 'channel' in label.lower()):
valid = True
# Other.
if not valid:
if len(label.strip().split(' ')) == 1 or not any(
[label.lower().strip().startswith(lab) for lab in [
'temp', 'resp', 'sao2', 'light', 'sound', 'event', 'vol',
'eog', 'erg', 'emg', 'meg', 'mcg', 'ep',
'dist', 'area', 'vol', 'dur', 'vel', 'mass', 'angle', '%', 'value',
]]):
label = 'Unspec {}'.format(label)
return label, valid