跳到正文

WFDB-x 发布:WFDB 软件包在七种编程语言中的一致性重实现

WFDB-x: Conformance-Tested Implementations of the WFDB Software Package in Seven Programming Languages

摘要

Reza Sameni 发布 WFDB-x,将 WFDB Software Package 10.7.0 原生重实现于 Python、C++、Rust、Julia、R、MATLAB/Octave 和 Kotlin 七种语言,每种都提供库函数、高层 API 和 33 个命令行工具。

摘要由模型根据原文撰写,以原文为准。

正文 · 原文

Reza Sameni1,2 Affiliation: 1Department of Biomedical Informatics, Emory University, Atlanta, GA, USA Affiliation: 2Department of Biomedical Engineering, Georgia Institute of Technology and Emory University, Atlanta, GA, USA Email: rsameni@emory.edu

Abstract

Objective: The WFDB format is widely used to store and exchange physiological waveforms and annotations, including many PhysioNet datasets. However, existing software implementations are limited to C, Python, and MATLAB/Octave (no longer maintained), can produce different results in corner cases and checksum calculations, and have defaults such as sampling frequency and gain, that can lead to silent misinterpretation of recordings. We developed WFDB-x, a cross-language, performance-optimized reimplementation of WFDB in seven popular programming languages, with extensive unit tests, to provide consistent WFDB processing across programming languages.

Approach: We reimplemented the WFDB Software Package 10.7.0 natively in Python, C++, Rust, Julia, R, MATLAB/Octave, and Kotlin, using AI-assisted development under human direction and review. Each implementation provides library functions, a high-level interface, and command-line tools. We compared their outputs with those of the original C programs using 1098 conformance cases, 877 legacy-mode cases, unit tests, and differential fuzzing. Deliberate changes remove implicit waveform parameters, restrict file and network access, and prevent annotation loss. A legacy mode retains the original behavior.

Main results: All seven implementations passed every conformance and legacy-mode case on the tested Linux platform, with matching outputs. The unit tests contain 9353 assertions. C++, Rust, and Julia read records 1.5–6.9 times faster than the original C library, while the Python implementation wrote records 9.2 times faster than the existing wfdb-python library in the benchmark.

Significance: WFDB-x provides a tested, open-source basis for reading and writing physiological recordings consistently across seven languages, supporting reproducible research and software development without requiring a shared programming environment. We also share details of the AI-assisted development process and token utilization, which may be useful for other applications.

keywords

WFDB, PhysioNet, Python, C++, Rust, MATLAB, Octave, Julia, R, Kotlin, open-source software, unit testing

1 Introduction

Advances in physiological signal processing depend on the availability of well-annotated, publicly accessible data. A cardiac beat detector, an arrhythmia classifier, or a sleep-staging model is only as credible as the recordings and reference annotations used to develop and evaluate it. Reproducible research and reliable comparisons between methods also require standardized data formats and software that consistently read, process, and write physiological signals and annotations. Most modern data formats also insert some form of checksum to check data integrity. For more than four decades, the WFDB (WaveForm DataBase) format and its associated software package have served this purpose. Originally developed by George B. Moody and team at the Massachusetts Institute of Technology (MIT), the WFDB Software Package provides tools for storing, accessing, and processing physiological recordings and their annotations (Moody et al., 2022). The earliest functions of its C library date from 1983, and its latest release, version 10.7.0, was published in 2022.

The WFDB format originated with the MIT-BIH Arrhythmia Database, recorded between 1975 and 1979 and distributed beginning in 1980. The database contains 48 half-hour excerpts of two-channel ambulatory electrocardiograms (ECGs), with approximately 110,000 beat annotations, and became one of the first widely available benchmarks for arrhythmia detection algorithms (Moody and Mark, 2001). PhysioNet, established in 1999, made this and many subsequent databases freely available, together with the WFDB software needed to access them (Goldberger et al., 2000; Moody et al., 2001). As of 2026, PhysioNet hosts 457 databases and has registered users from more than 180 countries (MIT News, 2026; Pollard et al., 2026). The data resources include the MIT-BIH databases, waveform recordings associated with the MIMIC critical-care databases (Johnson et al., 2016; Johnson et al., 2023), and the 21,837 twelve-lead ECGs of PTB-XL (Wagner et al., 2020). These datasets are distributed as WFDB records, consisting of a text header (.hea) describing the signals, one or more binary signal files (.dat), and annotation files identifying beats, rhythms, and other events.

The WFDB format also supports the George B. Moody PhysioNet Challenges, held annually since 2000 and attracting hundreds of participating teams worldwide (George B. Moody PhysioNet Challenges, 2026; Clifford, 2026). Many of these Challenges distribute their data in WFDB format, and their datasets, reference annotations, and submitted algorithms have become widely used benchmarks. The separation of data, metadata, and annotations has been one of the key features of WFDB, providing flexibility in linking different modalities, updating records efficiently, and deidentifying data in data challenges. Consequently, a substantial body of physiological signal processing research relies on software implementations of WFDB to access, exchange, and analyze data.

Despite the widespread use of WFDB, consistent handling of its records across programming languages is not guaranteed. The original software package is written in C, while researchers increasingly work in Python, MATLAB, R, Julia, and other environments. Existing alternatives either reimplement the format independently or rely on wrappers around the original C programs. Differences in their handling of signal formats, numerical conversions, annotations, and errors can produce inconsistent results. Moreover, some historical design choices of the C package, including implicit assumptions about sampling frequency, signal gain, resolution, and physical units, can silently affect the interpretation of recordings. These differences matter because the results of an analysis depend not only on the algorithm but also on the samples, scaling factors, timing, and annotations returned by the software. Errors or inconsistencies introduced when reading a record can propagate through an entire processing pipeline without being apparent in the final results. As a result, many of the public datasets in WFDB format include inconsistent checksums, irrelevant scaling factors and inaccurate sampling frequencies in their headers.

To address these issues, we developed WFDB-x, a cross-language AI-assisted reimplementation of the WFDB Software Package, version 10.7.0, implemented natively (not as caller wrappers) in seven programming languages: Python, C++, Rust, Julia, R, MATLAB/Octave, and Kotlin (Sameni, 2026b). Unlike independent implementations of the format, WFDB-x uses the original C source code as its reference and reproduces its behavior through a common conformance-testing framework. All seven implementations provide the most commonly used features of the WFDB library, including the 33 command-line tools for reading, writing and converting signals and annotations, and a high-level programming interface, without depending on the C library or on another programming language. The outputs of every implementation are verified against those of the reference C implementation, including byte-for-byte comparisons of the files it writes, with explicitly documented exceptions. WFDB-x also corrects a small set of legacy behaviors that can cause silent errors, unsafe file access or loss of annotations, and keeps the original behavior available through a legacy compatibility mode. The analysis, plotting and visualization programs of the C package, such as its beat detectors and evaluation tools, are outside the scope of WFDB-x. A broader collection of these tools are available in our open-source electrophysiological toolbox (OSET) (Sameni, 2006). The result is a consistent implementation of WFDB in seven languages, so that physiological signal processing can be reproduced without requiring researchers to use the same programming environment or include extra packages in deployed software. Each implementation has also been optimized for speed without changing its results: the C++, Rust and Julia implementations read records 1.5 to 6.9 times faster than the original C library, and the Python implementation writes records 9 times faster than wfdb-python (Section 8).

Section 2 reviews existing WFDB implementations and the limitations that motivated this work. Section 3 presents the design objectives, and Section 4 describes the software architecture. Section 5 explains the deliberate departures from the original C package. Sections 6 and 7 describe the development process and verification framework, respectively. Section 8 evaluates performance, and Section 10 discusses the methodology and limitations. The appendices provide examples of reading and writing signals and annotations in each language and using the command-line tools.

2 Background and motivation

2.1 The WFDB Software Package

The WFDB Software Package (Moody et al., 2022) includes a C library and more than 70 applications. The library reads and writes headers, signal files in about a dozen storage formats (from 8-bit first differences to the bit-packed 12-bit format 212 of the MIT-BIH recordings and, since 2020, FLAC-compressed formats), multi-segment and multi-frequency records, annotation files in the MIT and AHA formats, and EDF files (Kemp et al., 1992; Kemp and Olivan, 2003). It has tools that read and write samples and annotations (rdsamp, wrsamp, rdann, wrann), resample and convert records (xform, snip), and convert between WFDB and other formats (edf2mit, mit2edf, wav2mit, wfdb2mat and others). The C package serves as the reference implementation. Its behavior is described in the WFDB Programmer’s Guide and the WFDB Applications Guide (Moody et al., 2022).

Although the C library is portable, using it from another programming language requires platform-specific builds and language bindings. Much of today’s physiological signal processing and machine learning is performed in Python, MATLAB, Julia, and R (particularly in biostatistics communities), while mobile applications have additional deployment requirements in languages such as Kotlin and Java. Rust has also gained popularity for systems programming and performance-critical applications due to its memory safety and efficiency.

2.2 wfdb-python and the WFDB Toolbox for MATLAB and Octave

Two alternatives to the C library are widely used. wfdb-python (Xie et al., 2023), developed at the MIT Laboratory for Computational Physiology, is a native Python library. Rather than translating the C code, it implements the format independently and provides its own interface (rdrecord, rdsamp, rdann, wrsamp). The WFDB Toolbox for MATLAB and Octave (Silva and Moody, 2014), created in 2012, provides MATLAB and Octave access to the WFDB applications through MATLAB and Java wrappers that call compiled C libraries, rather than implementing the WFDB formats natively. Its latest published version, 0.10.0, was last updated in 2017 and published on PhysioNet in 2021 (Silva et al., 2021). The toolbox is no longer actively maintained (WFDB Working Group, 2026).

These independent implementations improve accessibility but differ from the C library in certain behaviors. One important example concerns checksums. A WFDB header can contain a 16-bit checksum of the samples of each signal. The C library computes it as the sum of the integer samples, allowed to overflow, and writes it as a signed 16-bit value; when the samples read do not match this checksum, it reports “checksum error in signal”. The existing implementations do not fully reproduce this 16-bit overflow design: each reduces the sum to 16 bits in its own way, so that the same samples can receive different checksums depending on the software that wrote the header. Moreover, in our test, wfdb-python 4.3.1 read a record whose samples had been modified after its header was written without issuing a warning, and wfdb-python’s issue tracker reports a conversion function that computes checksums from physical values rather than from the stored samples (wfdb-python contributors, 2026). A reader that does not verify the checksum cannot alert the user to a mismatch. As a result, the software used to read or write a record may affect subsequent analyses without any visible indication. Many of the publicly available WFDB datasets created by wfdb-python are affected by this issue.

