edfAsc can export an EDF signal to a file composed by float values. Float values are scaled to the units of the signal and no calculation is needed to get the signal properly scaled. Each value is coded in 4 bytes, so it uses about double space than the same signal in EDF format (EDF codes each value as a short integer using 2 bytes). The way to export the values is fairly similar to the export of ASCII files. The only difference is that we click the button Export as float
I would like to present here how to read this kind of files with some of my favorite programs. They are open source and some of them are GPL licensed. We will follow the next approach
All the programs considered are able to handle very long signals. So we are going to read the whole signal in the internal memory used by the program. Using edfAsc, we export the signal EEG Pz-Oz of the file st7121j0.rec. The file is avaliable at Physionet. We call the file EEG.fl. The file is composed by float values sampled at 100 Hz. Now let's review some programs
Scilab is a scientific software package for numerical computations providing a powerful open computing environment for engineering and scientific applications. It is being developed since 1990 by researchers from INRIA and ENPC.
The first thing to do is to search for the length of the file and divide this size by four (each value is stored in four bytes) to know the amount of data to be read.
So we have to read a lot of values. We can increase the stacksize to get such
amount of values, handling shorter files this step would not be necessary
(you could consult Scilab
documentation
)
We did it. For those people not familiar with Scilab we set the position of
the file at the beginning and read n little-endian float from the
file. It is a very fast procedure.
Scilab can do a lot of things such as filtering signals, making a
montage by subtracting two signals and many others. We are going to create a
wav file by saving the file as if it would have been recorded at 40000
Hz (i.e., a 400 times acceleration)
This file can be processed by programs designed to handle sounds. The screen of the file as seen in the screen of Wavesurfer
is shown in figure 4.1
The light band around of 5500 Hz It corresponds with the sleep spindles
(5500/400 = 13.75 Hz). We can see the slow wave sleep as well as the REM
periods without spindles. If you want to experiment the audition of sleep
recordings I recommend the use of
edf2wav. It is a much easier way
to create a wav file from an EDF file. If you are using Linux you can also
run this program using wine
-->name = "EEG.fl";
-->info = fileinfo(name);
-->n = info(1)/4
n =
3729000.
-->stacksize(20000000)
-->fid = mopen(name,"rb")
ans =
1.
-->mseek(0,fid)
-->eeg = mget(n,"fl",fid);
-->size(eeg)
ans =
! 1. 3729000. !
-->max(eeg)
ans =
2719.0991
-->min(eeg)
ans =
- 3000.
-->savewave("eeg.wav",eeg/3000,40000)
Writing Wave file: Microsoft PCM format, 1 channel, 40000 samp/sec
80000 byte/sec, 2 block align, 16 bits/samp
Finished writing Wave file, 7458000 data bytes
ans =
93.225
R is a language and environment for statistical computing and graphics. R provides a wide variety of statistical and graphical techniques. It is also able to handle very easily neurophysiological signals.
Now we can access the whole signal. As an example let's do the Maximal Overlap
Discrete Wavelet Transform of the segment. This is included in the package
called
Waveslim.
(See the incredible list of R
packages available)
The result is shown in figure 4.2
The goal of this example is to show that the whole signal is available and
that there are a lot of possibilities of digital signal processing using R.
In my humble opinion R it is second to none in Statistics.
> name = "EEG.fl"
> n <- as.numeric(file.info(name)$size)/4
> f<-file(name,"rb")
> seek(f,0)
[1] 0
> eeg <- as.matrix(readBin(f,n=n,double(),4))
> dim(eeg)
[1] 3729000 1
> library(waveslim)> segment = eeg[3000000:3003000,]
> segment.modwt<-modwt(segment,n.levels=3)
> names(segment.modwt)
[1] "d1" "d2" "d3" "s3"
> par (mfrow = c(5,1))
> ts.plot(segment)
> ts.plot(segment.modwt$d1)
> ts.plot(segment.modwt$d2)
> ts.plot(segment.modwt$d3)
> ts.plot(segment.modwt$s3)
LastWave is a signal processing oriented command language. It is somewhat difficult to install, specially in Windows, but it is very friendly and powerful once installed. Let's try a spectrogram of the whole signal. In this case we do not need to know the length of the file
That's all. It is also very fast. We have the signal available to process.
Let's do it
The result is shown in figure 4.3
51 wtrans a> eeg = <>
= <size=0>
52 wtrans a> read eeg "EEG.fl" -r 'little'
53 wtrans a> eeg
= <size=3729000;-11.1701,-8.24025,-7.14155,-7.14155,-5.67662,-7.50778,...>
57 wtrans a> eeg.dx = 0.01
= 0.01
58 wtrans a> eegs = [new &stft]
= <&stft;0x82e8cc0>
59 wtrans a> stftd eegs eeg 1024
60 wtrans a> disp eeg eegs
Everybody knows Perl. You can create small scripts to fill your needs. We are going to create a small program that reads all the floats of a file and detects the range of the signal. This is the code:
It is a simple program that reads all the content of the file and unpacks the
buffer as floats. Let's see the result. We can compare with the result
obtained using Scilab
One of the main advantages of using Perl is that you can create easily
standalone programs that are very well adapted to your needs.
#/usr/bin/perl
use strict;
my $filename = $ARGV[0] or die ;
my @infofile = stat($filename);
my $sizefile = $infofile[7];
my $nvalues = $sizefile/4;
open INPUT, "<$filename";
seek (INPUT,0,0);
read(INPUT,my $buffer,$sizefile);
my @values = unpack("f$nvalues",$buffer);
my $min = $values[0];
my $max = $values[0];
foreach (@values){
if( $_ > $max){ $max = $_};
if( $_ < $min){ $min = $_};
}
print "minimum $min\n";
print "maximum $max\n";
je@unit1:~/tmp/tutorial> perl maxmin.pl EEG.fl
minimum -3000
maximum 2719.09912109375
You could also consider using a library that allows to access the data directly. I would recommend libRASCH.
In summary, using a file of floats isn't the perfect solution to interchange data (e.g., we do not know the sampling rate, the date when the file was acquired and many other things) but it can be a convenient option to interchange information with other programs if you want to develop some processing tool. Reading these files can be very fast and the process can be carried out by many programs.