Skip to content

Commit 6eda4ff

Browse files
committed
add demos and tests
1 parent 30c16e0 commit 6eda4ff

File tree

6 files changed

+158
-249
lines changed

6 files changed

+158
-249
lines changed

devtests.ipynb

Lines changed: 0 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -18,48 +18,6 @@
1818
"import wfdb"
1919
]
2020
},
21-
{
22-
"cell_type": "code",
23-
"execution_count": null,
24-
"metadata": {
25-
"collapsed": false
26-
},
27-
"outputs": [],
28-
"source": [
29-
"import wfdb\n",
30-
"# Testing rdsamp multiple samples per frame (and fmt 12)\n",
31-
"sig, fields=wfdb.srdsamp('sampledata/03700181')\n",
32-
"print(sig[:20,:])\n",
33-
"print(\"\\n\\n\", sig.shape, \"\\n\\n\")\n",
34-
"print(fields)\n",
35-
"\n",
36-
"print(\"\\n\\n\\n\")\n",
37-
"print(sig[-20:,:])"
38-
]
39-
},
40-
{
41-
"cell_type": "code",
42-
"execution_count": null,
43-
"metadata": {
44-
"collapsed": false
45-
},
46-
"outputs": [],
47-
"source": [
48-
"import wfdb\n",
49-
"ann = wfdb.rdann('/home/chen/Downloads/chb01_03.edf','seizures')"
50-
]
51-
},
52-
{
53-
"cell_type": "code",
54-
"execution_count": null,
55-
"metadata": {
56-
"collapsed": false
57-
},
58-
"outputs": [],
59-
"source": [
60-
"ann.__dict__"
61-
]
62-
},
6321
{
6422
"cell_type": "code",
6523
"execution_count": null,
@@ -100,51 +58,6 @@
10058
"# print([sd & 255, sd & 768, (sd & 768) >> 8])"
10159
]
10260
},
103-
{
104-
"cell_type": "code",
105-
"execution_count": 18,
106-
"metadata": {
107-
"collapsed": false
108-
},
109-
"outputs": [
110-
{
111-
"data": {
112-
"text/plain": [
113-
"list"
114-
]
115-
},
116-
"execution_count": 18,
117-
"metadata": {},
118-
"output_type": "execute_result"
119-
}
120-
],
121-
"source": [
122-
"type(record.initvalue)"
123-
]
124-
},
125-
{
126-
"cell_type": "code",
127-
"execution_count": 20,
128-
"metadata": {
129-
"collapsed": false
130-
},
131-
"outputs": [
132-
{
133-
"data": {
134-
"text/plain": [
135-
"[1, 2]"
136-
]
137-
},
138-
"execution_count": 20,
139-
"metadata": {},
140-
"output_type": "execute_result"
141-
}
142-
],
143-
"source": [
144-
"x = [1,2,3]\n",
145-
"x[:-1]"
146-
]
147-
},
14861
{
14962
"cell_type": "code",
15063
"execution_count": null,

tests/test_annotations.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class test_rdann():
88
# Target file created with: rdann -r sampledata/100 -a atr > anntarget1
99
def test_1(self):
1010

11-
# Read data from WFDB python package
11+
# Read data using WFDB python package
1212
annotation = wfdb.rdann('sampledata/100', 'atr')
1313

1414

@@ -52,7 +52,16 @@ def test_1(self):
5252
np.array_equal(annotation.num, Tnum),
5353
annotation.aux == Taux]
5454

55+
# Test file streaming
56+
pbannotation = wfdb.rdann('100', 'atr', pbdir = 'mitdb')
57+
58+
# Test file writing
59+
annotation.wrsamp()
60+
annotationwrite = wfdb.rdann('100', 'atr')
61+
5562
assert (comp == [True] * 6)
63+
assert annotation.__eq__(pbannotation)
64+
assert annotation.__eq__(annotationwrite)
5665

5766
# Test 2 - Annotation file 12726.anI with many aux strings.
5867
# Target file created with: rdann -r sampledata/100 -a atr > anntarget2
@@ -93,5 +102,13 @@ def test_2(self):
93102
np.array_equal(annotation.chan, Tchan),
94103
np.array_equal(annotation.num, Tnum),
95104
annotation.aux == Taux]
105+
# Test file streaming
106+
pbannotation = wfdb.rdann('12726', 'anI', pbdir = 'prcp')
107+
108+
# Test file writing
109+
annotation.wrsamp()
110+
annotationwrite = wfdb.rdann('12726', 'anI')
96111

97112
assert (comp == [True] * 6)
113+
assert annotation.__eq__(pbannotation)
114+
assert annotation.__eq__(annotationwrite)

tests/test_records.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,13 @@ def test_7(self):
129129
# Compare data streaming from physiobank
130130
pbrecord= wfdb.rdsamp('s0010_re', physical=False, pbdir = 'ptbdb/patient001')
131131

132+
# Test file writing
133+
record.wrsamp()
134+
recordwrite = wfdb.rdsamp('s0010_re', physical=False)
135+
132136
assert np.array_equal(sig, targetsig)
133137
assert record.__eq__(pbrecord)
138+
assert record.__eq__(recordwrite)
134139

135140
# Test 8 - Multi-dat/Selected Duration/Selected Channels/Physical
136141
# Target file created with: rdsamp -r sampledata/s0010_re -f 5 -t 38 -P -s
@@ -164,8 +169,13 @@ def test_9(self):
164169
# Compare data streaming from physiobank
165170
pbrecord = wfdb.rdsamp('03700181', physical=False, pbdir = 'mimicdb/037')
166171

