2
2
import os
3
3
import math
4
4
from . import downloads
5
- import pdb
5
+
6
6
# All defined WFDB dat formats
7
7
datformats = ["80" ,"212" ,"16" ,"24" ,"32" ]
8
8
@@ -486,16 +486,11 @@ def rdsegment(filename, dirname, pbdir, nsig, fmt, siglen, byteoffset,
486
486
487
487
# Copy over the wanted signals
488
488
for cn in range (len (out_datchannel [fn ])):
489
-
490
489
signals [out_datchannel [fn ][cn ]] = datsignals [r_w_channel [fn ][cn ]]
491
490
492
-
493
-
494
491
return signals
495
492
496
493
497
-
498
-
499
494
def rddat (filename , dirname , pbdir , fmt , nsig ,
500
495
siglen , byteoffset , sampsperframe ,
501
496
skew , sampfrom , sampto , smoothframes ):
@@ -543,7 +538,7 @@ def rddat(filename, dirname, pbdir, fmt, nsig,
543
538
# Get the intermediate bytes or samples to process. Bit of a discrepancy. Recall special formats
544
539
# load uint8 bytes, other formats already load samples.
545
540
546
- #Get values from dat file, and append bytes/samples if needed.
541
+ # Read values from dat file, and append bytes/samples if needed.
547
542
if extraflatsamples :
548
543
if fmt in ['212' , '310' , '311' ]:
549
544
# Extra number of bytes to append onto the bytes read from the dat file.
@@ -557,8 +552,7 @@ def rddat(filename, dirname, pbdir, fmt, nsig,
557
552
else :
558
553
sigbytes = getdatbytes (filename , dirname , pbdir , fmt , startbyte , nreadsamples )
559
554
560
- # Read the required bytes from the dat file.
561
- # Then continue to process the read values into proper samples
555
+ # Continue to process the read values into proper samples
562
556
563
557
# Special formats
564
558
if fmt in ['212' , '310' , '311' ]:
@@ -599,7 +593,9 @@ def rddat(filename, dirname, pbdir, fmt, nsig,
599
593
else :
600
594
for frame in range (sampsperframe [ch ]):
601
595
sig [:, ch ] += sigbytes [sum (([0 ] + sampsperframe )[:ch + 1 ]) + frame ::tsampsperframe ]
602
- sig = (sig / sampsperframe )
596
+
597
+ # Have to change the dtype for averaging frames
598
+ sig = (sig .astype ('float64' ) / sampsperframe )
603
599
604
600
# Skew the signal
605
601
sig = skewsig (sig , skew , nsig , readlen , fmt , nanreplace )
@@ -657,7 +653,8 @@ def rddat(filename, dirname, pbdir, fmt, nsig,
657
653
else :
658
654
for frame in range (sampsperframe [ch ]):
659
655
sig [:, ch ] += sigbytes [sum (([0 ] + sampsperframe )[:ch + 1 ]) + frame ::tsampsperframe ]
660
- sig = (sig / sampsperframe )
656
+ # Have to change the dtype for averaging frames
657
+ sig = (sig .astype ('float64' ) / sampsperframe )
661
658
662
659
# Skew the signal
663
660
sig = skewsig (sig , skew , nsig , readlen , fmt , nanreplace )
@@ -834,7 +831,6 @@ def getdatbytes(filename, dirname, pbdir, fmt, startbyte, nsamp):
834
831
return sigbytes
835
832
836
833
837
-
838
834
def bytes2samples (sigbytes , nsamp , fmt ):
839
835
"""
840
836
Converts loaded uint8 blocks into samples for special formats
@@ -977,288 +973,6 @@ def checksigdims(sig, readlen, nsig, sampsperframe):
977
973
raise ValueError ('Samples were not loaded correctly' )
978
974
979
975
980
-
981
-
982
-
983
-
984
-
985
-
986
-
987
-
988
-
989
-
990
-
991
-
992
-
993
-
994
-
995
- # OLD! DO NOT USE
996
-
997
- # Read digital samples from a wfdb signal file
998
- # Returns the signal and the number of bytes read.
999
- def processwfdbbytes (filename , dirname , pbdir , fmt , startbyte , readlen , nsig , sampsperframe , floorsamp = 0 ):
1000
- """
1001
- Read digital samples from a wfdb dat file
1002
-
1003
- Input variables:
1004
- - filename: the name of the dat file.
1005
- - dirname: the full directory where the dat file is located, if the dat file is local.
1006
- - pbdir: the physiobank directory where the dat file is located, if the dat file is remote.
1007
- - fmt: the format of the dat file
1008
- - startbyte: the starting byte to skip to
1009
- - readlen: the length of the signal to be read, in samples.
1010
- - nsig:
1011
- - floorsamp: the extra sample index used to read special formats (212, 310, 311).
1012
-
1013
- """
1014
-
1015
- # Total number of samples per frame
1016
- tsampsperframe = sum (sampsperframe )
1017
-
1018
- # Total number of signal samples to be collected (including discarded ones)
1019
- nsamp = readlen * tsampsperframe + floorsamp
1020
-
1021
- # Reading the dat file into np array and reshaping. Formats 212, 310, and 311 need special processing.
1022
- # Note that for these formats with multi samples/frame, have to convert
1023
- # bytes to samples before returning average frame values.
1024
- if fmt == '212' :
1025
- # Read the bytes from the file as unsigned integer blocks
1026
- sigbytes , bytesloaded = getdatbytes (filename , dirname , pbdir , fmt , nsamp , startbyte )
1027
-
1028
- # use this for byte processing
1029
- processnsamp = nsamp
1030
-
1031
- # For odd sampled records, imagine an extra sample and add an extra byte
1032
- # to simplify the processing step and remove the extra sample at the end.
1033
- if processnsamp % 2 :
1034
- sigbytes = np .append (sigbytes , 0 ).astype ('uint64' )
1035
- processnsamp += 1
1036
-
1037
- # No extra samples/frame
1038
- if tsampsperframe == nsig :
1039
- # Turn the bytes into actual samples.
1040
- sig = np .zeros (processnsamp ) # 1d array of actual samples
1041
- # One sample pair is stored in one byte triplet.
1042
- sig [0 ::2 ] = sigbytes [0 ::3 ] + 256 * \
1043
- np .bitwise_and (sigbytes [1 ::3 ], 0x0f ) # Even numbered samples
1044
- if len (sig > 1 ):
1045
- # Odd numbered samples
1046
- sig [1 ::2 ] = sigbytes [2 ::3 ] + 256 * np .bitwise_and (sigbytes [1 ::3 ] >> 4 , 0x0f )
1047
- if floorsamp : # Remove extra sample read
1048
- sig = sig [floorsamp :]
1049
-
1050
- # Remove extra sample read if originally odd sampled
1051
- if nsamp % 2 :
1052
- sig = sig [:- 1 ]
1053
-
1054
- # Reshape into final array of samples
1055
- sig = sig .reshape (readlen , nsig )
1056
- sig = sig .astype (int )
1057
- # Loaded values as unsigned. Convert to 2's complement form: values
1058
- # > 2^11-1 are negative.
1059
- sig [sig > 2047 ] -= 4096
1060
- # At least one channel has multiple samples per frame. All extra samples are averaged
1061
- else :
1062
- # Turn the bytes into actual samples.
1063
- sigall = np .zeros (processnsamp ) # 1d array of actual samples
1064
- sigall [0 ::2 ] = sigbytes [0 ::3 ] + 256 * \
1065
- np .bitwise_and (sigbytes [1 ::3 ], 0x0f ) # Even numbered samples
1066
-
1067
- if len (sigall ) > 1 :
1068
- # Odd numbered samples
1069
- sigall [1 ::2 ] = sigbytes [2 ::3 ] + 256 * \
1070
- np .bitwise_and (sigbytes [1 ::3 ] >> 4 , 0x0f )
1071
- if floorsamp : # Remove extra sample read
1072
- sigall = sigall [floorsamp :]
1073
-
1074
- # Remove extra sample read if originally odd sampled
1075
- if nsamp % 2 :
1076
- sigall = sigall [:- 1 ]
1077
-
1078
- # Convert to int64 to be able to hold -ve values
1079
- sigall = sigall .astype ('int' )
1080
- # Loaded values as unsigned. Convert to 2's complement form: values
1081
- # > 2^11-1 are negative.
1082
- sigall [sigall > 2047 ] -= 4096
1083
- # Give the average sample in each frame for each channel
1084
- sig = np .zeros ([readlen , nsig ])
1085
- for ch in range (0 , nsig ):
1086
- if sampsperframe [ch ] == 1 :
1087
- sig [:, ch ] = sigall [
1088
- sum (([0 ] + sampsperframe )[:ch + 1 ])::tsampsperframe ]
1089
- else :
1090
- for frame in range (0 , sampsperframe [ch ]):
1091
- sig [:, ch ] += sigall [sum (([0 ] + sampsperframe )
1092
- [:ch + 1 ]) + frame ::tsampsperframe ]
1093
- sig = (sig / sampsperframe ).astype ('int' )
1094
- # Three 10 bit samples packed into 4 bytes with 2 bits discarded
1095
- elif fmt == '310' :
1096
-
1097
- # Read the bytes from the file as unsigned integer blocks
1098
- sigbytes , bytesloaded = getdatbytes (filename , dirname , pbdir , fmt , nsamp , startbyte )
1099
-
1100
- if tsampsperframe == nsig : # No extra samples/frame
1101
- # Turn the bytes into actual samples.
1102
- # 1d array of actual samples. Fill the individual triplets.
1103
-
1104
- sig = np .zeros (nsamp )
1105
-
1106
- sig [0 ::3 ] = (sigbytes [0 ::4 ] >> 1 )[0 :len (sig [0 ::3 ])] + 128 * \
1107
- np .bitwise_and (sigbytes [1 ::4 ], 0x07 )[0 :len (sig [0 ::3 ])]
1108
- if len (sig > 1 ):
1109
- sig [1 ::3 ] = (sigbytes [2 ::4 ] >> 1 )[0 :len (sig [1 ::3 ])] + 128 * \
1110
- np .bitwise_and (sigbytes [3 ::4 ], 0x07 )[0 :len (sig [1 ::3 ])]
1111
- if len (sig > 2 ):
1112
- sig [2 ::3 ] = np .bitwise_and ((sigbytes [1 ::4 ] >> 3 ), 0x1f )[0 :len (
1113
- sig [2 ::3 ])] + 32 * np .bitwise_and (sigbytes [3 ::4 ] >> 3 , 0x1f )[0 :len (sig [2 ::3 ])]
1114
- # First signal is 7 msb of first byte and 3 lsb of second byte.
1115
- # Second signal is 7 msb of third byte and 3 lsb of forth byte
1116
- # Third signal is 5 msb of second byte and 5 msb of forth byte
1117
-
1118
- if floorsamp : # Remove extra sample read
1119
- sig = sig [floorsamp :]
1120
- # Reshape into final array of samples
1121
- sig = sig .reshape (readlen , nsig )
1122
- # Convert to int64 to be able to hold -ve values
1123
- sig = sig .astype ('int' )
1124
- # Loaded values as unsigned. Convert to 2's complement form: values
1125
- # > 2^9-1 are negative.
1126
- sig [sig > 511 ] -= 1024
1127
-
1128
- else : # At least one channel has multiple samples per frame. All extra samples are averaged.
1129
- # Turn the bytes into actual samples.
1130
- # 1d array of actual samples. Fill the individual triplets.
1131
- sigall = np .zeros (nsamp )
1132
- sigall [0 ::3 ] = (sigbytes [0 ::4 ] >> 1 )[0 :len (
1133
- sigall [0 ::3 ])] + 128 * np .bitwise_and (sigbytes [1 ::4 ], 0x07 )[0 :len (sigall [0 ::3 ])]
1134
- if len (sigall > 1 ):
1135
- sigall [1 ::3 ] = (sigbytes [2 ::4 ] >> 1 )[0 :len (
1136
- sigall [1 ::3 ])] + 128 * np .bitwise_and (sigbytes [3 ::4 ], 0x07 )[0 :len (sigall [1 ::3 ])]
1137
- if len (sigall > 2 ):
1138
- sigall [2 ::3 ] = np .bitwise_and ((sigbytes [1 ::4 ] >> 3 ), 0x1f )[0 :len (
1139
- sigall [2 ::3 ])] + 32 * np .bitwise_and (sigbytes [3 ::4 ] >> 3 , 0x1f )[0 :len (sigall [2 ::3 ])]
1140
- if floorsamp : # Remove extra sample read
1141
- sigall = sigall [floorsamp :]
1142
- # Convert to int64 to be able to hold -ve values
1143
- sigall = sigall .astype ('int' )
1144
- # Loaded values as unsigned. Convert to 2's complement form: values
1145
- # > 2^9-1 are negative.
1146
- sigall [sigall > 511 ] -= 1024
1147
-
1148
- # Give the average sample in each frame for each channel
1149
- sig = np .zeros ([readlen , nsig ])
1150
- for ch in range (0 , nsig ):
1151
- if sampsperframe [ch ] == 1 :
1152
- sig [:, ch ] = sigall [
1153
- sum (([0 ] + sampsperframe )[:ch + 1 ])::tsampsperframe ]
1154
- else :
1155
- for frame in range (0 , sampsperframe [ch ]):
1156
- sig [:, ch ] += sigall [sum (([0 ] + sampsperframe )
1157
- [:ch + 1 ]) + frame ::tsampsperframe ]
1158
- sig = (sig / sampsperframe ).astype ('int' )
1159
-
1160
- elif fmt == '311' : # Three 10 bit samples packed into 4 bytes with 2 bits discarded
1161
-
1162
- # Read the bytes from the file as unsigned integer blocks
1163
- sigbytes , bytesloaded = getdatbytes (filename , dirname , pbdir , fmt , nsamp , startbyte )
1164
-
1165
- if tsampsperframe == nsig : # No extra samples/frame
1166
- # Turn the bytes into actual samples.
1167
- # 1d array of actual samples. Fill the individual triplets.
1168
- sig = np .zeros (nsamp )
1169
-
1170
- sig [0 ::3 ] = sigbytes [0 ::4 ][
1171
- 0 :len (sig [0 ::3 ])] + 256 * np .bitwise_and (sigbytes [1 ::4 ], 0x03 )[0 :len (sig [0 ::3 ])]
1172
- if len (sig > 1 ):
1173
- sig [1 ::3 ] = (sigbytes [1 ::4 ] >> 2 )[0 :len (sig [1 ::3 ])] + 64 * \
1174
- np .bitwise_and (sigbytes [2 ::4 ], 0x0f )[0 :len (sig [1 ::3 ])]
1175
- if len (sig > 2 ):
1176
- sig [2 ::3 ] = (sigbytes [2 ::4 ] >> 4 )[0 :len (sig [2 ::3 ])] + 16 * \
1177
- np .bitwise_and (sigbytes [3 ::4 ], 0x7f )[0 :len (sig [2 ::3 ])]
1178
- # First signal is first byte and 2 lsb of second byte.
1179
- # Second signal is 6 msb of second byte and 4 lsb of third byte
1180
- # Third signal is 4 msb of third byte and 6 msb of forth byte
1181
- if floorsamp : # Remove extra sample read
1182
- sig = sig [floorsamp :]
1183
- # Reshape into final array of samples
1184
- sig = sig .reshape (readlen , nsig )
1185
- # Convert to int64 to be able to hold -ve values
1186
- sig = sig .astype ('int' )
1187
- # Loaded values as unsigned. Convert to 2's complement form: values
1188
- # > 2^9-1 are negative.
1189
- sig [sig > 511 ] -= 1024
1190
-
1191
- else : # At least one channel has multiple samples per frame. All extra samples are averaged.
1192
- # Turn the bytes into actual samples.
1193
- # 1d array of actual samples. Fill the individual triplets.
1194
- sigall = np .zeros (nsamp )
1195
- sigall [
1196
- 0 ::3 ] = sigbytes [
1197
- 0 ::4 ][
1198
- 0 :len (
1199
- sigall [
1200
- 0 ::3 ])] + 256 * np .bitwise_and (
1201
- sigbytes [
1202
- 1 ::4 ], 0x03 )[
1203
- 0 :len (
1204
- sigall [
1205
- 0 ::3 ])]
1206
- if len (sigall > 1 ):
1207
- sigall [1 ::3 ] = (sigbytes [1 ::4 ] >> 2 )[0 :len (
1208
- sigall [1 ::3 ])] + 64 * np .bitwise_and (sigbytes [2 ::4 ], 0x0f )[0 :len (sigall [1 ::3 ])]
1209
- if len (sigall > 2 ):
1210
- sigall [2 ::3 ] = (sigbytes [2 ::4 ] >> 4 )[0 :len (
1211
- sigall [2 ::3 ])] + 16 * np .bitwise_and (sigbytes [3 ::4 ], 0x7f )[0 :len (sigall [2 ::3 ])]
1212
- if floorsamp : # Remove extra sample read
1213
- sigall = sigall [floorsamp :]
1214
- # Convert to int64 to be able to hold -ve values
1215
- sigall = sigall .astype ('int' )
1216
- # Loaded values as unsigned. Convert to 2's complement form: values
1217
- # > 2^9-1 are negative.
1218
- sigall [sigall > 511 ] -= 1024
1219
- # Give the average sample in each frame for each channel
1220
- sig = np .zeros ([readlen , nsig ])
1221
- for ch in range (0 , nsig ):
1222
- if sampsperframe [ch ] == 1 :
1223
- sig [:, ch ] = sigall [
1224
- sum (([0 ] + sampsperframe )[:ch + 1 ])::tsampsperframe ]
1225
- else :
1226
- for frame in range (0 , sampsperframe [ch ]):
1227
- sig [:, ch ] += sigall [sum (([0 ] + sampsperframe )
1228
- [:ch + 1 ]) + frame ::tsampsperframe ]
1229
- sig = (sig / sampsperframe ).astype ('int' )
1230
-
1231
- else : # Simple format signals that can be loaded as they are stored.
1232
-
1233
- # Read the dat file in the specified format
1234
- sigbytes , bytesloaded = getdatbytes (filename , dirname , pbdir , fmt , nsamp , startbyte )
1235
-
1236
- # No extra samples/frame. Just reshape results.
1237
- if tsampsperframe == nsig :
1238
- sig = sigbytes .reshape (readlen , nsig ).astype ('int' )
1239
- # At least one channel has multiple samples per frame. Extra samples are averaged.
1240
- else :
1241
- # Keep the first sample in each frame for each channel
1242
- sig = np .zeros ([readlen , nsig ])
1243
- for ch in range (0 , nsig ):
1244
- if sampsperframe [ch ] == 1 :
1245
- sig [:, ch ] = sigbytes [sum (([0 ] + sampsperframe )[:ch + 1 ])::tsampsperframe ]
1246
- else :
1247
- for frame in range (0 , sampsperframe [ch ]):
1248
- sig [:, ch ] += sigbytes [sum (([0 ] + sampsperframe )
1249
- [:ch + 1 ]) + frame ::tsampsperframe ]
1250
- sig = (sig / sampsperframe ).astype ('int' )
1251
-
1252
- # Adjust for byte offset formats
1253
- if fmt == '80' :
1254
- sig = sig - 128
1255
- elif fmt == '160' :
1256
- sig = sig - 32768
1257
-
1258
- return sig , bytesloaded
1259
-
1260
-
1261
-
1262
976
# Bytes required to hold each sample (including wasted space) for
1263
977
# different wfdb formats
1264
978
bytespersample = {'8' : 1 , '16' : 2 , '24' : 3 , '32' : 4 , '61' : 2 ,
0 commit comments