-
Notifications
You must be signed in to change notification settings - Fork 6
/
load_hl7xml.m
129 lines (105 loc) · 4.42 KB
/
load_hl7xml.m
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% BRAVEHEART - Open source software for electrocardiographic and vectorcardiographic analysis
% load_hl7xml.m -- Load HL7 XML ECGs
% Copyright 2016-2024 Hans F. Stabenau and Jonathan W. Waks
%
% Source code/executables: https://github.com/BIVectors/BRAVEHEART
% Contact: braveheart.ecg@gmail.com
%
% BRAVEHEART is free software: you can redistribute it and/or modify it under the terms of the GNU
% General Public License as published by the Free Software Foundation, either version 3 of the License,
% or (at your option) any later version.
%
% BRAVEHEART is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
% without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% See the GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License along with this program.
% If not, see <https://www.gnu.org/licenses/>.
%
% This software is for research purposes only and is not intended to diagnose or treat any disease.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [hz, I, II, III, avR, avF, avL, V1, V2, V3, V4, V5, V6] = load_hl7xml(filename)
% Mortara HL7 XML format - outputs in millivolts
% Declare variables
I = [];
II = [];
III = [];
avR = [];
avL = [];
avF = [];
V1 = [];
V2 = [];
V3 = [];
V4 = [];
V5 = [];
V6 = [];
% Read XML into a structure
D = readstruct(filename);
% Extract seconds per sample and convert to Hz
% Must use component(1) for the current file structure
time_string = D.component.series.component.sequenceSet.component(1).sequence.code.codeAttribute;
hz = 1/D.component.series.component.sequenceSet.component(1).sequence.value.increment.valueAttribute;
% Confirm that this is the correct tag to get the frequency
if ~strcmp(time_string, "TIME_ABSOLUTE")
error('Unexpected XML structure - unable to find signal frequency');
end
if ~isnumeric(hz)
error('Unexpected XML structure - frequency not numeric');
end
% Extract signal scale
scale = D.component.series.component.sequenceSet.component(2).sequence.value.scale.valueAttribute; % mv or uv per unit
scale_units = D.component.series.component.sequenceSet.component(2).sequence.value.scale.unitAttribute; % text of units
if ~isnumeric(scale)
error('Unexpected XML structure - scale per unit not numeric');
end
% To get signals from units to mv, multiple signal by scale, and then
% divide by 1000 if microvolts
if strcmp(scale_units, "uV")
scale = scale / 1000; % convert microvolts to millivolts
elseif strcmp(scale_units, "mV")
% leave scale as is if in mV already
end
% Lead names/signals
% max number of signals in the rhythm strip signal format
max_component = size(D.component.series.component.sequenceSet.component,2);
for i = 2:max_component
lead_name = D.component.series.component.sequenceSet.component(i).sequence.code.codeAttribute;
signal = D.component.series.component.sequenceSet.component(i).sequence.value.digits;
% Remove end of line characters that can be an issue on some systems
signal = regexprep(signal, '\r\n|\n|\r', '');
switch lead_name
case "MDC_ECG_LEAD_I"
I = str2num(signal).*scale;
case "MDC_ECG_LEAD_II"
II = str2num(signal).*scale;
case "MDC_ECG_LEAD_III"
III = str2num(signal).*scale;
case "MDC_ECG_LEAD_AVR"
avR = str2num(signal).*scale;
case "MDC_ECG_LEAD_AVL"
avL = str2num(signal).*scale;
case "MDC_ECG_LEAD_AVF"
avF = str2num(signal).*scale;
case "MDC_ECG_LEAD_V1"
V1 = str2num(signal).*scale;
case "MDC_ECG_LEAD_V2"
V2 = str2num(signal).*scale;
case "MDC_ECG_LEAD_V3"
V3 = str2num(signal).*scale;
case "MDC_ECG_LEAD_V4"
V4 = str2num(signal).*scale;
case "MDC_ECG_LEAD_V5"
V5 = str2num(signal).*scale;
case "MDC_ECG_LEAD_V6"
V6 = str2num(signal).*scale;
otherwise
end
end
% Check that are not mising any leads
if isempty(I) || isempty(II) || isempty(III) || ...
isempty(avR) || isempty(avL) || isempty(avF) || ...
isempty(V1) || isempty(V2) || isempty(V3) || ...
isempty(V4) || isempty(V5) || isempty(V6)
error('Missing one or more leads from xml file');
end