These differences make it difficult to determine whether reading or writing the same record in different programming environments produces the same samples, annotations, and files as the original C tools.

2.3 Legacy design choices and their consequences

Several defaults and file-handling conventions in the C package reflect the databases and computing environments of the 1980s. In modern workflows, they can lead to silent errors that are difficult to detect.

2.3.1 Built-in signal parameters:

When a record does not give a sampling frequency, the C library assumes 250 Hz (WFDB_DEFFREQ), the frequency of the AHA database. A missing gain becomes 200 analog-to-digital units (adu) per millivolt, a missing ADC resolution 12 bits, and missing units millivolts. The WAV and AHA converters have their own built-in frequencies and gains. These defaults reflect the characteristics of early databases. Modern recordings are sampled at anything from a few hertz to tens of kilohertz, with 16- or 24-bit converters, and are often not ECGs. When a defaulted parameter differs from the actual value, the resulting time intervals, resampled signals, or physical amplitudes are incorrect, with no indication that a default was used.

2.3.2 The WFDB path:

The C library finds a file by searching a list of locations, the WFDB path, whose default ends with PhysioNet’s server. For example, rdsamp -r 100 reads record 100 from whichever location has it first and downloads it if no local copy exists. Although convenient for interacting with PhysioNet datasets, this search procedure can select an outdated local copy, initiate an unexpected network request, or access different records when the same script is run on different machines. The library also asks the server for an optional .info file of every record it opens; for an absolute record name, the request contains the full local path. A crafted header can name signal files elsewhere on the file system. Finally, the network entry of the default path, http://physionet.org/physiobank/database, dates from PhysioNet’s former PhysioBank layout; PhysioNet now serves each database from a versioned location, such as https://physionet.org/files/mitdb/1.0.0/ for the MIT-BIH Arrhythmia Database, so that the default path no longer names the files of a specific database version.

2.3.3 Annotation sorting:

The C library delegates the sorting of out-of-order annotation files to a separate program, sortann, which it runs through the system shell when the file is closed. A library function therefore depends on the environment in which it runs: on whether, and which, sortann is installed, and on the shell’s interpretation of the record names it is given. Moreover, sortann can silently discard annotations. When an annotation at the very start of a record (time 0, annotation number 0, channel 0) arrives after later annotations, it is lost together with the annotations placed behind it; for example, annotations written at times 5, 0 and 3 produce a file that contains only the first. Since annotations are the reference labels against which detectors and classifiers are evaluated, such silent losses directly affect the validity of downstream results.

2.3.4 Malformed input and write errors:

Some malformed headers and EDF files cause the C programs to crash, attempt to allocate gigabytes, or give results that depend on the machine. Tools that fail to write their output, for example on a full disk, report the error and still exit with status 0, so that a script cannot detect the failure.

Many of these choices served the original applications of WFDB and helped sustain its use for decades. The relatively minor bugs are also a testament to the robustness of software developed and maintained over four decades by George B. Moody and team. Nevertheless, a new implementation should address their consequences in current workflows while retaining backward compatibility with the original software.

3 Design objectives

We set the following design requirements before implementing WFDB-x:

  1. 1.

    Behavioral equivalence to the original C code: Each implementation must read and write the same files as the C library. Command-line tools must reproduce the outputs, messages, exit statuses, and generated files of their C counterparts, except for documented deviations. The C source code, rather than its documentation or another implementation, serves as the reference.

  2. 2.

    Consistency across languages: The implementations must produce identical results for the same inputs, regardless of programming language.

  3. 3.

    Completeness: Each implementation must provide the full WFDB library and all signal, annotation, and conversion tools. Interactive viewers (WAVE), plotting tools, and the analysis programs in the package’s psd directory, that are readily covered by existing tools such as OSET (Sameni, 2006), and the PhysioNet Cardiovascular Toolbox (Vest et al., 2018), are outside the scope of this work.

  4. 4.

    Native implementation with minimal dependencies: Each implementation must be written in its own language, without calling the C library or another language. Dependencies are limited to the language’s standard library, except for NumPy (Harris et al., 2020) in Python. However, because performance varies across languages, we also support cross-language function calls and provide guidelines for developing language wrappers.

  5. 5.

    Efficiency: Codebase optimization and performance improvements must not change the results.

  6. 6.

    Documentation and testing: Each implementation must include tests and installation instructions. The Python implementation must also be installable from the Python Package Index (PyPI). We also plan to distribute the R implementation through the Comprehensive R Archive Network (CRAN) (R Core Team, 2026a; Hornik, 2012) and the Julia implementation through the Julia General registry (The Julia Language Contributors, 2026; Bezanson et al., 2017).

  7. 7.

    No default or implicit waveform parameters or physical units: Where the C implementation assumes default values for unspecified waveform parameters or physical units (Section 2.3), WFDB-x must remove these assumptions, document the changes and their rationale, and provide a legacy mode to reproduce the original behavior when explicitly requested by the user.

Strict compatibility also requires reproducing certain behaviors of the C package that may be unintended, such as platform-dependent printf formatting and the reuse of previously read values when input is incomplete. These behaviors are documented in the repository, separately from the deliberate changes made in WFDB-x.

4 Software architecture

Refer to caption
Figure 1: The structure of one WFDB-x implementation. The high-level API and the 33 command-line tools are built on a native reimplementation of the WFDB C library, written in the language of the implementation with one module per C source file, which keeps the C library’s function names and global state. Beneath it, a layer reproduces the C semantics on which the output depends. All seven implementations have this structure.

4.1 Programming interfaces

Each language implementation has three interfaces (Figure 1), all written natively in the language of the implementation; none of them calls the original C library or other languages.

  1. 1.

    A high-level API: read_record, read_header, read_annotations, write_record, write_annotations and check_record (readRecord and so on in Kotlin). A single function call reads a whole record into an array (a NumPy array, a Julia matrix, an R matrix, etc.) or writes one, with named options and errors reported as exceptions or error values. The function check_record reports problems in a record, such as samples out of range, checksums that do not match and inconsistent lengths, similar to the wfdbcheck toolbox (Moody, 2018). This layer has no counterpart in the original C library.

  2. 2.

    The WFDB library functions: a reimplementation, in each language, of the functions of the C library, under their C names and with their C behavior (isigopen, getvec, getann, putann, strtim, …). For example, getvec returns one frame of samples per call in Python, C++, Rust, Julia, R, MATLAB/Octave and Kotlin, exactly as it does in C. Arguments follow the conventions of each language: in R and MATLAB/Octave, for instance, values that the C function returns through pointer arguments are returned as results. This interface serves to port programs written for the C library and to process a record as a stream, one frame or one annotation at a time.

  3. 3.

    The 33 command-line tools: 18 signal and annotation tools (rdsamp, wrsamp, rdann, wrann, sortann, xform, snip and others) and 15 format converters (edf2mit, mit2edf, wav2mit, mit2wav, wfdb2mat, parsescp and others), with the options, output, messages and exit status of the C tools. Appendix B lists them.

The high-level API and the command-line tools are both built on the library functions of the second interface. The high-level API therefore returns the same samples and annotations as these functions and the original C library. For a more robust programming experience and to mitigate the risks and shortcomings of the original implementation, new applications are encouraged to use the high-level API.

4.2 A file by file translation of the C library

The library of each implementation is a translation of the WFDB C library, organized in a similar way. Each source file of the C library corresponds to one module in each language: lib/signal.c, for example, corresponds to _signal.py in Python, signal.cpp in C++, signal.rs in Rust, signal.jl in Julia, signal.R in R and Signal.kt in Kotlin. MATLAB/Octave, which requires one file per public function, has instead one file per C function (isigopen.m, getvec.m, …). Each translated function has the name of its C counterpart and serves the same purpose. The library also keeps the same state between calls as the C library, such as the open signal and annotation files and the current sampling frequency. Each C application, such as app/rdsamp.c, is translated into a command-line tool of the same name, which calls these functions in the same order as the C program calls the C library.

This one-to-one correspondence makes each function and each tool directly comparable with its C source. As a result, in future development and validation, when an output differs from that of the C package, the difference can be traced to a specific function/file. The header comment of every source file names the C file it translates, its original authors and copyright, and states how, why and where in the code it differs from the C implementation.

4.3 Reproducing C semantics

Matching the C programs byte for byte requires more than implementing the same algorithms. It also requires the same integer arithmetic, parsing of arguments (header files, command-line options, and text input/output), and text formatting as C on the reference platform (x86-64 Linux with glibc, in our tests). Each implementation except C++ therefore contains a small internal compatibility layer that reproduces these C behaviors: 32-bit integer wrap-around, which determines checksums and the samples read from format 8, a formerly popular format that stores each sample as an 8-bit difference from the previous one (allowing more efficient encoding of waveforms with a large dynamic range); truncating integer division; signed char; the parsing functions strtol, strtod, sscanf, and strtok, including the values that sscanf leaves unchanged when its input ends early, on which several tools depend; fgets with its fixed buffer sizes; glibc’s correctly rounded printf formatting for %g, %f, and %e; and glibc’s rand, which generates the dither used by wrsamp and xform. The C++ implementation calls the C standard library directly for parsing and formatting and reproduces only glibc’s rand and strtok, whose behavior differs between C libraries, so that its results do not depend on the platform.

Finally, all implementations treat text as a sequence of bytes, as C does: files and standard input and output are read and written in binary mode, without decoding into Unicode and without converting line endings, so that every byte, including non-ASCII characters in signal descriptions and annotation text and the \r\n line endings of header files, is preserved exactly.

4.4 FLAC without libFLAC

