Sleep stages
Demonstration code for analysis of sleep stages using SleepStages().
Link to script: feature_extraction/sleep_stages.py
import os
import numpy as np
import matplotlib.pyplot as plt
from nnsa import SleepStages, AnnotationSet, Annotation, print_object_summary, SUPPORTED_RESULT_FILE_TYPES, \
read_result_from_file, assert_equal, EdfReader
plt.close('all')
Parameters.
# Print the default parameters of SleepStages():
print(SleepStages().default_parameters())
# Descriptions of the parameters are documented in the default_parameters() code.
# Create an instance of the SleepStages class with custom parameters, overruling some defaults:
class_labels = ['QS', 'AS', 'AF']
ss = SleepStages(
class_labels=class_labels,
interpolate_artefacts_kwargs={'max_duration': 0}
)
# See if the custom parameters were accepted:
print('\nCustom parameters:')
print(ss.parameters)
Main method: sleep_stages.
# Now that we have initialized a SleepStages object with certain parameters, we can run the sleep_stages method,
# which converts text annotations to sleep stage labels. First we create some random annotations.
annotation_set = AnnotationSet([
Annotation(onset=on, duration=du, text=te) for on, du, te in zip([0, 10, 50.3, 1020, 4002.3, 7000],
[7.6, 20, 500, 2222, 2000, 100],
['QS TA', 'artefact', 'QS HVS', 'AS1', 'QS'])
])
# Print the annotations.
annotation_set.print_all_annotations()
# Convert the annotation_set to sleep stages using the custom parameters that were used when creating ss.
result = ss.sleep_stages(annotation_set)
# The returned object is a SleepStagesResult object, which is a high-level interface for
# manipulating/visualizing/saving the result:
print('\nSummary of result object:')
print_object_summary(result)
SleepStagesResult attributes.
# The main attribute is annotation_set, which contains the sleep stages labels as annotations:
print('result.annotation_set:')
result.annotation_set.print_all_annotations()
# Note at least 4 things that the sleep_stages method has done:
# 1) Convert each annotation to either 'QS' (quiet sleep), 'NQS' (non quiet sleep) or 'NL' (no label, also
# includes artefacts, dubious, etc.). Note that those class labels into which the annotations are converted can be
# chosen via the class_mapping parameter.
# 2) Fill 'empty'/unlabeled periods with 'NL' annotations.
# 3) Interpolate/replace 'NL' segments when applicable (e.g. the artefact annotation is replaced by QS since it's
# duration was short (shorter than the max_duration parameter) and surrounded by the same class label ('QS')).
# 4) Merge successive annotations if their label is the same.
# The labels of the classes and their mapping to class numbers are stored in the class_mapping attribute:
print('result.class_mapping: {}'.format(result.class_mapping))
SleepStagesResult methods.
# The methods allow to get certain information easily, some examples of available methods
# (see docs for complete overview):
print('Number of annotations per class:\n', result.count_annotations_per_class())
print('QS mask for query points:\n', result.create_mask(class_label='QS', query_times=np.array([0, 30, 60, 300, 750])))
print('Number of cycles going from QS -> AS -> QS:\n', result.cycle_count(class_label='QS', ignore_labels=['AF']))
print('Class numbers of annotations:\n', result.get_classes())
print('Times of intervals between QS segments:\n', result.inter_class_intervals(class_label='QS'))
print('Interpolation of classes at query points:\n', result.interpolate_classes(
query_times=np.array([0, 30, 60, 300, 750]),
kind='previous'))
print('Proportion of time in QS:\n', result.proportion(class_label='QS'))
# We can also graphically visualize the sleep stages with a hypnogram.
result.plot_hypnogram()
Save the result.
# We can save the result to any supported file. To list the supported file types/extensions:
print('Supported result file types: {}'.format(SUPPORTED_RESULT_FILE_TYPES))
# E.g. save as hdf5 (the file type to save is automatically detected from the extension of the filename).
filename = 'temp_result.hdf5'
result.save_to_file(filename)
# We can reload the result back to a SleepStagesCnnResult object:
result_loaded = read_result_from_file(filename)
# Remove temporary file.
os.remove(filename)
# Verify that the loaded object is equal to the original object:
assert_equal(actual=result_loaded, desired=result) # Will raise an AssertionError if not equal.
print('Loaded result object is equal to original object.')