Repository navigation
Expand file tree
/
Copy pathecg_history.py
More file actions
60 lines (51 loc) · 1.88 KB
/
Copy pathecg_history.py
File metadata and controls
60 lines (51 loc) · 1.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import csv
import numpy as np
from ecg_constants import FS
class HistoryPlayer:
def __init__(self):
self.data = None
self.playing = False
self.speed = 1.0
self.position = 0
self.total_samples = 0
self.file_path = None
def load(self, path):
with open(path, "r", encoding="utf-8") as f:
rows = list(csv.DictReader(f))
if not rows:
return False
self.file_path = path
self.total_samples = len(rows)
self.position = 0
self.playing = False
self.data = {
"raw": np.array([float(r.get("raw", 0) or 0) for r in rows]),
"filtered": np.array([float(r.get("filtered", 0) or 0) for r in rows]),
"energy": np.array([float(r.get("energy", 0) or 0) for r in rows]),
"hr": np.array([int(float(r.get("hr", 0) or 0)) for r in rows]),
"beats": np.array([int(float(r.get("beats", 0) or 0)) for r in rows]),
"leads_off": np.array([int(float(r.get("leads_off", 0) or 0)) for r in rows]),
}
return True
@property
def duration_s(self):
return self.total_samples / FS if self.total_samples else 0
@property
def current_time_s(self):
return self.position / FS
def get_window(self, window_samples):
if self.data is None:
return None
start = max(0, self.position - window_samples)
end = self.position
t = (np.arange(start, end) - self.position) / FS
return {
"t": t,
"raw": self.data["raw"][start:end],
"filtered": self.data["filtered"][start:end],
"energy": self.data["energy"][start:end],
}
def advance(self, samples):
self.position = min(self.position + samples, self.total_samples)
if self.position >= self.total_samples:
self.playing = False