Since version 10.7.0 (2022), the WFDB C package can store signals compressed with FLAC, a lossless compression format (signal formats 508, 516 and 524) (van Beurden and Weaver, 2024). To do so, it depends on an external library, libFLAC, which must be installed before the package is compiled. WFDB-x does not have this dependency: each implementation includes its own FLAC decoder, translated from that of libFLAC 1.4.3, and its own FLAC encoder. FLAC defines how a file is decoded, but leaves the encoder free to choose how to compress the samples, for example the block size and the prediction method. Two encoders can therefore produce different files from the same samples, both of which decode to exactly those samples. For this reason, the tests compare the FLAC files that WFDB-x writes with those of the C package by their decoded samples.

4.5 Optimized block reading

The WFDB C library reads a record one frame at a time: each call of getvec returns one sample of each signal. Reading a long record in this way costs one function call and one small copy per frame, which is significant in every language and even more significant in interpreter languages (Python, R and MATLAB/Octave). WFDB-x’s read_record therefore reads signal files through a block reader (getvecs in C++, Rust, Julia and Kotlin; getframes in Python, R and MATLAB/Octave), which returns many frames per call. It decodes the stored samples a block of frames at a time, and then processes them signal by signal, in tiles of 1024 frames that stay in the processor’s cache (C++, Rust, Julia and Kotlin) or with whole-array operations (Python, R and MATLAB/Octave).

Multi-frequency records (such as data collected from ICU bedside monitors with different sampling frequencies per modality) need one more step. In such a record, some signals have several samples in each frame (for example, an ECG sampled at 500 Hz in a record whose frames are at 125 Hz has 4 samples per frame). By default, getvec returns a single value per signal and frame: for a signal with several samples in the frame, the mean of these samples, rounded to the nearest integer (halves rounded up), or the invalid-sample value if any of them is invalid. Every signal is therefore returned at the frame rate. The block reader computes the same averages for all the frames of a block; signals with one sample per frame are copied unchanged. The block reader returns exactly what the same number of getvec calls would return, including the checksum verification, the handling of the end of the record and the rest of the library’s state. When physical units are requested, read_record converts the samples after reading them, without intermediate copies of the data.

In each language, randomized equivalence tests check every fast path against the frame-by-frame code it replaces, and the conformance suite unit-test checks every tool against the C programs.

4.6 Choice of languages

The seven languages were chosen to cover the major programming languages most widely used in healthcare applications (Seyedhasani et al., 2025), including those used for physiological signal analysis, and to include both compiled and interactive languages:

  • •

    Python is widely used in data science and machine learning. In WFDB-x, the Python implementation was written first and serves as the reference for the cross-language comparisons; the other implementations follow its structure. WFDB-x’s Python implementation represents samples as NumPy arrays (Harris et al., 2020), its only dependency, and is distributed on PyPI as wfdb-x (Sameni, 2026a).

  • •

    C++ (C++17) (ISO/IEC, 2017) and Rust (Matsakis and Klock, 2014) are compiled languages, used for systems software and for applications where speed and memory use matter. Like the other implementations, WFDB-x provides the complete library, the high-level API and the command-line tools, and has no dependency beyond the language’s standard library. Compiled to machine code, they are among the fastest of the seven implementations for reading and writing and use the least memory (Section 8), and their command-line tools start almost as fast as the WFDB C tools (about 2 ms, against 1.3 ms). Because the C++ implementation keeps the function names of the C library, programs written for the C library can be ported to it with few changes. Rust guarantees memory safety at compile time, without a garbage collector (Jung et al., 2017), which prevents classes of errors that C and C++ code can contain, such as buffer overflows and accesses to freed memory, while keeping a performance comparable to that of C and C++.

  • •

    Julia (Bezanson et al., 2017) is a language for scientific and numerical computing, designed to combine the interactive use of Python, R or MATLAB with the speed of compiled code. It compiles each function at its first call, so it suits numerical work in long-running sessions, where the compiled code is reused.

  • •

    R (R Core Team, 2026b) is widely used for statistics and biostatistics, including clinical and epidemiological research. WFDB-x implements it in base R, without additional packages, and returns signals as R matrices, ready for R’s statistical functions.

  • •

    MATLAB/Octave: MATLAB is widely used for signal processing in engineering research and teaching, and GNU Octave is a free language largely compatible with it. WFDB-x implements the subset of the language common to the two, without relying on any MATLAB toolboxes. It replaces the WFDB Toolbox for MATLAB and Octave (Silva and Moody, 2014), which is no longer maintained, with a native implementation.

  • •

    Kotlin Multiplatform: Kotlin is the language Google recommends for Android development (Google, 2026), and Kotlin Multiplatform compiles the same code to the Java Virtual Machine (JVM), including Android, and to native code for iOS. Many wearable and mobile health devices export their recordings either as text files, such as comma-separated values (CSV), which are large and slow to read, or in proprietary binary formats that other vendors’ software cannot read. WFDB-x’s Kotlin implementation addresses this need; it enables mobile and embedded applications, including those of wearable and bedside devices, to read and write recordings directly in the standard WFDB format, without a native C library to build for each platform.

5 Design decisions and deliberate departures from the original WFDB C package

WFDB-x follows the original C package except for the deliberate changes summarized in Table 1. These changes address the problems described in Section 2.3 and are implemented consistently in all seven languages. The author and collaborators selected them after examining the C behavior, its original purpose, and possible alternatives.

The repository includes the unmodified WFDB Software Package 10.7.0 sources in the third_party directory, under their original licenses: the GNU Library General Public License, version 2 or later, for the library, and the GNU General Public License, version 2 or later, for the applications. A patch in tests/reference applies the deliberate changes to a copy of these sources. The patched C programs provide the expected outputs for the cross-language conformance suite; they are not intended as a maintained or recommended WFDB distribution. The only exceptions are 20 test cases in which the C programs crash or produce machine-dependent results. For these cases, WFDB-x defines a consistent result (Section 7). Our deliberate design choices and divergences are detailed below.

Table 1: Deliberate departures of WFDB-x from the WFDB Software Package 10.7.0. Legacy mode restores the original behavior in each case.

5.1 Signal parameters

The C package assigns default sampling frequencies, gains, ADC resolutions and physical units when these are missing, and the WAV and AHA converters use their own fixed values. Such assumptions can silently affect subsequent analyses or records written from the data. WFDB-x instead requires these parameters and fails without them. For example, the header of record 100s from the MIT-BIH Arrhythmia Database (Moody and Mark, 2005) does not specify signal units. The C command rdsamp -p -v labels its physical values (mV), which is correct for this record but not a safe general assumption. WFDB-x displays (nd) (not defined), while legacy mode displays (mV). To use the C defaults when writing a record, the user specifies them explicitly (or explicitly requested --legacy mode behavior):

wrsamp -i data.txt -o rec -F 250 -G 200 -R 12 -U mV

5.2 File locations and network access

The C library searches the WFDB path and reads the first matching file, potentially from PhysioNet. It can also request optional .info files from the server, exposing local record paths. WFDB-x instead uses explicit file locations: absolute paths, paths under the user’s home directory (~), URLs, or paths resolved against user-selected input and output directories. Relative signal-file names remain relative to their headers. The directories may point to local or network-accessible locations. Network access is supported in all seven languages but is disabled by default. For example, reading the first 10 seconds of MIT-BIH record 100 from PhysioNet requires:

export WFDBX_INPUT_DIR=https://physionet.org/files/mitdb/1.0.0/

export WFDBX_NETWORK=1

rdsamp -r 100 -t 10

5.3 Checksums, annotation sorting and write protection

WFDB-x reports a checksum mismatch as a configurable warning rather than an error, allowing records with inconsistent checksums to be read. This is useful for records generated by software that computes checksums differently from the C package, including some versions of wfdb-python or WFDB for MATLAB and Octave.

Annotation files are sorted within the library instead of invoking an external sortann process, and no annotations are discarded. An output signal file is also prevented from overwriting an input signal file (from the same run), regardless of how its path is specified. Write failures are reported with a nonzero exit status so that scripts can detect them.

5.4 Legacy mode

The original behavior remains available through --legacy, specified as the first argument of a command-line tool, or through the legacy option of the library and high-level functions. This preserves the original function and tool names without requiring separate legacy interfaces. Legacy mode reproduces the unmodified C package, including its default signal parameters, WFDB path handling and sortann behavior, and is tested with a separate conformance suite (Section 7). It is intended for reproducing results obtained with the C tools with minimal changes to existing code. It is not recommended for new development because it retains the limitations and potentially unsafe behaviors that motivated WFDB-x.

5.5 Additions

WFDB-x also provides a high-level API, the check_record function for checking WFDB compatibility, configurable warnings for checksum mismatches with results available through a record flag, and separately selectable input and output directories. The high-level API is recommended for new applications.

6 AI-assisted codebase development

The initial WFDB-x codebase was developed interactively with Claude Code (model Claude Opus 5.5, Anthropic, in medium-effort mode), an AI coding assistant, under the author’s direction. The author defined the requirements (Section 3), architecture, order of work, and testing method; made all design decisions, including the departures from the C package (Section 5); reviewed the work at each stage; and independently validated the software on local and network machines (Linux and MacOS). The author also provided sample code from OSET (Sameni, 2006) and example codebases, which had identified design limitations and existing bugs in the existing MATLAB, wfdb-python, and C versions. The assistant wrote the code, tests, and documentation based exclusively on the WFDB C version 10.7.0, the public definitions of the WFDB file formats, and the additional codebases provided by the author and the author’s instructions. After development, the code was reviewed by a second AI system, ChatGPT Work (model GPT 6.1 Sol, OpenAI, in medium-effort mode) for corner cases, and by human experts experienced with the WFDB file format and software package. Improvements were made iteratively to address implementation and performance issues. WFDB-x is maintained on Github.com, enabling further improvements and bug fixes by the user community.

6.1 Instructions to the AI assistant

Throughout the development phase, the author’s messages to the assistant amounted to 250 prompts (messages) and 57,929 words, with a median length of 23 words; about 7,300 of these words were the author’s own instructions, and the remaining 50,600 were pasted material, such as external reviews and terminal outputs.

