This is wpg, produced by makeinfo version 4.0b from wpg.tex.

INFO-DIR-SECTION Libraries
START-INFO-DIR-ENTRY
* WFDB library: (wpg).		The Waveform Database library.
END-INFO-DIR-ENTRY


File: wpg,  Node: WFDB path syntax,  Next: exercises 1,  Prev: name restrictions,  Up: Usage

More About the WFDB Path
========================

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

   The default WFDB path is specified at the time the WFDB library is
compiled, by defining a value for the symbol `DEFWFDB' in `wfdblib.h'.
Current versions of the WFDB library are compiled with a
three-component default WFDB path; the first component is empty (i.e.,
it refers to the current directory), the second component names the
"system-wide database directory" (which contains the sample WFDB files
supplied with the WFDB software package), and the third component is
`http://www.physionet.org/physiobank/database' (referring to the
PhysioBank data archives).  Note that this default may be changed at the
time the WFDB library is compiled.  Normally, however, this means that
any record available from PhysioBank is readable by any WFDB application
provided that PhysioBank is accessible from the user's computer and that
the database name is included in the record name (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, and MacOS, the WFDB path can be
given in the format used for the MS-DOS `PATH' variable, with
semicolons used to separate prefixes (colons retain their customary
meanings, 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 any operating system); this
also implies that embedded spaces are not permitted within path
components.  *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 the current directory.  (As an example, an
application that analyzes one or more signals in a record may record its
findings in an annotation file in the current directory.)  If the record
name (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', the file
will be written in the `edb' subdirectory of the current directory.
The `edb' subdirectory will be created by the WFDB library if does not
exist already.  This feature was introduced in WFDB library version
10.2.0.)

   Note particularly that the current directory is _not_ necessarily
part of the WFDB path.  If you modify your WFDB path, you must
explicitly include an empty (null) component, which corresponds to the
current directory, in order to be sure that your WFDB applications can
read any WFDB files that you have previously written.  In most cases,
this null component should be the first in the WFDB path.  Thus, if you
write into the current directory a modified version of an existing WFDB
file, any later actions that would read this file will read your
modified version rather than the original.

   The WFDB path may contain `http://' and `ftp://' URL prefixes (other
schema, such as `file://' and `https://', may also be supported if they
are supported by your version of `libwww').  If NETFILES support is not
compiled into the WFDB library, any WFDB path components containing
`://' are ignored.  (These features were first introduced in 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 was first introduced in WFDB library
version 8.0.)  Indirect WFDB path files may be nested up to ten levels
(this arbitrary limit is imposed to avoid infinite recursion if the
contents of the indirect file are incorrect).  This method of indirect
assignment is useful under classic MacOS, where recompilation of the
WFDB library would otherwise be necessary in order to change the WFDB
path.  It may also be useful under MS-DOS to reduce the need for
environment space, or if the length of the command needed to set the
`WFDB' environment variable would otherwise approach or exceed the
128-byte limit for MS-DOS commands.

   If a WFDB header file (*note Database Files::) specifies that a
signal file is to be found in a directory that is not already in the
WFDB path, that directory is appended to the end of the WFDB path; in
this case, if the WFDB path is not set, it is created with an initial
null component followed by the directory that contains the signal file.
(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 WFDB path;  `%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', a request to
read a file associated with record 055n will cause the WFDB library to
look first in 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 other than `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 `%%'.  (Substitutions of `%'-strings in the WFDB path
were first introduced in WFDB library version 9.7.)


File: wpg,  Node: exercises 1,  Prev: WFDB path syntax,  Up: Usage

Exercises
=========

   These exercises should require only a few minutes.  If you work
