Skip to content

Commit 3c30345

Browse files
authored
Correctly write custom labels to annotation file (#404)
1 parent 4ee5d36 commit 3c30345

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

tests/test_annotation.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import unittest
44

55
import numpy as np
6+
import pandas as pd
67

78
import wfdb
89

@@ -252,13 +253,31 @@ def test_4(self):
252253
annotation2 = wfdb.rdann("huge", "qrs")
253254
self.assertEqual(annotation1, annotation2)
254255

256+
def test_5(self):
257+
"""
258+
Write and read annotations with custom labels.
259+
"""
260+
ann_idx = np.array([1, 1000, 2000, 3000])
261+
ann_chan = np.array([3, 1, 2, 3])
262+
# write custom labels
263+
ann_label_store = np.array([ 4, 2, 1, 3])
264+
ann_custom_labels = {'label_store': [1, 2, 3, 4],
265+
'symbol': ['v','l','r','z'],
266+
'description':['pvc','lbbb','rbbb','pac']}
267+
ann_custom_labels = pd.DataFrame(data=ann_custom_labels)
268+
wfdb.wrann('CustomLabel', 'atr', ann_idx, chan=ann_chan,
269+
custom_labels=ann_custom_labels, label_store=ann_label_store)
270+
ann = wfdb.rdann('CustomLabel', 'atr')
271+
self.assertEqual(ann.symbol, ['z', 'l', 'v', 'r'])
272+
255273
@classmethod
256274
def tearDownClass(cls):
257275
writefiles = [
258276
"100.atr",
259277
"1003.atr",
260278
"12726.anI",
261279
"huge.qrs",
280+
"CustomLabel.atr"
262281
]
263282
for file in writefiles:
264283
if os.path.isfile(file):

wfdb/io/annotation.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,14 +1170,14 @@ def calc_core_bytes(self):
11701170

11711171
# Process the samp (difference) and sym items
11721172
data_bytes.append(
1173-
field2bytes("samptype", [sampdiff[i], self.symbol[i]])
1173+
field2bytes("samptype", [sampdiff[i], self.symbol[i]], self.custom_labels)
11741174
)
11751175

11761176
# Process the extra optional fields
11771177
for field in extra_write_fields:
11781178
value = getattr(compact_annotation, field)[i]
11791179
if value is not None:
1180-
data_bytes.append(field2bytes(field, value))
1180+
data_bytes.append(field2bytes(field, value, self.custom_labels))
11811181

11821182
# Flatten and convert to correct format
11831183
data_bytes = np.array(
@@ -1600,7 +1600,7 @@ def compact_carry_field(full_field):
16001600
return compact_field
16011601

16021602

1603-
def field2bytes(field, value):
1603+
def field2bytes(field, value, custom_labels=None):
16041604
"""
16051605
Convert an annotation field into bytes to write.
16061606
@@ -1619,11 +1619,16 @@ def field2bytes(field, value):
16191619
"""
16201620
data_bytes = []
16211621

1622+
# allow use of custom labels
1623+
label_table = ann_label_table
1624+
if custom_labels is not None:
1625+
label_table = pd.concat([label_table, custom_labels], ignore_index=True)
1626+
16221627
# samp and sym bytes come together
16231628
if field == "samptype":
16241629
# Numerical value encoding annotation symbol
1625-
typecode = ann_label_table.loc[
1626-
ann_label_table["symbol"] == value[1], "label_store"
1630+
typecode = label_table.loc[
1631+
label_table["symbol"] == value[1], "label_store"
16271632
].values[0]
16281633

16291634
# sample difference

0 commit comments

Comments
 (0)