To make the development process of WFDB-x reproducible, we summarize the main instructions given to the AI coding assistants. These instructions were designed to ensure that the implementations remained faithful to the original C sources. A discussion regarding the reliability of this methodology is presented in Section 10. The highlights of the instructions provided throughout the development were as follows:

  • •

    Translate from the C code and WFDB format manual only; do not copy or reproduce other implementations: The assistant was asked to translate the C sources of the WFDB Software Package 10.7.0 and the publicly available WFDB header and data format, and not to copy from the web or reproduce from memory the behavior of existing Python or MATLAB implementations of WFDB, since these differ from the C package (Section 2).

  • •

    The C version defines the expected results: Expected test results were produced by running the C programs and the C library. The tests and their expected results were not to be changed to make an implementation pass; a suspected error in an expected result had to be reported, with evidence, rather than corrected automatically.

  • •

    Fix the cause, not the symptom and verify each design choice with the developer: A correction had to be the smallest algorithmic or programming change that fixes the cause of an error, verified and applied in every language that had the error, and checked against the full test suites of these languages.

  • •

    Paraphrase author requests for confirmation and explain before changing: The author requested the assistant to summarize and paraphrase each design requirement for author confirmation. Also, before any substantial change (a new feature, a departure from the C behavior or a change of design), the assistant had to explain the problem and its plan, and the author decided whether and how to proceed.

  • •

    Code and documentation standards: No dependency beyond the standard library of each language (and NumPy in Python); no unexplained numerical constants; in every source file, a header naming the C file translated, its original authors, license and the changes from the C code; documentation in plain human-readable language, consistent across the seven languages.

  • •

    No network access in tests: Tests could contact no host other than the local machine, so that their results do not depend on the network or model memory.

6.2 Order of work

The implementations were developed one language at a time. Each had to pass the full conformance suite before the next was started.

  1. 1.

    Test infrastructure and Python: A reference build of the C package (with FLAC support), the language-independent conformance harness and the test records were set up first. Python was then translated tool by tool, starting with rdsamp; the conformance cases of each tool were written and passed before the next tool was started. The Python implementation became the reference; its structure and conventions were used as templates for the other languages.

  2. 2.

    C++, MATLAB/Octave, Rust, Julia, and R were implemented in this order. Each was translated from the C sources, following the structure of the Python implementation, and checked against the same conformance cases. Unit tests of every library function, with expected values printed by the C library, were then added in each language.

  3. 3.

    Kotlin Multiplatform was added later for mobile and JVM applications, in four steps (foundation, signals and FLAC, tools, high-level API), and evaluated by the same tests.

  4. 4.

    Review of all languages: Every function was checked against its C original. Apparent errors in the C code were checked against the WFDB documentation, to distinguish errors from intended behavior. The code was checked for quality (e.g., for unexplained or hard-coded constants).

  5. 5.

    Deliberate departures from the C package: The changes of Section 5 (no built-in signal parameters, files only where they are named, network access off by default, sorting without loss, protection of input files, write errors in the exit status) and legacy mode were made one at a time. Each was first implemented in the Python implementation and in the patched C reference that produces the expected results, and then in the other languages.

  6. 6.

    Code optimization: Once all implementations passed the tests, the assistant was asked to make each one as fast as its language allows, without changing any result. The changes followed the best coding practices of each language: reading signal files through a block reader rather than one frame per call; processing samples in small blocks that stay in the processor’s cache (C++, Rust, Julia and Kotlin) or with whole-array operations instead of loops over indices (Python, R and MATLAB/Octave); allocating each result array once, from the length given in the header, rather than growing it; converting to physical units without temporary arrays; writing whole blocks of frames at once rather than one frame per call (Julia, R and MATLAB/Octave); formatting the output of rdsamp a block at a time; and, for the Kotlin tools, a class-data-sharing archive that halves the start-up time of the JVM. Each optimized version was checked against the code it replaces by randomized equivalence tests, and all implementations were benchmarked against each other, against wfdb-python and against the original C library (Section 8).

  7. 7.

    External reviews and corrections: Independent reviewers, a second AI assistant (GPT-6.1). Each reported problem was reproduced, classified, and corrected in every language that had it, with a new conformance case or unit test. In the last rounds, a differential fuzzer (Section 7.4) compared the implementations with the C programs on random records and tool options.

  8. 8.

    Documentation and release: The documentation of each language was rewritten in a common structure, with examples and example notebooks. Every source file was attributed to the authors of the C file it translates; WFDB-x itself is distributed under the GNU General Public License, version 3 or later. the Python package was published on PyPI.

From the departures of item 4 onward, each round of changes was made first in the Python implementation, and then carried to the other languages in parallel: a separate instance of the assistant worked on each language from a common written specification, could modify only the directory of its own language, and had to pass the conformance suite, the legacy suite, the unit tests of its language and, in the later rounds, the differential fuzzer (Section 7) before its work was accepted. In the last round of corrections, for example, each language had to show no difference from the C programs in at least 2,000 random cases (and 1,000 in legacy mode) for C++, Rust and Python, and 600 (and 300) for the other languages.

6.3 Review and validation

In addition to automated verification, WFDB-x was reviewed by independent human code reviewers and tested in several rounds by early users with backgrounds in biomedical signal processing and computer science. These reviewers had prior experience with the WFDB C package, wfdb-python, or the WFDB Toolbox for MATLAB and Octave, and tested public releases on their own records and applications. They included researchers working with PhysioNet data, organizers of and participants in PhysioNet Challenges, and developers adapting ICU bedside-monitor converters and recording viewers to the Rust, C++, and Python implementations. Their reports identified minor defects, slow operations on multi-segment records, unclear documentation, and design issues. Several design decisions described in this paper and the optimized reading paths of Section 4 resulted from this feedback.

The author reviewed every report before making changes. Each issue was reproduced and classified as a defect in WFDB-x, behavior inherited from the C package, or intended behavior that was not sufficiently documented. Confirmed defects were corrected in all affected language implementations, with conformance cases or unit tests added to prevent recurrence. The author also reviewed proposed design changes and decided whether to retain or revise the design or preserve the original C behavior as a legacy option. All reported issues were addressed.

The author independently validated the software by installing the Python package from both the PyPI test index and PyPI and running its tests on separate macOS and Linux systems, running the documented examples, comparing results with those from users’ applications, and reviewing the documentation for each implementation.

6.4 Codebase size

Table 2 provides the size of each implementation in the current WFDB-x version 1.1.0. For comparison, the part of the C package that WFDB-x translates (the library and the 33 programs) has about 22,300 lines. The implementations are larger, mainly because each also contains its own FLAC decoder and encoder (which the C package takes from libFLAC), the layer reproducing C behavior (Section 4), the high-level API, check_record, and documentation comments. In every language, about 15% of the codebase belongs to the tests.

Table 2: Lines of code of each implementation (comments and blank lines included), counted in the source files of the WFDB-x repository, version 1.1.0 (October 2026).

7 Verification

Refer to caption
Figure 2: How WFDB-x is verified. The expected results of the conformance suite are produced by the C programs: a build with the deliberate departures applied, for the normal suite, and the unmodified package, for the legacy suite. Each implementation must reproduce them byte for byte.

7.1 The conformance suite

The main test of WFDB-x is a language-independent conformance suite containing 1098 test cases (Figure 2). Each case runs a command-line tool with fixed arguments, input data, and environment settings, using a fresh copy of the test data. The test program then compares the results against the expected outputs, byte for byte, including standard output, error messages, exit status, and every file created or modified by the tool. All cases use the same locale and time-zone settings (LC_ALL=C, TZ=UTC) to ensure reproducibility. Write errors are tested by directing output to /dev/full, a special Linux device file that always acts as if a storage device is completely full and rejects every write, simulating conditions such as a full disk. These tests run on Linux and are skipped on systems where /dev/full is unavailable.

The expected results were produced by running the C programs themselves: the unmodified sources of version 10.7.0, built with FLAC support and with the patch that applies the changes of Section 5. The only exceptions are 20 cases in which the C programs crash or give results that depend on the machine. For these, WFDB-x defines the correct result, which was recorded from one implementation and is used across all seven languages.

A second suite tests legacy mode. It runs 877 cases with --legacy flag as the first argument of each tool, and compares the results with those of the unmodified C package, so that legacy mode must reproduce the original package exactly.

All seven implementations pass all 1098 normal cases and all 877 legacy cases on the reference platform: x86-64 Linux with glibc, Python 3.13, GCC 13, Rust 1.97, Julia 1.13, R 4.3, GNU Octave 8.4 and OpenJDK 21. Because all seven are checked against the same expected results, the suites also check that the seven implementations agree with each other.

Any bugs reported or failing test cases identified in the future will be addressed with a similar methodology across all languages, and the corresponding test cases will be added to the test suite.

7.2 Test records

The test records were written by the C library itself, using a small C program, so that their contents are exactly what the C package produces. Together, they cover every signal storage format, records with signals at different sampling rates, records made of several segments (including empty and missing segments), signals that are shifted in time relative to each other (skew), signal files with a header or a fixed block size, EDF and EDF+ files, and annotation files that use every feature of the annotation format. Additional input files in other formats (WAV, AHA, SCP-ECG, and headers in older formats) test the format converters.

7.3 Unit tests

The conformance suite tests the command-line tools. The library functions and the high-level API are tested separately, by the unit tests of each implementation. The expected values of the library tests were printed by the C library, not written by hand. The tests of the high-level API check that a record written and read back is unchanged, that invalid arguments are rejected before any file is created (for example, a sampling frequency that is not a positive number), and that the library is left in a clean state after an error. In total, the unit tests contain about 9,350 assertions, each comparing one result with its expected value: between about 1,100 and 1,600 in each language (Table 3). Since many assertions run inside loops over records, formats or parameter values, the number of checks performed when the tests run is much larger.

Table 3: Unit tests of each implementation: number of test files and of assertion statements in the test source code (counted in the Github repository as of WFDB-x version 1.1.0; assertions inside loops are counted once).

7.4 Differential fuzzing

In the later stages of development, a differential fuzzer11 1 Differential fuzzing is a software testing technique that feeds the same generated inputs into two or more different implementations of the same functions that should behave identically and compares their outputs. compared the implementations with the C programs on inputs that no one had written by hand. It generated random records, covering every storage format, several samples per frame, time-shifted signals, and multi-segment records with empty or unreadable segments. It then ran a randomly chosen tool with random options on each record, both with the C programs and with each implementation, and compared the results in the same way as the conformance suite. Every difference was reproduced and examined. When only some implementations differed from C, the cause was an error in WFDB-x, which was corrected. When all seven agreed with each other but differed from C, the cause was in the C code: these cases revealed reads of uninitialized or freed memory and integer overflows in the C programs, for which WFDB-x now defines and documents a result. Each difference found was added to the conformance suite as a new case. The differential fuzzer itself is not part of the repository; the cases it produced are.