through them, you will have an opportunity to become acquainted with a
few of the most common errors in using the WFDB 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 most recent version from
     PhysioNet first (*note Installing the WFDB Software Package:
     Installation.).

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

  3. Modify the example program so that you can specify the record to be
     opened, either as a command-line argument or by having the program
     prompt you to type a record name.  If you are unfamiliar with
     command-line argument processing, *note Example 2::.

  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 records have 4 and 6
     signals respectively, so you will need to make a few additional
     changes to the program in order to read these records successfully.

  5. Once again using the modified version of the example, what happens
     if you omit the path information from one of the records in the
     previous exercise (for example, if you try to open `e0103' instead
     of `edb/e0103'?  Figure out how to set the WFDB path 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 for record `edb/e0103'; this information
     will help you to determine how to set the WFDB path.)

  6. If you use MS-DOS or MS-Windows, explore and explain what happens
     in the previous exercise 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 the value it reads, as in `v = getvec()'?


File: wpg,  Node: Functions,  Next: Data Types,  Prev: Usage,  Up: Top

WFDB Library Functions
**********************

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

* Menu:

* introduction to functions::	General notes on functions.
				This node discusses arguments, return codes,
				and the organization of this section of
				the guide.

The remainder of the nodes in this section describe functions for:

* selecting::			Selecting database records (opening files).
* special input modes::         Setting the input sampling frequency and more.
* signal and annotation I/O::	Reading and writing signals and annotations.
* non-sequential::		Non-sequential access to WFDB files.
* conversion::			Time and other conversion functions.
* calibration::			Calibrating signals.
* miscellaneous functions::	Attribute-reading and other functions.


File: wpg,  Node: introduction to functions,  Next: selecting,  Prev: Functions,  Up: Functions

About these functions
=====================

   Each function description begins with an ANSI C function prototype,
which specifies the types of any arguments as well as the type of the
quantity returned by the function (see `K&R', pp. 217-218).  Note that
many of these functions take pointer arguments.  These can be traps for
newcomers to C.  Study the examples carefully!  Often a function will
return information 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 structures and to initialize
the pointers so that they point to the allocated storage.  If you fail
to do so, the compiler probably will not warn you of your error;
instead your program will fail mysteriously, probably with a core dump
and an "illegal memory reference" error message.*

   With few exceptions, WFDB library functions return integers that
indicate success or failure.  The tables that follow the function
prototypes list the possible returns and their meanings.  By
convention, a return code of -1 indicates end-of-file on input files,
and no error message is printed.  Other negative return codes signify
other types of errors, and are usually accompanied by descriptive
messages on the standard error output (but *note wfdbquiet and
wfdbverbose::).  Zero may indicate success or failure, depending on
context (see the descriptions of the individual functions below).
Positive codes (returned by only a few functions) always indicate
success.

   A comprehensive discussion of database files appears later in this
guide (*note Database Files::).  Most readers should not need to learn
about the gruesome details of how the data are actually stored.  You
should know, however, that there are files that contain digitized
signals, other files that contain annotations, and still others (called
"header" files) that describe attributes of the signals such as
sampling frequency.  The database path lists directories in which
database files are found; the WFDB library functions can find them given
only the record (and annotator) names, provided that `WFDB' has been
properly set (*note WFDB path::).  WFDB library functions responsible
for opening signal files find them by reading the header file (which
contains their names) first.

   The first two sections of this chapter describes functions that
extract information from header files in order to gain access to signal
and annotation files, and functions that control how these files are
read and written.  The following two sections describe functions that
read and write signal and annotation files.  Many readers will not need
to go any further; the remaining sections deal with special-purpose
functions that exist to serve unusual applications.


File: wpg,  Node: selecting,  Next: special input modes,  Prev: introduction to functions,  Up: Functions

Selecting Database Records
==========================

* Menu:

* annopen::		Opening input and output annotation files.
* isigopen::		Opening input signal files.
* osigopen::		Opening output signal files.
* osigfopen::		Opening output signal files by name.
* wfdbinit::		`annopen' and `isigopen' in one function.


