+ All Categories
Home > Documents > WFDB Programmer’s Guideinstrumentasi.lecture.ub.ac.id/files/2012/09/wpg.pdf · WFDB...

WFDB Programmer’s Guideinstrumentasi.lecture.ub.ac.id/files/2012/09/wpg.pdf · WFDB...

Date post: 11-Jul-2020
Category:
Upload: others
View: 8 times
Download: 0 times
Share this document with a friend
162
WFDB Programmer’s Guide Tenth Edition (revised and with additions for WFDB library version 10.5.10) 16 November 2011 George B. Moody Harvard-MIT Division of Health Sciences and Technology
Transcript
  • WFDB Programmer’s Guide

    Tenth Edition (revised and with additions for WFDB library version 10.5.10)16 November 2011

    George B. Moody

    Harvard-MIT Division of Health Sciences and Technology

  • Copyright c© 1980 – 2011 George B. Moody

    The most recent versions of the software described in this guide may be downloaded fromhttp://physionet.org/.See http://physionet.org/physiotools/wpg/ for an HTML version of this guide.

    Permission is granted to make and distribute verbatim copies of this guide provided thatthe copyright notice and this permission notice are preserved on all copies.Permission is granted to copy and distribute modified versions of this guide under theconditions for verbatim copying and under the conditions that follow in this paragraph.Each copy of the resulting derived work must contain a notice that it is a modified versionof this guide. The notice must state which edition of this guide was the source for thederived work, and it must credit the authors of this guide and of the modifications. Theentire resulting derived work must be distributed under the terms of a permission noticeidentical to this one.Permission is granted to copy and distribute translations of this guide into another language,under the above conditions for modified versions.The author would appreciate receiving copies of any modified or translated versions of thisguide for reference purposes.

    http://physionet.org/http://physionet.org/physiotools/wpg/

  • i

    Table of Contents

    Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Signals, Samples, and Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2Annotations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3About this Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

    1 Using the WFDB Library . . . . . . . . . . . . . . . . . . . . . . 71.1 A Trivial Example Program in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.2 Compiling a Program with the WFDB Library . . . . . . . . . . . . . . . . . 81.3 Using the WFDB library with other languages . . . . . . . . . . . . . . . . . . 9

    C++ bindings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9Fortran wrappers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9SWIG wrappers for Java, Perl, Python, and other languages . . . . . 10Matlab toolbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

    1.4 The Database Path and Other Environment Variables . . . . . . . . . 121.5 Running the Example Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131.6 A Note on Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131.7 More About the WFDB Path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

    2 WFDB Library Functions . . . . . . . . . . . . . . . . . . . . 17About these functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172.2 Selecting Database Records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

    annopen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18isigopen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19osigopen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20osigfopen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21wfdbinit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

    2.3 Special I/O Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23setifreq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23getifreq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24setgvmode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24getgvmode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24getspf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25setafreq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25getafreq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

    2.4 Reading and Writing Signals and Annotations . . . . . . . . . . . . . . . . . 26getvec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26getframe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27putvec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27getann . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

  • ii WFDB Programmer’s Guide

    ungetann . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29putann . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

    2.5 Non-Sequential Access to WFDB Files . . . . . . . . . . . . . . . . . . . . . . . . 31isigsettime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31isgsettime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31tnextvec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31iannsettime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31sample and sample valid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

    2.6 Conversion Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33annstr, anndesc, and ecgstr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33strann and strecg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34setannstr, setanndesc, and setecgstr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34[ms]timstr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35strtim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35datstr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36strdat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37aduphys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37physadu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37adumuv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38muvadu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

    2.7 Calibration Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39calopen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39getcal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39putcal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39newcal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40flushcal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

    2.8 Miscellaneous WFDB Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41newheader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41setheader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41setmsheader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42getseginfo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42wfdbquit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42iannclose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43oannclose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43wfdbquiet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43wfdbverbose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44wfdberror . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44wfdbmemerr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44sampfreq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44setsampfreq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45setbasetime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45getcfreq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46setcfreq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46getbasecount . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46setbasecount . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47setwfdb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47getwfdb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47resetwfdb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

  • iii

    wfdbfile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48wfdbflush . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48getinfo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48putinfo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49setibsize . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49setobsize . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50wfdbgetskew . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50wfdbsetskew . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51wfdbgetstart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51wfdbsetstart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51wfdbputprolog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

    2.9 memory allocation macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53MEMERR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53SFREE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53SUALLOC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53SALLOC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53SREALLOC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54SSTRCPY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

    3 Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 553.1 Signal Information Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563.2 Calibration Information Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583.3 Annotator Information Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583.4 Annotation Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 593.5 Segment Information Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

    4 Annotation Codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 614.1 Macros for Mapping Annotation Codes . . . . . . . . . . . . . . . . . . . . . . . . 62

    5 Database Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655.1 File Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

    Header Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65Signal Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65Annotation Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66Calibration Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66EDF Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66AHA Format Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

    5.2 Using Standard I/O for Database Files . . . . . . . . . . . . . . . . . . . . . . . . 675.3 Multiplexed Signal Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 675.4 Multi-Frequency Records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 675.5 Multi-Segment Records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 685.6 Simultaneous Access to Multiple Records . . . . . . . . . . . . . . . . . . . . . . 695.7 Signals That Are Not Stored in Disk Files . . . . . . . . . . . . . . . . . . . . . 705.8 Piped and Local Records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 705.9 NETFILES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 715.10 Annotation Order . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

  • iv WFDB Programmer’s Guide

    6 Programming Examples . . . . . . . . . . . . . . . . . . . . . . 75Example 1: An Annotation Filter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75Example 2: An Annotation Translator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76Example 3: An Annotation Printer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78Example 4: Generating an R-R Interval Histogram . . . . . . . . . . . . . . . . . 79Example 5: Reading Signal Specifications . . . . . . . . . . . . . . . . . . . . . . . . . . . 80Example 6: A Differentiator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82Example 7: A General-Purpose FIR Filter . . . . . . . . . . . . . . . . . . . . . . . . . . 83Example 8: Creating a New Database Record . . . . . . . . . . . . . . . . . . . . . . . 86Example 9: A Signal Averager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90Example 10: A QRS Detector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

    Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

    Appendix A Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . 101

    Appendix B Installing the WFDB SoftwarePackage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

    The WFDB library and languages other than C . . . . . . . . . . . . . . . . . . . 109

    Appendix C WFDB Application Programs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111

    How to use these programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111Annotation File Processing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111Evaluation of ECG Analyzers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112Signal Processing Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114Graphical Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

    Appendix D Extensions . . . . . . . . . . . . . . . . . . . . . . . 117

    Appendix E Sources . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

    Answers to Selected Exercises . . . . . . . . . . . . . . . . . . 129

  • v

    Recent Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131WFDB 10.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131

    Changes in version 10.5.10 (15 November 2011) . . . . . . . . . . . . . . . . . 131Changes in version 10.5.9 (10 September 2011) . . . . . . . . . . . . . . . . . 131Changes in version 10.5.8 (12 March 2011) . . . . . . . . . . . . . . . . . . . . . 131Changes in version 10.5.7 (16 December 2010) . . . . . . . . . . . . . . . . . . 132Changes in version 10.5.6 (29 November 2010) . . . . . . . . . . . . . . . . . . 132Changes in version 10.5.4 (13 July 2010) . . . . . . . . . . . . . . . . . . . . . . . 132Changes in version 10.5.3 (22 June 2010) . . . . . . . . . . . . . . . . . . . . . . . 132Changes in version 10.5.2 (18 April 2010) . . . . . . . . . . . . . . . . . . . . . . . 132Changes in version 10.5.1 (19 March 2010) . . . . . . . . . . . . . . . . . . . . . 133Changes in version 10.5.0 (16 March 2010) . . . . . . . . . . . . . . . . . . . . . 133

    WFDB 10.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133Changes in version 10.4.25 (21 January 2010) . . . . . . . . . . . . . . . . . . . 133Changes in version 10.4.23 (7 August 2009) . . . . . . . . . . . . . . . . . . . . . 133Changes in version 10.4.22 (28 July 2009) . . . . . . . . . . . . . . . . . . . . . . 134Changes in version 10.4.21 (14 May 2009) . . . . . . . . . . . . . . . . . . . . . . 134Changes in version 10.4.20 (4 May 2009) . . . . . . . . . . . . . . . . . . . . . . . 134Changes in version 10.4.18 (15 March 2009) . . . . . . . . . . . . . . . . . . . . 134Changes in version 10.4.17 (5 March 2009) . . . . . . . . . . . . . . . . . . . . . 134Changes in version 10.4.16 (3 March 2009) . . . . . . . . . . . . . . . . . . . . . 134Changes in version 10.4.15 (26 February 2009) . . . . . . . . . . . . . . . . . . 134Changes in version 10.4.14 (23 February 2009) . . . . . . . . . . . . . . . . . . 134Changes in version 10.4.13 (16 February 2009) . . . . . . . . . . . . . . . . . . 135Changes in version 10.4.12 (20 January 2009) . . . . . . . . . . . . . . . . . . . 135Changes in version 10.4.10 (31 October 2008) . . . . . . . . . . . . . . . . . . . 136Changes in version 10.4.9 (10 October 2008) . . . . . . . . . . . . . . . . . . . . 136Changes in version 10.4.7 (15 July 2008) . . . . . . . . . . . . . . . . . . . . . . . 136Changes in version 10.4.6 (9 April 2008) . . . . . . . . . . . . . . . . . . . . . . . . 136Changes in version 10.4.5 (6 February 2008) . . . . . . . . . . . . . . . . . . . . 136Changes in version 10.4.2 (4 May 2006) . . . . . . . . . . . . . . . . . . . . . . . . 137Changes in version 10.4.1 (6 April 2006) . . . . . . . . . . . . . . . . . . . . . . . . 137Changes in version 10.4.0 (2 March 2006) . . . . . . . . . . . . . . . . . . . . . . . 137

    WFDB 10.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138Changes in version 10.3.17 (20 August 2005) . . . . . . . . . . . . . . . . . . . 138Changes in version 10.3.16 (13 June 2005) . . . . . . . . . . . . . . . . . . . . . . 139Changes in version 10.3.15 (31 January 2005) . . . . . . . . . . . . . . . . . . . 139Changes in version 10.3.14 (29 December 2004) . . . . . . . . . . . . . . . . . 139Changes in version 10.3.13 (5 May 2004) . . . . . . . . . . . . . . . . . . . . . . . 139Changes in version 10.3.12 (9 March 2004) . . . . . . . . . . . . . . . . . . . . . 139Changes in version 10.3.11 (17 October 2003) . . . . . . . . . . . . . . . . . . . 139Changes in version 10.3.10 (3 August 2003) . . . . . . . . . . . . . . . . . . . . . 140Changes in version 10.3.9 (16 July 2003) . . . . . . . . . . . . . . . . . . . . . . . 140Changes in version 10.3.8 (12 July 2003) . . . . . . . . . . . . . . . . . . . . . . . 140Changes in version 10.3.6 (7 April 2003) . . . . . . . . . . . . . . . . . . . . . . . . 140Changes in version 10.3.5 (31 March 2003) . . . . . . . . . . . . . . . . . . . . . 140Changes in version 10.3.2 (25 February 2003) . . . . . . . . . . . . . . . . . . . 141Changes in version 10.3.0 (26 November 2002) . . . . . . . . . . . . . . . . . . 141

  • vi WFDB Programmer’s Guide

    WFDB 10.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141Changes in version 10.2.9 (27 October 2002) . . . . . . . . . . . . . . . . . . . . 141Changes in version 10.2.7 (14 October 2002) . . . . . . . . . . . . . . . . . . . . 141Changes in version 10.2.6 (24 June 2002) . . . . . . . . . . . . . . . . . . . . . . . 141Changes in version 10.2.5 (10 March 2002) . . . . . . . . . . . . . . . . . . . . . 142Changes in version 10.2.4 (20 December 2001) . . . . . . . . . . . . . . . . . . 142Changes in version 10.2.3 (14 December 2001) . . . . . . . . . . . . . . . . . . 142Changes in version 10.2.1 (16 November 2001) . . . . . . . . . . . . . . . . . . 142Changes in version 10.2.0 (15 October 2001) . . . . . . . . . . . . . . . . . . . . 142

    WFDB 10.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143Changes in version 10.1.6 (1 August 2001) . . . . . . . . . . . . . . . . . . . . . . 143Changes in version 10.1.5 (11 June 2000) . . . . . . . . . . . . . . . . . . . . . . . 143Changes in version 10.1.4 (6 June 2000) . . . . . . . . . . . . . . . . . . . . . . . . 143Changes in version 10.1.3 (26 April 2000) . . . . . . . . . . . . . . . . . . . . . . . 143Changes in version 10.1.2 (11 March 2000) . . . . . . . . . . . . . . . . . . . . . 143Changes in version 10.1.1 (30 January 2000) . . . . . . . . . . . . . . . . . . . . 143Changes in version 10.1.0 (15 January 2000) . . . . . . . . . . . . . . . . . . . . 144

    WFDB 10.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144Changes in version 10.0.1 (19 November 1999) . . . . . . . . . . . . . . . . . . 144Changes in version 10.0.0 (25 June 1999) . . . . . . . . . . . . . . . . . . . . . . . 144

    Concept Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147

    Function and Macro Index . . . . . . . . . . . . . . . . . . . . . . 153

  • Preface 1

    Preface

    This guide documents the Waveform Database interface library (the WFDB library), apackage of C-callable functions that provide clean and uniform access to digitized, annotatedsignals stored in a variety of formats. These functions were originally designed for use withdatabases of electrocardiograms, including the MIT-BIH Arrhythmia Database (MIT DB)and the AHA Database for the Evaluation of Ventricular Arrhythmia Detectors (AHA DB).In February 1990, the predefined annotation set was expanded to accommodate the needsof the European ST-T Database (ESC DB). The WFDB library is sufficiently general,however, to be useful for dealing with any similar collection of digitized signals, which mayor may not be annotated. The WFDB library has evolved to support the development ofnumerous other databases that include signals such as blood pressure, respiration, oxygensaturation, EEG, as well as ECGs. Among these multi-parameter databases are the MIT-BIH Polysomnographic Database, the MGH/Marquette Foundation Waveform Database,and the MIMIC Database. Thus the WFDB library is considerably more than an ECGdatabase interface.

    This guide describes how to write C-language programs that use databases of ECGs andother signals. A standard set of such programs is included in the WFDB Software Package,and is described in the WFDB Applications Guide; other documents describe the databasesthemselves, and existing programs that use them (see Appendix E [Sources], page 121, forinformation about obtaining these and related items).

    There are a few important concepts that should be well understood before going further.These concepts include records; signals, samples, and time; and annotations.

    Records

    The databases for which the WFDB library was designed consist of a small number ofrecords, each of which is quite large (typically a megabyte or more). Before 1990, databaserecords usually originated as multi-channel analog tape recordings that had been digitizedand stored as disk files. For this historical reason, they are sometimes referred to as tapes,although most newly created records are digitally recorded onto disk media. Each recordcontains a continuous recording from a single subject. A typical application program ac-cesses only a single record, and most (if not all) of the access within the record is sequential.Much less frequently, it may be of interest to compare the contents of several records, or toselect sets of records. These databases are therefore qualitatively different from those forwhich conventional database management software is written.

    Records are identified by record names of up to 20 characters (the limit is MAXRNL,defined in ‘’). For example, record names in the MIT DB are three-digitnumbers, those in the AHA DB are four-digit numbers, and those in the ESC DB arefour-digit numbers prefixed by the letter ‘e’. You may create database records with namescontaining letters, digits, and underscores. Case is significant in record names that containletters, even in environments such as MS-Windows for which case translation is normallyperformed by the operating system on file names; thus ‘e0104’ is the name of a recordfound in the ESC DB, whereas ‘E0104’ is not. A record is comprised of several files, whichcontain signals, annotations, and specifications of signal attributes; each file belonging to agiven record normally includes the record name as the first part of its name. A record isan extensible collection of files, which need not all be located in the same directory, or even

  • 2 WFDB Programmer’s Guide

    on the same physical device. Thus it is possible, for example, to create a local disk file ofyour own annotations for a record read from a web server or a CDROM, and to treat yourfile as part of the record.

    Signals, Samples, and Time

    Signals are commonly understood to be functions of time obtained by observation of physicalvariables. In this guide, a signal is defined more restrictively as a finite sequence of integersamples, usually obtained by digitizing a continuous observed function of time at a fixedsampling frequency expressed in Hz (samples per second). The time interval between anypair of adjacent samples in a given signal is a sample interval; all sample intervals for agiven signal are equal. The integer value of each sample is usually interpreted as a voltage,and the units are called analog-to-digital converter units, or adu. The gain defined for eachsignal specifies how many adus correspond to one physical unit (usually one millivolt, thenominal amplitude of a normal QRS complex on a body-surface ECG lead roughly parallelto the mean cardiac electrical axis). All signals in a given record are usually sampled atthe same frequency, but not necessarily at the same gain (see Section 5.4 [Multi-FrequencyRecords], page 67, for exceptions to this rule). MIT DB records are sampled at 360 Hz;AHA and ESC DB records are sampled at 250 Hz.

    The sample number is an attribute of a sample, defined as the number of samples ofthe same signal that precede it; thus the sample number of the first sample in each signalis zero. Within this guide, the units of time are sample intervals; hence the “time” of asample is synonymous with its sample number.

    Samples having the same sample number in different signals of the same record aretreated as simultaneous. In truth, they are usually not precisely simultaneous, since mostmulti-channel digitizers sample signals in “round-robin” fashion. If this subtlety makes adifference to you, you should be prepared to compensate for inter-signal sampling skew inyour programs.

    Annotations

    MIT DB records are each 30 minutes in duration, and are annotated throughout; by thiswe mean that each beat (QRS complex) is described by a label called an annotation. Typ-ically an annotation file for an MIT DB record contains about 2000 beat annotations, andsmaller numbers of rhythm and signal quality annotations. AHA DB records are either35 minutes or 3 hours in duration, and only the last 30 minutes of each record are anno-tated. ESC DB records are each 2 hours long, and are annotated throughout. The “time”of an annotation is simply the sample number of the sample with which the annotationis associated. Annotations may be associated with a single signal, if desired. Like sam-ples in signals, annotations are kept in time and signal order in annotation files (but seeSection 5.10 [Annotation Order], page 72, for exceptions to this rule). No more than oneannotation in a given annotation file may be associated with any given sample of any givensignal. There may be many annotation files associated with the same record, however; theyare distinguished by annotator names. The annotator name ‘atr’ is reserved to identifyreference annotation files supplied by the developers of the databases to document correctbeat labels. You may use other annotator names (which may contain letters, digits andunderscores, as for record names) to identify annotation files that you create. You may

  • Preface 3

    wish to adopt the convention that the annotator name is the name of the file’s creator (aprogram or a person).

    Annotations are visible to the WFDB library user as C structures, the fields of whichspecify time, beat type, and several user-definable variables. The WFDB library performsefficient conversions between these structures and a compact bit-packed representation usedfor storage of annotations in annotation files.

    Applications

    Some typical uses of the WFDB library are these:• A waveform editor, such as wave (see the WAVE User’s Guide), reads the digitized

    signals of a database record and displays them with annotations superimposed on thewaveforms. Such a program allows the user to select any portion of the signals fordisplay at various scales, and to add, delete, or correct annotations.

    • Signal processing programs (e.g., see [Example 7], page 83) apply digital filters to thesignals of a database record and then record the filtered signals as a new record. Similarprograms perform sampling frequency conversion.

    • Analysis programs (e.g., see [Example 10], page 92) read the digitized signals, analyzethem, and then record their own annotations.

    • An annotation comparator, such as bxb (see Appendix C [WFDB Applications],page 111), reads two or more sets of annotations corresponding to a given record,and tabulates discrepancies between them. If the reference annotations supplied withthe database are compared in this way with annotations produced using an analysisprogram, this comparison is a means of establishing the accuracy of the analysisprogram’s output.

    The WFDB library provides the means for programs such as those described aboveto select a database record, read and write signals, read and write annotations, jump toarbitrary points in the record, and determine attributes of the signals such as the samplingfrequency. The library also provides a variety of other more specialized services for programsthat need them. The library defines an interface between programs and the database thatis sufficiently powerful, general, and efficient to eliminate the need for ad hoc user-writtendatabase I/O.

    About this Guide

    You should have a good grasp of the C language in order to make the best use of this guide.If ANSI C prototypes, used here to document the WFDB library functions, are unfamiliar toyou, see pp. 217–218 in the second edition of The C Programming Language by Kernighanand Ritchie, Prentice Hall, 1988. (This is the famous K&R; all K&R references in this guideinclude page numbers for the second edition. Newcomers to C should have a copy for readyreference while reading this guide.) It may also be helpful to have a copy of a databasedirectory, such as the MIT-BIH Arrhythmia Database Directory . The WFDB ApplicationsGuide will be useful as a reference for existing WFDB library-based applications (availablefrom PhysioNet, http://physionet.org/).

    You should have access to a computer that has the WFDB library and at least one ortwo database records on-line, or access to the World Wide Web, where database records

    http://physionet.org/physiotools/wug/http://physionet.org/physiobank/database/html/mitdbdir/http://physionet.org/physiotools/wag/http://physionet.org/physiotools/wag/http://physionet.org/

  • 4 WFDB Programmer’s Guide

    can be obtained from PhysioNet and other sources. (If you are installing the WFDB libraryon a new computer for the first time, please read the installation notes supplied with theWFDB library first, or see Appendix B [Installing the WFDB Software Package], page 109,then return here.) You should know how to create a C source file using your favorite editor,and you should know how to compile it and how to run the resulting executable program.

    Resist all temptation to plunge into the esoteric details of file formats. (Those who findsuch details irresistible will find them in Section 5 of the WFDB Applications Guide; note,however, that support for new file formats is added to the WFDB library from time to time,so that the information you find there may be incomplete.) The WFDB library providesan efficient means of reading and writing files in many formats; it is not a trivial task toduplicate it, and time spent doing so is time that could be spent doing something useful,enjoyable, or possibly both. If you really think you need to understand the file formats inorder to translate them into whatever the ECGWhizz Model 666 needs, consider insteadwriting a format translator using the WFDB library to read the files; then you will at leasthave a program that requires only recompilation with a new version of the WFDB librarywhen file formats change. In extremis, use ‘rdann’ and ‘rdsamp’ — available from PhysioNetin source and ready-to run formats — to translate files into text format.

    Chapter 1 of this guide begins with a simple example program that reads a few samplesfrom a database record. The C version of this program is also translated into a variety ofother languages supported by the WFDB library itself or by separately available bindings.This example should help you understand the mechanics of compiling and using a programthat does something with an ECG database. Chapter 2 introduces the library functionsthemselves, with a number of brief examples; you may wish to skim through this materialon a first reading to get acquainted with what is available, and then refer to it as neededwhile writing your programs. Data structures for annotations and for signal and annotatorattributes are described in chapter 3. Chapter 4 contains a table of annotation types anddescriptions of several annotation-mapping macros. Database files and related topics arediscussed in chapter 5, which can be skipped on a first reading. Chapter 6 contains addi-tional example programs that illuminate a few of the darker corners of the WFDB library.The glossary defines the ordinary-sounding words such as signal that have specialized mean-ings in this guide; such words are emphasized in their first appearances in order to warn youthat you should look them up in the glossary on a first reading (see Appendix A [Glossary],page 101).

    If the WFDB library has not yet been installed on your system, see Appendix B [In-stalling the WFDB Software Package], page 109. Another appendix (see Appendix C[WFDB Applications], page 111) includes brief descriptions of the application programsthat are distributed with the WFDB library as part of the WFDB software package.

    Another appendix discusses porting the WFDB library to new machines or operatingsystems, and includes notes on adding support for new file formats, annotation codes, andother enhancements (see Appendix D [Extensions], page 117). The WFDB library has beenwritten with portability in mind. It runs on a wide variety of machines and operatingsystems, including Unix (BSD 4.x, System V, SunOS, Solaris, HP-UX, OSF/1, Version 7,XENIX, VENIX, ULTRIX, GNU/Linux, FreeBSD, OpenBSD, IRIX, AIX, AUX, Darwin,Mac OS X, SCO, Coherent, and more), MS-DOS, MS-Windows, VMS, and classic MacOS. This guide was written for Unix users (with notes for MS-Windows and MS-DOS userswhere differences exist), but others should find only minor differences.

  • Preface 5

    At the end of the guide is a list of sources for databases and other materials that maybe useful to readers (see Appendix E [Sources], page 121), and a log of changes made tothis library since 1999 (see [Recent Changes], page 131).

    Many friends have contributed to the development of the WFDB library. Thanks to PaulAlbrecht, Ted Baker, Phil Devlin, Scott Greenwald, Thomas Heldt, Isaac Henry, David Is-rael, Roger Mark, Joe Mietus, Warren Muldrow, Ikaro Silva, Wei Zong, and especially toPaul Schluter, whose elegant 8080 assembly language functions inspired these (long livegetann!). Pat Hamilton and Bob Farrell contributed ports, to classic Mac OS and the MS32-bit Windows environments, respectively. Jose Garcia Moros and Salvador Olmos con-tributed Matlab/Octave reimplementations of a useful subset of the WFDB library. JonasCarlson wrote, documented, and contributed a set of Matlab wrappers for the WFDB li-brary, and Michael Craig created and contributed the WFDB Toolbox for Matlab. IsaacHenry contributed SWIG wrappers that provide interfaces for a variety of scripting lan-guages, as well as a set of translations of the C example programs in this guide into thelanguages supported by the SWIG wrappers. Mike Dakin provided the first implementationof NETFILES (HTTP client support in the WFDB library) based on the W3C’s libwww.Following the W3C’s decision to end development of libwww, Benjamin Moody reimple-mented NETFILES using libcurl, and also implemented variable-layout records. Bugreports (and in some cases fixes) have been contributed by Omar Abdala, Winton Baker,Ion Gaztaaga, Fred Geheb, Mathias Gruber, Guido Muesch, Joonas Paalasmaa, Tony Ricke,Dave Schaffer, Dan Scott, Allavatam Venugopal, Mauro Villarroel, Andrew Walsh, PiotrWlodarek, and Yinqi Zhang. Thanks also to the many readers of earlier versions of thisguide; if this edition answers your questions, it is because someone else has already askedthem, and hounded the author until he produced comprehensible answers.

    Before May, 1999, and the release of version 10.0.0 of the library, the WFDB librarywas known as the DB library, and this guide was the ECG Database Programmer’s Guide.The name of the library was changed because of confusion caused by the proliferationof another library with the same name (a reimplementation of the Berkeley Unix DBMlibrary). The names of this guide, and of the WFDB Applications Guide (formerly theECG Database Applications Guide), have been changed in view of the increasingly broadrange of applications in which the library is being used.

    The first edition of this guide was written as a tutorial for MIT students using theECG databases for a variety of signal-processing and analysis projects. The guide, and theWFDB library itself, have been extensively revised since they first appeared in 1981. Yourcomments and suggestions are welcome. Please send them to:

    George B. Moody MIT Room E25-505ACambridge, MA 02139USA

    If you use the GNU emacs editor, you can peruse a hypertext version of this guide usinginfo if it has been installed on your system; among its many other features, emacs makesit easy to copy code from the examples into your own programs. Installation instructionsare included in the WFDB Software Package; type C-h i within GNU emacs to start upinfo (see Appendix E [Sources], page 121, for information about obtaining GNU emacs).

    mailto:[email protected]

  • 6 WFDB Programmer’s Guide

    An HTML version of this guide, suitable for viewing using any web browser, is in-cluded with the WFDB Software Package. The latest version may always be viewed athttp://physionet.org/physiotools/wpg/ using your web browser.

    You can format and print copies of this guide using TeX if you have it (see ‘makefile’ inthe ‘doc’ directory of the library distribution for instructions on doing so). You may obtainpreformatted versions in PDF and PostScript formats from http://physionet.org/.

    http://physionet.org/physiotools/wpg/http://physionet.org/

  • Chapter 1: Using the WFDB Library 7

    1 Using the WFDB Library

    This chapter gives a brief overview of the steps needed to compile, load, and run a programthat uses the WFDB library. It assumes that you are able to log onto a Unix-based computeron which the WFDB Software Package has been installed (see Appendix B [Installing theWFDB Software Package], page 109), and that you know how to create a source file usinga text editor such as emacs or vi. If you are using an MS-DOS system, there are a fewdifferences noted below.

    1.1 A Trivial Example Program in C

    Suppose we wish to print the first ten samples of record ‘100s’. (Record ‘100s’ is the firstminute of MIT-BIH Arrhythmia Database record ‘100’, supplied as a sample in the datadirectory of all source distributions of the WFDB Software Package.) We might begin bycreating a source file called ‘psamples.c’ that contains:

    #include #include

    main(){

    int i;WFDB_Sample v[2];WFDB_Siginfo s[2];

    if (isigopen("100s", s, 2) < 2)exit(1);

    for (i = 0; i < 10; i++) {if (getvec(v) < 0)

    break;printf("%d\t%d\n", v[0], v[1]);

    }exit(0);

    }

    (See http://physionet.org/physiotools/wfdb/examples/psamples.c for a copy of thisprogram.)

    All programs that use the WFDB library must include the statement

    #include

    which defines function interfaces, data types (such as the WFDB_Sample and WFDB_Siginfotypes used in this example), and a few useful constants. (Most MS-DOS C compilers accept‘/’ as a directory separator. If you prefer to use the non-portable ‘\’ under MS-DOS,remember to quote it: ‘#include ’.)

    The functions used in the example are described in detail in the next chapter, and thedata types are described in the following chapter (see Chapter 3 [Data Types], page 55).For now, note that isigopen prepares a record to be read by getvec, which reads a samplefrom each of the two signals each time it is called.

    http://physionet.org/physiotools/wfdb/examples/psamples.c

  • 8 WFDB Programmer’s Guide

    Note that in some cases it may be important to insure that all memory allocated by theWFDB library is freed before the program exits; in the example program, this can be doneby adding the line

    wfdbquit();

    just above exit(0); (see [wfdbquit], page 42).

    1.2 Compiling a Program with the WFDB Library

    The WFDB library is developed and tested using gcc, the GNU C/C++ compiler, but carefulattention has been given to making it usable with any ANSI/ISO C compiler. Since gcc isfree, high quality, and supported, it is highly recommended that you use it for compilingyour WFDB applications.

    To compile the example program using gcc, we can say:gcc -o psamples psamples.c -lwfdb

    to produce an executable program called psamples. (Your C compiler may be named ‘cc’,‘acc’, ‘CC’, or something else, rather than ‘gcc’.) You may use any other compiler optionsyou choose, but the ‘-lwfdb’ option must appear in the cc command line following anyand all source (‘*.c’) and object (‘*.o’) file names, in order to instruct the loader to searchthe WFDB library for any functions that the program needs (in this case, isigopen andgetvec). Some programs will need additional libraries, and the corresponding ‘-l’ optionscan usually be given before or after the ‘-lwfdb’ option.

    If the WFDB library was installed with NETFILES support, it will make use of functionscontained in the libcurl or libwww libraries. If you have dynamically linkable versions ofthe libcurl or libwww libraries, as under GNU/Linux, these will be loaded automaticallywhen you run psamples. If you have only static versions of these libraries, however, itis necessary to provide additional arguments in the cc command line in order to compilesuccessfully. One way to do this is to follow the model used to compile the standard WFDBapplications supplied with the WFDB library; see ‘Makefile’ in the ‘app’ directory of theWFDB software package source tree.

    If you are using WFDB version 10.2.6 or a later version and ‘gcc’ or a compatiblecompiler, the ‘wfdb-config’ utility is available to help construct commands for compilingprograms that use the WFDB library (and the libcurl or libwww libraries, if available).Use it like this:

    gcc ‘wfdb-config --cflags‘ -o psamples psamples.c ‘wfdb-config --libs‘

    Note that this command contains backticks (‘), not apostrophes (’). ‘wfdb-config’ is par-ticularly useful if the WFDB library or its ‘*.h’ files are installed in non-standard locations,or if you have only static libcurl or libwww libraries.

    Under MS-Windows, ‘gcc’ is included in the freely available Cygwin software develop-ment system (http://www.cygwin.com/), and also in the freely available MinGW package(http://www.mingw.org/). An MS-DOS version of ‘gcc’ is available in the free djgpppackage (http://www.delorie.com/djgpp/). These are used within a Cygwin terminalemulator window or an MS-DOS box in exactly the same way as described above for Ccompilers on all other platforms. For most purposes, Cygwin is recommended, since itprovides a Unix-compatible standard C library (cygwin1.dll), so that applications behaveexactly as they do on all other platforms. WAVE can only be built under Windows in this

    http://www.cygwin.com/http://www.mingw.org/http://www.delorie.com/djgpp/

  • Chapter 1: Using the WFDB Library 9

    way. When building WFDB-based plugins for use with .NET applications or others suchas Matlab that rely on the native Windows C library, however, the WFDB library must berecompiled to use the native library. This can be done using either MinGW gcc, or Cygwingcc with its -mno-cygwin option.

    If you choose to use an incompatible proprietary compiler, you are on your own! Youmay be able to create a linkable version of the WFDB library from the sources in the‘lib’ directory of the WFDB source tree using a proprietary compiler, but doing so isunsupported (see your compiler’s documentation). If you are not able to build the WFDBlibrary using your compiler, you can compile the library sources together with the sourcefile(s) for your application. It may be easiest to copy the library sources (both the ‘*.c’and the ‘*.h’ files) into the same directory as the application sources. If you follow thisapproach, find the directory that contains ‘stdio.h’ on your system and make a ‘wfdb’subdirectory within that directory, then copy the WFDB library’s ‘*.h’ files into the ‘wfdb’subdirectory (this is necessary so that statements of the form ‘#include ’will be handled properly by your compiler). For example, to compile ‘psamples.c’ withMicrosoft C/C++, set up the WFDB library source files as just described, then use thiscommand:

    cl psamples.c wfdbio.c signal.c annot.c calib.c wfdbinit.c

    With Borland C/C++ or Turbo C or C++, substitute ‘bcc’ or ‘tcc’, respectively, for ‘cl’ inthe command above. You will find that some WFDB applications do not need to be compiledwith all of the WFDB library sources (for example, ‘psamples’ needs only ‘wfdbio.c’ and‘signal.c’); in such cases, you may omit the unneeded sources for faster compilation andsmaller executable binaries.

    1.3 Using the WFDB library with other languages

    Bindings and wrappers are available so that programs written in a number of other pro-gramming languages can make use of the WFDB library.

    C++ bindings

    If you prefer to write your applications in C++, you may do so, but note that the WFDBlibrary is written in C. (Most C++ compilers can be run in ANSI/ISO C compatibility modein order to compile the WFDB library itself.) Each C++ source file that uses WFDB li-brary functions must include ‘’, in order to instruct your compiler to useC conventions for argument passing and to use unmangled names for the WFDB libraryfunctions. In order for this to work, your C++ compiler should predefine ‘__cplusplus’ or‘c_plusplus’; if it predefines neither of these symbols, modify ‘’ so thatthe symbols ‘wfdb_CPP’ and ‘wfdb_PROTO’ are defined at the top of the file, or define‘__cplusplus’ in each of your source files before including ‘’. Compile andlink your program using whatever standard methods are supported by your compiler forlinking C++ programs with C libraries. See your compiler manual for further information.

    Fortran wrappers

    A set of wrapper functions is also available for those who wish to use the WFDB librarytogether with applications written in Fortran. These functions, defined in ‘wfdbf.c’, providea thin ‘wrapper’ around the WFDB library functions, by accepting Fortran-compatible

    http://physionet.org/physiotools/wfdb/fortran/wfdbf.c

  • 10 WFDB Programmer’s Guide

    arguments (there are no structures, and all arguments are passed by reference rather thanby value). For example, here is the Fortran equivalent of the example program in theprevious section:

    integer i, v(2), g

    i = isigopen("100s", 2)do i = 1, 10g = getvec(v)write (6,3) v(1), v(2)

    3 format("v(1) = ", i4, " v(2) = ", i4)end doend

    (See http://physionet.org/physiotools/wfdb/fortran/fsamples.f for a copy ofthis program; an extensively commented version of this program is also available, athttp://physionet.org/physiotools/wfdb/fortran/example.f.)To compile this program using g77 (the GNU Fortran compiler), save it as ‘fsamples.f’ inthe current directory, copy ‘wfdbf.c’ (which can be found in the same directory as ‘wfdb.h’,usually ‘/usr/include/wfdb’) to the current directory, then type:

    g77 -o fsamples -DFIXSTRINGS fsamples.f wfdbf.c -lwfdb

    The Fortran wrapper functions are not discussed in this guide; for further information, referto fortran/README in the WFDB Software Package.

    SWIG wrappers for Java, Perl, Python, and other languages

    Isaac Henry has contributed WFDB wrappers for Java, Perl, and Python, as well as for .NETlanguages such as C#, created using the Simplified Wrapper Interface Generator (SWIG,http://www.swig.org/). Using these wrappers, the example program can be written inany of these languages:

    Java:

    import wfdb.*;

    public class psamples {static {

    System.loadLibrary("wfdbjava");}

    public static void main(String argv[]) {WFDB_SiginfoArray siarray = new WFDB_SiginfoArray(2);if (wfdb.isigopen ("100s", siarray.cast(), 2) < 2)

    System.exit(1);WFDB_SampleArray v = new WFDB_SampleArray(2);for (int i = 0; i < 10; i++) {

    if (wfdb.getvec(v.cast()) < 0)break;

    System.out.println("\t" + v.getitem(0) +"\t"+ v.getitem(1));}

    http://physionet.org/physiotools/wfdb/fortran/fsamples.fhttp://physionet.org/physiotools/wfdb/fortran/example.fhttp://physionet.org/physiotools/wfdb/fortran/READMEhttp://www.swig.org/

  • Chapter 1: Using the WFDB Library 11

    }}

    Perl:

    package wfdb;use wfdb;

    $siarray = new wfdb::WFDB_SiginfoArray(2);if ($nsig = isigopen("100s", $siarray->cast(), 2) < 2) {

    exit(1);}$v = new wfdb::WFDB_SampleArray(2);for ($i=0; $i < 10; $i++) {

    if (getvec($v->cast()) < 0) {exit(2);

    }print "\t", $v->getitem(0), "\t", $v->getitem(1), "\n";

    }

    Python:

    import wfdb, sys

    def main(argv):siarray = wfdb.isigopen("100s")if siarray.nsig < 2: sys.exit(1)v = wfdb.WFDB_SampleArray(2)for i in range(0,10):

    if wfdb.getvec(v.cast()) < 0: sys.exit(2)print "\t%d\t%d" % (v[0], v[1])

    if __name__ == "__main__":main(sys.argv[1:])

    C#:

    using System;using Wfdb;

    public class psamples {static void Main(string[] argv) {

    WFDB_SiginfoArray siarray = new WFDB_SiginfoArray(2);if (wfdb.isigopen("100s", siarray.cast(), 2) < 2)

    Environment.Exit(1);WFDB_SampleArray v = new WFDB_SampleArray(2);for (int i = 0; i < 10; i++) {

    if (wfdb.getvec(v.cast()) < 0)break;

    Console.WriteLine("\t" + v.getitem(0) + "\t" + v.getitem(1));

  • 12 WFDB Programmer’s Guide

    }}

    }

    All SWIG wrappers for the WFDB library are generated using a single interface file,‘wfdb.i’. In principle, this file might be used to generate wrappers for other programminglanguages supported by SWIG, including several versions of LISP, Modula-3, PHP, Ruby,and Tcl.

    Matlab toolbox

    The WFDB Toolbox for Matlab, contributed by Michael Craig and available fromhttp://physionet.org/physiotools/matlab/wfdb-swig-matlab/, is a collection ofWFDB applications implemented as functions in Matlab, built on the SWIG Javawrappers for the WFDB library. For example, using it in Matlab, one can read and plotthe first five seconds of the same signals as in the example program above, by:

    r = rdsamp(’100s’, ’maxt’, ’:5’);plot(r(:,1), r(:,2));

    The WFDB Toolbox for Matlab replaces the wfdb_tools library of wrapper functionscontributed by Jonas Carlson, since current versions of Matlab are no longer compatiblewith the wfdb_tools library.

    The WFDB Software Package includes wfdb2mat, an application that converts all or anydesired segment of a signal file into a .mat file that can be read directly by Matlab.

    Jesus Olivan Palacios has written a tutorial (available at http://www.neurotraces.com/scilab/sciteam/)that includes a detailed section on using the WFDB Software Package with Scilab (anopen-source scientific software package for numerical computations, with a languagesimilar to that of Matlab, available from http://www-rocq.inria.fr/scilab/).The methods described in this tutorial can also be adapted for use with GNUOctave (another free language that is mostly compatible with Matlab, available fromhttp://www.gnu.org/software/octave/).

    Also available is a reimplementation of a useful subset of the WFDB libraryin native m-code (contributed by Jose Garcia Moros and Salvador Olmos) athttp://physionet.org/physiotools/matlab/.

    1.4 The Database Path and Other Environment Variables

    WFDB applications make use of several environment variables, which are named WFDB,WFDBCAL, WFDBGVMODE, and WFDBANNSORT. If these variables have not been otherwise definedby the user, their values are those given by DEFWFDB, DEFWFDBCAL, DEFWFDBGVMODE, andDEFWFDBANNSORT (defined in ‘wfdblib.h’ at the time the WFDB library was compiled).Unless you have a non-standard setup, you may not need to set these variables, but it willbe helpful to read this section to understand how they influence the behavior of WFDBapplications.

    When WFDB applications read database files, they must be able to find them in variouslocations that may vary from system to system. The WFDB library refers to a characterstring that consists of an ordered list of locations to be searched for input files. This stringis called the database path, or the WFDB path.

    http://physionet.org/physiotools/matlab/wfdb-swig-matlab/http://www.neurotraces.com/scilab/sciteam/http://www-rocq.inria.fr/scilab/http://www.gnu.org/software/octave/http://physionet.org/physiotools/matlab/

  • Chapter 1: Using the WFDB Library 13

    On most systems, the environment variable WFDB, if set, specifies the value of the WFDBpath, and overrides the default value. If you need to use a non-default WFDB path, you mustset the WFDB environment variable appropriately before running any WFDB applications,so that the WFDB path can be examined by the running program. The WFDB softwarepackage includes easily customizable shell scripts (batch files) that illustrate how to do thisfor popular shells and command interpreters; see setwfdb(1), in the WFDB ApplicationsGuide. (Under classic Mac OS, for which the concept of environment variables is foreign, theWFDB path may be set only by using DEFWFDB.) For further information, see Section 1.7[WFDB path syntax], page 14.

    The shell scripts that set WFDB also set the WFDBCAL environment variable, which isimportant if you make use of records that contain signals other than ECGs. WFDBCALnames a calibration file located in one of the directories named by WFDB. (The symbolDEFWFDBCAL is usually defined in ‘wfdblib.h’ to specify the name of a default calibrationfile, to be used by the WFDB library if WFDBCAL has not been set.) Each signal type maybe represented by an entry in the calibration file. Entries specify the characteristics of anycalibration pulses that may be present, and customary scales for plotting the signals.

    The other environment variables are less frequently used than WFDB and WFDBCAL, andin most cases, the compiled-in defaults will be appropriate (see Section 5.10 [AnnotationOrder], page 72, and see Section 5.4 [Multi-Frequency Records], page 67, for details).

    1.5 Running the Example Program

    If WFDB is properly set, MIT DB record ‘100s’ is on-line and readable, and the exampleprogram was compiled correctly, it can be run by typing

    psamples

    (Try ‘./psamples’ if ‘psamples’ doesn’t work.) Its output will appear as:995 1011995 1011995 1011995 1011995 1011995 1011995 1011995 10111000 1008997 1008

    The left column contains samples from signal 0, and the right column contains thosefrom signal 1.

    1.6 A Note on Identifiers

    External identifiers that begin with the underscore (‘_’) character are reserved under therules of ANSI C to the compiler and libraries. In order to make the WFDB library asportable as possible, its own external identifiers do not begin with underscores (since oth-erwise they might conflict with external identifiers used by a standard library).

    External identifiers beginning with ‘wfdb_’ are reserved for the use of the WFDB library.These names are used for functions and global variables that are intended for the private

  • 14 WFDB Programmer’s Guide

    use of the WFDB library; your programs should not need to use them. You should avoiddefining functions or global variables with such names in your programs.

    External identifiers beginning with ‘WFDB_’ are used for constants and data types de-fined within ‘’. Use these identifiers as needed in your programs, but avoidredefining them.

    1.7 More About the WFDB Path

    When a WFDB file must be opened for input, the WFDB library attempts to locate it byattaching each of the components of the WFDB path (one at a time) as a prefix to thefile name. If two or more matching files exist in different locations in the WFDB path, theWFDB library opens only the file that resides in the first of these locations. Any othermatching files are effectively invisible to WFDB applications unless the WFDB path isrearranged.

    The default WFDB path is specified at the time the WFDB library is compiled, bydefining a value for the symbol DEFWFDB in ‘wfdblib.h’. Current versions of the WFDBlibrary are compiled with a three-component default WFDB path; the first component isempty (i.e., it refers to the current directory), the second component names the system-widedatabase directory (which contains the sample WFDB files supplied with the WFDB soft-ware package), and the third component is http://physionet.org/physiobank/database(referring to the PhysioBank data archives). Note that this default may be changed at thetime the WFDB library is compiled. Normally, however, this means that any record avail-able from PhysioBank is readable by any WFDB application provided that PhysioBank isaccessible from the user’s computer and that the database name is included in the recordname (for example, ‘slpdb/slp60’ or ‘nsrdb/16265’).

    Under Unix and VMS, the WFDB path can be given as a colon-separated list of prefixes,in the format used for the Bourne shell’s PATH variable. Under MS-Windows, MS-DOS, andclassic Mac OS, the WFDB path can be given in the format used for the MS-DOS PATHvariable, with semicolons used to separate prefixes (colons retain their customary mean-ings, as drive letter suffixes under MS-DOS, or as directory separators on the Macintosh).Alternatively, components of the WFDB path may be separated by whitespace (under anyoperating system); this also implies that embedded spaces are not permitted within pathcomponents. For this reason, avoid using directories with names such as ‘My Documents’,or their subdirectories, to store WFDB files.

    When WFDB applications write database files, these files are generally written to thecurrent directory. (As an example, an application that analyzes one or more signals in arecord may record its findings in an annotation file in the current directory.) If the recordname (as provided by the application to the WFDB library) contains path information,however, output files are written to the corresponding subdirectory of the current directory.(For example, if a WFDB application writes an annotation file for record edb/e0103, thefile will be written in the edb subdirectory of the current directory. The edb subdirectorywill be created by the WFDB library if does not exist already. This feature was introducedin WFDB library version 10.2.0.)

    Note particularly that the current directory is not necessarily part of the WFDB path. Ifyou modify your WFDB path, you must explicitly include an empty (null) component, whichcorresponds to the current directory, in order to be sure that your WFDB applications can

    http://physionet.org/physiobank/database

  • Chapter 1: Using the WFDB Library 15

    read any WFDB files that you have previously written. In most cases, this null componentshould be the first in the WFDB path. Thus, if you write into the current directory amodified version of an existing WFDB file, any later actions that would read this file willread your modified version rather than the original.

    The WFDB path may contain http:// and ftp:// URL prefixes (other schema, suchas file:// and https://, may also be supported if they are supported by your version oflibcurl or libwww). If NETFILES support is not compiled into the WFDB library, anyWFDB path components containing ‘://’ are ignored. (These features were first introducedin WFDB library version 10.1.0.)

    If the WFDB library finds that the value assigned to the WFDB path is of the form‘@file ’, it replaces that value with the contents of the specified file. (This feature wasfirst introduced in WFDB library version 8.0.) Indirect WFDB path files may be nestedup to ten levels (this arbitrary limit is imposed to avoid infinite recursion if the contents ofthe indirect file are incorrect). This method of indirect assignment is useful under classicMac OS, where recompilation of the WFDB library would otherwise be necessary in orderto change the WFDB path. It may also be useful under MS-DOS to reduce the need forenvironment space, or if the length of the command needed to set the WFDB environmentvariable would otherwise approach or exceed the 128-byte limit for MS-DOS commands.

    If a WFDB header file (see Chapter 5 [Database Files], page 65) specifies that a signalfile is to be found in a directory that is not already in the WFDB path, that directory isappended to the end of the WFDB path; in this case, if the WFDB path is not set, it iscreated with an initial null component followed by the directory that contains the signalfile. (This feature was first introduced in WFDB library version 6.2.)

    The string ‘%r’ is replaced by the current record name wherever it appears in the WFDBpath; ‘%Nr’ is replaced by the first N digits of the record name, if N is a non-zero digit.For example, if (under Unix) the WFDB path is ‘:/cdrom/mimicdb/%3r:/cdrom/mitdb’, arequest to read a file associated with record 055n will cause the WFDB library to look firstin the current directory (since the WFDB path begins with an empty component), then in‘/cdrom/mimicdb/055’, and then in ‘/cdrom/mitdb’. If ‘%’ is followed by any character otherthan ‘r’ or a non-zero digit followed by ‘r’, that character is used as is in the WFDB path;thus a literal ‘%’ can be included in the WFDB path by ‘escaping’ it as ‘%%’. (Substitutionsof ‘%’-strings in the WFDB path were first introduced in WFDB library version 9.7.)

    1.8 Exercises

    These exercises should require only a few minutes. If you work through them, you will havean opportunity to become acquainted with a few of the most common errors in using theWFDB library.1. Compile the example program in this chapter and run it. If the WFDB Software

    Package has not already been installed on your system, download and install the mostrecent version from PhysioNet first (see Appendix B [Installing the WFDB SoftwarePackage], page 109).

    2. Find out where database records are kept on your system. What records are availablelocally?

    3. Modify the example program so that you can specify the record to be opened, eitheras a command-line argument or by having the program prompt you to type a record

    http://

  • 16 WFDB Programmer’s Guide

    name. If you are unfamiliar with command-line argument processing, see [Example 2],page 76.

    4. Use the modified version of the example to read samples from records ‘mitdb/200’,‘edb/e0103’, ‘slpdb/slp04’, and ‘mimicdb/237/237’. The last two of these recordshave 4 and 6 signals respectively, so you will need to make a few additional changes tothe program in order to read these records successfully.

    5. Once again using the modified version of the example, what happens if you omit thepath information from one of the records in the previous exercise (for example, ifyou try to open ‘e0103’ instead of ‘edb/e0103’? Figure out how to set the WFDBpath so that the program will work properly in this case. (Hint: use the application‘wfdbwhich’, included with the WFDB Software Package, to find the header file forrecord ‘edb/e0103’; this information will help you to determine how to set the WFDBpath.)

    6. If you use MS-DOS or MS-Windows, explore and explain what happens in the previousexercise if you type the record name using upper-case letters, or if you type a ‘\’(backslash) instead of ‘/’ (forward slash). (Hint: record names are not filenames!)

    7. What happens when you compile the example program as shown, but with the#include statement omitted? with the ‘-lwfdb’ (‘-link wfdb’, etc.) omitted?

    8. What is the type of the argument to getvec? Why can’t getvec simply return thevalue it reads, as in ‘v = getvec()’?

  • Chapter 2: WFDB Library Functions 17

    2 WFDB Library Functions

    This chapter describes the functions that are available to programs compiled with theWFDB library. The functions are introduced in several groups, with examples to illustratetheir usage.

    About these functions

    Each function description begins with an ANSI C function prototype, which specifies thetypes of any arguments as well as the type of the quantity returned by the function (seeK&R, pp. 217–218). Note that many of these functions take pointer arguments. These canbe traps for newcomers to C. Study the examples carefully! Often a function will returninformation to the caller in a variable or structure to which the pointer argument points.It is necessary in such cases for the caller to allocate storage for the variables or structuresand to initialize the pointers so that they point to the allocated storage. If you fail to doso, the compiler probably will not warn you of your error; instead your program will failmysteriously, probably with a core dump and an “illegal memory reference” error message.

    With few exceptions, WFDB library functions return integers that indicate success orfailure. The tables that follow the function prototypes list the possible returns and theirmeanings. By convention, a return code of −1 indicates end-of-file on input files, and noerror message is printed. Other negative return codes signify other types of errors, andare usually accompanied by descriptive messages on the standard error output (but see[wfdbquiet and wfdbverbose], page 43). Zero may indicate success or failure, dependingon context (see the descriptions of the individual functions below). Positive codes (returnedby only a few functions) always indicate success.

    A comprehensive discussion of database files appears later in this guide (see Chapter 5[Database Files], page 65). Most readers should not need to learn about the gruesome detailsof how the data are actually stored. You should know, however, that there are files thatcontain digitized signals, other files that contain annotations, and still others (called headerfiles) that describe attributes of the signals such as sampling frequency. The database pathlists directories in which database files are found; the WFDB library functions can find themgiven only the record (and annotator) names, provided that WFDB has been properly set (seeSection 1.4 [WFDB path], page 12). WFDB library functions responsible for opening signalfiles find them by reading the header file (which contains their names) first.

    The first two sections of this chapter describes functions that extract information fromheader files in order to gain access to signal and annotation files, and functions that con-trol how these files are read and written. The following two sections describe functionsthat read and write signal and annotation files. Many readers will not need to go any fur-ther; the remaining sections deal with special-purpose functions that exist to serve unusualapplications.

  • 18 WFDB Programmer’s Guide

    2.2 Selecting Database Records

    annopen

    int annopen(char *record, WFDB_Anninfo *aiarray, unsigned int nann)

    Return:

    0 Success

    -3 Failure: unable to open input annotation file

    -4 Failure: unable to open output annotation file

    -5 Failure: illegal stat (in aiarray) specified for annotation file

    This function opens input and output annotation files for a selected record. If record beginswith ‘+’, previously opened annotation files are left open, and the record name is taken to bethe remainder of record after discarding the ‘+’. Otherwise, annopen closes any previouslyopened annotation files, and takes all of record as the record name. aiarray is a pointer toan array of WFDB_Anninfo structures (see Section 3.3 [Annotator Information Structures],page 58), one for each annotator to be opened. nann is the number of WFDB_Anninfostructures in aiarray. The caller must fill in the WFDB_Anninfo structures to specify thenames of the annotators, and to indicate which annotators are to be read, and which are tobe written. Input and output annotators may be listed in any order in aiarray. Annotatornumbers (for both input and output annotators) are assigned in the order in which theannotators appear in aiarray. For example, this code fragment

    ...char *record = "100s";WFDB_Anninfo a[3];

    a[0].name = "a"; a[0].stat = WFDB_READ;a[1].name = "b"; a[1].stat = WFDB_WRITE;a[2].name = "c"; a[2].stat = WFDB_READ;if (annopen(record, a, 3) < 0)...

    attempts to open three annotation files for record ‘100s’. Annotator ‘a’ becomes inputannotator 0, ‘b’ becomes output annotator 0, and ‘c’ becomes input annotator 1. Thusgetann(1, &annot) (see [getann], page 28) will read an annotation from annotator ‘c’,and putann(0, &annot) will write an annotation for annotator ‘b’. Input annotation fileswill be found if they are located in any of the directories specified by WFDB (see Section 1.4[WFDB path], page 12); output annotators are created in the current directory (but notethat, under Unix at least, it is possible to specify annotator names such as ‘/here’ or‘zzz/there’ or even ‘../somewhere/else’; see [Annotation Files], page 66, for details ofhow file names are constructed from annotator and record names). Several of the exampleprograms in chapter 6 illustrate the use of annopen; for example, see [Example 1], page 75.

    As a special case, if nann is 0, aiarray can be NULL. This can be useful to force openannotation files to be closed without closing open signal files.

  • Chapter 2: WFDB Library Functions 19

    isigopen

    int isigopen(char *record, WFDB_Siginfo *siarray, int nsig)

    Return:

    >0 Success: the returned value is the number of input signals (i.e., the number ofvalid entries in siarray)

    0 Failure: no input signals available

    -1 Failure: unable to read header file (probably incorrect record name)

    -2 Failure: incorrect header file format

    This function opens input signal files for a selected record. If record begins with ‘+’, pre-viously opened input signal files are left open, and the record name is taken to be theremainder of record after discarding the ‘+’. Otherwise, isigopen closes any previouslyopened input signal files, and takes all of record as the record name. If the record name is‘-’, isigopen reads the standard input rather than a ‘hea’ file. Siarray is a pointer to anarray of WFDB_Siginfo structures (see Section 3.1 [Signal Information Structures], page 56),one for each signal to be opened.

    As a special case, if nsig is 0, siarray can be NULL. In this case, isigopen closes anyopen input signals, then returns the number of signals in record without opening them.Use this feature to determine the amount of storage needed for signal-related variables, asin the example below, or to force open input signal files to be closed without closing openannotation or output signal files. This action also sets internal WFDB library variables thatrecord the base time and date, the length of the record, and the sampling and counter fre-quencies, so that time conversion functions such as strtim that depend on these quantitieswill work properly.

    If nsig is greater than 0, isigopen normally returns the number of input signals itactually opened, which may be less than nsig but is never greater than nsig. The callermust allocate storage for the WFDB_Siginfo structures; isigopen will fill them in withinformation about the signals. Signal numbers are assigned in the order in which signalsare specified in the ‘hea’ file for the record; on return from isigopen, information for signali will be found in siarray[i]. For example, we can read the gain attributes of each signal inrecord ‘100s’ like this:

    #include #include

    main(){

    int i, nsig;WFDB_Siginfo *siarray;

    nsig = isigopen("100s", NULL, 0);if (nsig < 1)

    exit(1);siarray = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo));nsig = isigopen("100s", siarray, nsig);

  • 20 WFDB Programmer’s Guide

    for (i = 0; i < nsig; i++)printf("signal %d gain = %g\n", i, siarray[i].gain);

    exit(0);}

    (See http://physionet.org/physiotools/wfdb/examples/pgain.c for a copy of thisprogram.)This program, unlike the example in the previous chapter, does not assume that the numberof signals is known. The first invocation of isigopen determines this number (and theprogram quits if there are no signals). Next, the program allocates the array for the signalinformation, and then it opens the signals using the second invocation of isigopen, passingin the pointer siarray and the number of signals determined from the first call (nsig).

    An error message is produced if isigopen is unable to open any of the signals listedin the header file. It is not considered an error if only some of the signals can be opened,however. A signal will not be opened if its signal file is unreadable, if an input buffer cannotbe allocated for it, or if opening all of the signals in its group would exceed the limits definedby nsig. (Note, however, that most records have only one signal group; as a consequence,isigopen fails if nsig is less than the total number of signals in such cases.) If necessary,the caller can inspect the file names and signal descriptions in siarray to determine whichsignals were opened; see Section 3.1 [Signal Information Structures], page 56. Several of theexample programs in chapter 6 illustrate the use of isigopen; for example, see [Example5], page 80.

    If nsig is less than 0, isigopen fills in up to −nsig members of siarray, based on informa-tion from the header file for record, but no signals are actually opened. The value returnedin this case is the number of signals named in the ‘hea’ file. Note, however, that there isno guarantee that all (or indeed any) of the signals named in the ‘hea’ file are available tobe opened. The features described in this paragraph were first introduced in version 4.4 ofthe WFDB library.

    osigopen

    int osigopen(char *record, WFDB_Siginfo *siarray, unsigned int nsig)

    Return:

    >0 Success: the returned value is the number of output signals; this number shouldmatch nsig

    -1 Failure: unable to read header file

    -2 Failure: incorrect header file format

    -3 Failure: unable to open output signal(s)

    This function opens output signal files. Use it only if signals are to be written using putvec.The signal specifications, including the file names, are read from the header file for a specifiedrecord. Unmodified MIT or AHA database ‘hea’ files cannot be used, since osigopen wouldattempt to overwrite the (write-protected) signal files named within. If record begins with‘+’, previously opened output signal files are left open, and the record name is taken to bethe remainder of record after discarding the ‘+’. Otherwise, osigopen closes any previouslyopened output signal files, and takes all of record as the record name. If the record name

    http://physionet.org/physiotools/wfdb/examples/pgain.c

  • Chapter 2: WFDB Library Functions 21

    is ‘-’, osigopen reads the standard input rather than a ‘hea’ file. siarray is a pointer to anuninitialized array of WFDB_Siginfo structures; siarray must contain at least nsig members.The caller must allocate storage for the WFDB_Siginfo structures. On return, osigopenwill have filled in the WFDB_Siginfo structures with the signal specifications.

    No more than nsig (additional) output signals will be opened by osigopen, even ifthe header file contains specifications for more than nsig signals. For example, this codefragment

    ...WFDB_Siginfo s[2];int i, nsig;

    nsig = osigopen("8l", s, 2);for (i = 0; i < nsig; i++)

    printf("signal %d will be written into ‘%s’\n", i, s[i].fname);...

    creates 2 output signals named ‘data0’ and ‘data1’ (see Section 5.8 [Piped and LocalRecords], page 70). See [Example 6], page 82, and see [Example 7], page 83, for illustrationsof the use of osigopen.

    As a special case, if nsig is 0, siarray can be NULL. This can be useful to force openoutput signal files to be closed without closing open annotation or input signal files.

    osigfopen

    int osigfopen(WFDB_Siginfo *siarray, unsigned int nsig)

    Return:

    >0 Success: the returned value is the number of output signals; this number shouldmatch nsig

    -2 Failure: error in signal specification (fname or desc too long, illegal fmt orbsize, or incorrect signal group assignment)

    -3 Failure: unable to open output signal(s)

    This function opens output signals as does osigopen, but the signal specifications, includingthe signal file names, are supplied by the caller to osigfopen, rather than read from a headerfile as in osigopen. Any previously open output signals are closed by osigfopen. siarrayis a pointer to an array of WFDB_Siginfo structures (see Section 3.1 [Signal InformationStructures], page 56), one for each signal to be opened. nsig is the number of WFDB_Siginfostructures in siarray.

    Before invoking osigfopen, the caller must fill in the fields of the WFDB_Siginfo struc-tures in siarray (see Chapter 3 [Data Types], page 55; the initval, nsamp, and cksumfields may be left uninitialized, however). To make a multiplexed signal file, specify thesame fname and group for each signal to be included (see Section 5.3 [Multiplexed SignalFiles], page 67). For ordinary (non-multiplexed) signal files, specify a unique fname andgroup for each signal. See [Example 8], page 86, for an illustration of the use of osigfopen.

    As a special case, if nsig is 0, siarray can be NULL. This can be useful to force openoutput signal files to be closed without closing open annotation or input signal files.

  • 22 WFDB Programmer’s Guide

    wfdbinit

    int wfdbinit(char *record, WFDB_Anninfo *aiarray, unsigned int nann,WFDB_Siginfo *siarray, unsigned int nsig)

    Return:

    >0 Success: the returned value is the number of input signals (i.e., the number ofvalid entries in siarray)

    0 Annotation files opened successfully, input signals unavailable (not an error forprograms that don’t need them; no error message is printed if nsig is 0)

    -1 Failure: unable to read header file (probably incorrect record name)

    -2 Failure: incorrect header file format

    -3 Failure: unable to open input annotation file

    -4 Failure: unable to open output annotation file

    -5 Failure: illegal stat (in aiarray) specified for annotation file (see Section 3.3[Annotator Information Structures], page 58)

    This function opens database files other than output signal files for a selected record. Thecode

    n = wfdbinit(record, a, na, s, ns);

    is exactly equivalent ton = annopen(record, a, na);if (n == 0)

    n = isigopen(record, s, ns);

    Avoid using wfdbinit and setifreq in the same program. See [Example 9], page 90, for anillustration of the use of wfdbinit. See [osigopen], page 20, and see [osigfopen], page 21,for methods of opening output signal files.

  • Chapter 2: WFDB Library Functions 23

    2.3 Special I/O Modes

    setifreq

    void setifreq(WFDB_Frequency frequency)

    This function sets the current input sampling frequency (in samples per second per signal).It should be invoked after opening the input signals (using isigopen or wfdbinit), andbefore using any of getvec, getann, putann, isigsettime, isgsettime, timstr, mstimstr,strtim, or annopen. Note that the operation of getframe is unaffected by setifreq.

    Use setifreq when your application requires input samples at a specific frequency. Af-ter invoking setifreq, getvec resamples the digitized signals from the input signals atthe desired frequency (see [getvec], page 26), and all of the WFDB library functions thataccept or return times in sample intervals automatically convert between the actual sam-pling intervals and those corresponding to the desired frequency. This slightly elaboratedversion of the example program from the previous chapter invokes setifreq, passing it thedesired sampling frequency from the command line, then prints the samples in record 100s,beginning 1 second (t0) and ending 2 seconds (t1) from the beginning of the record:

    #include #include

    main(int argc, char **argv){

    WFDB_Frequency f = (WFDB_Frequency)0;WFDB_Sample v[2];WFDB_Siginfo s[2];WFDB_Time t, t0, t1;

    if (argc > 1) sscanf(argv[1], "%lf", &f);if (f

  • 24 WFDB Programmer’s Guide

    as ‘psamplex 100’.) The QRS detector in chapter 6 also illustrates the use of setifreq(see [Example 10], page 92).Avoid using wfdbinit and setifreq in the same program.

    getifreq

    WFDB_Frequency getifreq(void)

    Return:

    (WFDB_Frequency)the input sampling frequency

    This function returns the current input sampling frequency (in samples per second persignal), which is either the raw sampling frequency for the record (as would be returned bysampfreq, see [sampfreq], page 44), or the frequency chosen using a previous invocation ofsetifreq.

    setgvmode

    void setgvmode(int *mode)

    This function sets the mode used by getvec when reading a multi-frequency record (seeSection 5.4 [Multi-Frequency Records], page 67). If mode is WFDB_LOWRES, getvec decimatesany signals sampled at multiples of the frame rate, so that one sample is returned per signalper frame (i.e., the oversampled signals are resampled by simple averaging of the samples foreach signal within each frame). If mode is WFDB_HIGHRES, each sample of any oversampledsignal is returned by successive invocations of getvec, and each sample of any signal sampledat a lower frequency is returned by two or more successive invocations of getvec (i.e.,the less frequently sampled signals are resampled using zero-order interpolation). getvecoperates in WFDB_LOWRES mode by default. WFDB_LOWRES and WFDB_HIGHRES are defined in‘’.

    In WFDB library version 9.6 and later versions, setgvmode also affects how annota-tions are read and written. If setgvmode(WFDB_HIGHRES) is invoked before using annopen,wfdbinit, getvec, sampfreq, strtim, or timstr, then all WFDB_Time data (including thetime attributes of annotations read by getann or written by putann) visible to the appli-cation are in units of the high-resolution sampling intervals. (Otherwise, WFDB_Time dataare in units of frame intervals.)

    Version 10.4 and late


Recommended