This section may be helpful if you wish to extend the capabilities of the DB library, or if you wish to port it to another environment. In order to make use of the information in this section, you should have the DB library sources (see section Sources). The sources are distributed among four `include' (`.h') files and five `.c' files:
db.h Constant and structure definitions, and function prototypes ecgcodes.h Annotation codes ecgmap.h Annotation code mapping macros dblib.h External definitions for private DB library functions dbinit.c Functionsdbinit
,dbquit
, anddbflush
signal.c Functions for signals calib.c Functions for signal calibration annot.c Functions for annotations dbio.c Low-level I/O and operating system-dependent functions
The first three of these files are the standard `include' files that are usually obtained by `#include <ecg/file.h>' statements. When modifying the DB library, however, make any necessary changes in the copies of these files that are kept in the library source directory. Install the modified versions of the `.h' files in the system's `include' directory after installing the modified DB library.
If you wish to increase the number of simultaneously accessible signals or
annotators, simply change DB_MAXSIG
or DB_MAXANN
in `db.h',
and recompile the DB library and your applications. Your operating system's
limit on the number of simultaneously open files may require you to use
multiplexed signal files if you increase DB_MAXSIG
substantially.
The cleanest mechanism for adding additional fields to `header' files is to include them in `info' strings (see section getinfo), rather than by modifying the code that reads and writes `header' files (in `signal.c').
A common problem is the need to import signal files generated by other
software. Often this problem can be solved by writing a format
conversion program that uses input functions provided with the other
software to read the signal files, and putvec
to write them
in one of the formats supported by the DB library. This solution is
unlikely to be satisfactory if you have many large signal files to
import, however, and you may wish to arrange for getvec
to read
the imported files directly. This may be done by defining a new signal
file format, as outlined below.
To define a new format for signal files, choose a numeric code to
represent your format. (Values between 900 and 999 are reserved for
user-defined signal file format codes.) In `db.h', add your format
code to FMT_LIST
and increment NFMTS
. In `signal.c',
define functions (macros if possible for efficiency) for reading and
writing single samples; these should be named rnnn
and
wnnn
, where nnn is your format code. Follow the
examples in `signal.c'; it will almost certainly be easier to make
use of the existing macros r8
and w8
than to begin from
scratch. Add additional case
statements in getvec
and
putvec
, again following the existing models. You will also need
to add a case
in isgsettime
, including a formula to
determine the number of bytes needed per sample, given the number of
signals multiplexed. (All currently-defined formats use fixed-length
encoding. If you wish to implement variable-length encoding, it may be
easiest to implement an indexed-search method for isgsettime
in
such cases.) If the ADC resolution exceeds the number of bits in a C
int
on your system, change the typedef
for `Sample'
in `<ecg/db.h>' as necessary; be aware that this change is likely
to require additional changes to application programs (use `lint'
or an ANSI C compiler to check your code).
Although the DB library generally assumes that signal files are "pure",
it is possible to read imported signal files that contain prologs
(data that precede the first sample). To do so, you must construct a
`header' file in which the format
fields encode the length
of the prolog in bytes. For example, a signal file with a 512-byte
prolog followed by format 16 samples would be specified using `16+512'
in the format
field or fields (if the file contains more than one
signal, the format
fields for all signals in the file must be
identical). Note that this facility is provided only for signal file
import; the DB library is not equipped to create signal files with
embedded prologs.
In a similar fashion, though with substantially more effort in most
cases, you may define a new format for annotation files. Add additional
stat
values for reading and writing to the list in `db.h'.
In `annot.c', add additional case
statements and code to
annopen
, getann
, putann
, and db_anclose
. If
you are designing a new format, you may wish to specify a `magic number'
with which your files will begin, to allow annopen
to recognize
the format automatically; a good choice of such a number is one in which
the first byte is non-zero (to distinguish it from AHA format files) and
the high six bits of the second byte are zero (to distinguish it from MIT
format files).
Some users may wish to define additional annotation codes. An easy and
portable way to accomplish this is to use setannstr
and
setanndesc
within programs that create your annotation files,
before opening them using annopen
(or dbinit
). Annotation
files created in this way contain modification labels at the beginning
that document the non-standard code definitions, and that permit them to
be read properly by standard DB applications. Another solution is to
modify the DB library. This method has the disadvantage that all of
your applications that read annotation files must be recompiled, and
they may no longer read standard annotation files properly. If despite
this disadvantage you prefer to modify the DB library, begin by defining
symbolic names and numeric values for your new codes in
`ecgcodes.h'. (Values between 42 and 49 are reserved for
user-defined annotation codes. Unused values less than 42 may be
assigned in future versions of the DB library, and values greater than
49 are reserved to indicate the presence of optional fields such as
subtyp
.) Next, decide how the new codes are to be mapped by
isqrs
, map1
, map2
, mamap
, and annpos
,
and set the appropriate entries in each of the code map arrays in
`ecgmap.h'. Finally, add mnemonic and descriptive strings for the
new codes in the cstring
, astring
, and tstring
arrays in `annot.c'.
The modular design of the library makes it fairly easy to remove unneeded functionality in order to conserve memory for special applications. The `calib.c' package is not referenced by any other DB library modules. For signal processing applications that do not involve ECGs, the entire `annot.c' package may be removed (with trivial modifications to the functions in `dbinit.c'). If you wish to add functions to the library, you will find that it will be easier to maintain your modified version and to merge updates if you preserve the existing arrangement of functions, which requires no global variables. Rather than defining global variables, consider implementing query functions (global-scope functions that read or write local variables). If you wish to define new types of binary files, consider using the low-level I/O routines in `dbio.c' for reading and writing them in a machine-independent format.
Porting the DB library to another environment is a straightforward
operation if an ANSI C compiler is available in the target environment.
Since all direct access to database files is performed using the
(private) function db_open
, it is possible to include file name
translation in that function if needed, to accommodate file naming
schemes that may be imposed by the operating system or other
requirements. If the notion of environment variables is foreign to the
target environment, getdb
can be modified to read the DB path
from a file. You may wish to modify the private function
db_error
(which is responsible for all error reporting from DB
library functions) if the `standard error output' is unavailable or
inadequate for use in the target environment. All of these functions are
contained within `dbio.c'; it is unlikely that any other code will
require changes for a port.
If you encounter errors while compiling `signal.c', you may wish to
try using the functions provided in that file as alternatives to the
standard macros r16
and w16
; the fully-expanded versions
of these macros are quite complex and are known to cause difficulty for
at least one C compiler. (Define the symbol `BROKEN_CC' while compiling
`signal.c' in order to obtain the function versions of r16
and w16
.) While compiling `signal.c', it may be necessary
to disable code optimization for some C compilers.
Go to the first, previous, next, last section, table of contents.