7.5 Documentation of behaviors

The repository includes three documents that describe the behavior of WFDB-x and how it was tested: 1) DIVERGENCES.md lists the deliberate departures from the C package (Section 5) and the reason for each; 2) KNOWN_C_BEHAVIORS.md documents three kinds of C behavior: behaviors that WFDB-x reproduces although they are not described in the WFDB documentation or differ from it; behaviors that depend on the platform, such as the operating system or the C library; and undefined behaviors of the C code (for example, reads of uninitialized memory), for which WFDB-x defines and documents a result; 3) INVENTORY.md lists every command-line tool and library function, with its test status in each language.

8 Performance

We benchmarked the execution time and memory use of the seven implementations, the original C library and command-line tools, and wfdb-python 4.3.1 on a single machine: an x86-64 Linux virtual machine with 4 cores of an Intel Xeon at 2.1 GHz. The C library and tools were the unmodified WFDB Software Package 10.7.0, built by its own configure script with its own compiler options (-g -O), as a user would install it. The benchmarks used three synthetic records modeled on real datasets, containing 12.5 million samples in total: long, two ECG signals in format 212 at 360 Hz for one hour (1,296,000 frames), like the MIT-BIH records, with an annotation file of 4,500 beat annotations; mimic, a multi-segment record of 12 segments and 4 signals at 125 Hz, the first at 500 Hz, modeled on records from the MIMIC database; and wide, a 12-lead ECG in format 16 at 500 Hz for 10 minutes.

Each WFDB-x implementation performed each operation with one call of its high-level API (read_record, write_record, read_annotations, write_annotations). The C library has no high-level functions, so a short C program performed the same operations with the library functions that a C program uses: isigopen and getvec, one frame per call, to read; aduphys for physical units; osigfopen, putvec and newheader to write; and annopen, getann and putann for annotations. To compare the libraries themselves, long was also read frame by frame with getvec through WFDB-x’s C++ library functions, with the same code as in C. Each library time is the fastest of 7 calls after one untimed call, taking the better of two complete runs. Every program saved the result of each operation, and the benchmark program stopped if any two implementations, the C library included, disagreed. All results were identical, value for value and byte for byte, in every run. Figure 3 and Tables 4 and 5 summarize the results.

Refer to caption
Figure 3: Time of one call in each WFDB-x implementation (high-level API), in the original C library (its library functions) and in wfdb-python 4.3.1, for four operations (best of 7 calls, and the better of two complete runs; files in the operating system’s cache) in logarithmic scale. The values are those of Table 4. All returned identical samples and annotations and wrote identical files.
Table 4: Time of one call (ms) and peak memory of the process (MB). C is the original WFDB C library, called through its library functions. The samples of long take 10 MB.
C++ Rust Julia Kotlin Python R MATLAB/ C wfdb-
Octave (original) python
Read long (ADC units) 6.0 3.8 5.8 12.7 29.0 67.3 45.7 26.0 21.3
Read long (physical units) 12.9 14.8 12.1 17.1 37.2 99.5 71.9 30.1 36.4
Read mimic 21.7 14.1 18.3 37.8 82.9 217 313 49.3 117
Read wide 9.8 6.3 13.2 11.5 7.9 92.3 55.5 19.4 15.1
Write long (format 16) 17.6 20.9 6.7 17.3 25.2 118 46.9 17.7 231
Read 4,500 annotations 0.28 0.24 0.58 1.2 7.0 6.9 11.8 0.07 14.1
Write 4,500 annotations 0.14 0.17 0.34 1.1 0.86 3.8 6.3 0.14 6.9
Read long frame by frame (getvec) 23.9 21.6
First call: read long 14.4 9.4 57.3 75.8 142 102 95.8 32.7 123
Memory: read long (MB) 24 13 311 149 80 157 115 12 118
Memory: read mimic (MB) 35 17 313 168 69 221 165 17 159
Tool: rdsamp -r long 40.1 51.4 374 179 395 750 570 210
Tool: rdann -r long -a atr 3.4 3.7 302 102 58.3 240 127 2.5
Tool: wfdbdesc long 1.8 1.9 337 60.7 32.8 230 87.0 1.3
Table 5: Speed relative to the original C library: the time of the C library divided by the time of each WFDB-x implementation (from the unrounded times of Table 4). Above 1, WFDB-x is faster; below 1, the C library is faster.

8.1 Comparison with the original C library:

C++, Rust and Julia read records 1.5 to 6.9 times faster than the C library: the hour of ECG takes 3.8 to 6.0 ms, against 26.0 ms in C. Kotlin reads records 1.3 to 2.1 times faster than C. The Python implementation reads the 12-lead record 2.4 times faster than C and the other records 1.1 to 1.7 times slower, while R and MATLAB/Octave read them 1.8 to 6.3 times slower. The difference in reading speed comes from WFDB-x’s block reader (Section 4), not from the language: read frame by frame with getvec, WFDB-x’s C++ library and the C library take the same time (23.9 and 21.6 ms, within the variation between runs). Writing a record takes the same time in C, C++ and Kotlin, and Julia is 2.6 times faster. The C library reads annotation files fastest, in 0.07 ms for 4,500 annotations against 0.24 to 0.58 ms in Rust, C++ and Julia: getann returns each annotation as it is decoded, whereas read_annotations also builds the mnemonic (annotation symbol) of each annotation and the arrays of its result. C, C++ and Rust write annotation files in the same time (0.14 to 0.17 ms). A build of the C library with -O2 gave the same times, within the variation between runs (the hour of ECG in 24.5 ms).

8.2 Reading and writing across languages:

Rust, Julia and C++ are the fastest implementations. Kotlin reads and writes records 1.0 to 2.1 times slower than C++, once the JVM has compiled the code, and annotation files 4 to 8 times slower. Compared with wfdb-python, the Python implementation is 1.4 times slower on the single-segment record in ADC units and equally fast in physical units, and it is faster on every other operation: 1.4 times on the multi-segment record, 1.9 times on the 12-lead record, 2.0 times for reading annotations, 9.2 times for writing records and 8.0 times for writing annotations. R and MATLAB/Octave read the hour-long ECG in 46 to 67 ms.

8.3 Start-up and memory:

The first calls in Julia and Kotlin involve compilation and take 2 to 30 times longer than subsequent calls. This overhead has less impact in long-running applications. The C library, Rust and C++ use the least memory, 12 to 35 MB for a record whose samples take 10 MB; Julia’s 310 MB is mostly its runtime and compiler.

8.4 Command-line tools:

The C++ and Rust rdsamp print the hour of ECG 4.1 to 5.3 times faster than the C rdsamp (40.1 and 51.4 ms against 210 ms), and the Kotlin rdsamp 1.2 times faster. For small tasks, start-up time dominates: the C tools start fastest (1.3 ms for wfdbdesc), followed by the C++ and Rust tools (1.8 and 1.9 ms), while the tools of the other languages pay the start-up time of their runtime (from 32.8 ms in Python to 337 ms in Julia).

8.5 Limitations of the measurements:

All results come from one shared virtual machine, whose times vary by up to about 30% between sessions; the ratios between implementations are more reliable than the absolute times. The processes were not pinned to a CPU core, and the tables give best times, not medians with confidence intervals. The files were in the operating system’s cache. Peak memory includes about 11 MB inherited from the benchmark runner, so values near it (C and Rust) are upper bounds. The MATLAB/Octave code ran in GNU Octave only because MATLAB license was unavailable on the tested VM, and the Kotlin code on the JVM only. The benchmark programs, including the C driver, are shared in the WFDB-x repository, so that the measurements can be repeated on other machines.

9 Token and energy utilization of the AI-assisted development

The AI-assisted development of the core codebase of WFDB-x version 1.0.0 (the initial release) took 15 days, and consisted of one main Claude Opus 5.5 assistant session and 166 sub-agent sessions (excluding prior manual coding, bug detection, experimental setups, and architectural design by the author and team). The main session interacted with the author, wrote specifications for the sub-agents, assigned each sub-agent a single task (for example, translating one language or completing one round of corrections in one language), and reviewed and integrated the results. Together, the sessions made 18,655 model calls and generated 10.0 million output tokens, including code, tests, documentation, commands, and the model’s intermediate reasoning. They read 4.73 billion input tokens because each call reads the full context of its session again, averaging about 254,000 tokens per call. Of these input tokens, 97.5% (4.61 billion) were read from the prompt cache, 2.5% (117 million) were written to it (104.6 million to the five-minute cache and 12.2 million to the one-hour cache), and fewer than 63,000 were read without caching. Table 6 breaks these figures down by language according to each sub-agent’s task. The main session accounts for a quarter of the output and most of the Python implementation, which the main agent wrote before sub-agents were used for the other languages; the sub-agents listed in the Python row worked only on later changes. Kotlin, the last language added, has the largest output per sub-agent (about 100,000 tokens, compared with 30,000 to 50,000 for the other languages) because it was written in four large tasks, each covering a major part of the implementation: the foundation, signals and FLAC, tools, and the high-level API. The row “Several languages” groups tasks that were not limited to one language: extensions to the C reference and conformance suite, reference implementations of coordinated changes, cross-language corrections, documentation reviews, and benchmarks. The final codebase contains about 254,000 lines across the seven languages (Table 2), corresponding to about 40 output tokens per final line. This ratio reflects the tests, review rounds, and code rewritten during development.

At Anthropic’s list prices for Claude Opus 5.5 (Anthropic, 2026a; Anthropic, 2026b) ($4 per million uncached input tokens, $20 per million output tokens, $0.20 per million tokens read from the cache, and $5 or $8 per million tokens written to the five-minute or one-hour cache), these tokens correspond to an API-equivalent cost of about $1,740: $920 for reading cached context, $620 for writing to the cache, and $200 for output. Although input tokens outnumber output tokens by a factor of almost 500, they cost only about eight times as much as the output, because nearly all of them were cache reads, billed at one twentieth of the uncached input price.