File: wpg,  Node: annopen,  Next: isigopen,  Prev: selecting,  Up: selecting

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 begins with `+', previously opened annotation files
are left open, and the record name is taken to be the remainder of
RECORD after discarding the `+'.  Otherwise, `annopen' closes any
previously opened annotation files, and takes all of RECORD as the
record name.  AIARRAY is a pointer to an array of `WFDB_Anninfo'
structures (*note WFDB_Anninfo structures::), one for each annotator to
be opened.  NANN is the number of `WFDB_Anninfo' structures in AIARRAY.
The caller must fill in the `WFDB_Anninfo' structures to specify the
names of the annotators, and to indicate which annotators are to be
read, and which are to be written.  Input and output annotators may be
listed in any order in AIARRAY.  "Annotator numbers" (for both input and
output annotators) are assigned in the order in which the annotators
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 input annotator 0, `b' becomes output annotator 0, and `c'
becomes input annotator 1.  Thus `getann(1, &annot)' (*note getann::)
will read an annotation from annotator `c', and `putann(0, &annot)'
will write an annotation for annotator `b'.  Input annotation files
will be found if they are located in any of the directories specified
by `WFDB' (*note WFDB path::); output annotators are created in the
current directory (but note that, under Unix at least, it is possible
to specify annotator names such as `/here' or `zzz/there' or even
`../somewhere/else'; *note Annotation Files::, for details of how file
names are constructed from annotator and record names).  Several of the
example programs in chapter 6 illustrate the use of `annopen'; for
example, *note Example 1::.

   As a special case, if NANN is 0, AIARRAY can be `NULL'.  This can be
useful to force open annotation files to be closed without closing open
signal files.


File: wpg,  Node: isigopen,  Next: osigopen,  Prev: annopen,  Up: selecting

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 of valid 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 `+', previously opened input signal files are left
open, and the record name is taken to be the remainder of RECORD after
discarding the `+'.  Otherwise, `isigopen' closes any previously opened
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 an array of `WFDB_Siginfo'
structures (*note WFDB_Siginfo structures::), one for each signal to be
opened.

   As a special case, if NSIG is 0, SIARRAY can be `NULL'.  In this
case, `isigopen' closes any open 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, as
in the example below, or to force open input signal files to be closed
without closing open annotation or output signal files.  This action
also sets internal WFDB library variables that record the base time and
date, the length of the record, and the sampling and counter
frequencies, so that time conversion functions such as `strtim' that
depend on these quantities will work properly.

   If `nsig' is greater than 0, `isigopen' normally returns the number
of input signals it actually opened, which may be less than NSIG but is
never greater than NSIG.  The caller must allocate storage for the
`WFDB_Siginfo' structures; `isigopen' will fill them in with
information about the signals.  "Signal numbers" are assigned in the
order in which signals are specified in the `hea' file for the record;
on return from `isigopen', information for signal I will be found in
SIARRAY[I].  For example, we can read the `gain' attributes of each
signal in record `100s' like this:

     #include <stdio.h>
     #include <wfdb/wfdb.h>
     
     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);
         for (i = 0; i < nsig; i++)
             printf("signal %d gain = %g\n", i, siarray[i].gain);
         exit(0);
     }

(See `http://www.physionet.org/physiotools/wfdb/examples/pgain.c' for a
copy of this program.)

This program, unlike the example in the previous chapter, does not
assume that the number of signals is known.  The first invocation of
`isigopen' determines this number (and the program quits if there are
no signals).  Next, the program allocates the array for the signal
information, and then it opens the signals using the second invocation
of `isigopen', passing in 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 listed in 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
cannot be allocated for it, or if opening all of the signals in its
group would exceed the limits defined by 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 which signals were opened; *note
WFDB_Siginfo structures::.  Several of the example programs in chapter 6
illustrate the use of `isigopen'; for example, *note Example 5::.

   If NSIG is less than 0, `isigopen' fills in up to -NSIG members of
SIARRAY, based on information from the header file for RECORD, but _no
signals are actually opened_.  The value returned in this case is the
number of signals named in the `hea' file.  Note, however, that there
is no guarantee that all (or indeed any) of the signals named in the
`hea' file are available to be opened.  The features described in this
paragraph were first introduced in version 4.4 of the WFDB library.


File: wpg,  Node: osigopen,  Next: osigfopen,  Prev: isigopen,  Up: selecting

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 should match 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 specified record.
Unmodified MIT or AHA database `hea' files cannot be used, since
`osigopen' would attempt 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 be
the remainder of RECORD after discarding the `+'.  Otherwise,
`osigopen' closes any previously opened output signal files, and takes
all of RECORD as the record name.  If the record name is `-',
`osigopen' reads the standard input rather than a `hea' file.  SIARRAY
is a pointer to an uninitialized array of `WFDB_Siginfo' structures;
SIARRAY must contain at least NSIG members.  The caller must allocate
storage for the `WFDB_Siginfo' structures.  On return, `osigopen' will
have filled in the `WFDB_Siginfo' structures with the signal
specifications.

   No more than NSIG (additional) output signals will be opened by
`osigopen', even if the header file contains specifications for more
than NSIG signals.  For example, this code fragment

     ...
     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' (*note Piped and
