Initial commit
9
.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
.DS_Store
|
||||||
|
/.build
|
||||||
|
/Packages
|
||||||
|
xcuserdata/
|
||||||
|
DerivedData/
|
||||||
|
.swiftpm/configuration/registries.json
|
||||||
|
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||||
|
.netrc
|
||||||
|
*.class
|
||||||
24
Package.resolved
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"originHash" : "bf0b92ec2751ab82eed76f0b5f4c42d45557a303569895153367fd1d19d1045a",
|
||||||
|
"pins" : [
|
||||||
|
{
|
||||||
|
"identity" : "swift-algorithms",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/apple/swift-algorithms",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "f6919dfc309e7f1b56224378b11e28bab5bccc42",
|
||||||
|
"version" : "1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "swift-numerics",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/apple/swift-numerics.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "0a5bc04095a675662cf24757cc0640aa2204253b",
|
||||||
|
"version" : "1.0.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version" : 3
|
||||||
|
}
|
||||||
33
Package.swift
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// swift-tools-version: 6.0
|
||||||
|
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||||
|
|
||||||
|
import PackageDescription
|
||||||
|
|
||||||
|
let package = Package(
|
||||||
|
name: "EcgSynKit",
|
||||||
|
products: [
|
||||||
|
// Products define the executables and libraries a package produces, making them visible to other packages.
|
||||||
|
.library(
|
||||||
|
name: "EcgSynKit",
|
||||||
|
targets: ["EcgSynKit"]),
|
||||||
|
],
|
||||||
|
dependencies: [
|
||||||
|
.package(url: "https://github.com/apple/swift-algorithms", from: "1.2.0"),
|
||||||
|
// .package(url: "https://github.com/AudioKit/KissFFT.git", from: "1.0.0")
|
||||||
|
.package(path: "./KissFFT/")
|
||||||
|
],
|
||||||
|
targets: [
|
||||||
|
// Targets are the basic building blocks of a package, defining a module or a test suite.
|
||||||
|
// Targets can depend on other targets in this package and products from dependencies.
|
||||||
|
.target(
|
||||||
|
name: "EcgSynKit",
|
||||||
|
dependencies: [
|
||||||
|
.product(name: "Algorithms", package: "swift-algorithms"),
|
||||||
|
.product(name: "KissFFT", package: "kissfft")
|
||||||
|
]),
|
||||||
|
.testTarget(
|
||||||
|
name: "EcgSynKitTests",
|
||||||
|
dependencies: ["EcgSynKit"]
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
186
Sources/EcgSynKit/EcgSynKit.swift
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
import Algorithms
|
||||||
|
import Foundation
|
||||||
|
import KissFFT
|
||||||
|
|
||||||
|
struct Parameters {
|
||||||
|
/// The number of beats to simulate.
|
||||||
|
let numBeats: Int = 256
|
||||||
|
|
||||||
|
/// The ECG sampling frequency in Hz.
|
||||||
|
let sfEcg: Int = 256
|
||||||
|
|
||||||
|
/// The internal sampling frequency in Hz.
|
||||||
|
var sfInternal: Int = 512
|
||||||
|
|
||||||
|
/// The mean heart rate in beats per minute.
|
||||||
|
let hrMean: Double = 60.0
|
||||||
|
|
||||||
|
/// The standard deviation of the heart rate.
|
||||||
|
let hrStd: Double = 1.0
|
||||||
|
|
||||||
|
/// The ratio of power between low and high frequencies.
|
||||||
|
let lfhfRatio: Double = 0.5
|
||||||
|
|
||||||
|
/// The ECT amplitude in mV.
|
||||||
|
let amplitude: Double = 1.4
|
||||||
|
|
||||||
|
/// RNG seed value.
|
||||||
|
let seed: Int = 0
|
||||||
|
|
||||||
|
/// Amplitude of the noise.
|
||||||
|
let aNoise: Double = 0.0
|
||||||
|
|
||||||
|
/// The angle of each attractor (P, Q, R, S, T) around the limit cycle, in radians.
|
||||||
|
let theta: [Double] = [-60, -15, 0, 15, 90].map { $0 * .pi / 180 }
|
||||||
|
|
||||||
|
/// Widths of the attractors (P, Q, R, S, T).
|
||||||
|
let a: [Double] = [1.2, -5, 30, -7.5, 0.75]
|
||||||
|
|
||||||
|
/// The position of attractors (P, Q, R, S, T) above or below the z=0 plane.
|
||||||
|
let b: [Double] = [0.25, 0.1, 0.1, 0.1, 0.4]
|
||||||
|
|
||||||
|
/// Mayer wave frequency in Hz.
|
||||||
|
let flo = 0.1
|
||||||
|
|
||||||
|
/// flo standard deviation.
|
||||||
|
let flostd = 0.01
|
||||||
|
|
||||||
|
/// Respiratory rate frequency in Hz.
|
||||||
|
let fhi = 0.25
|
||||||
|
|
||||||
|
/// fhi standard deviation.
|
||||||
|
let fhistd = 0.01
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compute fft or inverse (based on sign) of vector data, where [i] is real and [i+1] is imaginary, i starts
|
||||||
|
/// from 0.
|
||||||
|
func fft(data: inout [Double], isign: Int) {
|
||||||
|
let isign = Double(isign)
|
||||||
|
let n = data.count
|
||||||
|
|
||||||
|
var j = 0
|
||||||
|
for i in stride(from: 0, to: n, by: 2) {
|
||||||
|
if j > i {
|
||||||
|
data.swapAt(j, i)
|
||||||
|
data.swapAt(j + 1, i + 1)
|
||||||
|
}
|
||||||
|
var m = n / 2
|
||||||
|
while m >= 2, j >= m {
|
||||||
|
j -= m
|
||||||
|
m /= 2
|
||||||
|
}
|
||||||
|
j += m
|
||||||
|
}
|
||||||
|
|
||||||
|
var mmax = 2
|
||||||
|
while mmax < n {
|
||||||
|
let istep = 2 * mmax
|
||||||
|
let theta = isign * (2.0 * .pi / Double(mmax))
|
||||||
|
let wtemp = sin(0.5 * theta)
|
||||||
|
let wpr = -2.0 * wtemp * wtemp
|
||||||
|
let wpi = sin(theta)
|
||||||
|
var wr = 1.0
|
||||||
|
var wi = 0.0
|
||||||
|
|
||||||
|
for m in stride(from: 0, to: mmax, by: 2) {
|
||||||
|
for i in stride(from: m, to: n, by: istep) {
|
||||||
|
let j = i + mmax
|
||||||
|
let tempr = wr * data[j] - wi * data[j + 1]
|
||||||
|
let tempi = wr * data[j + 1] + wi * data[j]
|
||||||
|
data[j] = data[i] - tempr
|
||||||
|
data[j + 1] = data[i + 1] - tempi
|
||||||
|
data[i] += tempr
|
||||||
|
data[i + 1] += tempi
|
||||||
|
}
|
||||||
|
let wrtemp = wr
|
||||||
|
wr = wr * wpr - wi * wpi + wr
|
||||||
|
wi = wi * wpr + wrtemp * wpi + wi
|
||||||
|
}
|
||||||
|
mmax = istep
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func rrprocess(params: Parameters, nrr: Int) -> [Double] {
|
||||||
|
let w1 = 2.0 * .pi * params.flo
|
||||||
|
let w2 = 2.0 * .pi * params.fhi
|
||||||
|
let c1 = 2.0 * .pi * params.flostd
|
||||||
|
let c2 = 2.0 * .pi * params.fhistd
|
||||||
|
|
||||||
|
let sig2 = 1.0
|
||||||
|
let sig1 = params.lfhfRatio
|
||||||
|
|
||||||
|
let rrmean = 60.0 / params.hrMean
|
||||||
|
let rrstd = 60.0 * params.hrStd / (params.hrMean * params.hrMean)
|
||||||
|
|
||||||
|
let sf = Double(params.sfInternal)
|
||||||
|
let df = sf / Double(nrr)
|
||||||
|
|
||||||
|
var swc = (0 ..< nrr / 2 + 1).map {
|
||||||
|
let w = df * Double($0) * 2.0 * .pi
|
||||||
|
let dw1 = w - w1
|
||||||
|
let dw2 = w - w2
|
||||||
|
let hw = sig1 * exp(-dw1 * dw1 / (2.0 * c1 * c1)) / sqrt(2.0 * .pi * c1 * c1)
|
||||||
|
+ sig2 * exp(-dw2 * dw2 / (2.0 * c2 * c2)) / sqrt(2.0 * .pi * c2 * c2)
|
||||||
|
|
||||||
|
let sw = (sf / 2.0) * sqrt(hw)
|
||||||
|
|
||||||
|
let ph = 2.0 * .pi * Double.random(in: 0.0 ..< 1.0)
|
||||||
|
return kiss_fft_cpx(r: sw * cos(ph), i: sw * sin(ph))
|
||||||
|
}
|
||||||
|
swc[0].i = 0.0
|
||||||
|
swc[nrr / 2].i = 0.0
|
||||||
|
|
||||||
|
let fft = kiss_fftr_alloc(Int32(nrr), 1, nil, nil)
|
||||||
|
|
||||||
|
let outptr = UnsafeMutablePointer<Double>.allocate(capacity: nrr)
|
||||||
|
kiss_fftri(fft, swc, outptr)
|
||||||
|
|
||||||
|
var rr = (0 ..< nrr).map { outptr[$0] * (1.0 / Double(nrr)) }
|
||||||
|
outptr.deallocate()
|
||||||
|
|
||||||
|
let xstd = stdev(rr)
|
||||||
|
let ratio = rrstd / xstd
|
||||||
|
|
||||||
|
for i in 0 ..< nrr {
|
||||||
|
rr[i] = rr[i] * ratio + rrmean
|
||||||
|
}
|
||||||
|
|
||||||
|
return rr
|
||||||
|
}
|
||||||
|
|
||||||
|
func stdev(_ data: [Double]) -> Double {
|
||||||
|
let n = Double(data.count)
|
||||||
|
let mean = data.reduce(0.0, +) / n
|
||||||
|
return sqrt(data.lazy.map { ($0 - mean) * ($0 - mean) }.reduce(0.0, +) / (n - 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
func compute(params: Parameters) {
|
||||||
|
// adjust extrema parameters for mean heart rate
|
||||||
|
let hrFact = sqrt(params.hrMean / 60)
|
||||||
|
let hrFact2 = sqrt(hrFact)
|
||||||
|
|
||||||
|
let bi = params.b.map { $0 * hrFact }
|
||||||
|
|
||||||
|
/// XXX: Discrepancy here between Java/C and Matlab, the former uses 1.0 for ti[4] adjustment.
|
||||||
|
let ti = zip([hrFact2, hrFact, 1, hrFact, hrFact2], params.theta).map(*)
|
||||||
|
|
||||||
|
let ai = params.a
|
||||||
|
|
||||||
|
let x0 = SIMD3<Double>(1.0, 0.0, 0.04) // XXX: Convert to init from vector3d
|
||||||
|
let rseed = params.seed
|
||||||
|
|
||||||
|
// calculate time scales
|
||||||
|
let h = 1.0 / Double(params.sfInternal)
|
||||||
|
let tstep = 1.0 / Double(params.sfEcg)
|
||||||
|
|
||||||
|
// calculate length of the RR time series
|
||||||
|
let rrmean = (60.0 / params.hrMean)
|
||||||
|
|
||||||
|
let numRr = Int(pow(2.0, ceil(log2(Double(params.numBeats * params.sfInternal) * rrmean))))
|
||||||
|
|
||||||
|
var rr = [Double](repeating: 0.0, count: numRr)
|
||||||
|
|
||||||
|
// TODO: check sfInternal is integer multple of sfEcg
|
||||||
|
|
||||||
|
// define frequency parameters for rr process
|
||||||
|
}
|
||||||
14
Tests/EcgSynKitTests/EcgSynKitTests.swift
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import Testing
|
||||||
|
@testable import EcgSynKit
|
||||||
|
@testable import KissFFT
|
||||||
|
|
||||||
|
@Test func fftTest () {
|
||||||
|
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
|
||||||
|
let p = Parameters()
|
||||||
|
|
||||||
|
|
||||||
|
let rr = rrprocess(params: p, nrr: 131072)
|
||||||
|
//fft(data: &a, isign: -1)
|
||||||
|
//print("out: \(rr)")
|
||||||
|
|
||||||
|
}
|
||||||
11
ecgsyn-1.0.0/C/index.html
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<html>
|
||||||
|
<head><title>Index of /static/published-projects/ecgsyn/1.0.0/C/</title></head>
|
||||||
|
<body>
|
||||||
|
<h1>Index of /static/published-projects/ecgsyn/1.0.0/C/</h1><hr><pre><a href="../">../</a>
|
||||||
|
<a href="linux/">linux/</a> 12-Apr-2019 17:35 -
|
||||||
|
<a href="solaris/">solaris/</a> 12-Apr-2019 17:35 -
|
||||||
|
<a href="src/">src/</a> 12-Apr-2019 17:35 -
|
||||||
|
<a href="windows/">windows/</a> 12-Apr-2019 17:35 -
|
||||||
|
<a href="index.shtml">index.shtml</a> 12-Apr-2019 17:35 4274
|
||||||
|
</pre><hr></body>
|
||||||
|
</html>
|
||||||
114
ecgsyn-1.0.0/C/index.shtml
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
<!--#set var="TITLE" value="Compiling and using the C version of ECGSYN"-->
|
||||||
|
<!--#include virtual="/head.shtml"-->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Compiling ECGSYN</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Sources for the C version of <a href="../">ECGSYN</a> are <a
|
||||||
|
href="src/">here</a>. Note, however, that two additional files are required in
|
||||||
|
order to compile ECGSYN. These files (<tt>dfour1.c</tt> and <tt>ran1.c</tt>)
|
||||||
|
are those included in <a href="http://www.nr.com" target="other">Numerical
|
||||||
|
Recipes in C</a>. Before attempting to compile ECGSYN, obtain these two files
|
||||||
|
from Numerical Recipes in C and place them in the same directory as the other
|
||||||
|
sources. (These files are not provided here because they cannot be freely
|
||||||
|
redistributed.)
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If you cannot obtain <tt>dfour1.c</tt> and <tt>ran1.c</tt>, several
|
||||||
|
alternatives are available, including ready-to-run executable versions of
|
||||||
|
ECGSYN for <a href="linux/">GNU/Linux</a>, <a href="solaris/">Solaris</a>, and
|
||||||
|
<a href="windows/">MS-Windows</a>, as well as <a
|
||||||
|
href="../Matlab/">Matlab/Octave</a> and <a href="../Java/">Java</a>
|
||||||
|
implementations of ECGSYN.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
On most platforms, including GNU/Linux, MacOS X, and Unix, compile ECGSYN
|
||||||
|
by typing
|
||||||
|
<pre>
|
||||||
|
make
|
||||||
|
</pre>
|
||||||
|
in a terminal window. This will also work under MS-Windows if you have
|
||||||
|
installed the free <a href="http://www.cygwin.com" target="other">Cygwin/gcc
|
||||||
|
development toolkit</a>. If you wish to use another compiler under MS-Windows,
|
||||||
|
you are on your own.
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Running ECGSYN</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The executable version is named <tt>ecgsyn</tt> (or, under MS-Windows,
|
||||||
|
<tt>ecgsyn.exe</tt>). Once you have this file, move it into any directory in
|
||||||
|
your PATH and run it by typing
|
||||||
|
<pre>
|
||||||
|
ecgsyn
|
||||||
|
</pre>
|
||||||
|
in a terminal window. You may add options (switches) to the '<tt>ecgsyn</tt>'
|
||||||
|
command; the option '<tt>$</tt>', as in
|
||||||
|
<pre>
|
||||||
|
ecgsyn $
|
||||||
|
</pre>
|
||||||
|
starts ECGSYN in interactive mode, as shown below:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
>> ecgsyn $
|
||||||
|
ECGSYN: A program for generating a realistic synthetic ECG
|
||||||
|
Copyright (c) 2003 by Patrick McSharry & Gari Clifford. All rights reserved.
|
||||||
|
|
||||||
|
O Name of output data file "ecgsyn.dat"
|
||||||
|
n Approximate number of heart beats 256
|
||||||
|
s ECG sampling frequency [Hz] 256
|
||||||
|
S Internal Sampling frequency [Hz] 256
|
||||||
|
a Amplitude of additive uniform noise [mV] 0
|
||||||
|
h Heart rate mean [bpm] 60
|
||||||
|
H Heart rate standard deviation [bpm] 1
|
||||||
|
f Low frequency [Hz] 0.1
|
||||||
|
F High frequency [Hz] 0.25
|
||||||
|
v Low frequency standard deviation [Hz] 0.01
|
||||||
|
V High frequency standard deviation [Hz] 0.01
|
||||||
|
q LF/HF ratio 0.5
|
||||||
|
R Seed 1
|
||||||
|
(Type ? for Help)
|
||||||
|
->
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
At the prompt, you can then type <tt>?</tt> for help, or simply specify each
|
||||||
|
parameter that you want to change by typing the corresponding option letter (in
|
||||||
|
the first column above) followed by a space and the new value, then
|
||||||
|
<enter>. To review the current settings, enter a blank line. After you
|
||||||
|
have modified all the parameters you want, type = followed by <enter> to
|
||||||
|
run the program. You may also specify the parameters in a file called
|
||||||
|
<tt>ecgsyn.opt</tt>, which is automatically read (if it exists) the next time
|
||||||
|
you run the program.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Any of the options can also be entered directly on the command line, by
|
||||||
|
prefixing the option letter with '<tt>-</tt>', as in:
|
||||||
|
<pre>
|
||||||
|
ecgsyn -h 80 -n 100
|
||||||
|
</pre>
|
||||||
|
(which would create output at a mean heart rate of 80 bpm, lasting for about
|
||||||
|
100 beats).
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The source files <tt>opt.c</tt> and <tt>opt.h</tt> provide the option
|
||||||
|
interpreter for ECGSYN; they were written by James Theiler. For additional
|
||||||
|
information, and for the most recent version of <tt>opt</tt>, see
|
||||||
|
<a href="http://nis-www.lanl.gov/~jt/Software/"
|
||||||
|
target="other"><tt>http://nis-www.lanl.gov/~jt/Software/</tt></a>.
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Interpreting ECGSYN's output</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Unless you have changed the name of the output file with the '<tt>O</tt>'
|
||||||
|
parameter, you will find the synthetic ECG written to a text file called
|
||||||
|
<tt>ecgsyn.dat</tt>. Click <a href="../sample-output/">here</a> for a sample
|
||||||
|
of ECGSYN output and for a description of the format of this file.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<!--#include virtual="/footer.shtml"-->
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
10
ecgsyn-1.0.0/C/linux/HEADER.shtml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<!--#set var="TITLE" value="ECGSYN for GNU/Linux"-->
|
||||||
|
<!--#include virtual="/head.shtml"-->
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The executable <tt>ecgsyn</tt> file in this directory was compiled from
|
||||||
|
these <a href="../src/">ECGSYN sources</a> with gcc 2.96 under Red Hat
|
||||||
|
Linux 7.2. It is known to work under Red Hat Linux 7.1, 7.2, 7.3, 8, and 9,
|
||||||
|
and may also work under other versions of GNU/Linux.
|
||||||
|
|
||||||
BIN
ecgsyn-1.0.0/C/linux/ecgsyn
Normal file
8
ecgsyn-1.0.0/C/linux/index.html
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<html>
|
||||||
|
<head><title>Index of /static/published-projects/ecgsyn/1.0.0/C/linux/</title></head>
|
||||||
|
<body>
|
||||||
|
<h1>Index of /static/published-projects/ecgsyn/1.0.0/C/linux/</h1><hr><pre><a href="../">../</a>
|
||||||
|
<a href="HEADER.shtml">HEADER.shtml</a> 12-Apr-2019 17:35 371
|
||||||
|
<a href="ecgsyn">ecgsyn</a> 12-Apr-2019 17:35 46457
|
||||||
|
</pre><hr></body>
|
||||||
|
</html>
|
||||||
9
ecgsyn-1.0.0/C/solaris/HEADER.shtml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<!--#set var="TITLE" value="ECGSYN for Solaris"-->
|
||||||
|
<!--#include virtual="/head.shtml"-->
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The executable <tt>ecgsyn</tt> file in this directory was compiled from
|
||||||
|
these <a href="../src/">ECGSYN sources</a> with gcc 3.1 under SunOS 5.8
|
||||||
|
(Solaris 8).
|
||||||
|
|
||||||
BIN
ecgsyn-1.0.0/C/solaris/ecgsyn
Normal file
8
ecgsyn-1.0.0/C/solaris/index.html
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<html>
|
||||||
|
<head><title>Index of /static/published-projects/ecgsyn/1.0.0/C/solaris/</title></head>
|
||||||
|
<body>
|
||||||
|
<h1>Index of /static/published-projects/ecgsyn/1.0.0/C/solaris/</h1><hr><pre><a href="../">../</a>
|
||||||
|
<a href="HEADER.shtml">HEADER.shtml</a> 12-Apr-2019 17:35 253
|
||||||
|
<a href="ecgsyn">ecgsyn</a> 12-Apr-2019 17:35 43854
|
||||||
|
</pre><hr></body>
|
||||||
|
</html>
|
||||||
116
ecgsyn-1.0.0/C/src/00README
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
ECGSYN: A program for generating a realistic synthetic ECG
|
||||||
|
Copyright (C) 2003 by Patrick McSharry & Gari Clifford. All rights reserved.
|
||||||
|
|
||||||
|
|
||||||
|
Compiling ECGSYN
|
||||||
|
================
|
||||||
|
|
||||||
|
This directory contains sources for the C version of ECGSYN. Note, however,
|
||||||
|
that two additional files are required in order to compile ECGSYN. These
|
||||||
|
files (dfour1.c and ran1.c) are those included in Numerical Recipes in C
|
||||||
|
(http://www.nr.com/). Before attempting to compile ECGSYN, obtain these
|
||||||
|
two files from Numerical Recipes in C and place them in this directory.
|
||||||
|
(These files are missing from this directory because they cannot be freely
|
||||||
|
redistributed.)
|
||||||
|
|
||||||
|
If you cannot obtain dfour1.c and ran1.c, several alternatives are available,
|
||||||
|
including ready-to-run executable versions of ECGSYN for GNU/Linux, Solaris,
|
||||||
|
and MS-Windows (see the directory above this one), as well as Matlab/Octave
|
||||||
|
and Java implementations of ECGSYN. See http://www.physionet.org/ for details.
|
||||||
|
|
||||||
|
On most platforms, including GNU/Linux, MacOS X, and Unix, compile ECGSYN
|
||||||
|
by typing
|
||||||
|
make
|
||||||
|
in a terminal window. This will also work under MS-Windows if you have
|
||||||
|
installed the free Cygwin/gcc development toolkit (http://www.cygwin.com/).
|
||||||
|
If you wish to use another compiler under MS-Windows, you are on your own.
|
||||||
|
|
||||||
|
|
||||||
|
Running ECGSYN
|
||||||
|
==============
|
||||||
|
|
||||||
|
The executable version is named 'ecgsyn' (or, under MS-Windows, 'ecgsyn.exe').
|
||||||
|
Once you have this file, move it into any directory in your PATH and run
|
||||||
|
it by typing
|
||||||
|
ecgsyn
|
||||||
|
in a terminal window. You may add options (switches) to the 'ecgsyn' command;
|
||||||
|
the option '$', as in
|
||||||
|
ecgsyn $
|
||||||
|
starts 'ecgsyn' in interactive mode, as shown below:
|
||||||
|
|
||||||
|
>> ecgsyn $
|
||||||
|
ECGSYN: A program for generating a realistic synthetic ECG
|
||||||
|
Copyright (c) 2003 by Patrick McSharry & Gari Clifford. All rights reserved.
|
||||||
|
|
||||||
|
O Name of output data file "ecgsyn.dat"
|
||||||
|
n Approximate number of heart beats 256
|
||||||
|
s ECG sampling frequency [Hz] 256
|
||||||
|
S Internal Sampling frequency [Hz] 256
|
||||||
|
a Amplitude of additive uniform noise [mV] 0
|
||||||
|
h Heart rate mean [bpm] 60
|
||||||
|
H Heart rate standard deviation [bpm] 1
|
||||||
|
f Low frequency [Hz] 0.1
|
||||||
|
F High frequency [Hz] 0.25
|
||||||
|
v Low frequency standard deviation [Hz] 0.01
|
||||||
|
V High frequency standard deviation [Hz] 0.01
|
||||||
|
q LF/HF ratio 0.5
|
||||||
|
R Seed 1
|
||||||
|
(Type ? for Help)
|
||||||
|
->
|
||||||
|
|
||||||
|
At the prompt, you can then type ? for help, or simply specify each parameter
|
||||||
|
above that you want to change by typing the corresponding option letter (in the
|
||||||
|
first column above) followed by a space and the new value, then <enter>. To
|
||||||
|
review the current settings, enter a blank line. After you have modified all
|
||||||
|
the parameters you want, type = followed by <enter> to run the program. You may
|
||||||
|
also specify the parameters in a file called ecgsyn.opt, which is automatically
|
||||||
|
read (if it exists) the next time you run the program.
|
||||||
|
|
||||||
|
Any of the options can also be entered directly on the command line, by
|
||||||
|
prefixing the option letter with '-', as in:
|
||||||
|
ecgsyn -h 80 -n 100
|
||||||
|
(which would create output at a mean heart rate of 80 bpm, lasting for about
|
||||||
|
100 beats).
|
||||||
|
|
||||||
|
The source files opt.c and opt.h provide the option interpreter for ecgsyn;
|
||||||
|
they were written by James Theiler. For additional information, and for the
|
||||||
|
most recent version of 'opt', see http://nis-www.lanl.gov/~jt/Software/.
|
||||||
|
|
||||||
|
|
||||||
|
Interpreting ECGSYN's output
|
||||||
|
============================
|
||||||
|
|
||||||
|
Unless you have changed the name of the output file with the 'O' parameter,
|
||||||
|
you will find the synthetic ECG written to a text file called ecgsyn.dat,
|
||||||
|
which contains three columns:
|
||||||
|
* the time in seconds
|
||||||
|
* the ECG amplitude in millivolts
|
||||||
|
* markers to indicate the locations of the waveform peaks:
|
||||||
|
0 - (no peak)
|
||||||
|
1 - Top of P-wave
|
||||||
|
2 - Q-point
|
||||||
|
3 - Peak of R-wave
|
||||||
|
4 - S-point
|
||||||
|
5 - Peak of T-wave
|
||||||
|
|
||||||
|
To convert the ECG output into PhysioBank (WFDB) format, use a command
|
||||||
|
such as
|
||||||
|
wrsamp -F 256 -o synth -x 200 1 <ecgsyn.dat
|
||||||
|
(assuming you have not changed the default sampling frequency of 256 Hz).
|
||||||
|
This command produces a record named 'synth' (a signal file named 'synth.dat'
|
||||||
|
and a header file named 'synth.hea'), which can be read by other PhysioToolkit
|
||||||
|
applications. 'wrsamp' is part of the WFDB software package; see
|
||||||
|
http://www.physionet.org/physiotools/wfdb.shtml for details.
|
||||||
|
|
||||||
|
|
||||||
|
Further information
|
||||||
|
===================
|
||||||
|
|
||||||
|
The most recent version of this software can always be obtained from
|
||||||
|
http://www.physionet.org/physiotools/ecgsyn/
|
||||||
|
|
||||||
|
See IEEE Transactions on Biomedical Engineering, 50(3),289-294, March 2003.
|
||||||
|
|
||||||
|
Authors: P. McSharry (patrick AT mcsharry DOT net)
|
||||||
|
G. Clifford (gari AT mit DOT edu)
|
||||||
|
|
||||||
19
ecgsyn-1.0.0/C/src/Makefile
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# file: Makefile
|
||||||
|
|
||||||
|
# 'make' description file for compiling ecgsyn
|
||||||
|
|
||||||
|
CFILES = ecgsyn.c opt.c dfour1.c ran1.c
|
||||||
|
CFLAGS = -O
|
||||||
|
|
||||||
|
ecgsyn: $(CFILES) opt.h
|
||||||
|
$(CC) $(CFLAGS) -o ecgsyn $(CFILES) -lm
|
||||||
|
|
||||||
|
dfour1.c ran1.c:
|
||||||
|
@echo "To compile ecgsyn, first get copies of dfour1.c and ran1.c"
|
||||||
|
@echo "(from Numerical Recipes in C) and place them in this directory."
|
||||||
|
@echo "Then type:"
|
||||||
|
@echo " make ecgsyn"
|
||||||
|
@exit 1
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *~ *.o *.obj
|
||||||
664
ecgsyn-1.0.0/C/src/ecgsyn.c
Normal file
@@ -0,0 +1,664 @@
|
|||||||
|
/* 09 Oct 2003 "ecgsyn.c" */
|
||||||
|
/* */
|
||||||
|
/* Copyright (c)2003 by Patrick McSharry & Gari Clifford, All Rights Reserved */
|
||||||
|
/* See IEEE Transactions On Biomedical Engineering, 50(3),289-294, March 2003.*/
|
||||||
|
/* Contact P. McSharry (patrick AT mcsharry DOT net) or */
|
||||||
|
/* G. Clifford (gari AT mit DOT edu) */
|
||||||
|
/* */
|
||||||
|
/* This program is free software; you can redistribute it and/or modify */
|
||||||
|
/* it under the terms of the GNU General Public License as published by */
|
||||||
|
/* the Free Software Foundation; either version 2 of the License, or */
|
||||||
|
/* (at your option) any later version. */
|
||||||
|
/* */
|
||||||
|
/* This program is distributed in the hope that it will be useful, */
|
||||||
|
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||||
|
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||||
|
/* GNU General Public License for more details. */
|
||||||
|
/* */
|
||||||
|
/* You should have received a copy of the GNU General Public License */
|
||||||
|
/* along with this program; if not, write to the Free Software Foundation */
|
||||||
|
/* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
/* */
|
||||||
|
/* ecgsyn.m and its dependents are freely availble from Physionet - */
|
||||||
|
/* http://www.physionet.org/ - please report any bugs to the authors above. */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "opt.h"
|
||||||
|
#define PI (2.0*asin(1.0))
|
||||||
|
#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
|
||||||
|
#define MIN(a,b) (a < b ? a : b)
|
||||||
|
#define MAX(a,b) (a > b ? a : b)
|
||||||
|
#define PI (2.0*asin(1.0))
|
||||||
|
#define OFFSET 1
|
||||||
|
#define ARG1 char*
|
||||||
|
|
||||||
|
#define IA 16807
|
||||||
|
#define IM 2147483647
|
||||||
|
#define AM (1.0/IM)
|
||||||
|
#define IQ 127773
|
||||||
|
#define IR 2836
|
||||||
|
#define NTAB 32
|
||||||
|
#define NDIV (1+(IM-1)/NTAB)
|
||||||
|
#define EPS 1.2e-7
|
||||||
|
#define RNMX (1.0-EPS)
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* DEFINE PARAMETERS AS GLOBAL VARIABLES */
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
char outfile[100]="ecgsyn.dat";/* Output data file */
|
||||||
|
int N = 256; /* Number of heart beats */
|
||||||
|
int sfecg = 256; /* ECG sampling frequency */
|
||||||
|
int sf = 256; /* Internal sampling frequency */
|
||||||
|
double Anoise = 0.0; /* Amplitude of additive uniform noise*/
|
||||||
|
double hrmean = 60.0; /* Heart rate mean */
|
||||||
|
double hrstd = 1.0; /* Heart rate std */
|
||||||
|
double flo = 0.1; /* Low frequency */
|
||||||
|
double fhi = 0.25; /* High frequency */
|
||||||
|
double flostd = 0.01; /* Low frequency std */
|
||||||
|
double fhistd = 0.01; /* High frequency std */
|
||||||
|
double lfhfratio = 0.5; /* LF/HF ratio */
|
||||||
|
|
||||||
|
int Necg = 0; /* Number of ECG outputs */
|
||||||
|
int mstate = 3; /* System state space dimension */
|
||||||
|
double xinitial = 1.0; /* Initial x co-ordinate value */
|
||||||
|
double yinitial = 0.0; /* Initial y co-ordinate value */
|
||||||
|
double zinitial = 0.04; /* Initial z co-ordinate value */
|
||||||
|
int seed = 1; /* Seed */
|
||||||
|
long rseed;
|
||||||
|
double h;
|
||||||
|
double *rr,*rrpc;
|
||||||
|
double *ti,*ai,*bi;
|
||||||
|
|
||||||
|
/* prototypes for externally defined functions */
|
||||||
|
void dfour1(double data[], unsigned long nn, int isign);
|
||||||
|
float ran1(long *idum);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* ALLOCATE MEMORY FOR VECTOR */
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
double *mallocVect(long n0, long nx)
|
||||||
|
{
|
||||||
|
double *vect;
|
||||||
|
|
||||||
|
vect=(double *)malloc((size_t) ((nx-n0+1+OFFSET)*sizeof(double)));
|
||||||
|
if (!vect){
|
||||||
|
printf("Memory allocation failure in mallocVect");
|
||||||
|
}
|
||||||
|
return vect-n0+OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* FREE MEMORY FOR MALLOCVECT */
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void freeVect(double *vect, long n0, long nx)
|
||||||
|
{
|
||||||
|
free((ARG1) (vect+n0-OFFSET));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* MEAN CALCULATOR */
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
double mean(double *x, int n)
|
||||||
|
/* n-by-1 vector, calculate mean */
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
double add;
|
||||||
|
|
||||||
|
add = 0.0;
|
||||||
|
for(j=1;j<=n;j++) add += x[j];
|
||||||
|
|
||||||
|
return (add/n);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* STANDARD DEVIATION CALCULATOR */
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
double stdev(double *x, int n)
|
||||||
|
/* n-by-1 vector, calculate standard deviation */
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
double add,mean,diff,total;
|
||||||
|
|
||||||
|
add = 0.0;
|
||||||
|
for(j=1;j<=n;j++) add += x[j];
|
||||||
|
mean = add/n;
|
||||||
|
|
||||||
|
total = 0.0;
|
||||||
|
for(j=1;j<=n;j++)
|
||||||
|
{
|
||||||
|
diff = x[j] - mean;
|
||||||
|
total += diff*diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (sqrt(total/(n-1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* WRITE VECTOR IN A FILE */
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vecfile(char filename[], double *x, int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
fp = fopen(filename,"w");
|
||||||
|
for(i=1;i<=n;i++) fprintf(fp,"%e\n",x[i]);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* INTERP */
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void interp(double *y, double *x, int n, int r)
|
||||||
|
{
|
||||||
|
int i,j;
|
||||||
|
double a;
|
||||||
|
|
||||||
|
for(i=1;i<=n-1;i++)
|
||||||
|
{
|
||||||
|
for(j=1;j<=r;j++)
|
||||||
|
{
|
||||||
|
a = (j-1)*1.0/r;
|
||||||
|
y[(i-1)*r+j] = (1.0-a)*x[i] + a*x[i+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* GENERATE RR PROCESS */
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void rrprocess(double *rr, double flo, double fhi,
|
||||||
|
double flostd, double fhistd, double lfhfratio,
|
||||||
|
double hrmean, double hrstd, double sf, int n)
|
||||||
|
{
|
||||||
|
int i,j;
|
||||||
|
double c1,c2,w1,w2,sig1,sig2,rrmean,rrstd,xstd,ratio;
|
||||||
|
double df,dw1,dw2,*w,*Hw,*Sw,*ph0,*ph,*SwC;
|
||||||
|
|
||||||
|
w = mallocVect(1,n);
|
||||||
|
Hw = mallocVect(1,n);
|
||||||
|
Sw = mallocVect(1,n);
|
||||||
|
ph0 = mallocVect(1,n/2-1);
|
||||||
|
ph = mallocVect(1,n);
|
||||||
|
SwC = mallocVect(1,2*n);
|
||||||
|
|
||||||
|
|
||||||
|
w1 = 2.0*PI*flo;
|
||||||
|
w2 = 2.0*PI*fhi;
|
||||||
|
c1 = 2.0*PI*flostd;
|
||||||
|
c2 = 2.0*PI*fhistd;
|
||||||
|
sig2 = 1.0;
|
||||||
|
sig1 = lfhfratio;
|
||||||
|
rrmean = 60.0/hrmean;
|
||||||
|
rrstd = 60.0*hrstd/(hrmean*hrmean);
|
||||||
|
|
||||||
|
df = sf/n;
|
||||||
|
for(i=1;i<=n;i++) w[i] = (i-1)*2.0*PI*df;
|
||||||
|
for(i=1;i<=n;i++)
|
||||||
|
{
|
||||||
|
dw1 = w[i]-w1;
|
||||||
|
dw2 = w[i]-w2;
|
||||||
|
Hw[i] = sig1*exp(-dw1*dw1/(2.0*c1*c1))/sqrt(2*PI*c1*c1)
|
||||||
|
+ sig2*exp(-dw2*dw2/(2.0*c2*c2))/sqrt(2*PI*c2*c2);
|
||||||
|
}
|
||||||
|
for(i=1;i<=n/2;i++) Sw[i] = (sf/2.0)*sqrt(Hw[i]);
|
||||||
|
for(i=n/2+1;i<=n;i++) Sw[i] = (sf/2.0)*sqrt(Hw[n-i+1]);
|
||||||
|
|
||||||
|
|
||||||
|
/* randomise the phases */
|
||||||
|
for(i=1;i<=n/2-1;i++) ph0[i] = 2.0*PI*ran1(&rseed);
|
||||||
|
ph[1] = 0.0;
|
||||||
|
for(i=1;i<=n/2-1;i++) ph[i+1] = ph0[i];
|
||||||
|
ph[n/2+1] = 0.0;
|
||||||
|
for(i=1;i<=n/2-1;i++) ph[n-i+1] = - ph0[i];
|
||||||
|
|
||||||
|
|
||||||
|
/* make complex spectrum */
|
||||||
|
for(i=1;i<=n;i++) SwC[2*i-1] = Sw[i]*cos(ph[i]);
|
||||||
|
for(i=1;i<=n;i++) SwC[2*i] = Sw[i]*sin(ph[i]);
|
||||||
|
|
||||||
|
/* calculate inverse fft */
|
||||||
|
dfour1(SwC,n,-1);
|
||||||
|
|
||||||
|
/* extract real part */
|
||||||
|
for(i=1;i<=n;i++) rr[i] = (1.0/n)*SwC[2*i-1];
|
||||||
|
|
||||||
|
xstd = stdev(rr,n);
|
||||||
|
ratio = rrstd/xstd;
|
||||||
|
|
||||||
|
for(i=1;i<=n;i++) rr[i] *= ratio;
|
||||||
|
for(i=1;i<=n;i++) rr[i] += rrmean;
|
||||||
|
|
||||||
|
freeVect(w,1,n);
|
||||||
|
freeVect(Hw,1,n);
|
||||||
|
freeVect(Sw,1,n);
|
||||||
|
freeVect(ph0,1,n/2-1);
|
||||||
|
freeVect(ph,1,n);
|
||||||
|
freeVect(SwC,1,2*n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* THE ANGULAR FREQUENCY */
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
double angfreq(double t)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = 1 + (int)floor(t/h);
|
||||||
|
|
||||||
|
return 2.0*PI/rrpc[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* THE EXACT NONLINEAR DERIVATIVES */
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void derivspqrst(double t0,double x[],double dxdt[])
|
||||||
|
{
|
||||||
|
int i,k;
|
||||||
|
double a0,w0,r0,x0,y0,z0;
|
||||||
|
double t,dt,dt2,*xi,*yi,zbase;
|
||||||
|
|
||||||
|
k = 5;
|
||||||
|
xi = mallocVect(1,k);
|
||||||
|
yi = mallocVect(1,k);
|
||||||
|
|
||||||
|
w0 = angfreq(t0);
|
||||||
|
r0 = 1.0; x0 = 0.0; y0 = 0.0; z0 = 0.0;
|
||||||
|
a0 = 1.0 - sqrt((x[1]-x0)*(x[1]-x0) + (x[2]-y0)*(x[2]-y0))/r0;
|
||||||
|
|
||||||
|
for(i=1;i<=k;i++) xi[i] = cos(ti[i]);
|
||||||
|
for(i=1;i<=k;i++) yi[i] = sin(ti[i]);
|
||||||
|
|
||||||
|
zbase = 0.005*sin(2.0*PI*fhi*t0);
|
||||||
|
|
||||||
|
t = atan2(x[2],x[1]);
|
||||||
|
dxdt[1] = a0*(x[1] - x0) - w0*(x[2] - y0);
|
||||||
|
dxdt[2] = a0*(x[2] - y0) + w0*(x[1] - x0);
|
||||||
|
dxdt[3] = 0.0;
|
||||||
|
for(i=1;i<=k;i++)
|
||||||
|
{
|
||||||
|
dt = fmod(t-ti[i],2.0*PI);
|
||||||
|
dt2 = dt*dt;
|
||||||
|
dxdt[3] += -ai[i]*dt*exp(-0.5*dt2/(bi[i]*bi[i]));
|
||||||
|
}
|
||||||
|
dxdt[3] += -1.0*(x[3] - zbase);
|
||||||
|
|
||||||
|
freeVect(xi,1,k);
|
||||||
|
freeVect(yi,1,k);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* RUNGA-KUTTA FOURTH ORDER INTEGRATION */
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void drk4(double y[], int n, double x, double h, double yout[],
|
||||||
|
void (*derivs)(double, double [], double []))
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
double xh,hh,h6,*dydx,*dym,*dyt,*yt;
|
||||||
|
|
||||||
|
dydx=mallocVect(1,n);
|
||||||
|
dym=mallocVect(1,n);
|
||||||
|
dyt=mallocVect(1,n);
|
||||||
|
yt=mallocVect(1,n);
|
||||||
|
|
||||||
|
hh=h*0.5;
|
||||||
|
h6=h/6.0;
|
||||||
|
xh=x+hh;
|
||||||
|
(*derivs)(x,y,dydx);
|
||||||
|
for (i=1;i<=n;i++) yt[i]=y[i]+hh*dydx[i];
|
||||||
|
(*derivs)(xh,yt,dyt);
|
||||||
|
for (i=1;i<=n;i++) yt[i]=y[i]+hh*dyt[i];
|
||||||
|
(*derivs)(xh,yt,dym);
|
||||||
|
for (i=1;i<=n;i++) {
|
||||||
|
yt[i]=y[i]+h*dym[i];
|
||||||
|
dym[i] += dyt[i];
|
||||||
|
}
|
||||||
|
(*derivs)(x+h,yt,dyt);
|
||||||
|
for (i=1;i<=n;i++)
|
||||||
|
yout[i]=y[i]+h6*(dydx[i]+dyt[i]+2.0*dym[i]);
|
||||||
|
|
||||||
|
freeVect(dydx,1,n);
|
||||||
|
freeVect(dym,1,n);
|
||||||
|
freeVect(dyt,1,n);
|
||||||
|
freeVect(yt,1,n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* DETECT PEAKS */
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
double detectpeaks(double *ipeak, double *x, double *y, double *z, int n)
|
||||||
|
{
|
||||||
|
int i,j,j1,j2,jmin,jmax,d;
|
||||||
|
double thetap1,thetap2,thetap3,thetap4,thetap5;
|
||||||
|
double theta1,theta2,d1,d2,zmin,zmax;
|
||||||
|
|
||||||
|
/* use globally defined angles for PQRST */
|
||||||
|
thetap1 = ti[1];
|
||||||
|
thetap2 = ti[2];
|
||||||
|
thetap3 = ti[3];
|
||||||
|
thetap4 = ti[4];
|
||||||
|
thetap5 = ti[5];
|
||||||
|
|
||||||
|
for(i=1;i<=n;i++) ipeak[i] = 0.0;
|
||||||
|
theta1 = atan2(y[1],x[1]);
|
||||||
|
for(i=1;i<n;i++)
|
||||||
|
{
|
||||||
|
theta2 = atan2(y[i+1],x[i+1]);
|
||||||
|
if( (theta1 <= thetap1) && (thetap1 <= theta2) )
|
||||||
|
{
|
||||||
|
d1 = thetap1 - theta1;
|
||||||
|
d2 = theta2 - thetap1;
|
||||||
|
if(d1 < d2) ipeak[i] = 1.0;
|
||||||
|
else ipeak[i+1] = 1.0;
|
||||||
|
}
|
||||||
|
else if( (theta1 <= thetap2) && (thetap2 <= theta2) )
|
||||||
|
{
|
||||||
|
d1 = thetap2 - theta1;
|
||||||
|
d2 = theta2 - thetap2;
|
||||||
|
if(d1 < d2) ipeak[i] = 2.0;
|
||||||
|
else ipeak[i+1] = 2.0;
|
||||||
|
}
|
||||||
|
else if( (theta1 <= thetap3) && (thetap3 <= theta2) )
|
||||||
|
{
|
||||||
|
d1 = thetap3 - theta1;
|
||||||
|
d2 = theta2 - thetap3;
|
||||||
|
if(d1 < d2) ipeak[i] = 3.0;
|
||||||
|
else ipeak[i+1] = 3.0;
|
||||||
|
}
|
||||||
|
else if( (theta1 <= thetap4) && (thetap4 <= theta2) )
|
||||||
|
{
|
||||||
|
d1 = thetap4 - theta1;
|
||||||
|
d2 = theta2 - thetap4;
|
||||||
|
if(d1 < d2) ipeak[i] = 4.0;
|
||||||
|
else ipeak[i+1] = 4.0;
|
||||||
|
}
|
||||||
|
else if( (theta1 <= thetap5) && (thetap5 <= theta2) )
|
||||||
|
{
|
||||||
|
d1 = thetap5 - theta1;
|
||||||
|
d2 = theta2 - thetap5;
|
||||||
|
if(d1 < d2) ipeak[i] = 5.0;
|
||||||
|
else ipeak[i+1] = 5.0;
|
||||||
|
}
|
||||||
|
theta1 = theta2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* correct the peaks */
|
||||||
|
d = (int)ceil(sfecg/64);
|
||||||
|
for(i=1;i<=n;i++)
|
||||||
|
{
|
||||||
|
if( ipeak[i]==1 || ipeak[i]==3 || ipeak[i]==5 )
|
||||||
|
{
|
||||||
|
j1 = MAX(1,i-d);
|
||||||
|
j2 = MIN(n,i+d);
|
||||||
|
jmax = j1;
|
||||||
|
zmax = z[j1];
|
||||||
|
for(j=j1+1;j<=j2;j++)
|
||||||
|
{
|
||||||
|
if(z[j] > zmax)
|
||||||
|
{
|
||||||
|
jmax = j;
|
||||||
|
zmax = z[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(jmax != i)
|
||||||
|
{
|
||||||
|
ipeak[jmax] = ipeak[i];
|
||||||
|
ipeak[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( ipeak[i]==2 || ipeak[i]==4 )
|
||||||
|
{
|
||||||
|
j1 = MAX(1,i-d);
|
||||||
|
j2 = MIN(n,i+d);
|
||||||
|
jmin = j1;
|
||||||
|
zmin = z[j1];
|
||||||
|
for(j=j1+1;j<=j2;j++)
|
||||||
|
{
|
||||||
|
if(z[j] < zmin)
|
||||||
|
{
|
||||||
|
jmin = j;
|
||||||
|
zmin = z[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(jmin != i)
|
||||||
|
{
|
||||||
|
ipeak[jmin] = ipeak[i];
|
||||||
|
ipeak[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* MAIN PROGRAM */
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
main(argc,argv)
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
{
|
||||||
|
|
||||||
|
/* First step is to register the options */
|
||||||
|
|
||||||
|
optregister(outfile,CSTRING,'O',"Name of output data file");
|
||||||
|
optregister(N,INT,'n',"Approximate number of heart beats");
|
||||||
|
optregister(sfecg,INT,'s',"ECG sampling frequency [Hz]");
|
||||||
|
optregister(sf,INT,'S',"Internal Sampling frequency [Hz]");
|
||||||
|
optregister(Anoise,DOUBLE,'a',"Amplitude of additive uniform noise [mV]");
|
||||||
|
optregister(hrmean,DOUBLE,'h',"Heart rate mean [bpm]");
|
||||||
|
optregister(hrstd,DOUBLE,'H',"Heart rate standard deviation [bpm]");
|
||||||
|
optregister(flo,DOUBLE,'f',"Low frequency [Hz]");
|
||||||
|
optregister(fhi,DOUBLE,'F',"High frequency [Hz]");
|
||||||
|
optregister(flostd,DOUBLE,'v',"Low frequency standard deviation [Hz]");
|
||||||
|
optregister(fhistd,DOUBLE,'V',"High frequency standard deviation [Hz]");
|
||||||
|
optregister(lfhfratio,DOUBLE,'q',"LF/HF ratio");
|
||||||
|
optregister(seed,INT,'R',"Seed");
|
||||||
|
opt_title_set("ECGSYN: A program for generating a realistic synthetic ECG\n"
|
||||||
|
"Copyright (c) 2003 by Patrick McSharry & Gari Clifford. All rights reserved.\n");
|
||||||
|
|
||||||
|
getopts(argc,argv);
|
||||||
|
|
||||||
|
dorun();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* DORUN PART OF PROGRAM */
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int dorun()
|
||||||
|
{
|
||||||
|
int i,j,k,q,Nrr,Nt,Nts;
|
||||||
|
double *x,tstep,tecg,rrmean,qd,hrfact,hrfact2;
|
||||||
|
double *xt,*yt,*zt,*xts,*yts,*zts;
|
||||||
|
double timev,*ipeak,zmin,zmax,zrange;
|
||||||
|
FILE *fp;
|
||||||
|
void (*derivs)(double, double [], double []);
|
||||||
|
|
||||||
|
/* perform some checks on input values */
|
||||||
|
q = (int)rint(sf/sfecg);
|
||||||
|
qd = (double)sf/(double)sfecg;
|
||||||
|
if(q != qd) {
|
||||||
|
printf("Internal sampling frequency must be an integer multiple of the \n");
|
||||||
|
printf("ECG sampling frequency!\n");
|
||||||
|
printf("Your current choices are:\n");
|
||||||
|
printf("ECG sampling frequency: %d Hertz\n",sfecg);
|
||||||
|
printf("Internal sampling frequency: %d Hertz\n",sf);
|
||||||
|
exit(1);}
|
||||||
|
|
||||||
|
|
||||||
|
/* declare and initialise the state vector */
|
||||||
|
x=mallocVect(1,mstate);
|
||||||
|
x[1] = xinitial;
|
||||||
|
x[2] = yinitial;
|
||||||
|
x[3] = zinitial;
|
||||||
|
|
||||||
|
/* declare and define the ECG morphology vectors (PQRST extrema parameters) */
|
||||||
|
ti=mallocVect(1,5);
|
||||||
|
ai=mallocVect(1,5);
|
||||||
|
bi=mallocVect(1,5);
|
||||||
|
/* P Q R S T */
|
||||||
|
ti[1]=-60.0; ti[2]=-15.0; ti[3]=0.0; ti[4]=15.0; ti[5]=90.0;
|
||||||
|
ai[1]=1.2; ai[2]=-5.0; ai[3]=30.0; ai[4]=-7.5; ai[5]=0.75;
|
||||||
|
bi[1]=0.25; bi[2]=0.1; bi[3]=0.1; bi[4]=0.1; bi[5]=0.4;
|
||||||
|
|
||||||
|
/* convert angles from degrees to radians */
|
||||||
|
for(i=1;i<=5;i++) ti[i] *= PI/180.0;
|
||||||
|
|
||||||
|
/* adjust extrema parameters for mean heart rate */
|
||||||
|
hrfact = sqrt(hrmean/60.0);
|
||||||
|
hrfact2 = sqrt(hrfact);
|
||||||
|
for(i=1;i<=5;i++) bi[i] *= hrfact;
|
||||||
|
ti[1]*=hrfact2; ti[2]*=hrfact; ti[3]*=1.0; ti[4]*=hrfact; ti[5]*=1.0;
|
||||||
|
|
||||||
|
|
||||||
|
/* calculate time scales */
|
||||||
|
h = 1.0/sf;
|
||||||
|
tstep = 1.0/sfecg;
|
||||||
|
|
||||||
|
printf("ECGSYN: A program for generating a realistic synthetic ECG\n"
|
||||||
|
"Copyright (c) 2003 by Patrick McSharry & Gari Clifford. All rights reserved.\n"
|
||||||
|
"See IEEE Transactions On Biomedical Engineering, 50(3), 289-294, March 2003.\n"
|
||||||
|
"Contact P. McSharry (patrick@mcsharry.net) or G. Clifford (gari@mit.edu)\n");
|
||||||
|
|
||||||
|
printf("Approximate number of heart beats: %d\n",N);
|
||||||
|
printf("ECG sampling frequency: %d Hertz\n",sfecg);
|
||||||
|
printf("Internal sampling frequency: %d Hertz\n",sf);
|
||||||
|
printf("Amplitude of additive uniformly distributed noise: %g mV\n",Anoise);
|
||||||
|
printf("Heart rate mean: %g beats per minute\n",hrmean);
|
||||||
|
printf("Heart rate std: %g beats per minute\n",hrstd);
|
||||||
|
printf("Low frequency: %g Hertz\n",flo);
|
||||||
|
printf("High frequency std: %g Hertz\n",fhistd);
|
||||||
|
printf("Low frequency std: %g Hertz\n",flostd);
|
||||||
|
printf("High frequency: %g Hertz\n",fhi);
|
||||||
|
printf("LF/HF ratio: %g\n",lfhfratio);
|
||||||
|
|
||||||
|
/* initialise seed */
|
||||||
|
rseed = -seed;
|
||||||
|
|
||||||
|
|
||||||
|
/* select the derivs to use */
|
||||||
|
derivs = derivspqrst;
|
||||||
|
|
||||||
|
/* calculate length of RR time series */
|
||||||
|
rrmean = (60/hrmean);
|
||||||
|
Nrr = (int)pow(2.0, ceil(log10(N*rrmean*sf)/log10(2.0)));
|
||||||
|
printf("Using %d = 2^%d samples for calculating RR intervals\n",
|
||||||
|
Nrr,(int)(log10(1.0*Nrr)/log10(2.0)));
|
||||||
|
|
||||||
|
|
||||||
|
/* create rrprocess with required spectrum */
|
||||||
|
rr = mallocVect(1,Nrr);
|
||||||
|
rrprocess(rr, flo, fhi, flostd, fhistd, lfhfratio, hrmean, hrstd, sf, Nrr);
|
||||||
|
vecfile("rr.dat",rr,Nrr);
|
||||||
|
|
||||||
|
/* create piecewise constant rr */
|
||||||
|
rrpc = mallocVect(1,2*Nrr);
|
||||||
|
tecg = 0.0;
|
||||||
|
i = 1;
|
||||||
|
j = 1;
|
||||||
|
while(i <= Nrr)
|
||||||
|
{
|
||||||
|
tecg += rr[j];
|
||||||
|
j = (int)rint(tecg/h);
|
||||||
|
for(k=i;k<=j;k++) rrpc[k] = rr[i];
|
||||||
|
i = j+1;
|
||||||
|
}
|
||||||
|
Nt = j;
|
||||||
|
vecfile("rrpc.dat",rrpc,Nt);
|
||||||
|
|
||||||
|
printf("Printing ECG signal to file: %s\n",outfile);
|
||||||
|
|
||||||
|
/* integrate dynamical system using fourth order Runge-Kutta*/
|
||||||
|
xt = mallocVect(1,Nt);
|
||||||
|
yt = mallocVect(1,Nt);
|
||||||
|
zt = mallocVect(1,Nt);
|
||||||
|
|
||||||
|
timev = 0.0;
|
||||||
|
for(i=1;i<=Nt;i++)
|
||||||
|
{
|
||||||
|
xt[i] = x[1];
|
||||||
|
yt[i] = x[2];
|
||||||
|
zt[i] = x[3];
|
||||||
|
drk4(x, mstate, timev, h, x, derivs);
|
||||||
|
timev += h;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* downsample to ECG sampling frequency */
|
||||||
|
xts = mallocVect(1,Nt);
|
||||||
|
yts = mallocVect(1,Nt);
|
||||||
|
zts = mallocVect(1,Nt);
|
||||||
|
|
||||||
|
j=0;
|
||||||
|
for(i=1;i<=Nt;i+=q)
|
||||||
|
{
|
||||||
|
j++;
|
||||||
|
xts[j] = xt[i];
|
||||||
|
yts[j] = yt[i];
|
||||||
|
zts[j] = zt[i];
|
||||||
|
}
|
||||||
|
Nts = j;
|
||||||
|
|
||||||
|
|
||||||
|
/* do peak detection using angle */
|
||||||
|
ipeak = mallocVect(1,Nts);
|
||||||
|
detectpeaks(ipeak, xts, yts, zts, Nts);
|
||||||
|
|
||||||
|
/* scale signal to lie between -0.4 and 1.2 mV */
|
||||||
|
zmin = zts[1];
|
||||||
|
zmax = zts[1];
|
||||||
|
for(i=2;i<=Nts;i++)
|
||||||
|
{
|
||||||
|
if(zts[i] < zmin) zmin = zts[i];
|
||||||
|
else if(zts[i] > zmax) zmax = zts[i];
|
||||||
|
}
|
||||||
|
zrange = zmax-zmin;
|
||||||
|
for(i=1;i<=Nts;i++) zts[i] = (zts[i]-zmin)*(1.6)/zrange - 0.4;
|
||||||
|
|
||||||
|
/* include additive uniformly distributed measurement noise */
|
||||||
|
for(i=1;i<=Nts;i++) zts[i] += Anoise*(2.0*ran1(&rseed) - 1.0);
|
||||||
|
|
||||||
|
/* output ECG file */
|
||||||
|
fp = fopen(outfile,"w");
|
||||||
|
for(i=1;i<=Nts;i++) fprintf(fp,"%f %f %d\n",(i-1)*tstep,zts[i],(int)ipeak[i]);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
|
||||||
|
printf("Finished ECG output\n");
|
||||||
|
|
||||||
|
freeVect(x,1,mstate);
|
||||||
|
freeVect(rr,1,Nrr);
|
||||||
|
freeVect(rrpc,1,2*Nrr);
|
||||||
|
freeVect(ti,1,5);
|
||||||
|
freeVect(ai,1,5);
|
||||||
|
freeVect(bi,1,5);
|
||||||
|
freeVect(xt,1,Nt);
|
||||||
|
freeVect(yt,1,Nt);
|
||||||
|
freeVect(zt,1,Nt);
|
||||||
|
freeVect(xts,1,Nt);
|
||||||
|
freeVect(yts,1,Nt);
|
||||||
|
freeVect(zts,1,Nt);
|
||||||
|
freeVect(ipeak,1,Nts);
|
||||||
|
|
||||||
|
/* END OF DORUN */
|
||||||
|
}
|
||||||
|
|
||||||
11
ecgsyn-1.0.0/C/src/index.html
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<html>
|
||||||
|
<head><title>Index of /static/published-projects/ecgsyn/1.0.0/C/src/</title></head>
|
||||||
|
<body>
|
||||||
|
<h1>Index of /static/published-projects/ecgsyn/1.0.0/C/src/</h1><hr><pre><a href="../">../</a>
|
||||||
|
<a href="00README">00README</a> 12-Apr-2019 17:35 4672
|
||||||
|
<a href="Makefile">Makefile</a> 12-Apr-2019 17:35 426
|
||||||
|
<a href="ecgsyn.c">ecgsyn.c</a> 12-Apr-2019 17:35 20586
|
||||||
|
<a href="opt.c">opt.c</a> 12-Apr-2019 17:35 56582
|
||||||
|
<a href="opt.h">opt.h</a> 12-Apr-2019 17:35 5237
|
||||||
|
</pre><hr></body>
|
||||||
|
</html>
|
||||||
2581
ecgsyn-1.0.0/C/src/opt.c
Normal file
159
ecgsyn-1.0.0/C/src/opt.h
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
opt.h version 3.17 - User Include File for options package.
|
||||||
|
|
||||||
|
OPT is a subroutine library which facilitates the convenient
|
||||||
|
input of parameters to a C or C++ program. Parameters are parsed
|
||||||
|
from a command line, with further facilities for reading options
|
||||||
|
from files, from environment strings, or from an interactive
|
||||||
|
environment. The aim of the opt package is to permit programs to
|
||||||
|
be both user- and programmer- friendly. The package attempts to
|
||||||
|
on the one hand provide a direct and relatively full-featured
|
||||||
|
input interface to the ultimate user of the program, and at the
|
||||||
|
same time impose a minimal amount of work on the programmer to
|
||||||
|
"attach" the package to his or her software. A texinfo file is
|
||||||
|
part of the distribution; or you can view the html documentation at:
|
||||||
|
http://nis-www.lanl.gov/~jt/Software/opt/opt_toc.html
|
||||||
|
|
||||||
|
Download the lastest version of the source code from:
|
||||||
|
http://nis-www.lanl.gov/~jt/Software/
|
||||||
|
|
||||||
|
opt is available to the public under the GNU General Public License:
|
||||||
|
http://www.gnu.org/copyleft/gpl.html
|
||||||
|
|
||||||
|
This SOFTWARE has been authored by an employee of the University of
|
||||||
|
California, operator of the Los Alamos National Laboratory under
|
||||||
|
Contract No. W-7405-ENG-36 with the U.S. Department of Energy. The
|
||||||
|
U.S. Government has rights to use, reproduce, and distribute this
|
||||||
|
SOFTWARE. The public may copy, distribute, prepare derivative works
|
||||||
|
and publicly display this SOFTWARE without charge, provided that this
|
||||||
|
Notice and any statement of authorship are reproduced on all
|
||||||
|
copies. Neither the Government nor the University makes any warranty,
|
||||||
|
express or implied, or assumes any liability or responsibility for the
|
||||||
|
use of this SOFTWARE. If SOFTWARE is modified to produce derivative
|
||||||
|
works, such modified SOFTWARE should be clearly marked, so as not to
|
||||||
|
confuse it with the version available from LANL.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _OPT_H
|
||||||
|
#define _OPT_H /* Signal that this header file has been included */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are delimiter characters
|
||||||
|
*/
|
||||||
|
#define DELIM '-' /* option delimiter character */
|
||||||
|
#define ALTDELIM '/' /* alternate delimiter character */
|
||||||
|
#define OPTFROMFILE '@' /* denotes options are in a file */
|
||||||
|
#define OPTTOFILE '%' /* says to put options in a file */
|
||||||
|
#define DOCUMENT '-' /* write document to file */
|
||||||
|
#define INTERACT '$' /* Flags interactive menu */
|
||||||
|
#define HELPCH '?' /* Help character */
|
||||||
|
/*
|
||||||
|
* These are not available on command line
|
||||||
|
* But may be invoked from a file
|
||||||
|
*/
|
||||||
|
#define IGNOREEOL ';' /* Ignore until the end of line */
|
||||||
|
#define RUN '=' /* Says to just run to completion */
|
||||||
|
#define QUITCH '.' /* Quit character */
|
||||||
|
/*
|
||||||
|
* These are not available on command line or from a file
|
||||||
|
* But may be invoked from the menu
|
||||||
|
*/
|
||||||
|
#define BANG '!' /* Shell escape character */
|
||||||
|
#define ADDITIONAL_OPTS '+' /* Additional options */
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
INT, UNSINT, LONG, CHAR,
|
||||||
|
INTLEVEL,
|
||||||
|
FLOAT, DOUBLE,
|
||||||
|
FLAG, NEGFLAG, ABSFLAG, ABSNEGFLAG,
|
||||||
|
VSTRING, CSTRING, UNDELIMV, UNDELIMC
|
||||||
|
}
|
||||||
|
opt_TYPE;
|
||||||
|
|
||||||
|
|
||||||
|
typedef int (*PFI)();
|
||||||
|
|
||||||
|
#define OPT_EXT ".opt" /* standard options file extension */
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ARGCHECK
|
||||||
|
#ifdef __TURBOC__
|
||||||
|
#define ARGCHECK
|
||||||
|
#endif /* __TURBOC__ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define ARGCHECK
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* ARGCHECK */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ARGCHECK
|
||||||
|
extern int opt_register(char *,opt_TYPE,char,char *);
|
||||||
|
extern void opt_usage_set(char *);
|
||||||
|
extern void opt_title_set(char *);
|
||||||
|
extern void opt_verify_set(PFI);
|
||||||
|
extern void opt_doc_set(PFI);
|
||||||
|
extern void opt_quit_set(PFI);
|
||||||
|
extern void opt_run_set(PFI);
|
||||||
|
extern void opt_help_setf(PFI);
|
||||||
|
extern void opt_help_set(char,char *);
|
||||||
|
extern void opt_ufilter_set(PFI);
|
||||||
|
extern void opt_dfilter_set(PFI);
|
||||||
|
extern void opt_env_set(char *);
|
||||||
|
extern void opt_default_set(char *);
|
||||||
|
#if DISABLE_VARARGS
|
||||||
|
extern void opt_errmess(char *);
|
||||||
|
extern void opt_message(char *);
|
||||||
|
extern void opt_warning(char *);
|
||||||
|
extern void opt_fatal(char *);
|
||||||
|
#else
|
||||||
|
extern void opt_errmess();
|
||||||
|
extern void opt_message();
|
||||||
|
extern void opt_warning();
|
||||||
|
extern void opt_fatal();
|
||||||
|
#endif /* DISABLE_VARARGS */
|
||||||
|
extern void opt_abort_run(void);
|
||||||
|
extern int opt_begin_run(PFI);
|
||||||
|
extern int getopts(int,char **);
|
||||||
|
#else
|
||||||
|
extern int opt_register();
|
||||||
|
extern void opt_usage_set();
|
||||||
|
extern void opt_title_set();
|
||||||
|
extern void opt_verify_set();
|
||||||
|
extern void opt_doc_set();
|
||||||
|
extern void opt_quit_set();
|
||||||
|
extern void opt_run_set();
|
||||||
|
extern void opt_help_setf();
|
||||||
|
extern void opt_help_set();
|
||||||
|
extern void opt_help_set();
|
||||||
|
extern void opt_ufilter_set();
|
||||||
|
extern void opt_dfilter_set();
|
||||||
|
extern void opt_env_set();
|
||||||
|
extern void opt_default_set();
|
||||||
|
|
||||||
|
extern void opt_errmess();
|
||||||
|
extern void opt_message();
|
||||||
|
extern void opt_warning();
|
||||||
|
extern void opt_fatal();
|
||||||
|
|
||||||
|
extern void opt_abort_run();
|
||||||
|
extern int opt_begin_run();
|
||||||
|
extern int getopts();
|
||||||
|
|
||||||
|
#endif /* ARGCHECK */
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************
|
||||||
|
* Macro's for registering options
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define optregister(val,typ,c,str) opt_register((char *)&val,typ,c,str)
|
||||||
|
#define optrunset(r) {int r(); opt_run_set( r );}
|
||||||
|
|
||||||
|
#endif /* _OPT_H */
|
||||||
14
ecgsyn-1.0.0/C/windows/HEADER.shtml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<!--#set var="TITLE" value="ECGSYN for Windows"-->
|
||||||
|
<!--#include virtual="/head.shtml"-->
|
||||||
|
|
||||||
|
<p>
|
||||||
|
There are two versions of the <code>ecgsyn.exe</code> executable in this directory. Using the
|
||||||
|
<a href="../src/">ECGSYN source files</a>, the first version was compiled with <code>Cygwin64 2.6.0 gcc 5.4.0</code>,
|
||||||
|
and the second version with <code>MinGW-w64 gcc 4.9.2</code>, both under Windows 10.</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
To run the Cygwin executable, you will need to have the Cygwin DLLs installed in your PATH in
|
||||||
|
order to run this program successfully. The simplest and most reliable
|
||||||
|
way to do this is to install the <a href="http://www.cygwin.com/" target="other">Cygwin development toolkit</a>.
|
||||||
|
To run the MinGW executable, you should install <a href="https://sourceforge.net/projects/mingw-w64/" target="other">MinGW-w64</a>.
|
||||||
|
</p>
|
||||||
BIN
ecgsyn-1.0.0/C/windows/cygwin_ecgsyn.zip
Normal file
10
ecgsyn-1.0.0/C/windows/index.html
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<html>
|
||||||
|
<head><title>Index of /static/published-projects/ecgsyn/1.0.0/C/windows/</title></head>
|
||||||
|
<body>
|
||||||
|
<h1>Index of /static/published-projects/ecgsyn/1.0.0/C/windows/</h1><hr><pre><a href="../">../</a>
|
||||||
|
<a href="HEADER.shtml">HEADER.shtml</a> 12-Apr-2019 17:35 821
|
||||||
|
<a href="HEADER.shtml~">HEADER.shtml~</a> 12-Apr-2019 17:35 647
|
||||||
|
<a href="cygwin_ecgsyn.zip">cygwin_ecgsyn.zip</a> 12-Apr-2019 17:35 35146
|
||||||
|
<a href="mingw_ecgsyn.zip">mingw_ecgsyn.zip</a> 12-Apr-2019 17:35 34966
|
||||||
|
</pre><hr></body>
|
||||||
|
</html>
|
||||||
BIN
ecgsyn-1.0.0/C/windows/mingw_ecgsyn.zip
Normal file
BIN
ecgsyn-1.0.0/Java/FormatNumber.class
Normal file
21
ecgsyn-1.0.0/Java/HEADER.shtml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<!--#set var="TITLE" value="ECGSYN implemented in Java"-->
|
||||||
|
<!--#include virtual="/head.shtml"-->
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This directory contains Mauricio Villarroel's implementation of
|
||||||
|
<a href="../">ECGSYN</a> as a Java applet.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
To run the applet in your web browser, click
|
||||||
|
<a href="ecgsyn-java.html">here</a>.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The individual Java files can be downloaded by following the links
|
||||||
|
below, or you may download all of them, together with the C and Matlab
|
||||||
|
implementations of ECGSYN, as a single gzip-compressed tar archive, <a
|
||||||
|
href="../ecgsyn.tar.gz"><tt>ecgsyn.tar.gz</tt></a>. (See <a
|
||||||
|
href="/faq.shtml#tar-gz">How can I unpack a .tar.gz archive?</a> if
|
||||||
|
you need help doing this.)
|
||||||
|
|
||||||
|
<hr>
|
||||||
1200
ecgsyn-1.0.0/Java/ecgApplet.form
Normal file
64
ecgsyn-1.0.0/Java/ecgApplet.html
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<TITLE>ECGSYN Java Application</TITLE>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"></HEAD>
|
||||||
|
<BODY bgcolor="#003366" text="#FFFFCC" link="#FFFF33" vlink="#FFCC00" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0">
|
||||||
|
<table width="925" border="0" align="center" cellpadding="0" cellspacing="5">
|
||||||
|
<tr>
|
||||||
|
<td height="50" colspan="2">
|
||||||
|
<H3>
|
||||||
|
<HR WIDTH="100%">
|
||||||
|
</H3>
|
||||||
|
<H3 align="center"><font color="#FF9900">JAVA Application for <br>
|
||||||
|
ECGSYN: A Dynamical Model for Generating
|
||||||
|
Synthetic Electrocardiogram Signals
|
||||||
|
</font></H3>
|
||||||
|
<H3>
|
||||||
|
<HR WIDTH="100%">
|
||||||
|
</H3>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="300" align="left" valign="top"><p><strong>ECGSYN</strong>:</p>
|
||||||
|
<p><strong>©</strong> ECGSYN Copyright by Patrick E. McSharry and Gari
|
||||||
|
D. Clifford. <br>
|
||||||
|
© Java code copyright by Mauricio Villarroel.<br>
|
||||||
|
<br>
|
||||||
|
For the Mathematical Model, see:</p>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="5">
|
||||||
|
<tr>
|
||||||
|
<td align="left" valign="top">IEEE Transactions On Biomedical Engineering,
|
||||||
|
50(3), 289-294, March 2003</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<p> Contact: </p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="mailto:patrick@mcsharry.net">Patrck McSharry</a></li>
|
||||||
|
<li><a href="mailto:gari@mit.edu">Gari Clifford</a></li>
|
||||||
|
<li><a href="mailto:mauricio.villarroel@estudiantes.ucb.edu.bo">Mauricio Villarroel</a></li>
|
||||||
|
</ul>
|
||||||
|
<p>Please read the <a href="ecgLicense.txt">Software License</a>.
|
||||||
|
</p></td>
|
||||||
|
<td align="center" valign="middle">ECG Ouput Sample image:<br><p><img src="ecgplot.PNG" alt="ECGSYN-Java Output Sample image" width="580" height="330" border="1"></p>
|
||||||
|
<p>Source code: <a href="ecgApplet.tar.gz">ecgApplet.tar.gz</a></p></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="50"> </td>
|
||||||
|
<td height="50" align="center" valign="middle"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2" align="center" valign="top"><strong><font size="4">You can
|
||||||
|
test the ECGSYN Java Application:</font></strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2" align="center" valign="top"><applet name= "ecgApplet" code="ecgApplet.class" width=915 height=570>
|
||||||
|
</applet></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<H3> </H3>
|
||||||
|
<P> </P>
|
||||||
|
<HR WIDTH="100%"><FONT SIZE=-1><I>ECGSYN Java Application<br>
|
||||||
|
Last updated on October 27, 2003</I></FONT>
|
||||||
|
<p align="justify">Return to ECGSYN <a href="http://www.maths.ox.ac.uk/~mcsharry/ecgsyn">Home page</a>.</p>
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
||||||
2623
ecgsyn-1.0.0/Java/ecgApplet.java
Normal file
39
ecgsyn-1.0.0/Java/ecgLicense.txt
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* ECGSYN Java Application */
|
||||||
|
/* */
|
||||||
|
/* Copyright (C) 2003 Mauricio Villarroel */
|
||||||
|
/* (mauricio DOT villarroel AT estudiantes DOT ucb DOT edu DOT bo) */
|
||||||
|
/* */
|
||||||
|
/* ecgApplet.java and all its components are free software; you can */
|
||||||
|
/* redistribute them and/or modify it under the terms of the */
|
||||||
|
/* GNU General Public License as published by the Free Software */
|
||||||
|
/* Foundation; either version 2 of the License, or (at your option) */
|
||||||
|
/* any later version. */
|
||||||
|
/* */
|
||||||
|
/* This file is distributed in the hope that it will be useful, but */
|
||||||
|
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||||
|
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */
|
||||||
|
/* See the GNU General Public License for more details. */
|
||||||
|
/* */
|
||||||
|
/************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* This file was created for the ECGSYN Application. */
|
||||||
|
/* */
|
||||||
|
/* ECGSYN: A program for generating a realistic synthetic */
|
||||||
|
/* Electrocardiogram Signals. */
|
||||||
|
/* Copyright (c) 2003 by Patrick McSharry & Gari Clifford. */
|
||||||
|
/* All rights reserved. */
|
||||||
|
/* */
|
||||||
|
/* See IEEE Transactions On Biomedical Engineering, */
|
||||||
|
/* 50(3), 289-294, March 2003. */
|
||||||
|
/* Contact: */
|
||||||
|
/* P. McSharry (patrick AT mcsharry DOT net) */
|
||||||
|
/* G. Clifford (gari AT mit DOT edu) */
|
||||||
|
/* */
|
||||||
|
/************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* Further updates to this software will be published on: */
|
||||||
|
/* http://www.physionet.org/ */
|
||||||
|
/* */
|
||||||
|
/************************************************************************/
|
||||||
BIN
ecgsyn-1.0.0/Java/ecgplot.PNG
Normal file
|
After Width: | Height: | Size: 10 KiB |
64
ecgsyn-1.0.0/Java/ecgsyn-java.html
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<TITLE>ECGSYN Java Application</TITLE>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"></HEAD>
|
||||||
|
<BODY bgcolor="#003366" text="#FFFFCC" link="#FFFF33" vlink="#FFCC00" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0">
|
||||||
|
<table width="925" border="0" align="center" cellpadding="0" cellspacing="5">
|
||||||
|
<tr>
|
||||||
|
<td height="50" colspan="2">
|
||||||
|
<H3>
|
||||||
|
<HR WIDTH="100%">
|
||||||
|
</H3>
|
||||||
|
<H3 align="center"><font color="#FF9900">JAVA Application for <br>
|
||||||
|
ECGSYN: A Dynamical Model for Generating
|
||||||
|
Synthetic Electrocardiogram Signals
|
||||||
|
</font></H3>
|
||||||
|
<H3>
|
||||||
|
<HR WIDTH="100%">
|
||||||
|
</H3>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="300" align="left" valign="top"><p><strong>ECGSYN</strong>:</p>
|
||||||
|
<p><strong>©</strong> ECGSYN Copyright by Patrick E. McSharry and Gari
|
||||||
|
D. Clifford. <br>
|
||||||
|
© Java code copyright by Mauricio Villarroel.<br>
|
||||||
|
<br>
|
||||||
|
For the Mathematical Model, see:</p>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="5">
|
||||||
|
<tr>
|
||||||
|
<td align="left" valign="top">IEEE Transactions On Biomedical Engineering,
|
||||||
|
50(3), 289-294, March 2003</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<p> Contact: </p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="mailto:patrick@mcsharry.net">Patrck McSharry</a></li>
|
||||||
|
<li><a href="mailto:gari@mit.edu">Gari Clifford</a></li>
|
||||||
|
<li><a href="mailto:mauricio.villarroel@estudiantes.ucb.edu.bo">Mauricio Villarroel</a></li>
|
||||||
|
</ul>
|
||||||
|
<p>Please read the <a href="ecgLicense.txt">Software License</a>.
|
||||||
|
</p></td>
|
||||||
|
<td align="center" valign="middle">ECG Ouput Sample image:<br><p><img src="ecgplot.PNG" alt="ECGSYN-Java Output Sample image" width="580" height="330" border="1"></p>
|
||||||
|
<p>Source code: <a href="../ecgsyn.tar.gz">ecgsyn.tar.gz</a></p></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="50"> </td>
|
||||||
|
<td height="50" align="center" valign="middle"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2" align="center" valign="top"><strong><font size="4">You can
|
||||||
|
test the ECGSYN Java Application:</font></strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2" align="center" valign="top"><applet name= "ecgApplet" code="ecgApplet.class" width=915 height=570>
|
||||||
|
</applet></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<H3> </H3>
|
||||||
|
<P> </P>
|
||||||
|
<HR WIDTH="100%"><FONT SIZE=-1><I>ECGSYN Java Application<br>
|
||||||
|
Last updated on October 27, 2003</I></FONT>
|
||||||
|
<p align="justify">Return to ECGSYN <a href="../">Home page</a>.</p>
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
||||||
40
ecgsyn-1.0.0/Java/index.html
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<html>
|
||||||
|
<head><title>Index of /static/published-projects/ecgsyn/1.0.0/Java/</title></head>
|
||||||
|
<body>
|
||||||
|
<h1>Index of /static/published-projects/ecgsyn/1.0.0/Java/</h1><hr><pre><a href="../">../</a>
|
||||||
|
<a href="FormatNumber.class">FormatNumber.class</a> 12-Apr-2019 17:35 1020
|
||||||
|
<a href="HEADER.shtml">HEADER.shtml</a> 12-Apr-2019 17:35 673
|
||||||
|
<a href="ecgApplet%241.class">ecgApplet$1.class</a> 12-Apr-2019 17:35 989
|
||||||
|
<a href="ecgApplet%2410.class">ecgApplet$10.class</a> 12-Apr-2019 17:35 671
|
||||||
|
<a href="ecgApplet%2411.class">ecgApplet$11.class</a> 12-Apr-2019 17:35 671
|
||||||
|
<a href="ecgApplet%2412.class">ecgApplet$12.class</a> 12-Apr-2019 17:35 671
|
||||||
|
<a href="ecgApplet%2413.class">ecgApplet$13.class</a> 12-Apr-2019 17:35 671
|
||||||
|
<a href="ecgApplet%2414.class">ecgApplet$14.class</a> 12-Apr-2019 17:35 671
|
||||||
|
<a href="ecgApplet%2415.class">ecgApplet$15.class</a> 12-Apr-2019 17:35 671
|
||||||
|
<a href="ecgApplet%2416.class">ecgApplet$16.class</a> 12-Apr-2019 17:35 672
|
||||||
|
<a href="ecgApplet%2417.class">ecgApplet$17.class</a> 12-Apr-2019 17:35 672
|
||||||
|
<a href="ecgApplet%2418.class">ecgApplet$18.class</a> 12-Apr-2019 17:35 672
|
||||||
|
<a href="ecgApplet%242.class">ecgApplet$2.class</a> 12-Apr-2019 17:35 669
|
||||||
|
<a href="ecgApplet%243.class">ecgApplet$3.class</a> 12-Apr-2019 17:35 669
|
||||||
|
<a href="ecgApplet%244.class">ecgApplet$4.class</a> 12-Apr-2019 17:35 669
|
||||||
|
<a href="ecgApplet%245.class">ecgApplet$5.class</a> 12-Apr-2019 17:35 941
|
||||||
|
<a href="ecgApplet%246.class">ecgApplet$6.class</a> 12-Apr-2019 17:35 941
|
||||||
|
<a href="ecgApplet%247.class">ecgApplet$7.class</a> 12-Apr-2019 17:35 941
|
||||||
|
<a href="ecgApplet%248.class">ecgApplet$8.class</a> 12-Apr-2019 17:35 1108
|
||||||
|
<a href="ecgApplet%249.class">ecgApplet$9.class</a> 12-Apr-2019 17:35 669
|
||||||
|
<a href="ecgApplet%24ECGAnimate.class">ecgApplet$ECGAnimate.class</a> 12-Apr-2019 17:35 2716
|
||||||
|
<a href="ecgApplet%24doubleVerifier.class">ecgApplet$doubleVerifier.class</a> 12-Apr-2019 17:35 1485
|
||||||
|
<a href="ecgApplet%24ecgCalc.class">ecgApplet$ecgCalc.class</a> 12-Apr-2019 17:35 13305
|
||||||
|
<a href="ecgApplet%24ecgPanel.class">ecgApplet$ecgPanel.class</a> 12-Apr-2019 17:35 2618
|
||||||
|
<a href="ecgApplet%24integerVerifier.class">ecgApplet$integerVerifier.class</a> 12-Apr-2019 17:35 1489
|
||||||
|
<a href="ecgApplet%24sfVerifier.class">ecgApplet$sfVerifier.class</a> 12-Apr-2019 17:35 1825
|
||||||
|
<a href="ecgApplet%24sfecgVerifier.class">ecgApplet$sfecgVerifier.class</a> 12-Apr-2019 17:35 1615
|
||||||
|
<a href="ecgApplet.class">ecgApplet.class</a> 12-Apr-2019 17:35 40664
|
||||||
|
<a href="ecgApplet.form">ecgApplet.form</a> 12-Apr-2019 17:35 79509
|
||||||
|
<a href="ecgApplet.html">ecgApplet.html</a> 12-Apr-2019 17:35 2583
|
||||||
|
<a href="ecgApplet.java">ecgApplet.java</a> 12-Apr-2019 17:35 109386
|
||||||
|
<a href="ecgLicense.txt">ecgLicense.txt</a> 12-Apr-2019 17:35 2964
|
||||||
|
<a href="ecgplot.PNG">ecgplot.PNG</a> 12-Apr-2019 17:35 10273
|
||||||
|
<a href="ecgsyn-java.html">ecgsyn-java.html</a> 12-Apr-2019 17:35 2541
|
||||||
|
</pre><hr></body>
|
||||||
|
</html>
|
||||||
9
ecgsyn-1.0.0/Matlab/HEADER.shtml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<!--#set var="TITLE" value="ECGSYN for Matlab/Octave"-->
|
||||||
|
<!--#include virtual="/head.shtml"-->
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This directory contains <a href="../">ECGSYN</a> implemented in Matlab
|
||||||
|
m-code.
|
||||||
|
|
||||||
|
<hr>
|
||||||
52
ecgsyn-1.0.0/Matlab/derivsecgsyn.m
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
function dxdt = derivsecgsyn(t,x,flag,rr,sfint,ti,ai,bi)
|
||||||
|
% dxdt = derivsecgsyn(t,x,flag,rr,sampfreq,ti,ai,bi)
|
||||||
|
% ODE file for generating the synthetic ECG
|
||||||
|
% This file provides dxdt = F(t,x) taking input paramters:
|
||||||
|
% rr: rr process
|
||||||
|
% sfint: Internal sampling frequency [Hertz]
|
||||||
|
% Order of extrema: [P Q R S T]
|
||||||
|
% ti = angles of extrema [radians]
|
||||||
|
% ai = z-position of extrema
|
||||||
|
% bi = Gaussian width of peaks
|
||||||
|
% Copyright (c) 2003 by Patrick McSharry & Gari Clifford, All Rights Reserved
|
||||||
|
% See IEEE Transactions On Biomedical Engineering, 50(3), 289-294, March 2003.
|
||||||
|
% Contact P. McSharry (patrick AT mcsharry DOT net) or
|
||||||
|
% G.D. Clifford (gari AT mit DOT edu)
|
||||||
|
|
||||||
|
% This program is free software; you can redistribute it and/or modify
|
||||||
|
% it under the terms of the GNU General Public License as published by
|
||||||
|
% the Free Software Foundation; either version 2 of the License, or
|
||||||
|
% (at your option) any later version.
|
||||||
|
%
|
||||||
|
% This program is distributed in the hope that it will be useful,
|
||||||
|
% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
% GNU General Public License for more details.
|
||||||
|
%
|
||||||
|
% You should have received a copy of the GNU General Public License
|
||||||
|
% along with this program; if not, write to the Free Software
|
||||||
|
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
%
|
||||||
|
% ecgsyn.m and its dependents are freely availble from Physionet -
|
||||||
|
% http://www.physionet.org/ - please report any bugs to the authors above.
|
||||||
|
|
||||||
|
|
||||||
|
xi = cos(ti);
|
||||||
|
yi = sin(ti);
|
||||||
|
ta = atan2(x(2),x(1));
|
||||||
|
r0 = 1;
|
||||||
|
a0 = 1.0 - sqrt(x(1)^2 + x(2)^2)/r0;
|
||||||
|
ip = 1+floor(t*sfint);
|
||||||
|
w0 = 2*pi/rr(ip);
|
||||||
|
|
||||||
|
|
||||||
|
fresp = 0.25;
|
||||||
|
zbase = 0.005*sin(2*pi*fresp*t);
|
||||||
|
|
||||||
|
dx1dt = a0*x(1) - w0*x(2);
|
||||||
|
dx2dt = a0*x(2) + w0*x(1);
|
||||||
|
|
||||||
|
dti = rem(ta - ti, 2*pi);
|
||||||
|
dx3dt = - sum(ai.*dti.*exp(-0.5*(dti./bi).^2)) - 1.0*(x(3) - zbase);
|
||||||
|
|
||||||
|
dxdt = [dx1dt; dx2dt; dx3dt];
|
||||||
240
ecgsyn-1.0.0/Matlab/ecgsyn.m
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
function [s, ipeaks] = ecgsyn(sfecg,N,Anoise,hrmean,hrstd,lfhfratio,sfint,ti,ai,bi)
|
||||||
|
% [s, ipeaks] = ecgsyn(sfecg,N,Anoise,hrmean,hrstd,lfhfratio,sfint,ti,ai,bi)
|
||||||
|
% Produces synthetic ECG with the following outputs:
|
||||||
|
% s: ECG (mV)
|
||||||
|
% ipeaks: labels for PQRST peaks: P(1), Q(2), R(3), S(4), T(5)
|
||||||
|
% A zero lablel is output otherwise ... use R=find(ipeaks==3);
|
||||||
|
% to find the R peaks s(R), etc.
|
||||||
|
%
|
||||||
|
% Operation uses the following parameters (default values in []s):
|
||||||
|
% sfecg: ECG sampling frequency [256 Hertz]
|
||||||
|
% N: approximate number of heart beats [256]
|
||||||
|
% Anoise: Additive uniformly distributed measurement noise [0 mV]
|
||||||
|
% hrmean: Mean heart rate [60 beats per minute]
|
||||||
|
% hrstd: Standard deviation of heart rate [1 beat per minute]
|
||||||
|
% lfhfratio: LF/HF ratio [0.5]
|
||||||
|
% sfint: Internal sampling frequency [256 Hertz]
|
||||||
|
% Order of extrema: [P Q R S T]
|
||||||
|
% ti = angles of extrema [-70 -15 0 15 100] degrees
|
||||||
|
% ai = z-position of extrema [1.2 -5 30 -7.5 0.75]
|
||||||
|
% bi = Gaussian width of peaks [0.25 0.1 0.1 0.1 0.4]
|
||||||
|
% Copyright (c) 2003 by Patrick McSharry & Gari Clifford, All Rights Reserved
|
||||||
|
% See IEEE Transactions On Biomedical Engineering, 50(3), 289-294, March 2003.
|
||||||
|
% Contact P. McSharry (patrick@mcsharry.net) or G. Clifford (gari@mit.edu)
|
||||||
|
|
||||||
|
% This program is free software; you can redistribute it and/or modify
|
||||||
|
% it under the terms of the GNU General Public License as published by
|
||||||
|
% the Free Software Foundation; either version 2 of the License, or
|
||||||
|
% (at your option) any later version.
|
||||||
|
%
|
||||||
|
% This program is distributed in the hope that it will be useful,
|
||||||
|
% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
% GNU General Public License for more details.
|
||||||
|
%
|
||||||
|
% You should have received a copy of the GNU General Public License
|
||||||
|
% along with this program; if not, write to the Free Software
|
||||||
|
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
%
|
||||||
|
% ecgsyn.m and its dependents are freely availble from Physionet -
|
||||||
|
% http://www.physionet.org/ - please report any bugs to the authors above.
|
||||||
|
|
||||||
|
% set parameter default values
|
||||||
|
if nargin < 1
|
||||||
|
sfecg = 256;
|
||||||
|
end
|
||||||
|
if nargin < 2
|
||||||
|
N = 256;
|
||||||
|
end
|
||||||
|
if nargin < 3
|
||||||
|
Anoise = 0;
|
||||||
|
end
|
||||||
|
if nargin < 4
|
||||||
|
hrmean = 60;
|
||||||
|
end
|
||||||
|
if nargin < 5
|
||||||
|
hrstd = 1;
|
||||||
|
end
|
||||||
|
if nargin < 6
|
||||||
|
lfhfratio = 0.5;
|
||||||
|
end
|
||||||
|
if nargin < 7
|
||||||
|
sfint = 512;
|
||||||
|
end
|
||||||
|
if nargin <8
|
||||||
|
% P Q R S T
|
||||||
|
ti = [-70 -15 0 15 100];
|
||||||
|
end
|
||||||
|
% convert to radians
|
||||||
|
ti = ti*pi/180;
|
||||||
|
if nargin <9 % z position of attractor
|
||||||
|
% P Q R S T
|
||||||
|
ai = [1.2 -5 30 -7.5 0.75];
|
||||||
|
end
|
||||||
|
if nargin <10 % Gaussian width of each attractor
|
||||||
|
% P Q R S T
|
||||||
|
bi = [0.25 0.1 0.1 0.1 0.4];
|
||||||
|
end
|
||||||
|
|
||||||
|
% adjust extrema parameters for mean heart rate
|
||||||
|
hrfact = sqrt(hrmean/60);
|
||||||
|
hrfact2 = sqrt(hrfact);
|
||||||
|
bi = hrfact*bi;
|
||||||
|
ti = [hrfact2 hrfact 1 hrfact hrfact2].*ti;
|
||||||
|
|
||||||
|
% check that sfint is an integer multiple of sfecg
|
||||||
|
q = round(sfint/sfecg);
|
||||||
|
qd = sfint/sfecg;
|
||||||
|
if q ~= qd
|
||||||
|
error(['Internal sampling frequency (sfint) must be an integer multiple ' ...
|
||||||
|
'of the ECG sampling frequency (sfecg). Your current choices are: ' ...
|
||||||
|
'sfecg = ' int2str(sfecg) ' and sfint = ' int2str(sfint) '.']);
|
||||||
|
end
|
||||||
|
|
||||||
|
% define frequency parameters for rr process
|
||||||
|
% flo and fhi correspond to the Mayer waves and respiratory rate respectively
|
||||||
|
flo = 0.1;
|
||||||
|
fhi = 0.25;
|
||||||
|
flostd = 0.01;
|
||||||
|
fhistd = 0.01;
|
||||||
|
|
||||||
|
fid = 1;
|
||||||
|
fprintf(fid,'ECG sampled at %d Hz\n',sfecg);
|
||||||
|
fprintf(fid,'Approximate number of heart beats: %d\n',N);
|
||||||
|
fprintf(fid,'Measurement noise amplitude: %d \n',Anoise);
|
||||||
|
fprintf(fid,'Heart rate mean: %d bpm\n',hrmean);
|
||||||
|
fprintf(fid,'Heart rate std: %d bpm\n',hrstd);
|
||||||
|
fprintf(fid,'LF/HF ratio: %g\n',lfhfratio);
|
||||||
|
fprintf(fid,'Internal sampling frequency: %g\n',sfint);
|
||||||
|
fprintf(fid,' P Q R S T\n');
|
||||||
|
fprintf(fid,'ti = [%g %g %g %g %g] radians\n',ti(1),ti(2),ti(3),ti(4),ti(5));
|
||||||
|
fprintf(fid,'ai = [%g %g %g %g %g]\n',ai(1),ai(2),ai(3),ai(4),ai(5));
|
||||||
|
fprintf(fid,'bi = [%g %g %g %g %g]\n',bi(1),bi(2),bi(3),bi(4),bi(5));
|
||||||
|
|
||||||
|
|
||||||
|
% calculate time scales for rr and total output
|
||||||
|
sampfreqrr = 1;
|
||||||
|
trr = 1/sampfreqrr;
|
||||||
|
tstep = 1/sfecg;
|
||||||
|
rrmean = (60/hrmean);
|
||||||
|
Nrr = 2^(ceil(log2(N*rrmean/trr)));
|
||||||
|
|
||||||
|
% compute rr process
|
||||||
|
rr0 = rrprocess(flo,fhi,flostd,fhistd,lfhfratio,hrmean,hrstd,sampfreqrr,Nrr);
|
||||||
|
|
||||||
|
% upsample rr time series from 1 Hz to sfint Hz
|
||||||
|
rr = interp(rr0,sfint);
|
||||||
|
|
||||||
|
% make the rrn time series
|
||||||
|
dt = 1/sfint;
|
||||||
|
rrn = zeros(length(rr),1);
|
||||||
|
tecg=0;
|
||||||
|
i = 1;
|
||||||
|
while i <= length(rr)
|
||||||
|
tecg = tecg+rr(i);
|
||||||
|
ip = round(tecg/dt);
|
||||||
|
rrn(i:ip) = rr(i);
|
||||||
|
i = ip+1;
|
||||||
|
end
|
||||||
|
Nt = ip;
|
||||||
|
|
||||||
|
% integrate system using fourth order Runge-Kutta
|
||||||
|
fprintf(fid,'Integrating dynamical system\n');
|
||||||
|
x0 = [1,0,0.04];
|
||||||
|
Tspan = [0:dt:(Nt-1)*dt];
|
||||||
|
[T,X0] = ode45('derivsecgsyn',Tspan,x0,[],rrn,sfint,ti,ai,bi);
|
||||||
|
|
||||||
|
% downsample to required sfecg
|
||||||
|
X = X0(1:q:end,:);
|
||||||
|
|
||||||
|
% extract R-peaks times
|
||||||
|
ipeaks = detectpeaks(X, ti, sfecg);
|
||||||
|
|
||||||
|
% Scale signal to lie between -0.4 and 1.2 mV
|
||||||
|
z = X(:,3);
|
||||||
|
zmin = min(z);
|
||||||
|
zmax = max(z);
|
||||||
|
zrange = zmax - zmin;
|
||||||
|
z = (z - zmin)*(1.6)/zrange -0.4;
|
||||||
|
|
||||||
|
% include additive uniformly distributed measurement noise
|
||||||
|
eta = 2*rand(length(z),1)-1;
|
||||||
|
s = z + Anoise*eta;
|
||||||
|
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
function rr = rrprocess(flo, fhi, flostd, fhistd, lfhfratio, hrmean, hrstd, sfrr, n)
|
||||||
|
w1 = 2*pi*flo;
|
||||||
|
w2 = 2*pi*fhi;
|
||||||
|
c1 = 2*pi*flostd;
|
||||||
|
c2 = 2*pi*fhistd;
|
||||||
|
sig2 = 1;
|
||||||
|
sig1 = lfhfratio;
|
||||||
|
rrmean = 60/hrmean;
|
||||||
|
rrstd = 60*hrstd/(hrmean*hrmean);
|
||||||
|
|
||||||
|
df = sfrr/n;
|
||||||
|
w = [0:n-1]'*2*pi*df;
|
||||||
|
dw1 = w-w1;
|
||||||
|
dw2 = w-w2;
|
||||||
|
|
||||||
|
Hw1 = sig1*exp(-0.5*(dw1/c1).^2)/sqrt(2*pi*c1^2);
|
||||||
|
Hw2 = sig2*exp(-0.5*(dw2/c2).^2)/sqrt(2*pi*c2^2);
|
||||||
|
Hw = Hw1 + Hw2;
|
||||||
|
Hw0 = [Hw(1:n/2); Hw(n/2:-1:1)];
|
||||||
|
Sw = (sfrr/2)*sqrt(Hw0);
|
||||||
|
|
||||||
|
ph0 = 2*pi*rand(n/2-1,1);
|
||||||
|
ph = [ 0; ph0; 0; -flipud(ph0) ];
|
||||||
|
SwC = Sw .* exp(j*ph);
|
||||||
|
x = (1/n)*real(ifft(SwC));
|
||||||
|
|
||||||
|
xstd = std(x);
|
||||||
|
ratio = rrstd/xstd;
|
||||||
|
rr = rrmean + x*ratio;
|
||||||
|
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
function ind = detectpeaks(X, thetap, sfecg)
|
||||||
|
N = length(X);
|
||||||
|
irpeaks = zeros(N,1);
|
||||||
|
|
||||||
|
theta = atan2(X(:,2),X(:,1));
|
||||||
|
ind0 = zeros(N,1);
|
||||||
|
for i=1:N-1
|
||||||
|
a = ( (theta(i) <= thetap) & (thetap <= theta(i+1)) );
|
||||||
|
j = find(a==1);
|
||||||
|
if ~isempty(j)
|
||||||
|
d1 = thetap(j) - theta(i);
|
||||||
|
d2 = theta(i+1) - thetap(j);
|
||||||
|
if d1 < d2
|
||||||
|
ind0(i) = j;
|
||||||
|
else
|
||||||
|
ind0(i+1) = j;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
d = ceil(sfecg/64);
|
||||||
|
d = max([2 d])
|
||||||
|
ind = zeros(N,1);
|
||||||
|
z = X(:,3);
|
||||||
|
zmin = min(z);
|
||||||
|
zmax = max(z);
|
||||||
|
zext = [zmin zmax zmin zmax zmin];
|
||||||
|
sext = [1 -1 1 -1 1];
|
||||||
|
for i=1:5
|
||||||
|
clear ind1 Z k vmax imax iext;
|
||||||
|
ind1 = find(ind0==i);
|
||||||
|
n = length(ind1);
|
||||||
|
Z = ones(n,2*d+1)*zext(i)*sext(i);
|
||||||
|
for j=-d:d
|
||||||
|
k = find( (1 <= ind1+j) & (ind1+j <= N) );
|
||||||
|
Z(k,d+j+1) = z(ind1(k)+j)*sext(i);
|
||||||
|
end
|
||||||
|
[vmax, ivmax] = max(Z,[],2);
|
||||||
|
iext = ind1 + ivmax-d-1;
|
||||||
|
ind(iext) = i;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
9
ecgsyn-1.0.0/Matlab/index.html
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<html>
|
||||||
|
<head><title>Index of /static/published-projects/ecgsyn/1.0.0/Matlab/</title></head>
|
||||||
|
<body>
|
||||||
|
<h1>Index of /static/published-projects/ecgsyn/1.0.0/Matlab/</h1><hr><pre><a href="../">../</a>
|
||||||
|
<a href="HEADER.shtml">HEADER.shtml</a> 12-Apr-2019 17:35 186
|
||||||
|
<a href="derivsecgsyn.m">derivsecgsyn.m</a> 12-Apr-2019 17:35 1911
|
||||||
|
<a href="ecgsyn.m">ecgsyn.m</a> 12-Apr-2019 17:35 6795
|
||||||
|
</pre><hr></body>
|
||||||
|
</html>
|
||||||
BIN
ecgsyn-1.0.0/ecgsyn.tar.gz
Normal file
12
ecgsyn-1.0.0/index.html
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<html>
|
||||||
|
<head><title>Index of /static/published-projects/ecgsyn/1.0.0/</title></head>
|
||||||
|
<body>
|
||||||
|
<h1>Index of /static/published-projects/ecgsyn/1.0.0/</h1><hr><pre><a href="../">../</a>
|
||||||
|
<a href="C/">C/</a> 12-Apr-2019 17:35 -
|
||||||
|
<a href="Java/">Java/</a> 12-Apr-2019 17:35 -
|
||||||
|
<a href="Matlab/">Matlab/</a> 12-Apr-2019 17:35 -
|
||||||
|
<a href="paper/">paper/</a> 12-Apr-2019 17:35 -
|
||||||
|
<a href="sample-output/">sample-output/</a> 12-Apr-2019 17:35 -
|
||||||
|
<a href="ecgsyn.tar.gz">ecgsyn.tar.gz</a> 12-Apr-2019 17:35 165286
|
||||||
|
</pre><hr></body>
|
||||||
|
</html>
|
||||||
30
ecgsyn-1.0.0/paper/ecgpqrst.css
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/* Century Schoolbook font is very similar to Computer Modern Math: cmmi */
|
||||||
|
.MATH { font-family: "Century Schoolbook", serif; }
|
||||||
|
.MATH I { font-family: "Century Schoolbook", serif; font-style: italic }
|
||||||
|
.BOLDMATH { font-family: "Century Schoolbook", serif; font-weight: bold }
|
||||||
|
|
||||||
|
/* implement both fixed-size and relative sizes */
|
||||||
|
SMALL.XTINY { font-size : xx-small }
|
||||||
|
SMALL.TINY { font-size : x-small }
|
||||||
|
SMALL.SCRIPTSIZE { font-size : smaller }
|
||||||
|
SMALL.FOOTNOTESIZE { font-size : small }
|
||||||
|
SMALL.SMALL { }
|
||||||
|
BIG.LARGE { }
|
||||||
|
BIG.XLARGE { font-size : large }
|
||||||
|
BIG.XXLARGE { font-size : x-large }
|
||||||
|
BIG.HUGE { font-size : larger }
|
||||||
|
BIG.XHUGE { font-size : xx-large }
|
||||||
|
|
||||||
|
/* heading styles */
|
||||||
|
H1 { }
|
||||||
|
H2 { }
|
||||||
|
H3 { }
|
||||||
|
H4 { }
|
||||||
|
H5 { }
|
||||||
|
|
||||||
|
/* mathematics styles */
|
||||||
|
DIV.displaymath { } /* math displays */
|
||||||
|
TD.eqno { } /* equation-number cells */
|
||||||
|
|
||||||
|
|
||||||
|
/* document-specific styles come next */
|
||||||
79
ecgsyn-1.0.0/paper/footnode.html
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||||
|
|
||||||
|
<!--Converted with jLaTeX2HTML 2002 (1.62) JA patch-1.4
|
||||||
|
patched version by: Kenshi Muto, Debian Project.
|
||||||
|
LaTeX2HTML 2002 (1.62),
|
||||||
|
original version by: Nikos Drakos, CBLU, University of Leeds
|
||||||
|
* revised and updated by: Marcus Hennecke, Ross Moore, Herb Swan
|
||||||
|
* with significant contributions from:
|
||||||
|
Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
|
||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<TITLE>Footnotes</TITLE>
|
||||||
|
<META NAME="description" CONTENT="Footnotes">
|
||||||
|
<META NAME="keywords" CONTENT="ecgpqrst">
|
||||||
|
<META NAME="resource-type" CONTENT="document">
|
||||||
|
<META NAME="distribution" CONTENT="global">
|
||||||
|
|
||||||
|
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
||||||
|
<META NAME="Generator" CONTENT="jLaTeX2HTML v2002 JA patch-1.4">
|
||||||
|
<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
|
||||||
|
|
||||||
|
<LINK REL="STYLESHEET" HREF="ecgpqrst.css">
|
||||||
|
|
||||||
|
<LINK REL="previous" HREF="node8.html">
|
||||||
|
<LINK REL="up" HREF="index.shtml">
|
||||||
|
</HEAD>
|
||||||
|
|
||||||
|
<BODY >
|
||||||
|
|
||||||
|
<DL>
|
||||||
|
<DT><A NAME="foot31">...<IMG
|
||||||
|
WIDTH="21" HEIGHT="17" ALIGN="BOTTOM" BORDER="0"
|
||||||
|
SRC="img6.png"
|
||||||
|
ALT="$^{2,3}$"></A><A
|
||||||
|
HREF="index.shtml#tex2html1"><SUP><IMG ALIGN="BOTTOM" BORDER="1" ALT="[*]"
|
||||||
|
SRC="file:/usr/share/latex2html/icons/footnote.png"></SUP></A></DT>
|
||||||
|
<DD><IMG
|
||||||
|
WIDTH="11" HEIGHT="17" ALIGN="BOTTOM" BORDER="0"
|
||||||
|
SRC="img5.png"
|
||||||
|
ALT="$^1$">Department of Engineering Science,
|
||||||
|
University of Oxford, Oxford OX1 3PJ.
|
||||||
|
|
||||||
|
<PRE>.
|
||||||
|
</PRE>
|
||||||
|
</DD>
|
||||||
|
<DT><A NAME="foot32">...</A><A
|
||||||
|
HREF="index.shtml#tex2html2"><SUP><IMG ALIGN="BOTTOM" BORDER="1" ALT="[*]"
|
||||||
|
SRC="file:/usr/share/latex2html/icons/footnote.png"></SUP></A></DT>
|
||||||
|
<DD><IMG
|
||||||
|
WIDTH="11" HEIGHT="17" ALIGN="BOTTOM" BORDER="0"
|
||||||
|
SRC="img7.png"
|
||||||
|
ALT="$^2$">Mathematical Institute, University of Oxford, Oxford OX1 3LB.
|
||||||
|
|
||||||
|
<PRE>.
|
||||||
|
</PRE>
|
||||||
|
</DD>
|
||||||
|
<DT><A NAME="foot33">...</A><A
|
||||||
|
HREF="index.shtml#tex2html3"><SUP><IMG ALIGN="BOTTOM" BORDER="1" ALT="[*]"
|
||||||
|
SRC="file:/usr/share/latex2html/icons/footnote.png"></SUP></A></DT>
|
||||||
|
<DD><IMG
|
||||||
|
WIDTH="11" HEIGHT="17" ALIGN="BOTTOM" BORDER="0"
|
||||||
|
SRC="img8.png"
|
||||||
|
ALT="$^3$">Centre for the Analysis of Time Series, London School
|
||||||
|
of Economics, London WC2A 2AE.
|
||||||
|
|
||||||
|
<PRE>.
|
||||||
|
</PRE>
|
||||||
|
</DD>
|
||||||
|
<DT><A NAME="foot34">...</A><A
|
||||||
|
HREF="index.shtml#tex2html4"><SUP><IMG ALIGN="BOTTOM" BORDER="1" ALT="[*]"
|
||||||
|
SRC="file:/usr/share/latex2html/icons/footnote.png"></SUP></A></DT>
|
||||||
|
<DD>E-mail: mcsharry@robots.ox.ac.uk
|
||||||
|
|
||||||
|
<PRE>.
|
||||||
|
</PRE>
|
||||||
|
</DD>
|
||||||
|
</DL>
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
||||||
BIN
ecgsyn-1.0.0/paper/img1.png
Normal file
|
After Width: | Height: | Size: 446 B |
BIN
ecgsyn-1.0.0/paper/img10.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
ecgsyn-1.0.0/paper/img11.png
Normal file
|
After Width: | Height: | Size: 393 B |
BIN
ecgsyn-1.0.0/paper/img12.png
Normal file
|
After Width: | Height: | Size: 182 B |
BIN
ecgsyn-1.0.0/paper/img13.png
Normal file
|
After Width: | Height: | Size: 274 B |
BIN
ecgsyn-1.0.0/paper/img14.png
Normal file
|
After Width: | Height: | Size: 293 B |
BIN
ecgsyn-1.0.0/paper/img15.png
Normal file
|
After Width: | Height: | Size: 289 B |
BIN
ecgsyn-1.0.0/paper/img16.png
Normal file
|
After Width: | Height: | Size: 275 B |
BIN
ecgsyn-1.0.0/paper/img17.png
Normal file
|
After Width: | Height: | Size: 264 B |
BIN
ecgsyn-1.0.0/paper/img18.png
Normal file
|
After Width: | Height: | Size: 217 B |
BIN
ecgsyn-1.0.0/paper/img19.png
Normal file
|
After Width: | Height: | Size: 150 B |
BIN
ecgsyn-1.0.0/paper/img2.png
Normal file
|
After Width: | Height: | Size: 392 B |
BIN
ecgsyn-1.0.0/paper/img20.png
Normal file
|
After Width: | Height: | Size: 426 B |
BIN
ecgsyn-1.0.0/paper/img21.png
Normal file
|
After Width: | Height: | Size: 232 B |
BIN
ecgsyn-1.0.0/paper/img22.png
Normal file
|
After Width: | Height: | Size: 445 B |
BIN
ecgsyn-1.0.0/paper/img23.png
Normal file
|
After Width: | Height: | Size: 202 B |
BIN
ecgsyn-1.0.0/paper/img24.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
ecgsyn-1.0.0/paper/img25.png
Normal file
|
After Width: | Height: | Size: 655 B |
BIN
ecgsyn-1.0.0/paper/img26.png
Normal file
|
After Width: | Height: | Size: 813 B |
BIN
ecgsyn-1.0.0/paper/img27.png
Normal file
|
After Width: | Height: | Size: 662 B |
BIN
ecgsyn-1.0.0/paper/img28.png
Normal file
|
After Width: | Height: | Size: 214 B |
BIN
ecgsyn-1.0.0/paper/img29.png
Normal file
|
After Width: | Height: | Size: 236 B |
BIN
ecgsyn-1.0.0/paper/img3.png
Normal file
|
After Width: | Height: | Size: 553 B |
BIN
ecgsyn-1.0.0/paper/img30.png
Normal file
|
After Width: | Height: | Size: 260 B |
BIN
ecgsyn-1.0.0/paper/img31.png
Normal file
|
After Width: | Height: | Size: 823 B |
BIN
ecgsyn-1.0.0/paper/img32.png
Normal file
|
After Width: | Height: | Size: 394 B |
BIN
ecgsyn-1.0.0/paper/img33.png
Normal file
|
After Width: | Height: | Size: 472 B |
BIN
ecgsyn-1.0.0/paper/img34.png
Normal file
|
After Width: | Height: | Size: 256 B |
BIN
ecgsyn-1.0.0/paper/img35.png
Normal file
|
After Width: | Height: | Size: 257 B |
BIN
ecgsyn-1.0.0/paper/img36.png
Normal file
|
After Width: | Height: | Size: 237 B |
BIN
ecgsyn-1.0.0/paper/img37.png
Normal file
|
After Width: | Height: | Size: 249 B |
BIN
ecgsyn-1.0.0/paper/img38.png
Normal file
|
After Width: | Height: | Size: 590 B |
BIN
ecgsyn-1.0.0/paper/img39.png
Normal file
|
After Width: | Height: | Size: 296 B |
BIN
ecgsyn-1.0.0/paper/img4.png
Normal file
|
After Width: | Height: | Size: 220 B |
BIN
ecgsyn-1.0.0/paper/img40.png
Normal file
|
After Width: | Height: | Size: 320 B |
BIN
ecgsyn-1.0.0/paper/img41.png
Normal file
|
After Width: | Height: | Size: 287 B |
BIN
ecgsyn-1.0.0/paper/img42.png
Normal file
|
After Width: | Height: | Size: 274 B |
BIN
ecgsyn-1.0.0/paper/img43.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
ecgsyn-1.0.0/paper/img44.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
ecgsyn-1.0.0/paper/img45.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
ecgsyn-1.0.0/paper/img46.png
Normal file
|
After Width: | Height: | Size: 369 B |
BIN
ecgsyn-1.0.0/paper/img47.png
Normal file
|
After Width: | Height: | Size: 318 B |
BIN
ecgsyn-1.0.0/paper/img48.png
Normal file
|
After Width: | Height: | Size: 275 B |
BIN
ecgsyn-1.0.0/paper/img49.png
Normal file
|
After Width: | Height: | Size: 268 B |
BIN
ecgsyn-1.0.0/paper/img5.png
Normal file
|
After Width: | Height: | Size: 138 B |
BIN
ecgsyn-1.0.0/paper/img50.png
Normal file
|
After Width: | Height: | Size: 494 B |
BIN
ecgsyn-1.0.0/paper/img51.png
Normal file
|
After Width: | Height: | Size: 410 B |
BIN
ecgsyn-1.0.0/paper/img52.png
Normal file
|
After Width: | Height: | Size: 383 B |
BIN
ecgsyn-1.0.0/paper/img53.png
Normal file
|
After Width: | Height: | Size: 473 B |
BIN
ecgsyn-1.0.0/paper/img54.png
Normal file
|
After Width: | Height: | Size: 361 B |
BIN
ecgsyn-1.0.0/paper/img55.png
Normal file
|
After Width: | Height: | Size: 453 B |
BIN
ecgsyn-1.0.0/paper/img56.png
Normal file
|
After Width: | Height: | Size: 553 B |
BIN
ecgsyn-1.0.0/paper/img57.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
ecgsyn-1.0.0/paper/img58.png
Normal file
|
After Width: | Height: | Size: 358 B |
BIN
ecgsyn-1.0.0/paper/img59.png
Normal file
|
After Width: | Height: | Size: 492 B |
BIN
ecgsyn-1.0.0/paper/img6.png
Normal file
|
After Width: | Height: | Size: 248 B |
BIN
ecgsyn-1.0.0/paper/img60.png
Normal file
|
After Width: | Height: | Size: 250 B |
BIN
ecgsyn-1.0.0/paper/img61.png
Normal file
|
After Width: | Height: | Size: 348 B |
BIN
ecgsyn-1.0.0/paper/img62.png
Normal file
|
After Width: | Height: | Size: 701 B |
BIN
ecgsyn-1.0.0/paper/img63.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |