This repository has been archived by the owner on May 3, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
FindPlans.m
224 lines (178 loc) · 6.9 KB
/
FindPlans.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
function plans = FindPlans(varargin)
% FindPlans loads all delivery plan trial UIDs from a specified TomoTherapy
% patient archive. Only approved, non-DQA plans are returned. This function
% has currently been validated for version 3.X, 4.X and 5.X archives.
%
% The following variables are required for proper execution:
% varargin{1}: path to the patient archive XML file
% varargin{2}: name of patient XML file in path
% varargin{3} (optional): type of plan to load ('Helical'). If left out,
% all plan types are returned.
%
% The following variable is returned upon succesful completion:
% plans: cell array of approved plan UIDs and plan labels
%
% Below is an example of how this function is used:
%
% path = '/path/to/archive/';
% name = 'Anon_0001_patient.xml';
% plans = FindPlans(path, name);
%
% % This time only retrieve Helical plans
% helical = FindPlans(path, name, 'Helical');
%
% Author: Mark Geurts, mark.w.geurts@gmail.com
% Copyright (C) 2015 University of Wisconsin Board of Regents
%
% This program 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.
%
% This program 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 http://www.gnu.org/licenses/.
% Execute in try/catch statement
try
% Log start of matching and start timer
if exist('Event', 'file') == 2
Event(sprintf('Searching %s for approved plans', varargin{2}));
tic;
end
% If a third argument was provided
if nargin == 3 && exist('Event', 'file') == 2
Event(sprintf('Plan types restricted to %s', varargin{3}));
end
% The patient XML is parsed using xpath class
import javax.xml.xpath.*
% Read in the patient XML and store the Document Object Model node
if exist('Event', 'file') == 2
Event('Loading file contents data using xmlread');
end
doc = xmlread(fullfile(varargin{1}, varargin{2}));
% Initialize a new xpath instance to the variable factory
factory = XPathFactory.newInstance;
% Initialize a new xpath to the variable xpath
xpath = factory.newXPath;
% Declare a new xpath search expression. Search for all fullPlanDataArrays
expression = ...
xpath.compile('//fullPlanDataArray/fullPlanDataArray/plan/briefPlan');
% Retrieve the results
nodeList = expression.evaluate(doc, XPathConstants.NODESET);
% Preallocate cell array
plans = cell(2, nodeList.getLength);
% Log number of delivery plans found
if exist('Event', 'file') == 2
Event(sprintf('%i plans found, now searching for approval status', ...
nodeList.getLength));
end
% Loop through the deliveryPlanDataArrays
for i = 1:nodeList.getLength
% Retrieve a handle to this delivery plan
node = nodeList.item(i-1);
% Search for approved plan trial UID
subexpression = xpath.compile('approvedPlanTrialUID');
% Evaluate xpath expression and retrieve the results
subnodeList = subexpression.evaluate(node, XPathConstants.NODESET);
% If no approved plan trial UID was found, continue to next result
if subnodeList.getLength == 0
continue
end
% Retrieve a handle to the results
subnode = subnodeList.item(0);
% Otherwise, if approved plan trial UID is empty, continue
if strcmp(char(subnode.getFirstChild.getNodeValue), '') || ...
strcmp(char(subnode.getFirstChild.getNodeValue), ...
'* * * DO NOT CHANGE THIS STRING VALUE * * *')
continue
end
% If a third argument was provided
if nargin == 3
% Search for plan delivery type
subexpression = xpath.compile('planDeliveryType');
% Evaluate xpath expression and retrieve the results
subnodeList = subexpression.evaluate(node, XPathConstants.NODESET);
% If plan delivery type was found, continue to next result
if subnodeList.getLength == 0
continue
end
% Retrieve a handle to the results
subnode = subnodeList.item(0);
% Otherwise, if approved plan delivery type is not equal to the
% provided type, continue
if ~strcmp(char(subnode.getFirstChild.getNodeValue), varargin{3})
continue
end
end
% Search for plan type
subexpression = xpath.compile('typeOfPlan');
% Evaluate xpath expression and retrieve the results
subnodeList = subexpression.evaluate(node, XPathConstants.NODESET);
% If plan type was found, continue to next result
if subnodeList.getLength == 0
continue
end
% Retrieve a handle to the results
subnode = subnodeList.item(0);
% Otherwise, if plan type is not PATIENT, continue
if ~strcmp(char(subnode.getFirstChild.getNodeValue), 'PATIENT')
continue
end
% Search for plan database UID
subexpression = xpath.compile('dbInfo/databaseUID');
% Evaluate xpath expression and retrieve the results
subnodeList = subexpression.evaluate(node, XPathConstants.NODESET);
% If no database UID was found, continue to next result
if subnodeList.getLength == 0
continue
end
% Otherwise, retrieve a handle to the results
subnode = subnodeList.item(0);
% Store the plan UID
plans{i, 1} = char(subnode.getFirstChild.getNodeValue);
% Search for plan label
subexpression = xpath.compile('planLabel');
% Evaluate xpath expression and retrieve the results
subnodeList = subexpression.evaluate(node, XPathConstants.NODESET);
% If plan label was found
if subnodeList.getLength == 0
plans{i, 2} = 'UNK';
else
% Retrieve a handle to the results
subnode = subnodeList.item(0);
% Store the plan label
plans{i, 2} = char(subnode.getFirstChild.getNodeValue);
end
end
% Remove empty cells due invalid plans
p = plans';
plans = reshape(p(~cellfun(@isempty, p)), 2, [])';
% Clear temporary variables
clear doc factory xpath i node subnode nodeList subnodeList expression ...
subexpression;
% If no valid delivery plans were found
if size(plans, 1) == 0
% Throw a warning
if exist('Event', 'file') == 2
Event(sprintf('No approved plans found in %s', varargin{2}), 'WARN');
end
% Otherwise the execution was successful
else
% Log completion
if exist('Event', 'file') == 2
Event(sprintf(['%i approved plans successfully identified in ', ...
'%0.3f seconds'], size(plans, 1), toc));
end
end
% Catch errors, log, and rethrow
catch err
if exist('Event', 'file') == 2
Event(getReport(err, 'extended', 'hyperlinks', 'off'), 'ERROR');
else
rethrow(err);
end
end