Local Records::).  *Note Example 6::, and *note Example 7::, for
illustrations of the use of `osigopen'.

   As a special case, if NSIG is 0, SIARRAY can be `NULL'.  This can be
useful to force open output signal files to be closed without closing
open annotation or input signal files.


File: wpg,  Node: osigfopen,  Next: wfdbinit,  Prev: osigopen,  Up: selecting

osigfopen
---------

     int osigfopen(WFDB_Siginfo *SIARRAY, unsigned int NSIG)

*Return:*
>0
     Success: the returned value is the number of output signals;  this
     number should match NSIG

-2
     Failure: error in signal specification (`fname' or `desc' too
     long, illegal `fmt' or `bsize', 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, including the signal file names, are supplied by the
caller to `osigfopen', rather than read from a header file as in
`osigopen'.  Any previously open output signals are closed by
`osigfopen'.  SIARRAY is a pointer to an array of `WFDB_Siginfo'
structures (*note WFDB_Siginfo structures::), one for each signal to be
opened.  NSIG is the number of `WFDB_Siginfo' structures in SIARRAY.

   Before invoking `osigfopen', the caller must fill in the fields of
the `WFDB_Siginfo' structures in SIARRAY (*note Data Types::; the
`initval', `nsamp', and `cksum' fields may be left uninitialized,
however).  To make a multiplexed signal file, specify the same `fname'
and `group' for each signal to be included (*note Multiplexed Signal
Files::).  For ordinary (non-multiplexed) signal files, specify a
unique `fname' and `group' for each signal.  *Note Example 8::, 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 open output signal files to be closed without closing
open annotation or input signal files.


File: wpg,  Node: wfdbinit,  Prev: osigfopen,  Up: selecting

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 of valid entries in SIARRAY)

 0
     Annotation files opened successfully, input signals unavailable
     (not an error for programs 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
     (*note WFDB_Anninfo structures::)

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

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

is exactly equivalent to

     n = annopen(record, a, na);
     if (n == 0)
         n = isigopen(record, s, ns);

*Note Example 9::, for an illustration of the use of `wfdbinit'.  *Note
osigopen::, and *note osigfopen::, for methods of opening output signal
files.


File: wpg,  Node: special input modes,  Next: signal and annotation I/O,  Prev: selecting,  Up: Functions

Special Input Modes
===================

* Menu:

* setifreq::			Setting the input sampling frequency.
* getifreq::                    Determining the input sampling frequency.
* setgvmode::                   Setting the resolution for a multifrequency
                                record.
* getspf::                      Determining the number of samples per frame.


File: wpg,  Node: setifreq,  Next: getifreq,  Prev: special input modes,  Up: special input 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'), and before using any of
`getvec', `getann', `putann', `isigsettime', `isgsettime', `timstr',
`mstimstr', or `strtim'.  _Note that the operation of `getframe' is
unaffected by `setifreq'._

   Use `setifreq' when your application requires input samples at a
specific frequency.  After invoking `setifreq', `getvec' resamples the
digitized signals from the input signals at the desired frequency
(*note getvec::), and all of the WFDB library functions that accept or
return times in sample intervals automatically convert between the
actual sampling intervals and those corresponding to the desired
frequency.  This slightly elaborated version of the example program from
the previous chapter invokes `setifreq', passing it the desired 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 <wfdb/wfdb.h>
     
     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 <= (WFDB_Frequency)0) f = sampfreq("100s");
     
         if (isigopen("100s", s, 2) < 1)
             exit(1);
         setifreq(f);
         t0 = strtim("1");
         isigsettime(t0);
         t1 = strtim("2");
         for (t = t0; t <= t1; t++) {
             if (getvec(v) < 0)
                 break;
             printf("%d\t%d\n", v[0], v[1]);
         }
         exit(0);
     }

(See `http://www.physionet.org/physiotools/wfdb/examples/psamplex.c'
for a copy of this program.  Compile it as shown in the previous
chapter, then run it using a command such as `psamplex 100'.)  The QRS
detector in chapter 6 also illustrates the use of `setifreq' (*note
Example 10::).