Anthropic does not publish the energy consumed per token by its models, so the energy of the development can only be estimated. We used the per-token estimates of Couch (2026), who derived them from Epoch AI’s estimate of the energy of a typical language-model query and from the ratios between Anthropic’s prices for the different kinds of tokens: about 390 Wh per million uncached input tokens, 39 Wh per million tokens read from the cache, and 1,950 Wh per million output tokens. For tokens written to the cache, which these estimates do not list, we applied the same price ratios (1.25 times the uncached input price for the five-minute cache and twice for the one-hour cache), that is, 487.5 and 780 Wh per million tokens. With these values, the development consumed an estimated 260 kWh (Table 6): 180 kWh for reading cached context, 60 kWh for writing to the cache, and 20 kWh for generating output22 2 For comparison, according to the U.S. Energy Information Administration’s 2020–2024 Residential Energy Consumption Survey, a four-person household in the United States consumes an average of 13,072 kWh of electricity annually, equivalent to approximately 1,089 kWh per month (U.S. Energy Information Administration, 2024). Our AI-assisted coding token utilization totaled 24% of this monthly utilization.. Reading the context dominates, because each of the 18,655 calls read on average about 254,000 tokens. This estimate is uncertain by a large factor: the per-token values were not derived for Claude Opus 5.5; they assume that energy is proportional to price (Claude Opus 5.5 prices cache reads at 0.05 times the input price, not the 0.1 assumed in the estimate); and they exclude the energy of the computers that ran the builds and tests, as well as data-center overheads beyond those included in the original estimate. At the average electricity price in the United States as of 1 November 2026 (about 0.183 USD/kWh), 260 kWh corresponds to about USD 48.

Token usage for the second AI assistant (ChatGPT GPT-6.1, the code reviewer) was approximately 46.3 million tokens, comprising 45.1 million cached input tokens, 1.03 million uncached input tokens, and 0.12 million output tokens, including reasoning. Subsequent adjustments, updates, and reviews are not included in the above figures.

Meanwhile, in total, the author spent approximately USD 160 on Claude cloud and ChatGPT credits for this development and review, which was above the estimated energy cost but significantly below the token-based cost estimate, suggesting that the actual power consumption per Claude token is significantly lower than publicly reported estimates.

Table 6: Token utilization, API-equivalent cost and estimated energy of the AI-assisted development, from 15 to 29 October 2026, by session and by the language on which each sub-agent worked. Input tokens include the context read from and written to the prompt cache. Cost is computed at Anthropic’s list prices for Claude Opus 5.5; energy is estimated from third-party per-token values (Couch, 2026) (see text) and is uncertain by a large factor.

10 Discussion

10.1 The need for a cross-language WFDB implementation with identical behavior

The widespread use of WFDB in PhysioNet databases, public data challenges, published algorithms and clinical research makes consistent reading and writing of these records important. Sharing the same file format is not sufficient if different software returns different samples, annotations, timing or physical values. This problem is particularly relevant when researchers develop algorithms in one language, validate them in another or transfer them to a deployed system. WFDB-x addresses this need by providing native implementations in seven languages, all tested against the original WFDB C code. The implementations also share a high-level API and the same 33 signal, annotation and conversion tools.

Compatibility does not mean retaining every historical behavior by default. Implicit sampling frequencies, gains and units may silently misrepresent a recording; file searches may retrieve an unintended copy or access the network; and annotation sorting may discard labels. WFDB-x addresses these problems while retaining the original C behavior in an explicitly selected legacy mode (Section 5). This is important for both new development and reproducibility: a researcher can use the revised behavior in a new application and still reproduce the behavior of older C-based workflows when necessary.

10.2 Evidence for correctness and conformance

The principal evidence for the consistency of WFDB-x is not that the seven implementations were generated from similar instructions, but that their results were tested against a common, independently executable reference. The original, human-written C library provides the expected behavior for the supported operations. All seven implementations pass 1098 normal conformance cases and 877 legacy cases, with comparisons of standard output, error messages, exit status and generated files. Separate unit tests contain 9,353 assertion statements across the languages, and randomized differential fuzzing compares the implementations with the C programs on records and options beyond the hand-written test cases (Section 7). Optimized reading paths are also checked against their frame-by-frame counterparts. Human reviewers and early users have tested the public software on their own applications and recordings, and confirmed consistent behavior and improved speed.

These results are strong evidence of agreement for the tested inputs and operations, but they are not a formal proof of program equivalence. The seven codebases contain 254,252 lines in total, including tests, comments and blank lines (Table 2); not every line has undergone individual human inspection. Nor can a finite collection of tests establish identical behavior for every valid or malformed input. Some C behaviors are undefined or platform-dependent, and WFDB-x explicitly defines a result for these cases rather than claiming equivalence to every possible C build. The scope and limitations of the conformance claim are therefore important: the implementations match the designated C reference on the tested cases, subject to the documented departures and the separate treatment of FLAC encoding.

The approach nevertheless provides a practical way to assess and maintain cross-language consistency. Because the original C sources, patched reference and test harness remain available, future human developers and AI coding tools can check changes against an established reference instead of relying on earlier AI-generated translations. A defect in one implementation can be reproduced, compared with C and corrected across the others. This does not prevent errors from propagating automatically, but it provides a means to detect and stop them before changes are accepted. The reference and tests are therefore at least as important to the long-term value of WFDB-x as the initial translations.

10.3 AI-assisted development and performance

The codebase was developed with AI assistance under the author’s direction, including decisions on design, deviations from C, testing and acceptance of changes (Section 6). Large language models are stochastic, but the compilers and interpreters that build and run the codes are deterministic. Therefore, repeating the same prompts, even with the same settings, need not produce the same code. The documented instructions and development records make the process transparent, but they should not be interpreted as a recipe that will regenerate identical implementations. The more reproducible part of the methodology is the verification procedure, which can be rerun on the released source code without access to the original AI sessions.

The benchmarks also show that matching the C results need not impose a performance penalty. On the tested machine, C++, Rust and Julia read records 1.5 to 6.9 times faster than the original C library, mainly because the high-level API reads blocks instead of calling getvec for every frame. When C++ uses the same frame-by-frame interface as C, their reading times are comparable. The Python implementation performs competitively with wfdb-python and is substantially faster for writing records and annotations, although the original C library remains faster for reading annotations (Section 8). These differences depend on the operation and execution environment. They were measured on one virtual machine with cached files and best-of-run timings, not across a representative range of computers or workloads.

The measured token use during code development, estimated cost and energy consumption describe the resources used in development, not the correctness of the result; the energy estimates are particularly uncertain.

The financial and environmental costs of AI-assisted development, including electricity consumption and associated carbon emissions, remain subjects of considerable debate. Based on our estimated token usage, the electricity consumed during the development of WFDB-x was approximately 24% of the average monthly electricity consumption of a four-person household in the United States. However, this cost should also be considered against the potential long-term benefits of the software. WFDB and other physiological waveform formats are increasingly used in intensive care units, healthcare systems, and wearable monitoring devices, where large volumes of data are continuously recorded, transferred, and processed. Improvements in the efficiency of widely used data-processing and storage libraries can reduce computational demands, energy consumption, and cloud computing costs over repeated use. Even modest improvements per operation may become significant when applied to large datasets and millions of recordings. Although we have not yet quantified these downstream savings, the development of WFDB-x illustrates how AI-assisted software engineering may help improve computational tools whose cumulative resource consumption could substantially exceed the one-time cost of their development. Similar approaches may be useful for other widely deployed computational libraries and data-processing engines.

10.4 Limitations and future validation

The main limitation of WFDB-x’s current release is the breadth of validation. The full conformance suites were run on x86-64 Linux with glibc. Broader testing is needed on Windows and macOS, on different processor architectures and with different C libraries, particularly for operations with platform-dependent behavior. The MATLAB/Octave implementation has been tested in GNU Octave but still needs direct testing in MATLAB. Kotlin has been tested on the JVM, while its native iOS targets remain to be built and evaluated. Tests should also be expanded for unusual combinations of storage formats, multi-segment records, malformed files and failure conditions.

A further useful step would be systematic testing against many other WFDB datasets hosted on PhysioNet, rather than only the constructed and user-supplied records used here. Such testing could expose unsupported corner cases and identify records with inconsistent checksums, incorrect scaling metadata, or conversion errors introduced by different software implementations. These findings would need to distinguish an error in a dataset from an error in the reader or writer; check_record and the original C tools provide starting points for that work. Extending the tests to new datasets, platforms and real applications is more meaningful than increasing the number of test cases without broadening their coverage.

Finally, WFDB-x is a recent project. It covers the WFDB library and 33 signal, annotation and conversion tools, not the C package’s detectors, evaluation programs, spectral-analysis tools or WAVE viewer. Other tools, including OSET (Sameni, 2006), address parts of that broader scope. Continued use, independent review and reports from the community will be essential. Future discrepancies should be reproduced against the reference, corrected in all affected languages and added to the tests.

11 Conclusion

WFDB-x addresses a practical source of irreproducibility in physiological signal processing: different software implementations of the same WFDB format may read or write records differently. It provides native implementations in seven programming languages, with high-level APIs and command-line tools, using the original C code as a common reference. Agreement across the conformance suites, unit tests, differential fuzzing, and independent reviews supports the consistency of the implementations for the tested operations, without constituting a formal proof of equivalence. Documented changes remove several unsafe or ambiguous legacy behaviors, while an optional legacy mode preserves the original results when required. By keeping the reference code, test data, and verification procedures available, WFDB-x enables both human developers and future AI tools to check and improve the software while maintaining its connection to the established WFDB implementation developed by the late George B. Moody and his team.

Software availability

WFDB-x is freely available as open-source software. Version 1.1.0, described in this paper, is available from https://github.com/alphanumericslab/wfdb-x. The repository contains the native implementations in seven programming languages, the command-line tools, installation instructions, examples, test data, unit tests, conformance suites, benchmark scripts, and documentation. The Python package is also distributed through the Python Package Index (PyPI) and can be downloaded from https://pypi.org/project/wfdb-x/ or installed using pip install wfdb-x. The repository’s docs directory documents the deliberate departures from the C package, reproduced C behaviors, verification procedures, benchmarks, and source-code attribution. Bug reports and contributions can be submitted through the GitHub repository.

WFDB-x is distributed under the GNU General Public License (GPL), version 3 or later. The unmodified WFDB C sources included in the repository for reference testing retain their original licenses: the GNU Library General Public License (LGPL), version 2 or later, for the library, and the GPL, version 2 or later, for the applications.

