Read EDF Header and Signal Header

Read EDF Header and Signal Header

In this tutorial, you will learn how to:

  1. Read the attributes from the EDF Header
  2. Iterate through the EDF Signal Header

The Requirements for running this tutorial are described after the discussion of the tutorial script.

The script

require 'rubygems'
require 'colorize'
require 'edfize'
require 'nsrr'
require 'nsrr/commands/download'

Nsrr::Commands::Download.run(%w(download learn/polysomnography/edfs/learn-nsrr01.edf --token=public))

puts "EDFs Downloaded: #{Edfize.edf_paths.count}"
Edfize.edfs.each do |edf|
  puts "\nEDF                            : #{edf.filename}"
  puts "Total File Size                : #{edf.edf_size} bytes"
  puts "\nHeader Information"
  puts "\nGeneral Information"
  puts "Expected Size of Header (bytes): #{edf.expected_size_of_header}"
  puts "Expected Size of Data   (bytes): #{edf.expected_data_size}"
  puts "Expected Total Size     (bytes): #{edf.expected_edf_size}"

  puts "                        version: #{edf.version}"
  puts "   local_patient_identification: #{edf.local_patient_identification}"
  puts " local_recording_identification: #{edf.local_recording_identification}"
  puts "        start_date_of_recording: #{edf.start_date_of_recording}"
  puts "        start_time_of_recording: #{edf.start_time_of_recording}"
  puts "      number_of_bytes_in_header: #{edf.number_of_bytes_in_header}"
  puts "                       reserved: #{edf.reserved}"
  puts "         number_of_data_records: #{edf.number_of_data_records}"
  puts "      duration_of_a_data_record: #{edf.duration_of_a_data_record}"
  puts "              number_of_signals: #{edf.number_of_signals}"

  puts "\nSignal Information"
  edf.signals.each_with_index do |signal, index|
    puts "\n                       Position: #{index + 1}"
    puts "                          Label: #{signal.label}"
    puts "                Transducer Type: #{signal.transducer_type}"
    puts "             Physical Dimension: #{signal.physical_dimension}"
    puts "               Physical Minimum: #{signal.physical_minimum}"
    puts "               Physical Maximum: #{signal.physical_maximum}"
    puts "                Digital Minimum: #{signal.digital_minimum}"
    puts "                Digital Maximum: #{signal.digital_maximum}"
    puts "                   Prefiltering: #{signal.prefiltering}"
    puts "        Samples Per Data Record: #{signal.samples_per_data_record}"
    puts "                  Reserved Area: #{signal.reserved_area}"
  end
end

puts "\nCongrats! You have completed your second tutorial!".colorize(:green).on_white

download script

Breaking down the script

The script downloads a single EDF from the Learn dataset using the Nsrr::Commands::Download.run method.

Next, the script iterates through all EDFs loaded in the current directory, and prints out information about each EDF. An EDF header has two distinct parts, a fixed size attribute header, and a signal header of varying size. The following attributes exist in the EDF header.

EDF Header

  • :version
    • Version
  • :local_patient_identification
    • Local Patient Identification
  • :local_recording_identification
    • Local Recording Identification
  • :start_date_of_recording
    • Start Date of Recording, stored as (dd.mm.yy)
  • :start_time_of_recording
    • Start Time of Recording', stored as (hh.mm.ss)
  • :number_of_bytes_in_header
    • Number of Bytes in Header
  • :reserved
    • Reserved'
  • :number_of_data_records
    • Number of Data Records'
  • :duration_of_a_data_record
    • Duration of a Data Record, in seconds
  • :number_of_signals
    • Number of Signals'

The size of the EDF signal header depends on the number of signals present in the EDF. Each signal is described in the signal header and has the following attributes. These attributes help describe how each signal is read and allows EDF readers to reconstruct the EDF signals.

EDF Signal Header

  label:                   { size: 16, after_read: :strip, name: 'Label' },
  transducer_type:         { size: 80, after_read: :strip, name: 'Transducer Type' },
  physical_dimension:      { size:  8, after_read: :strip, name: 'Physical Dimension' },
  physical_minimum:        { size:  8, after_read: :to_f,  name: 'Physical Minimum' },
  physical_maximum:        { size:  8, after_read: :to_f,  name: 'Physical Maximum' },
  digital_minimum:         { size:  8, after_read: :to_i,  name: 'Digital Minimum' },
  digital_maximum:         { size:  8, after_read: :to_i,  name: 'Digital Maximum' },
  prefiltering:            { size: 80, after_read: :strip, name: 'Prefiltering' },
  samples_per_data_record: { size:  8, after_read: :to_i,  name: 'Samples Per Data Record' },
  reserved_area:           { size: 32,                     name: 'Reserved Area' }

In the script, edfize provides an enumerator to the signals that can be accessed by using the edf.signals signals method on the loaded EDF. Iterating through multiple signals is simplified using this enumerator or array of signals.

Try This

  1. Edfize can load portions of the EDF signals using the following method: load_epoch(epoch_number, epoch_size) The epoch number is zero-indexed (starts with epoch zero), and epoch size is in number of seconds. For example, you can load the first 30 seconds into memory by typing: edf.load_epoch(0, 30). Modify the script to load the EDF, load the first 30 second epoch, and the corresponding array of physical_values for each signal.

If you completed this tutorial, please leave a review and check out the next tutorial in the series:

Tutorial 03 - Rewrite EDF Header Start Date of Recording

Requirements

This tutorial requires that you have Ruby 2.2 or above installed, preferably Ruby 2.3 or higher.

Extract

Extract the script to your desktop to a folder of the same name. Open your console (Command Prompt on Windows or Terminal on Mac/Linux) and navigate to your tutorial folder.

MacOS/Linux

cd ~/Desktop/tutorial_02

Windows

cd %USERPROFILE%\Desktop\tutorial_02

Notes

  • cd stands for "Change Directory"
  • ~, and %USERPROFILE% represents your user home directory

Installing the required gems.

This script requires you to have the colorize, nsrr, and edfize gems installed. The colorize gem is used to color command line output. The nsrr gem is used to easily download sets of files from the National Sleep Research Resource (https://sleepdata.org). The edfize gem is used to read and write EDF files using Ruby.

In your console type:

gem install colorize nsrr edfize --no-document

This command will get you the latest stable release of the colorize, nsrr, and edfize gem from RubyGems.org. The --no-document flag specifies to skip the installation of the documentation for the gems.

Running the script.

In your console and from the tutorial_02 directory, type:

ruby tutorial_02.rb

Questions?

Remember, if you have any questions on this script, please let us know on the NSRR forum here: https://sleepdata.org/forum, or email us at support@sleepdata.org.