File: wpg,  Node: getifreq,  Next: setgvmode,  Prev: setifreq,  Up: special input modes

getifreq
--------

     WFDB_Frequency getifreq(void)

*Return:*
(WFDB_Frequency)
     the input sampling frequency

This function returns the current input sampling frequency (in samples
per second per signal), which is either the raw sampling frequency for
the record (as would be returned by `sampfreq', *note sampfreq::), or
the frequency chosen using a previous invocation of `setifreq'.


File: wpg,  Node: setgvmode,  Next: getspf,  Prev: getifreq,  Up: special input modes

setgvmode
---------

     void setgvmode(int *MODE)

This function sets the mode used by `getvec' when reading a
multi-frequency record (*note Multi-Frequency Records::).  If MODE is
`WFDB_LOWRES', `getvec' decimates any signals sampled at multiples of
the frame rate, so that one sample is returned per signal per frame
(i.e., the oversampled signals are resampled by simple averaging of the
samples for each signal within each frame).  If MODE is `WFDB_HIGHRES',
each sample of any oversampled signal is returned by successive
invocations of `getvec', and each sample of any signal sampled at 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).  `getvec' operates in `WFDB_LOWRES' mode by
default.  `WFDB_LOWRES' and `WFDB_HIGHRES' are defined in
`<wfdb/wfdb.h>'.

   In WFDB library version 9.6 and later versions, `setgvmode' also
affects how annotations 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 the `time' attributes of annotations read
by `getann' or written by `putann') visible to the application are in
units of the high-resolution sampling intervals.  (Otherwise,
`WFDB_Time' data are in units of frame intervals.)


File: wpg,  Node: getspf,  Prev: setgvmode,  Up: special input modes

getspf
------

     int getspf(void)

*Return:*
(int)
     the number of samples per signal per frame

Unless the application is operating in `WFDB_HIGHRES' mode (*note
setgvmode::) and has then opened a multi-frequency record, this
function returns 1.  For the case of a multi-frequency record being read
in high resolution mode, however, `getspf' returns the number of
samples per signal per frame (hence `sampfreq(NULL)/getspf()' is the
number of frames per second).


File: wpg,  Node: signal and annotation I/O,  Next: non-sequential,  Prev: special input modes,  Up: Functions

Reading and Writing Signals and Annotations
===========================================

* Menu:

* getvec::		Reading input signals.
* getframe::            Reading input signals from multifrequency records.
* putvec::		Writing output signals.
* getann::		Reading annotations.
* ungetann::		Pushing an annotation onto an input stream.
* putann::		Writing annotations.


File: wpg,  Node: getvec,  Next: getframe,  Prev: signal and annotation I/O,  Up: signal and annotation I/O

getvec
------

     int getvec(WFDB_Sample *VECTOR)

*Return:*
>0
     Success;  the returned value is the number of input signals (the
     number of valid entries in VECTOR)

-1
     End of data (contents of VECTOR not valid)

-3
     Failure: unexpected physical end of file

-4
     Failure: checksum error (detected only at end of file)

This function reads a sample from each input signal.  The caller should
allocate storage for an array of `WFDB_Sample's (integers) and pass a
pointer to this array to `getvec'.  (The length of the array must be no
less than the number of input signals, as obtained from `isigopen' or
`wfdbinit'.)  On return, VECTOR[I] contains the next sample from signal
I.  For example, this modified version of the example from chapter 1
reads and prints the first ten samples of each available input signal:

     #include <stdio.h>
     #include <malloc.h>
     #include <wfdb/wfdb.h>
     
     main()
     {
         int i, j, nsig;
         WFDB_Sample *v;
         WFDB_Siginfo *s;
     
         nsig = isigopen("100s", NULL, 0);
         if (nsig < 1)
             exit(1);
         s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo));
         if (isigopen("100s", s, nsig) != nsig)
             exit(1);
         v = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample));
         for (i = 0; i < 10; i++) {
             if (getvec(v) < 0)
                 break;
             for (j = 0; j < nsig; j++)
                 printf("%8d", v[j]);
             printf("\n");
         }
         exit(0);
     }