AI usage disclosure

Generative AI was used in the development, testing, documentation, and review of WFDB-x. Claude Code (Claude Opus 5.5, Anthropic) was used for code development under the author’s direction, and ChatGPT Work (GPT 6.1 Sol, OpenAI) was used for additional code review. The author defined the design and requirements, directed and reviewed the development, and independently validated the results. Human experts and early users also reviewed and tested the software. The development and verification procedures are detailed in Sections 6 and 7. The author reviewed and revised all AI-assisted work and takes full responsibility for the software and findings.

Acknowledgements

WFDB-x would not exist without the WFDB Software Package, written by the late George B. Moody and maintained by Benjamin Moody, with contributions credited file by file in the WFDB-x sources, nor without PhysioNet and Ary L. Goldberger and the late Roger G. Mark. We thank the external reviewers and early users whose reports improved the software. The author acknowledges suppot from Georgia CTSA under the NIH-NCATS award UL1TR002378. The author declares no competing interests.

References

  • Anthropic Pricing. Note: https://platform.claude.com/docs/en/about-claude/pricingClaude Developer Platform documentation. Accessed 31 October 2026 Cited by: §9.
  • Anthropic (2026b) Anthropic Prompt caching. Note: https://platform.claude.com/docs/en/build-with-claude/prompt-cachingClaude Developer Platform documentation. Accessed 31 October 2026 Cited by: §9.
  • Bezanson et al. (2017) J. Bezanson, A. Edelman, S. Karpinski, and V. B. Shah Julia: A Fresh Approach to Numerical Computing. SIAM Review 59 (1), pp. 65–98. External Links: ISSN 1095-7200, Link, Document Cited by: item 6, 3rd item.
  • Clifford (2026) G. D. Clifford From PhysioNet to foundation models—a history and potential futures. Physiological Measurement 47 (8), pp. 080301. External Links: Document Cited by: §1.
  • Couch (2026) S. P. Couch Electricity use of AI coding agents. Note: https://simonpcouch.com/blog/2026-01-20-cc-impact/Blog post, 20 January 2026. Accessed 31 October 2026 Cited by: Table 6, §9.
  • George B. Moody PhysioNet Challenges (2026) George B. Moody PhysioNet Challenges The George B. Moody PhysioNet Challenges. External Links: Link Cited by: §1.
  • Goldberger et al. (2000) A. L. Goldberger, L. A. N. Amaral, L. Glass, J. M. Hausdorff, P. Ch. Ivanov, R. G. Mark, J. E. Mietus, G. B. Moody, C. Peng, and H. E. Stanley PhysioBank, PhysioToolkit, and PhysioNet: components of a new research resource for complex physiologic signals. Circulation 101 (23), pp. e215–e220. External Links: Document Cited by: §1.
  • Google (2026) Google Android’s Kotlin-first approach. Note: https://developer.android.com/kotlin/firstAccessed 30 October 2026 Cited by: 6th item.
  • Harris et al. (2020) C. R. Harris, K. J. Millman, S. J. van der Walt, R. Gommers, P. Virtanen, D. Cournapeau, E. Wieser, J. Taylor, S. Berg, N. J. Smith, R. Kern, M. Picus, S. Hoyer, M. H. van Kerkwijk, M. Brett, A. Haldane, J. F. del Río, M. Wiebe, P. Peterson, P. Gérard-Marchant, K. Sheppard, T. Reddy, W. Weckesser, H. Abbasi, C. Gohlke, and T. E. Oliphant Array programming with NumPy. Nature 585 (7825), pp. 357–362. External Links: ISSN 1476-4687, Link, Document Cited by: item 4, 1st item.
  • Hornik (2012) K. Hornik The Comprehensive R Archive Network. WIREs Computational Statistics 4 (4), pp. 394–398. External Links: ISSN 1939-0068, Link, Document Cited by: item 6.
  • ISO/IEC (2017) ISO/IEC ISO/IEC 14882:2017: programming languages — C++. Fifth edition, International Organization for Standardization, Geneva, Switzerland. Cited by: 2nd item.
  • Johnson et al. (2023) A. E. W. Johnson, L. Bulgarelli, L. Shen, A. Gayles, A. Shammout, S. Horng, T. J. Pollard, S. Hao, B. Moody, B. Gow, L. H. Lehman, L. A. Celi, and R. G. Mark MIMIC-IV, a freely accessible electronic health record dataset. Scientific Data 10, pp. 1. External Links: Document Cited by: §1.
  • Johnson et al. (2016) A. E. W. Johnson, T. J. Pollard, L. Shen, L. H. Lehman, M. Feng, M. Ghassemi, B. Moody, P. Szolovits, L. A. Celi, and R. G. Mark MIMIC-III, a freely accessible critical care database. Scientific Data 3, pp. 160035. External Links: Document Cited by: §1.
  • Jung et al. (2017) R. Jung, J. Jourdan, R. Krebbers, and D. Dreyer RustBelt: securing the foundations of the Rust programming language. Proceedings of the ACM on Programming Languages 2 (POPL), pp. 1–34. External Links: ISSN 2475-1421, Link, Document Cited by: 2nd item.
  • Kemp and Olivan (2003) B. Kemp and J. Olivan European data format ‘plus’ (EDF+), an EDF alike standard format for the exchange of physiological data. Clinical Neurophysiology 114 (9), pp. 1755–1761. External Links: ISSN 1388-2457, Link, Document Cited by: §2.1.
  • Kemp et al. (1992) B. Kemp, A. Värri, A. C. Rosa, K. D. Nielsen, and J. Gade A simple format for exchange of digitized polygraphic recordings. Electroencephalography and Clinical Neurophysiology 82 (5), pp. 391–393. External Links: ISSN 0013-4694, Link, Document Cited by: §2.1.
  • Matsakis and Klock (2014) N. D. Matsakis and F. S. Klock The Rust Language. ACM SIGAda Ada Letters 34 (3), pp. 103–104. External Links: ISSN 1094-3641, Link, Document Cited by: 2nd item.
  • MIT News (2026) MIT News How an MIT database evolved into a global standard for data sharing. Note: 29 July 2026 External Links: Link Cited by: §1.
  • Moody (2018) B. Moody Wfdbcheck. Note: https://github.com/bemoody/wfdbcheckAccessed 30 October 2026 Cited by: item 1.
  • Moody et al. (2001) G.B. Moody, R.G. Mark, and A.L. Goldberger PhysioNet: a web-based resource for the study of physiologic signals. IEEE Engineering in Medicine and Biology Magazine 20 (3), pp. 70–75. External Links: ISSN 0739-5175, Link, Document Cited by: §1.
  • Moody and Mark (2001) G. B. Moody and R. G. Mark The impact of the MIT-BIH arrhythmia database. IEEE Engineering in Medicine and Biology Magazine 20 (3), pp. 45–50. External Links: Document Cited by: §1.
  • Moody et al. (2022) G. B. Moody, T. Pollard, and B. Moody WFDB software package (version 10.7.0). PhysioNet. External Links: Document, Link Cited by: §1, §2.1.
  • Moody and Mark (2005) G. Moody and R. Mark MIT-BIH Arrhythmia Database. PhysioNet. External Links: Document, Link Cited by: §5.1.
  • Pollard et al. (2026) T. Pollard, B. E. Moody, L. Lehman, B. Gow, C. Fernandes, C. Xie, A. Johnson, R. G. Mark, and T. Heldt PhysioNet as a global platform for biomedical research. Nature Health 1, pp. 792–795. External Links: Document Cited by: §1.
  • R Core Team (2026a) R Core Team CRAN: the comprehensive R archive network. R Foundation for Statistical Computing, Vienna, Austria. Note: https://cran.r-project.org/Accessed 30 October 2026 Cited by: item 6.
  • R Core Team (2026b) R Core Team R: a language and environment for statistical computing. R Foundation for Statistical Computing, Vienna, Austria. External Links: Link Cited by: 4th item.
  • Sameni (2006) R. Sameni OSET: The Open-Source Electrophysiological Toolbox. Note: GitHub repositoryOriginally released in 2006 External Links: Link Cited by: §1, §10.4, item 3, §6.
  • Sameni (2026a) R. Sameni WFDB-x: A Multilanguage Implementation of the Waveform Database Software Package. Python Package Index (PyPI). External Links: Link Cited by: 1st item.
  • Sameni (2026b) R. Sameni WFDB-x: the WFDB library and command-line tools in Python, C++, Rust, Julia, R, MATLAB/Octave and Kotlin (version 1.1.0). Note: https://github.com/alphanumericslab/wfdb-xAdd the Zenodo DOI of the release here Cited by: §1.
  • Seyedhasani et al. (2025) S. N. Seyedhasani, A. Arzehgar, M. A. Bakhshali, M. Sohrabifar, and S. M. Tabatabaei The Critical Role of Programming Languages among Healthcare Data Scientists: A Systematic Review of Trends, Applications, and Future Directions. Journal of Social Behavior and Community Health. External Links: ISSN 2783-2104, Link, Document Cited by: §4.6.
  • Silva et al. (2021) I. Silva, B. Moody, and G. Moody Waveform Database Software Package (WFDB) for MATLAB and Octave. PhysioNet. External Links: Document, Link Cited by: §2.2.
  • Silva and Moody (2014) I. Silva and G. B. Moody An open-source toolbox for analysing and processing PhysioNet databases in MATLAB and Octave. Journal of Open Research Software 2 (1), pp. e27. External Links: Document Cited by: §2.2, 5th item.
  • The Julia Language Contributors (2026) The Julia Language Contributors General: the official Julia package registry. Note: https://github.com/JuliaRegistries/GeneralAccessed 30 October 2026 Cited by: item 6.
  • U.S. Energy Information Administration (2024) U.S. Energy Information Administration 2020 Residential Energy Consumption Survey: Table CE2.1, Annual Household Site Fuel Consumption in the United States—Totals and Averages, 2020. Technical report U.S. Energy Information Administration. Note: Revised March 2024 External Links: Link Cited by: footnote 2.
  • van Beurden and Weaver (2024) M. van Beurden and A. Weaver Free Lossless Audio Codec (FLAC). Request for Comments Technical Report 9639, RFC Editor, Internet Engineering Task Force (IETF). External Links: Document, Link Cited by: §4.4.
  • Vest et al. (2018) A. N. Vest, G. Da Poian, Q. Li, C. Liu, S. Nemati, A. J. Shah, and G. D. Clifford An open source benchmarked toolbox for cardiovascular waveform and interval analysis. Physiological Measurement 39 (10), pp. 105004. External Links: ISSN 1361-6579, Link, Document Cited by: item 3.
  • Wagner et al. (2020) P. Wagner, N. Strodthoff, R. Bousseljot, D. Kreiseler, F. I. Lunze, W. Samek, and T. Schaeffter PTB-XL, a large publicly available electrocardiography dataset. Scientific Data 7, pp. 154. External Links: Document Cited by: §1.
  • WFDB Working Group (2026) WFDB Working Group WFDB toolbox for MATLAB. Note: https://wfdb.io/software/matlab.htmlStates that the toolbox is no longer actively maintained. Accessed 30 October 2026 Cited by: §2.2.
  • wfdb-python contributors (2026) wfdb-python contributors Issue #593: csv_to_wfdb computes checksums from physical values. Note: https://github.com/MIT-LCP/wfdb-python/issues/593Accessed 30 October 2026 Cited by: §2.2.
  • Xie et al. (2023) C. Xie, L. McCullum, A. Johnson, T. Pollard, B. Gow, and B. Moody Waveform Database Software Package (WFDB) for Python (version 4.1.0). PhysioNet. External Links: Document, Link Cited by: §2.2.