172+
# Test file writing. Multiple Samples per frame. To do...
173+
#record.wrsamp()
174+
#recordwrite = wfdb.rdsamp('03700181', physical=False)
175+
167176
assert np.array_equal(sig, targetsig)
168177
assert record.__eq__(pbrecord)
178+
#assert record.__eq__(recordwrite)
169179

170180
# Test 10 - Format 12 multi-samples per frame and skew/Selected Duration/Selected Channels/Physical
171181
# Target file created with: rdsamp -r sampledata/03700181 -f 8 -t 128 -s 0

wfdb/annotations.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def wrann(self):
8686
# Return indices of anntype field which are not encoded, and thus need
8787
# to be moved to the aux field.
8888
def checkfields(self):
89-
# Enforce mandatory write fields
89+
# Enforce the presence of mandatory write fields
9090
for field in ['recordname', 'annotator', 'annsamp', 'anntype']:
9191
if getattr(self, field) is None:
9292
print('The ', field, ' field is mandatory for writing annotation files')
@@ -127,9 +127,9 @@ def checkfield(self, field):
127127
else:
128128
fielditem = getattr(self, field)
129129

130-
# Ensure the field item is a list.
131-
if type(fielditem) != list:
132-
print('The ', field, ' field must be a list')
130+
# Ensure the field item is a list or array.
131+
if type(fielditem) not in [list, np.ndarray]:
132+
print('The ', field, ' field must be a list or numpy array')
133133
sys.exit()
134134

135135
# Check the data types of the elements
@@ -164,20 +164,20 @@ def checkfield(self, field):
164164
if set(self.anntype) - set(annsyms.values()) != set():
165165
print("The 'anntype' field contains items not encoded in the WFDB annotation library.")
166166
print('To see the valid annotation codes call: showanncodes()')
167-
print('To transfer non-encoded anntype items into the aux field call: self.type2aux')
167+
print('To transfer non-encoded anntype items into the aux field call: self.type2aux()')
168168
sys.exit()
169-
elif field == 'num':
170-
# signed character
171-
if min(self.num) < 0 or max(self.num) >255:
172-
sys.exit("The 'num' field must only contain non-negative integers up to 255")
173169
elif field == 'subtype':
174170
# signed character
175171
if min(self.subtype) < 0 or max(self.subtype) >127:
176172
sys.exit("The 'subtype' field must only contain non-negative integers up to 127")
177173
elif field == 'chan':
178174
# unsigned character
179-
if min(self.chan) < 0 or max(self.chan) >127:
180-
sys.exit("The 'chan' field must only contain non-negative integers up to 127")
175+
if min(self.chan) < 0 or max(self.chan) >255:
176+
sys.exit("The 'chan' field must only contain non-negative integers up to 255")
177+
elif field == 'num':
178+
# signed character
179+
if min(self.num) < 0 or max(self.num) >127:
180+
sys.exit("The 'num' field must only contain non-negative integers up to 127")
181181
#elif field == 'aux': # No further conditions for aux field.
182182

183183

@@ -769,7 +769,7 @@ def proccustomtypes(annsamp,anntype,num,subtype,chan,aux):
769769

770770
# Mapping annotation symbols to the annotation codes
771771
# For printing/user guidance
772-
symcodes = pd.DataFrame({'Ann Symbol': list(annsyms.values()), 'Ann Code/Meaning': list(anncodes.values())})
772+
symcodes = pd.DataFrame({'Ann Symbol': list(annsyms.values()), 'Ann Code Meaning': list(anncodes.values())})
773773
symcodes = symcodes.set_index('Ann Symbol', list(annsyms.values()))
774774

775775
annfields = ['recordname', 'annotator', 'annsamp', 'anntype', 'num', 'subtype', 'chan', 'aux', 'fs']

wfdb/records.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def checkfield(self, field, ch=None):
8888
elif field == 'basetime':
8989
_ = parsetimestring(self.basetime)
9090
elif field == 'basedate':
91-
_ = parsetimestring(self.basedate)
91+
_ = parsedatestring(self.basedate)
9292

9393
# Signal specification fields. Lists of elements.
9494
elif field == 'filename':
@@ -114,15 +114,10 @@ def checkfield(self, field, ch=None):
114114
f = self.skew[ch]
115115
if f < 0:
116116
sys.exit('skew values must be non-negative integers')
117-
# Writing a signal with skew shouldn't require anything different
118-
#if f > 0:
119-
# sys.exit('Sorry, I have not implemented skew into wrsamp yet')
120117
elif field == 'byteoffset':
121118
f = self.byteoffset[ch]
122119
if f < 0:
123120
sys.exit('byteoffset values must be non-negative integers')
124-
#if f > 0:
125-
# sys.exit('Sorry, I have not implemented byte offset into wrsamp yet')
126121
elif field == 'adcgain':
127122
f = self.adcgain[ch]
128123
if f <= 0:
@@ -1027,7 +1022,7 @@ def orderednoconseclist(fulllist):
10271022

10281023
# *This downloading files gateway function relies on the Record/MultiRecord objects.
10291024
# It is placed here rather than in downloads.py in order to avoid circular imports
1030-
1025+
# These download function only targets databases with WFDB records (EDF and MIT format). If the database doesn't have a 'RECORDS" file,
10311026

10321027
# Download WFDB files from a physiobank database
10331028
def dldatabase(pbdb, dlbasedir, records = 'all', annotators = 'all' , keepsubdirs = True, overwrite = False):

0 commit comments

Comments
 (0)