(See `http://www.physionet.org/physiotools/wfdb/examples/exgetvec.c'
for a copy of this program.)

   Notice how the value returned by the first invocation of `isigopen'
is used to determine how many input signals there are.  Several of the
example programs in chapter 6 illustrate the use of `getvec'; for
example, *note Example 6::.

   If `setifreq' has been used to modify the input sampling rate,
`getvec' resamples the input signals at the desired rate, using linear
interpolation between the pair of samples nearest in time to that of
the sample to be returned.  The results will generally be satisfactory,
provided that the original signals do not contain frequencies near or
above the Nyquist limit (half of the desired sampling frequency).  If
this is a concern, you may wish to low-pass filter the input signals
using, for example, `fir' (see the `WFDB Applications Guide') before
resampling them.  If you use `setifreq' to _increase_ the sampling
frequency by a large factor, you may wish to filter the resampled
signals within your application to remove harmonics of the original
sampling frequency introduced by resampling.


File: wpg,  Node: getframe,  Next: putvec,  Prev: getvec,  Up: signal and annotation I/O

getframe
--------

     int getframe(WFDB_Sample *VECTOR)

*Return:*
>0
     Success;  the returned value is the number of input signals

-1
     End of data (contents of VECTOR not valid)

-3
     Failure: unexpected physical end of file

-4
     Failure: checksum error (detected only at end of file)

This function reads a vector of samples, including at least one sample
from each open input signal.  If all signals are sampled at the same
frequency, only one sample is read from each signal.  Otherwise,
signals sampled at multiples of the frame frequency are represented by
two or more consecutive elements of the returned VECTOR.  For example,
if the frame frequency is 125 Hz, signal 0 is sampled at 500 Hz, and
the remaining 3 signals are sampled at 125 Hz each, then the returned
VECTOR has 7 valid components: the first 4 are samples of signal 0, and
the remaining 3 are samples of signals 1, 2, and 3.  The caller should
allocate storage for an array of `WFDB_Sample's (integers) and pass a
pointer to this array to `getframe'.  The length of VECTOR must be
determined by summing the values of the `spf' (samples per frame)
fields in the `WFDB_Siginfo' structures associated with the input
signals (*note isigopen::).


File: wpg,  Node: putvec,  Next: getann,  Prev: getframe,  Up: signal and annotation I/O

putvec
------

     int putvec(WFDB_Sample *VECTOR)

*Return:*
>0
     Success: the returned value is the number of output signals (the
     number of entries in VECTOR that were written)

 0
     Slew rate too high for one or more signals (difference format
     only; the DC level(s) will be corrected as soon as the slew rate
     permits)

-1
     Failure: write error

This function writes a sample to each input signal.  The caller should
fill an array of `WFDB_Sample's with the samples and pass a pointer to
this array to `putvec'.  (The length of the array must be no less than
the number of output signals, as given to `osigfopen' or `osigopen'.)
On entry, VECTOR[I] contains the next sample from signal I.  For
example, this modified version of the previous example (*note getvec::)
copies the first ten samples of each available input signal:

     #include <stdio.h>
     #include <wfdb/wfdb.h>
     
     main()
     {
         int i, j, nsig;
         WFDB_Sample *v;
         WFDB_Siginfo *s;
     
         nsig = isigopen("100s", NULL, 0);
         if (nsig < 1)
             exit(1);
         s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo));
         if (isigopen("100s", s, nsig) != nsig ||
             osigopen("8l", s, nsig) != nsig)
             exit(1);
         v = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample));
         for (i = 0; i < 10; i++)
             if (getvec(v) < 0 || putvec(v) < 0)
                 break;
         wfdbquit();
         exit(0);
     }