Appendix A Reading and writing records and annotations

The examples use 100s, the first minute of record 100 from the MIT-BIH Arrhythmia Database. It contains two ECG signals sampled at 360 Hz (21,600 samples per signal) and 75 beat annotations. The record is included in the repository’s tests/data directory and in the Python package. The examples write new records to the current directory. The values in the comments are those printed by the code.

A.1 Python

import numpy as np

import wfdbx

wfdbx.wfdbx_set_input_dir(wfdbx.sample_data_dir())

rec = wfdbx.read_record("100s", physical=True)

print(rec.fs, rec.names, rec.signals.shape)

seg = wfdbx.read_record("100s", channels=["MLII"], sampfrom="0:10", sampto="0:20")

hdr = wfdbx.read_header("100s")

print(hdr.nsig, hdr.nsamples)

ann = wfdbx.read_annotations("100s", "atr")

print(len(ann), ann.symbols[:3], ann.samples[:3])

x = np.random.randn(3600, 2)

wfdbx.write_record("rand", x, fs=360, fmt=16, physical=True,

gains=1000, adcres=16, units="mV", names=["A", "B"])

wfdbx.write_annotations("rand", "qrs", samples=[100, 460, 820],

symbols=["N", "N", "V"])

r100 = wfdbx.read_record("100", input_dir="https://physionet.org/files/mitdb/1.0.0/",

network=True, sampto="0:10")

A.2 C++

#include <wfdbx/record.hpp>

#include <cstdio>

int main() {

wfdbx::wfdbx_set_input_dir("tests/data");

wfdbx::ReadOptions opt;

opt.to = "0:10";

wfdbx::Record rec = wfdbx::read_record("100s", opt);

std::printf("%g %d %zu\n", rec.fs, rec.nsig, rec.nsamples());

std::printf("%d %g\n", rec.at(0, 0), rec.physical(0, 0));

wfdbx::Annotations ann = wfdbx::read_annotations("100s", "atr");

std::printf("%zu %s %lld\n", ann.size(), ann.symbols[1].c_str(),

ann.samples[1]);

wfdbx::WriteOptions w;

w.gains = {200};

w.baselines = {1024};

w.adcres = {11};

w.units = {"mV"};

w.names = rec.names();

wfdbx::write_record("copy", rec.samples, rec.nsig, rec.fs, w);

wfdbx::Annotations qrs;

qrs.samples = {100, 460, 820};

qrs.symbols = {"N", "N", "V"};

wfdbx::write_annotations("copy", "qrs", qrs);

}

A.3 Rust

use wfdbx::{read_annotations, read_record, write_annotations, write_record,

Annotations, ReadOptions, WriteOptions};

fn main() -> Result<(), wfdbx::record::Error> {

wfdbx::wfdbx_set_input_dir("tests/data");

// Read waveforms.

let rec = read_record("100s", &ReadOptions::default())?; // ADC units

println!("{} {} {}", rec.fs, rec.nsig, rec.nsamples()); // 360 2 21600

let mlii = rec.physical_signal(0)?; // physical units

println!("{:?}", &mlii[..3]); // [-0.145, -0.145, -0.145]

// Read annotations.

let ann = read_annotations("100s", "atr", None, None, None, false)?;

println!("{} {:?}", ann.len(), &ann.samples[..3]); // 75 [18, 77, 370]

// Write waveforms: the first 10 seconds as record "copy".

let opt = ReadOptions { to: Some("0:10".into()), ..Default::default() };

let x = read_record("100s", &opt)?;

let w = WriteOptions {

gains: x.siginfo.iter().map(|s| s.gain).collect(),

baselines: x.siginfo.iter().map(|s| s.baseline).collect(),

adcres: vec![11],

units: vec![Some("mV".into())],

names: x.names(),

..Default::default()

};

write_record("copy", &x.samples, x.nsig, x.fs, &w)?;

// Write annotations for "copy".

let qrs = Annotations {

samples: vec![100, 460, 820],

symbols: vec!["N".into(), "N".into(), "V".into()],

..Default::default()

};

write_annotations("copy", "qrs", &qrs, 0.0, None)?;

Ok(())

}

A.4 Julia

using WFDBX

wfdbx_set_input_dir("/path/to/wfdb-x/tests/data")

# Read waveforms.

rec = read_record("100s") # ADC units

println(rec.fs, " ", size(rec.samples)) # 360.0 (21600, 2)

x = physical(rec) # physical units

println(x[1, :]) # [-0.145, -0.065]

# Read annotations.

ann = read_annotations("100s", "atr")

println(length(ann), " ", ann.samples[1:3]) # 75 [18, 77, 370]

# Write waveforms: the first 10 seconds as record "copy".

r10 = read_record("100s"; to="0:10")

write_record("copy", r10.samples, r10.fs; fmt=16,

gains=[s.gain for s in r10.siginfo],

baselines=[s.baseline for s in r10.siginfo],

adcres=11, units="mV", names=signal_names(r10))

# Write annotations for "copy".

write_annotations("copy", "qrs",

Annotations(samples=[100, 460, 820], symbols=[b"N", b"N", b"V"]))

A.5 R

library(wfdbx)

wfdbx_set_input_dir("wfdb-x/tests/data")

rec <- read_record("100s", physical = TRUE)

rec$fs

rec$names

dim(rec$signals)

ann <- read_annotations("100s", "atr")

nrow(ann)

head(ann$symbol, 3)

x <- read_record("100s", sampto = "0:10")

write_record("copy", x$signals, fs = x$fs, fmt = 16, gains = x$gains,

baselines = x$baselines, adcres = 11, units = "mV", names = x$names)

write_annotations("copy", "qrs", sample = c(100, 460, 820),

symbol = c("N", "N", "V"))

A.6 MATLAB and GNU Octave

wfdbx.wfdbx_set_input_dir(’/path/to/wfdb-x/tests/data’);

rec = wfdbx.read_record(’100s’, ’physical’, true);

rec.fs

size(rec.signals)

ann = wfdbx.read_annotations(’100s’, ’atr’);

numel(ann.samples)

ann.symbols(1:3)’ % {’+’, ’N’, ’N’}

% Write waveforms: the first 10 seconds as record ’copy’.

x = wfdbx.read_record(’100s’, ’sampto’, ’0:10’); % ADC units

wfdbx.write_record(’copy’, x.signals, x.fs, ’fmt’, 16, ’gains’, x.gains, ...

’baselines’, x.baselines, ’adcres’, 11, ’units’, ’mV’, ’names’, x.names);

% Write annotations for ’copy’.

wfdbx.write_annotations(’copy’, ’qrs’, [100 460 820], ’symbols’, {’N’, ’N’, ’V’});’

A.7 Kotlin

import wfdbx.*

fun main() {

wfdbxSetInputDir("tests/data")

// Read waveforms (ADC and physical units).

val rec = readRecord("100s", physical = true)

println("${rec.fs} ${rec.names} ${rec.nsamples}") // 360.0 [MLII, V5] 21600

// Read annotations.

val ann = readAnnotations("100s", "atr")

println("${ann.size} ${ann.symbols.take(3)}") // 75 [+, N, N]

// Write waveforms: the first 10 seconds as record "copy".

val x = readRecord("100s", to = TimeSpec("0:10")) // ADC units

writeRecord("copy", x.samples, x.nsig, x.fs, fmt = 16,

gains = x.gains.toDoubleArray(), baselines = x.baselines.toIntArray(),

adcres = intArrayOf(11), units = listOf("mV"), names = x.names)

// Write annotations for "copy".

writeAnnotations("copy", "qrs", longArrayOf(100, 460, 820),

symbols = listOf("N", "N", "V"))

}

A.8 The command-line tools

The tools have the same names and options in every language. In C++ and Rust, they are installed as programs (rdsamp); in the other languages they run through a launcher (wfdbx rdsamp in Python, Julia, R and MATLAB/Octave, kotlin/bin/wfdbx rdsamp for Kotlin).

rdsamp -r 100s -t 10 -p -v

rdann -r 100s -a atr -t 0:30

wrsamp -i data.txt -o rec -F 360 -G 200 -R 11 -U mV 0 1

rdann -r 100s -a atr | wrann -r 100s -a copy

rdsamp --legacy -r 100s -t 10 -p -v

Appendix B The command-line tools

Table 7: The 33 command-line tools of WFDB-x: the 18 signal and annotation tools of the C package’s app directory and the 15 converters of its convert directory, each available in all seven languages.

注意转载授权 · 阅读原文

来源:arXiv cs.DL 数字图书馆 · arxiv.org

引用原文

Reza Sameni. WFDB-x: Conformance-Tested Implementations of the WFDB Software Package in Seven Programming Languages[EB/OL]. (2026-11-03)[访问日期]. https://arxiv.org/abs/2611.01358.