-
Notifications
You must be signed in to change notification settings - Fork 33
Home
This project provides reference implementations of readers for the Philips Sierra ECG XML format (v. 1.03 and 1.04), specifically focusing on the XLI compression format used. There are sample libraries for:
The XLI compression scheme utilizes LZW compression of deinterleaved delta codes. The format itself is not documented publicly, and the example applications given by Philips are not cross platform. This project enables end users of Sierra ECG data to utilize it in the language or their choice and on the platform of their choice.
The XLI compression format is relatively straightforward. Each lead is stored in a contiguous block of data, delimited by header records. Each header record describes the information necessary to decompress a given lead. The general decompression process is as follows:
- Read the 8-byte header
- Bytes 0-3: compressed data size (32-bit integer)
- Bytes 4-5: currently unknown what it signifies, but always 1 (16-bit signed integer).
- Bytes 6-7: first delta code in the sequence (16-bit signed integer).
- Read compressed data size bytes
- Decompress using LZW with 10-bit codes.
- The resulting buffer is split into two halves, interleave to create 16-bit delta codes
- The first half contains the most significant bytes
- The second half contains the least significant bytes
- Decode the data from the delta codes
- Reconstruct leads III, aVR, aVL, and aVF from leads I and II
The decompressed data is split into two halves, the MSB in the first half and the LSB in the second half. This is presumably done to improve the compression as the is little difference among the MSBs.
# input contains the decompressed data
# output will contain the interleaved 16-bit delta codes
fun unpack( input[], output[], nSamples )
for i <- 1..nSamples
output[i] <- (input[i] << 8) | input[nSamples + i]
endfor
endfun
The delta coding scheme used appears to require the two prior samples and is bias-64; this is possibly a form of linear predictive coding.
# output contains the 16-bit delta codes
# first is the 16-bit delta code from the chunk header
fun deltaDecompression( output[], nSamples, first )
x <- output[1]
y <- output[2]
prev <- first
for i <- 3..nSamples
z <- (2 * y) - x - prev
prev <- output[i] - 64
output[i] <- z
x <- y
y <- z
endfor
endfun
Reconstruction of the remaining limb leads (III, aVR, aVL, and aVF) should be done after the completion of the delta decompression. The channel data for each of the leads appears to be used to ensure the proper sign of the output data, and also includes what may be a noise component.
# Lead III
for i <- 1..nSamples
leads{III}[i] = leads{II}[i] - leads{I}[i] - leads{III}[i]
endfor
# Leads aVR, aVL, and aVF
# (these rely on Lead III, so be sure to calculate it first)
for i <- 1..nSamples
leads{aVR}[i] = -leads{aVR}[i] - (leads{I}[i] + leads{II}[i]) / 2
leads{aVL}[i] = (leads{I}[i] - leads{III}[i]) / 2 - leads{aVL}[i]
leads{aVF}[i] = (leads{II}[i] + leads{III}[i]) / 2 - leads{aVF}[i]
endfor