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 |