Go to the first, previous, next, last section, table of contents.
These exercises are based on the material in the previous chapters.
Answers to some of them are at the back of the book, but try to work
through them first.
-
Type in the first program from the previous chapter, compile it, and run
it. Remember to set and export the environment variable
DB
(see section The Database Path). It is a good idea to include this step in your
`.profile', `.cshrc', or `autoexec.bat'. As input, try
record `100s', input annotator `atruth', and output annotator
`normal'. The program should finish in five seconds or less.
The annotations will have been written into a file called
`normal.100s' (under MS-DOS, `100s.nor') in the current
directory. Now type "rdann atruth 100s
" and observe the output
for a few seconds, then try "rdann normal 100s
" and notice the
difference.
-
Modify the program from the previous exercise so that the non-QRS
annotations are put into a second output annotation file. Remember that
you will need three annotation files in all (one input and two
output).
-
The next five short exercises are to be worked out on paper, although you
may wish to check your work on the computer. All of them assume that
we are given a signal sampled at 100 Hz with the following
specifications:
fname = "signal.dat"
desc = "BP"
units = "mmHg"
gain = 10
initval = 80
group = 0
fmt = 212
spf = 1
bsize = 0
adcres = 12
adczero = 0
baseline = -300
nsamp = 1000000
cksum = 3109
For starters, convert a sample value of 280 into physical units.
-
Convert 120 mmHg into adus.
-
What are the maximum and minimum possible sample values in adu? in
mmHg?
-
How large is `signal.dat', in bytes? How much space could we save
if we converted it to format 8 (eight-bit first-differences)? What is
the maximum slew rate (in mmHg/second) that we can represent in that
format?
-
Oops! We have just discovered that the maximum slew rate in our signal
is 1500 mmHg/sec. Is there any way to store it at full precision in one
of the supported formats, that saves space compared to its present
format?
-
Figure out how to plot or display the first 1000 points from signal 0 of
a record in amplitude vs. time format. You may wish to begin with the
example program from the first chapter. Arrange for the record name to
be read from the command line (see K&R, pp. 114--115, if you
don't know how to do this).
-
Try plotting VCGs by modifying the program from the previous exercise to
plot pairs of samples from each of two signals rather than sample
number/value pairs.
-
Modify the program from the previous exercise, or Example 2 from the
previous chapter, so that you can specify a segment of the record to be
processed with start and end times. For example, the command
your-program record 10:0 10:10
should skip the first ten minutes, then process the next ten seconds of
signals from record.
-
Wesley Q. Phortran, IV, wrote this program to print beat times (in
minutes and seconds) and R-R intervals for the reference annotation file
of record `100'. Why doesn't it work?
1 #include <ecg/db.h>
2
3 main()
4 {
5 DB_Annotation *annot;
6 DB_Anninfo ai;
7 int t;
8
9 ai.name = "atruth";
10 ai.stat = READ;
11 if (annopen(100, ai, 1)) {
12 while (getann(1, annot)) {
13 printf("%s\t(%d)\t%s\n", timstr(annot.time),
14 annot.time, mstimstr(annot.time - t));
15 t = annot.time;
16 }
17 }
18 }
Extra credit: Without actually trying it out, what does it
produce on the standard output?
-
Using
isigsettime
on a format 8 signal introduces a random offset
into the signal, since the contents of a format 8 signal file are first
differences rather than amplitudes. For an AC-coupled signal such as an
ECG, this is usually inconsequential, but a DC-coupled signal such as a
blood pressure signal is usually useful only if absolute levels are
known. If we store such a signal in format 8, we must read it
sequentially from the beginning in order to get correct sample values.
If we intend to do a lot of non-sequential processing of such a signal,
it may be worthwhile to build a table containing the correct sample
values at periodic intervals; then we can use isigsettime
to
skip to a sample in the table, and read forward sequentially from that
point. Write a program to build such a table, and wrappers for
isigsettime
and getvec
to give random access to format 8
signal files without introducing offset errors. On your system, how
many sample intervals should be allowed between table entries in order
to obtain an isigsettime
equivalent that executes in an average
of 100 msec or less?
-
This exercise assumes that you have access to the MIT-BIH Arrhythmia
Database. Since the 360 Hz sampling frequency used in that database is
an integer multiple of 60 Hz, it is quite easy to design a 60 Hz notch
filter that can be applied to the database. Write a program that
filters two input signals and writes out the filtered data using
putvec
(see section Example 7: A General-Purpose FIR Filter, for a model program). Try it out on
MIT-BIH record `122'. Caution: signal files are quite large. In
order to avoid using too much disk space for this exercise, limit the
program to writing 10 seconds' worth of samples. Use your programs from
the previous exercises to display your output.
-
If you used Example 7 as a model in the previous exercise, you may have
noticed that it is quite slow. Make it faster by arranging for
sample
to return a pointer to a vector of samples from all
signals (thereby reducing the number of function calls). Speed it up
further by defining a macro that calls the function only if the proper
sample vector is not already in the circular buffer; otherwise the macro
should evaluate to a pointer to the correct sample vector.
-
Prof. Nottin Ventedhier says, "Real programmers don't use inefficient
library I/O routines -- they write their own, in assembly language."
Implement a version of the QRS detector in Example 10 without
using the DB library. (To keep it simple, assume that only one input
format -- of your choice -- needs to be supported.) How much faster
than the original is your version?
-
(Non-trivial) Write a QRS detector that is independent of sampling
frequency. Some useful constants (for adult human ECGs): average normal
QRS duration = 80 milliseconds, average QRS amplitude = 1 millivolt,
average R-R interval = 1 second; assume that upper and lower limits for
these quantities are within a factor of 3 of the average values. If you
have access to the MIT-BIH Arrhythmia Database, run your detector on
record `200'. Read the documentation on the annotation
comparator, `bxb', and figure out how to use it to compare the
annotation file produced by your program against the reference annotator
`atruth'. How does your detector compare to Example 10?
-
If the previous exercise was too easy, modify your detector so that the
annotations it generates match those in the `atruth' file. Copying
the `atruth' file is not permitted. You may find this rather
difficult. Good luck!
Go to the first, previous, next, last section, table of contents.
George B. Moody (george@hstbme.mit.edu)