(See `http://www.physionet.org/physiotools/wfdb/examples/exputvec.c'
for a copy of this program.)

   All programs that write signals or annotations _must_ invoke
`wfdbquit' to close the output files properly (*note wfdbquit::).  This
example uses record `8l' (*note Piped and Local Records::) for the
output signal specifications; the output signal files will be named
`data0' and `data1' in the current directory.  Several of the example
programs in chapter 6 illustrate the use of `putvec'; for example,
*note Example 6::.


File: wpg,  Node: getann,  Next: ungetann,  Prev: putvec,  Up: signal and annotation I/O

getann
------

     int getann(WFDB_Annotator AN, WFDB_Annotation *ANNOT)

*Return:*
 0
     Success

-1
     End of file (*ANNOT is not valid)

-2
     Failure: incorrect annotator number specified

-3
     Failure: unexpected physical end of file

This function reads the next annotation from the input annotator
specified by AN into the annotation structure (*note WFDB_Annotation
structures::) pointed to by ANNOT.  The caller must allocate storage
for the annotation structure.  Input annotators are numbered 0, 1, 2,
etc.  This short program uses `getann' to read the contents of the
reference (`atr') annotation file for record `100s':

     #include <wfdb/wfdb.h>
     
     main()
     {
         WFDB_Anninfo a;
         WFDB_Annotation annot;
     
         a.name = "atr"; a.stat = WFDB_READ;
         if (annopen("100s", &a, 1) < 0)
             exit(1);
         while (getann(0, &annot) == 0)
             printf("%s %s\n", mstimstr(annot.time), annstr(annot.anntyp));
         exit(0);
     }

(See `http://www.physionet.org/physiotools/wfdb/examples/exgetann.c'
for a copy of this program.)

   *Note WFDB_Anninfo structures::, for information on the contents of
the `WFDB_Anninfo' structure, and *note timstr and strtim::, and *note
annstr and strann::, for details of the functions used to print
portions of the annotations read by `getann' in this example.


File: wpg,  Node: ungetann,  Next: putann,  Prev: getann,  Up: signal and annotation I/O

ungetann
--------

     int ungetann(WFDB_Annotator AN, WFDB_Annotation *ANNOT)

*Return:*
 0
     Success

-1
     Failure: push-back buffer full (`*ANNOT' was not pushed back)

-2
     Failure: incorrect annotator number specified

This function arranges for the annotation structure pointed to by ANNOT
to be the next one read by `getann' from input annotator AN.  The
pushed-back annotation need not necessarily be one originally read by
`getann'.  No more than one annotation may be pushed back at a time for
each input annotator.  (This function was first introduced in WFDB
library version 5.3.)


File: wpg,  Node: putann,  Prev: ungetann,  Up: signal and annotation I/O

putann
------

     int putann(WFDB_Annotator AN, WFDB_Annotation *ANNOT)

*Return:*
 0
     Success

-1
     Failure: write error

-2
     Failure: incorrect annotator number specified

This function writes the next annotation for the output annotator
specified by AN from the annotation structure pointed to by ANNOT.
Output annotators are numbered 0, 1, 2, etc.  The caller must fill in
all fields of the annotation structure.  Using version 9.7 and later
versions of the WFDB library, annotations may be written in any order
(*note Annotation Order::).  Earlier versions require that annotations
be supplied to `putann' in canonical order, and return an error code of
-3 if an out-of-order annotation is supplied.  All programs that write
signals or annotations _must_ invoke `wfdbquit' to close the output
files properly (*note wfdbquit::).  Several of the example programs in
chapter 6 illustrate the use of `putann'; for example, *note Example
1::.


File: wpg,  Node: non-sequential,  Next: conversion,  Prev: signal and annotation I/O,  Up: Functions

Non-Sequential Access to WFDB Files
===================================

   The next three functions permit random access to signal and
annotation files.  It is not possible, however, to skip backwards on
piped input.

* Menu:

* isigsettime::			Setting time of next samples read.
* isgsettime::			As above, but for one signal group only.
* iannsettime::			Setting time of next annotations read.
* sample::			A random access interface to input signals.


File: wpg,  Node: isigsettime,  Next: isgsettime,  Prev: non-sequential,  Up: non-sequential

isigsettime
-----------

     int isigsettime(WFDB_Time T)

*Return:*
 0
     Success

-1
     Failure: EOF reached or improper seek

This function resets the input signal file pointers so that the next
samples returned from `getvec' will be those with sample number |T|.
Only the magnitude of T is significant, not its sign; hence values
returned by `strtim' can always be used safely as arguments to
`isigsettime' (*note timstr and strtim::).  This function will fail if
a pipe is used for input and |T| is less than the current sample
number.  *Note Example 7::, and *note Example 9::, for illustrations of
the use of `isigsettime'.


File: wpg,  Node: isgsettime,  Next: iannsettime,  Prev: isigsettime,  Up: non-sequential

isgsettime
----------

     int isgsettime(WFDB_Group SGROUP, WFDB_Time T)

*Return:*
 0
     Success

-1
     Failure: EOF reached or improper seek

-2
     Failure: incorrect signal group number specified

This function does the job of `isigsettime', but only for the signal
group specified by SGROUP.  This function may be of use if more than
one record is open simultaneously (*note Multiple Record Access::).


File: wpg,  Node: iannsettime,  Next: sample,  Prev: isgsettime,  Up: non-sequential

iannsettime
-----------

     int iannsettime(WFDB_Time T)

*Return:*
 0
     Success

-1
     Failure: EOF reached or improper seek

-3
     Failure: unexpected physical end of file

This function resets the input annotation file pointers so that the next
annotation read by `getann' from each input annotation file will be the
first occurring on or after sample number |T| in that file.  Only the
magnitude of T is significant, not its sign; hence values returned by
`strtim' can always be used safely as arguments to `iannsettime' (*note
timstr and strtim::).  This function will fail if a pipe is used for
input and |T| is less than the time of the most recent annotation read
from the pipe.  *Note Example 9::, for an illustration of the use of
`iannsettime'.

   The version of `iannsettime' that is included on the first edition
of the MIT-BIH Arrhythmia Database CD-ROM contains a bug that can
occasionally cause incorrect results.  To avoid this problem when using
that version of the library, make at least one call to `getann' before
using `iannsettime'.  The bug was corrected in version 4.0 of the
library.


File: wpg,  Node: sample,  Prev: iannsettime,  Up: non-sequential

sample and sample_valid
-----------------------

     WFDB_Sample sample(WFDB_Signal S, WFDB_Time T)
     int sample_valid(void)

*Return:*
n
     (from `sample'): The value (in raw adus) of sample number T in
     open signal S,if successful, or the value of the previous
     successfully read sample.

0
     (from `sample_valid'): The most recent value returned by `sample'
     was invalid

1
     (from `sample_valid'): The most recent value returned by `sample'
     was valid

The `sample' function allows the caller to read samples of the
currently open input signals in any order.  The first argument is a
signal number (a non-negative integer between 0 and NSIG-1, where NSIG
is the number of open input signals), and the second is a time,
expressed as a non-negative sample number. If `sample' is invoked with
valid input arguments, the companion function `sample_valid' returns 1.

   There are three ways in which `sample' can be invoked with invalid
input arguments.  In each case, `sample_valid' returns 0, but `sample'
attempts to return a reasonable value.  If S is invalid, `sample'
returns the value of signal 0 at the specified time.  If T is negative,
the returned value is that of sample number zero of the specified
signal.  If T specifies a sample number beyond the end of the record,
the returned value is that of the last valid sample of the specified
signal.  For an example of the use of `sample' and `sample_valid',
*note Example 7::.


File: wpg,  Node: conversion,  Next: calibration,  Prev: non-sequential,  Up: Functions

Conversion Functions
====================

   Functions in this section perform various useful conversions:
between annotation codes and printable strings, between times in sample
intervals and printable strings, between Julian dates and printable
strings, and between ADC units and physical units.

* Menu:

* annstr and strann::		annotation code <-> string
* timstr and strtim::		time in sample intervals <-> HH:MM:SS string
* datstr and strdat::		Julian date <-> DD/MM/YYYY string
* aduphys and physadu::		ADC units <-> physical units

