Branch data Line data Source code
1 : : /**
2 : : * @author: Shuran Wang
3 : : * @date: December 26, 2021
4 : : *
5 : : * \file file_parser.cxx \brief External file format wrapper implementation
6 : : *
7 : : * This file implements wrappers to external file format (XML) parsers
8 : : */
9 : :
10 : : #include <iostream>
11 : : #include <fstream>
12 : : #include "file_parser.h"
13 : : #include <algorithm>
14 : :
15 : : //! Default Constructor
16 : 0 : Parser::Parser() {
17 : 0 : _injection_points.region_id = -1; // not defined
18 : 0 : _sources.max_sources = -1; // not defined
19 : 0 : }
20 : :
21 : : /**
22 : : * Regular Constructor, reads data from data file
23 : : * @param filename [in]: Path to the data file
24 : : */
25 : 72 : Parser::Parser(string filename) {
26 [ + - ][ + - ]: 36 : if (read_from_xml(filename)) {
[ + - ]
27 [ + - ]: 36 : fprintf(stderr, "\n\033[1;%dmSuccessfully read XML file.\033[0m\n", 35);
28 : : }
29 : :
30 : : // TODO: add checks
31 : 36 : }
32 : :
33 : : /*
34 : : * Regular Destructor, deletes sources
35 : : */
36 : 62 : Parser::~Parser() {
37 [ + + ]: 311 : for (unsigned i = 0; i < _sources.sources_init.size(); i++) {
38 [ + - ][ + - ]: 280 : if (_sources.sources_init[i]) delete _sources.sources_init[i];
39 : : }
40 : 31 : }
41 : :
42 : 293 : void Parser::read_line_source(const boost::property_tree::ptree& token) {
43 : : using boost::property_tree::ptree;
44 : 586 : string location; // location for endpoint0
45 [ + - ]: 586 : vector<SP_Point> endpoints;
46 : 293 : double length = _INFINITY_;
47 [ + - ][ + - ]: 2637 : BOOST_FOREACH(ptree::value_type const& e, token) {
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ]
48 [ + - ][ + + ]: 1172 : if (e.first == "endpoint") {
49 : : // create endpoint
50 [ + - ]: 1172 : SP_Point endpoint;
51 [ + - ][ + - ]: 586 : endpoint.set_xcoord (e.second.get<float>("x"));
[ + - ]
52 [ + - ][ + - ]: 586 : endpoint.set_ycoord (e.second.get<float>("y"));
[ + - ]
53 [ + - ][ + - ]: 586 : endpoint.set_zcoord (e.second.get<float>("z"));
[ + - ]
54 : :
55 [ + + ]: 586 : if (endpoints.size() == 0) { // first endpoint
56 [ + - ][ + - ]: 293 : location = e.second.get<string>("<xmlattr>.location", "proximal");
[ + - ]
57 [ + - ]: 293 : endpoints.push_back(endpoint);
58 : :
59 : : // cout << "Pushing proximal endpoint " << endpoint << endl;
60 : : } else {
61 [ + - ][ + - ]: 293 : if (location == "proximal") {
62 [ + - ]: 293 : endpoints.push_back(endpoint);
63 : : // cout << "Pushing distal endpoint " << endpoint << endl;
64 [ # # ][ # # ]: 0 : } else if (location == "distal") {
65 [ # # ]: 0 : endpoints.emplace(endpoints.begin(), endpoint);
66 : : // cout << "Pushing proximal endpoint " << endpoint << endl;
67 : : } else {
68 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmInvalid attribute for endpoint, should be proximal or distal. \033[0m\n", 33);
69 : : }
70 : : }
71 [ + - ][ + + ]: 586 : } else if (e.first == "length") {
72 : : // set length
73 [ + - ]: 293 : length = boost::lexical_cast<double>(e.second.data());
74 [ + - ][ + - ]: 293 : } else if (e.first != "<xmlcomment>" && e.first != "<xmlattr>") {
[ + - ][ - + ]
[ - + ]
75 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmInvalid tag in source, should be endpoint. Exiting... \033[0m\n", 31);
76 : 0 : exit(-1);
77 : : }
78 : : }
79 : :
80 : : // if endpoints are not entered, use entered length to generate initial solution
81 [ - + ]: 293 : if (endpoints.size() == 0) {
82 [ # # ]: 0 : if (_sources.sources_init.size() != 0) {
83 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmAt least 1 line source not entered, ignoring entered sources and will generate initial solution. Exiting... \033[0m\n", 31);
84 : 0 : _sources.sources_init.clear();
85 : : }
86 [ # # ]: 0 : _sources.lengths.push_back(length);
87 : 0 : return;
88 : : }
89 : :
90 [ - + ]: 293 : if (endpoints.size() != 2) {
91 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmLine sources should have 2 endpoints, entered %lu. Exiting... \033[0m\n", 31, endpoints.size());
92 : 0 : exit(-1);
93 : : }
94 : :
95 : : // cout << "endpoints[0] " << endpoints[0] << " endpoints[1] " << endpoints[1] << endl;
96 [ - + ][ # # ]: 293 : if (length == _INFINITY_) length = endpoints[0].get_distance_from(endpoints[1]);
97 [ + - ]: 293 : _sources.lengths.push_back(length);
98 : :
99 [ + - ][ + - ]: 293 : Src_Line* s = new Src_Line(endpoints[0], endpoints[1]);
100 : : // cout << "Reading source " << s << endl;
101 [ + - ][ + - ]: 293 : _sources.sources_init.push_back(s);
102 : : }
103 : :
104 : 18 : void Parser::read_point_source(const boost::property_tree::ptree& token) {
105 : : using boost::property_tree::ptree;
106 : 36 : vector<SP_Point> endpoints;
107 [ + - ][ + - ]: 90 : BOOST_FOREACH(ptree::value_type const& e, token) {
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ]
108 [ + - ][ + + ]: 36 : if (e.first == "endpoint") {
109 : : // create endpoint
110 [ + - ]: 36 : SP_Point endpoint;
111 [ + - ][ + - ]: 18 : endpoint.set_xcoord (e.second.get<float>("x"));
[ + - ]
112 [ + - ][ + - ]: 18 : endpoint.set_ycoord (e.second.get<float>("y"));
[ + - ]
113 [ + - ][ + - ]: 18 : endpoint.set_zcoord (e.second.get<float>("z"));
[ + - ]
114 : :
115 [ + - ]: 18 : if (endpoints.size() == 0) { // first endpoint
116 [ + - ]: 18 : endpoints.push_back(endpoint);
117 : : } else {
118 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmPoint source should only have 1 endpoint. Exiting... \033[0m\n", 31);
119 : 0 : exit(-1);
120 : : }
121 [ + - ][ + - ]: 18 : } else if (e.first != "<xmlcomment>" && e.first != "<xmlattr>") {
[ + - ][ - + ]
[ - + ]
122 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmInvalid tag in source. Exiting... \033[0m\n", 31);
123 : 0 : exit(-1);
124 : : }
125 : : }
126 : :
127 : : // check for incomplete point source
128 [ - + ]: 18 : if (endpoints.size() == 0) {
129 [ # # ]: 0 : if (_sources.sources_init.size() != 0) {
130 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmAt least 1 point source not complete, ignoring entered sources and will generate initial solution. Exiting... \033[0m\n", 31);
131 : 0 : _sources.sources_init.clear();
132 : : }
133 [ # # ]: 0 : _sources.lengths.push_back(0);
134 : 0 : return;
135 : : }
136 : :
137 [ + - ]: 18 : _sources.lengths.push_back(0);
138 : :
139 [ + - ][ + - ]: 18 : Src_Point* s = new Src_Point(endpoints[0].get_xcoord(), endpoints[0].get_ycoord(), endpoints[0].get_zcoord());
[ + - ][ + - ]
[ + - ]
140 [ + - ][ + - ]: 18 : _sources.sources_init.push_back(s);
141 : : }
142 : :
143 : : //!
144 : : //! This method reads the fullmonte parameters specified in xml file
145 : : //! @param token [in]: string value of the <source> tag
146 : : //!
147 : 0 : void Parser::read_cutend_source(const boost::property_tree::ptree& token) {
148 : 0 : vector<SP_Point> endpoints;
149 : 0 : float r = 0, na= 0;
150 [ # # ]: 0 : SP_Point dir;
151 : 0 : bool set_r = false;
152 : 0 : bool set_na = false;
153 : 0 : bool set_dir = false;
154 : 0 : bool set_endpoint = false;
155 : : using boost::property_tree::ptree;
156 [ # # ][ # # ]: 0 : BOOST_FOREACH(ptree::value_type const& e, token) {
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
157 [ # # ][ # # ]: 0 : if (e.first == "endpoint") {
158 : : // create endpoint
159 [ # # ]: 0 : SP_Point endpoint;
160 [ # # ][ # # ]: 0 : endpoint.set_xcoord (e.second.get<float>("x"));
[ # # ]
161 [ # # ][ # # ]: 0 : endpoint.set_ycoord (e.second.get<float>("y"));
[ # # ]
162 [ # # ][ # # ]: 0 : endpoint.set_zcoord (e.second.get<float>("z"));
[ # # ]
163 : :
164 [ # # ]: 0 : if (endpoints.size() == 0) { // first endpoint
165 [ # # ]: 0 : endpoints.push_back(endpoint);
166 : : } else {
167 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmCut-end source should only have 1 endpoint. Exiting... \033[0m\n", 31);
168 : 0 : exit(-1);
169 : : }
170 : 0 : set_endpoint = true;
171 [ # # ][ # # ]: 0 : } else if (e.first == "radius") {
172 [ # # ]: 0 : r = boost::lexical_cast<float>(e.second.data());
173 : 0 : set_r = true;
174 [ # # ][ # # ]: 0 : } else if (e.first == "na") {
175 [ # # ]: 0 : na = boost::lexical_cast<float>(e.second.data());
176 : 0 : set_na = true;
177 [ # # ][ # # ]: 0 : } else if (e.first == "direction") {
178 : : // create endpoint
179 [ # # ][ # # ]: 0 : dir.set_xcoord (e.second.get<float>("x"));
[ # # ]
180 [ # # ][ # # ]: 0 : dir.set_ycoord (e.second.get<float>("y"));
[ # # ]
181 [ # # ][ # # ]: 0 : dir.set_zcoord (e.second.get<float>("z"));
[ # # ]
182 : 0 : set_dir = true;
183 [ # # ][ # # ]: 0 : } else if (e.first != "<xmlcomment>" && e.first != "<xmlattr>") {
[ # # ][ # # ]
[ # # ]
184 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmInvalid tag in source. Exiting... \033[0m\n", 31);
185 : 0 : exit(-1);
186 : : }
187 : : }
188 : :
189 [ # # ][ # # ]: 0 : if (!(set_dir && set_endpoint && set_na && set_r)) {
[ # # ][ # # ]
190 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmCutEnd source not entered properly. Exiting... \033[0m\n", 31);
191 : 0 : exit(-1);
192 : : }
193 [ # # ]: 0 : _sources.lengths.push_back(0);
194 : :
195 [ # # ]: 0 : Src_CutEnd* s = new Src_CutEnd(r, na, endpoints[0], dir);
196 [ # # ]: 0 : _sources.sources_init.push_back(s);
197 : 0 : }
198 : :
199 : : //!
200 : : //! This method sets the XML file and builds data structures
201 : : //! @param filename [in]: Path to the data file
202 : : //!
203 : 36 : bool Parser::read_from_xml(string filename) {
204 : : // use boost ptree to store xml information
205 : : using boost::property_tree::ptree;
206 [ + - ]: 72 : ptree pt;
207 : :
208 [ + - ]: 36 : fprintf(stderr, "\033[1;%dmReading XML file\033[0m\n", 33);
209 : :
210 : : // create istream to read from file
211 [ + - ]: 72 : ifstream f;
212 [ + - ]: 36 : f.open(filename);
213 [ + - ][ - + ]: 36 : if (!f) {
214 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmCannot open XML File to read. \033[0m\n", 31);
215 : 0 : return false;
216 : : }
217 : :
218 : : // read from xml file into ptree
219 [ + - ]: 36 : read_xml(f, pt);
220 [ + - ]: 36 : f.close();
221 : :
222 : : // traverse ptree
223 : : // fm_params
224 [ + - ]: 36 : fprintf(stderr, "\033[1;%dmReading fm_params\033[0m\n", 36);
225 : 36 : _fm_params_map.clear();
226 : 36 : _params_map.clear();
227 [ + - ][ + - ]: 1116 : BOOST_FOREACH(ptree::value_type const& v, pt.get_child("fm_params")) {
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ]
228 : : // check if tag is valid
229 [ + - ][ + - ]: 1980 : if (v.first == "use_cuda" || v.first == "pnf" || v.first == "num_packets" || v.first == "rand_seed" ||
[ + + ][ + - ]
[ + + ][ + - ]
[ + + ][ + + ]
[ + + ]
230 [ + - ][ + - ]: 1044 : v.first == "wavelength" || v.first == "mesh_file" || v.first == "max_hits" ||
[ + + ][ + - ]
[ + + ][ + + ]
231 [ + + ][ + - ]: 1332 : v.first == "roulette_pr_win" || v.first == "roulette_w_min" || v.first == "max_steps") {
[ + - ][ + + ]
[ + - ][ + + ]
232 [ + - ]: 360 : fprintf(stderr, "\033[1;%dmReading %s\033[0m\n", 36, v.first.c_str());
233 [ + - ][ + - ]: 360 : _fm_params_map[v.first] = v.second.data();
234 [ + - ][ + - ]: 360 : _params_map[v.first] = v.second.data(); // some params will be used by pdt_plan
235 [ + - ][ - + ]: 180 : } else if (v.first != "<xmlcomment>" && v.first != "<xmlattr>") {
[ # # ][ # # ]
[ - + ]
236 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmInvalid tag in fm_params. \033[0m\n", 33);
237 : : }
238 : : }
239 : :
240 : : // program_params
241 [ + - ]: 36 : fprintf(stderr, "\033[1;%dmReading program_params\033[0m\n", 36);
242 [ + - ][ + - ]: 622 : BOOST_FOREACH(ptree::value_type const& v, pt.get_child("program_params")) {
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ]
243 : : // check if tag is valid
244 [ + - ][ + - ]: 1023 : if (v.first == "read_vtk" || v.first == "tumor_weight" || v.first == "run_tests" || v.first == "fm_output_file" ||
[ + + ][ + - ]
[ + + ][ + - ]
[ + + ][ + + ]
[ + - ]
245 [ + - ][ + - ]: 396 : v.first == "override_file_path" || v.first == "vary_tumor_weight" || v.first == "target_tumor_cov" ||
[ + + ][ + - ]
[ + + ][ + - ]
246 [ + - ][ + - ]: 180 : v.first == "final_dist_file" || v.first == "run_rt_feedback" || v.first == "rt_feedback_seed" ||
[ + + ][ + - ]
[ + - ][ + - ]
247 [ + - ][ + - ]: 108 : v.first == "rt_feedback_det_rad" || v.first == "rt_feedback_det_na" || v.first == "rt_feedback_lut_file" ||
[ + - ][ + - ]
[ + - ][ + - ]
248 [ + + ][ + - ]: 586 : v.first == "rt_feedback_lut_size" || v.first == "placement_type") {
[ + - ][ + - ]
249 [ + - ]: 293 : fprintf(stderr, "\033[1;%dmReading %s\033[0m\n", 36, v.first.c_str());
250 [ + - ][ + - ]: 293 : _params_map[v.first] = v.second.data();
251 [ # # ][ # # ]: 0 : } else if (v.first != "<xmlcomment>" && v.first != "<xmlattr>") {
[ # # ][ # # ]
[ # # ]
252 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmInvalid tag in program_params. \033[0m\n", 33);
253 : : }
254 : : }
255 : :
256 [ + - ][ + - ]: 36 : if (_params_map["placement_type"] == "sa") {
[ + - ][ + + ]
257 [ + - ][ + - ]: 8 : _params_map["placement_type"] = "fixed";
[ + - ]
258 : 8 : _run_sa = true;
259 : : }
260 : : else {
261 : 28 : _run_sa = false;
262 : : }
263 : :
264 : : // sources
265 : 36 : _sources.sources_init.clear();
266 [ + - ]: 36 : fprintf(stderr, "\033[1;%dmReading sources\033[0m\n", 36);
267 [ + - ][ + - ]: 252 : BOOST_FOREACH(ptree::value_type const& v, pt.get_child("sources")) {
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ]
268 [ + - ][ + + ]: 108 : if (v.first == "max_sources") {
269 [ + - ]: 36 : fprintf(stderr, "\033[1;%dmReading max_sources\033[0m\n", 36);
270 [ + - ]: 36 : _sources.max_sources = boost::lexical_cast<int>(v.second.data());
271 [ + - ][ + + ]: 72 : } else if (v.first == "line_tailored") {
272 [ + - ]: 36 : fprintf(stderr, "\033[1;%dmReading line_tailored\033[0m\n", 36);
273 [ + - ]: 36 : _sources.tailored = (v.second.data() == "true") ? true : false;
274 [ + - ][ + - ]: 36 : } else if (v.first == "sources_init") {
275 [ + - ]: 36 : fprintf(stderr, "\033[1;%dmReading sources_init\033[0m\n", 36);
276 [ + - ][ + - ]: 658 : BOOST_FOREACH(ptree::value_type const& w, v.second) {
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ]
277 [ + - ][ + - ]: 311 : if (w.first == "source") {
278 [ + - ][ + - ]: 622 : string type = w.second.get<string>("<xmlattr>.type", "");
[ + - ]
279 : :
280 [ + - ][ + + ]: 311 : if (type == "line") {
281 [ + + ][ + + ]: 293 : if (_sources.sources_init.size() == 0 || _sources.source_type == Src_Abstract::Point)
[ + + ]
282 : 35 : _sources.source_type = Src_Abstract::Line;
283 [ + - ]: 258 : else if (_sources.unified_type) {
284 [ - + ]: 258 : if (_sources.source_type != Src_Abstract::Line)
285 : 0 : _sources.unified_type = false;
286 : : }
287 [ + - ]: 293 : read_line_source(w.second);
288 [ + - ][ + - ]: 18 : } else if (type == "point") {
289 [ + + ]: 18 : if (_sources.sources_init.size() == 0) {
290 : 3 : _sources.source_type = Src_Abstract::Point;
291 [ + - ][ + + ]: 15 : } else if (_sources.unified_type && _sources.source_type != Src_Abstract::Line) {
292 [ - + ]: 9 : if (_sources.source_type != Src_Abstract::Point)
293 : 0 : _sources.unified_type = false;
294 : : }
295 [ + - ]: 18 : read_point_source(w.second);
296 [ # # ][ # # ]: 0 : } else if (type == "cut-end") {
297 [ # # ]: 0 : if (_sources.sources_init.size() == 0)
298 : 0 : _sources.source_type = Src_Abstract::CutEnd;
299 [ # # ]: 0 : else if (_sources.unified_type) {
300 [ # # ]: 0 : if (_sources.source_type != Src_Abstract::CutEnd)
301 : 0 : _sources.unified_type = false;
302 : : }
303 [ # # ]: 0 : read_cutend_source(w.second);
304 : : } else {
305 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmNot supported source type. Exiting... \033[0m\n", 31);
306 : 0 : exit(-1);
307 : : }
308 [ # # ][ # # ]: 0 : } else if (w.first != "<xmlcomment>" && w.first != "<xmlattr>") {
[ # # ][ # # ]
[ # # ]
309 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmInvalid tag in sources_init, should be source. \033[0m\n", 33);
310 : : }
311 : : }
312 [ # # ][ # # ]: 0 : } else if (v.first != "<xmlcomment>" && v.first != "<xmlattr>") {
[ # # ][ # # ]
[ # # ]
313 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmInvalid tag in sources. \033[0m\n", 33);
314 : : }
315 : : }
316 : :
317 [ - + ]: 36 : if (_sources.max_sources == -1) {
318 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmRequired field max_sources missing in sources. \033[0m\n", 31);
319 : 0 : return false;
320 : : }
321 : :
322 [ - + ]: 36 : if (_sources.sources_init.size() == 0) {
323 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmInitial solution not provided. \033[0m\n", 31);
324 [ # # ]: 0 : if (!_run_sa) {
325 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmNot running SA, exiting... \033[0m\n", 31);
326 : 0 : return false;
327 : : }
328 : :
329 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmPDT-SPACE will generate an initial solution.\033[0m\n", 31);
330 : 0 : _sources.source_type = Src_Abstract::Line;
331 [ # # ]: 0 : while (_sources.lengths.size() < (unsigned)_sources.max_sources) {
332 [ # # ]: 0 : _sources.lengths.push_back(_INFINITY_);
333 : : }
334 : : }
335 [ + - ]: 36 : fprintf(stderr, "\033[1;%dmDone reading sources\033[0m\n", 36);
336 : :
337 : : // sa_options. Only read if running SA
338 : 36 : _constrain_injection_point = false;
339 [ + + ]: 36 : if (_run_sa) {
340 : : // injection_points
341 : 8 : _injection_points.injection_points.clear();
342 : 8 : _sa_params_map.clear();
343 : : // _placement_mode = PM_NONE;
344 [ + - ]: 8 : fprintf(stderr, "\033[1;%dmReading sa_options\033[0m\n", 36);
345 [ + - ][ + - ]: 88 : BOOST_FOREACH(ptree::value_type const& u, pt.get_child("sa_options")) {
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ]
346 : : // if (u.first == "placement_constraint") {
347 : : // if (u.second.data() == "none") _placement_mode = PM_NONE;
348 : : // else if (u.second.data() == "parallel") _placement_mode = PM_PARALLEL;
349 : : // else if (u.second.data() == "point") _placement_mode = PM_POINT;
350 : : // else {
351 : : // _placement_mode = PM_NONE;
352 : : // fprintf(stderr, "\033[1;%dmInvalid placement mode, defaulting to none. \033[0m\n", 33);
353 : : // }
354 [ + - ][ + - ]: 160 : if (u.first == "beta" || u.first == "lambda" || u.first == "mpt" || u.first == "sa_placement_file" || u.first == "sa_num_packets" ||
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + + ]
355 [ + - ][ + - ]: 136 : u.first == "max_src_distance" || u.first == "min_src_distance" || u.first == "distance_to_boundary" ||
[ + - ][ + + ]
[ + - ][ + + ]
[ - + ]
356 [ + - ]: 16 : u.first == "output_top_placements") {
357 [ + - ]: 24 : fprintf(stderr, "\033[1;%dmReading %s\033[0m\n", 36, u.first.c_str());
358 [ + - ][ + - ]: 24 : _sa_params_map[u.first] = u.second.data();
359 [ + - ][ + + ]: 16 : } else if (u.first == "injection_points") {
360 [ + - ][ + - ]: 8 : _constrain_injection_point = u.second.get<bool>("<xmlattr>.constraint", true);
361 [ + - ][ + - ]: 56 : BOOST_FOREACH(ptree::value_type const& v, u.second) {
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ]
362 [ + - ][ + + ]: 24 : if (v.first == "region_id") {
363 [ + - ]: 8 : _injection_points.region_id = boost::lexical_cast<int>(v.second.data());
364 [ + - ][ + + ]: 16 : } else if (v.first == "point") {
365 [ + - ]: 16 : Parser_injection_point ip;
366 : 8 : ip.id = -1;
367 : 8 : ip.diameter = -1;
368 [ + - ][ + - ]: 72 : BOOST_FOREACH(ptree::value_type const& w, v.second) {
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ]
369 [ + - ][ + + ]: 32 : if (w.first == "id") {
370 [ + - ]: 8 : ip.id = boost::lexical_cast<int>(w.second.data());
371 [ + - ][ + + ]: 24 : } else if (w.first == "diameter") {
372 [ + - ]: 8 : ip.diameter = boost::lexical_cast<float>(w.second.data());
373 [ + - ][ + + ]: 16 : } else if (w.first == "normal") {
374 [ + - ][ + - ]: 8 : float x = w.second.get<float>("x");
375 [ + - ][ + - ]: 8 : float y = w.second.get<float>("y");
376 [ + - ][ + - ]: 8 : float z = w.second.get<float>("z");
377 [ + - ]: 8 : ip.normal = SP_Point(x, y, z);
378 [ + - ][ + - ]: 8 : } else if (w.first == "center") {
379 [ + - ][ + - ]: 8 : float x = w.second.get<float>("x");
380 [ + - ][ + - ]: 8 : float y = w.second.get<float>("y");
381 [ + - ][ + - ]: 8 : float z = w.second.get<float>("z");
382 [ + - ]: 8 : ip.center = SP_Point(x, y, z);
383 [ # # ][ # # ]: 0 : } else if (w.first != "<xmlcomment>") {
384 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmInvalid tag in point. \033[0m\n", 33);
385 : : }
386 : : }
387 [ + - ][ - + ]: 8 : if (ip.id < 0 || ip.diameter < 0) {
388 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmInvalid injection point. \033[0m\n", 31);
389 : 0 : return false;
390 : : }
391 [ + - ][ + - ]: 8 : _injection_points.injection_points.push_back(ip);
392 [ + - ][ + - ]: 8 : } else if (v.first != "<xmlcomment>" && v.first != "<xmlattr>") {
[ + - ][ - + ]
[ - + ]
393 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmInvalid tag in injection_points. \033[0m\n", 33);
394 : : }
395 : : }
396 : :
397 [ - + ]: 8 : if (_injection_points.region_id < 0) {
398 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmMissing injection point region id. \033[0m\n", 31);
399 : 8 : return false;
400 : : }
401 [ + - ][ + - ]: 8 : } else if (u.first == "critical_tissues") {
402 [ + - ]: 16 : stringstream s (u.second.data());
403 : 8 : _critical_regions.clear();
404 : : unsigned region;
405 [ + - ][ + - ]: 32 : while (s >> region) {
[ + + ]
406 [ + - ]: 24 : _critical_regions.insert(region);
407 : : }
408 : :
409 [ + - ]: 8 : cout << "Read SA critical regions: ";
410 [ + + ]: 32 : for (auto const &elem: _critical_regions)
411 [ + - ][ + - ]: 24 : cout << elem << " ";
412 [ + - ]: 8 : cout << endl;
413 [ # # ][ # # ]: 0 : } else if (u.first != "<xmlcomment>") {
414 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmInvalid tag in sa_options. \033[0m\n", 33);
415 : : }
416 : : }
417 [ + - ]: 8 : fprintf(stderr, "\033[1;%dmDone reading sa_options\033[0m\n", 36);
418 : : }
419 : :
420 : : // materials
421 [ + - ]: 36 : fprintf(stderr, "\033[1;%dmReading materials\033[0m\n", 36);
422 : 36 : _materials.clear();
423 [ + - ][ + - ]: 540 : BOOST_FOREACH(ptree::value_type const& u, pt.get_child("materials")) {
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ]
424 [ + - ][ + + ]: 252 : if (u.first == "material") {
425 : : // do material read
426 : 432 : struct Parser_material m;
427 [ + - ][ + - ]: 216 : m.name = u.second.get<string>("<xmlattr>.name", "Unnamed");
[ + - ]
428 [ + - ][ + - ]: 216 : m.id = u.second.get<int>("id");
429 [ + - ]: 216 : fprintf(stderr, "\033[1;%dmReading material %d\033[0m\n", 36, m.id);
430 [ + - ][ + - ]: 216 : m.n = u.second.get<double>("n", 1);
431 [ + - ][ + - ]: 216 : m.g = u.second.get<double>("g", 0);
432 [ + - ][ + - ]: 216 : m.mu_a = u.second.get<double>("mu_a", 0);
433 [ + - ][ + - ]: 216 : m.mu_s = u.second.get<double>("mu_s", 0);
434 [ + - ][ + - ]: 216 : m.is_tumor = u.second.get<bool>("is_tumor", false);
435 [ + + ]: 216 : if (m.id != 0) {
436 : : // only set if not exterior
437 [ + - ][ + - ]: 180 : m.d_min = u.second.get<double>("d_min");
438 [ + - ][ + - ]: 180 : m.d_max = u.second.get<double>("d_max");
439 [ + + ][ + - ]: 180 : if (m.is_tumor && m.d_max < 1e-8) m.d_max = _INFINITY_;
440 [ + - ][ + - ]: 180 : m.guardband = u.second.get<double>("safety_multiplier", 1);
441 : : }
442 : :
443 [ + - ]: 216 : _materials.push_back(m);
444 [ + - ][ + - ]: 36 : } else if (u.first == "matched_boundary") {
445 [ + - ]: 36 : _matched_boundary = (u.second.data() == "true") ? true : false;
446 [ # # ][ # # ]: 0 : } else if (u.first != "<xmlcomment>") {
447 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmInvalid tag in materials. \033[0m\n", 33);
448 : : }
449 : : }
450 : :
451 : : // error checks for materials
452 [ - + ]: 36 : if (_materials.size() == 0) {
453 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmMaterials not read.\033[0m\n", 31);
454 : 0 : return false;
455 : : }
456 : :
457 : : // sort materials by id
458 : 36 : sort(_materials.begin(), _materials.end(), [](const Parser_material & p1,
459 [ + - ]: 756 : const Parser_material & p2) { return p1.id < p2.id; });
460 : :
461 : : // extensive error checks to avoid seg faults
462 : 36 : int last_id = _materials[0].id;
463 : : // check for exterior, id should start from 0
464 [ - + ]: 36 : if (_materials[0].id != 0) {
465 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmExterior (ID 0) not specified. Smallest ID is %u. Exiting... \033[0m\n", 31, _materials[0].id);
466 : 0 : exit(-1);
467 : : }
468 [ + + ]: 216 : for (unsigned i = 1; i < _materials.size(); i++) {
469 : : // check for overlapping ids
470 [ - + ]: 180 : if (_materials[i].id == last_id) {
471 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmMaterial ID should be unique. Exiting... \033[0m\n", 31);
472 : 0 : exit(-1);
473 : : }
474 : :
475 : : // check for discontinuity in indices. TODO: may want to support discontinued material id?
476 [ - + ]: 180 : if (_materials[i].id != last_id + 1) {
477 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmMaterial ID should be continuous. Missing ID %d. Exiting... \033[0m\n", 31, last_id + 1);
478 : 0 : exit(-1);
479 : : }
480 : :
481 : 180 : last_id = _materials[i].id;
482 : : }
483 [ + - ]: 36 : fprintf(stderr, "\033[1;%dmDone reading materials\033[0m\n", 36);
484 : :
485 : 36 : return true;
486 : : }
487 : :
488 : : //! Getter functions for injection points
489 : 4 : Parser_injection_points Parser::get_injection_points() {
490 : 4 : return _injection_points;
491 : : }
492 : :
493 : 4 : void Parser::get_injection_point_options(bool &constrain/*, PlacementMode &mode*/, unsigned &max_num) {
494 : 4 : constrain = _constrain_injection_point;
495 : : // mode = _placement_mode;
496 : 4 : max_num = (unsigned) (_sources.max_sources);
497 : 4 : }
498 : :
499 : 36 : void Parser::get_injection_point_options(bool &constrain/*, PlacementMode &mode*/) {
500 : 36 : constrain = _constrain_injection_point;
501 : : // mode = _placement_mode;
502 : 36 : }
503 : :
504 : : //! Getter function for sources called by sa_engine
505 : 4 : void Parser::get_sources(vector<SP_Line> &sources, vector<double> &lengths) {
506 [ - + ][ # # ]: 4 : if (!((_sources.source_type == Src_Abstract::Line || _sources.source_type == Src_Abstract::Point) && _sources.unified_type)) {
[ - + ]
507 : 0 : fprintf(stderr, "\033[1;%dmCurrently only line and point sources supported in SA.\nExiting...\033[0m\n", 31);
508 : 0 : std::exit(-1);
509 : : }
510 : 4 : sources.clear();
511 : 4 : sources.resize(_sources.sources_init.size());
512 [ + + ]: 16 : for (unsigned i = 0; i < _sources.sources_init.size(); i++) {
513 [ + - ]: 12 : if (_sources.sources_init[i]->get_type() == Src_Abstract::Line) {
514 [ + - ]: 12 : sources[i] = *((SP_Line*) (Src_Line*) (_sources.sources_init[i]));
515 : : } else {
516 [ # # ]: 0 : sources[i] = SP_Line(*((SP_Point*) (Src_Point*) _sources.sources_init[i]), *((SP_Point*) _sources.sources_init[i]));
517 : : }
518 : 12 : cout << "Reading source " << sources[i] << endl;
519 : : }
520 : 4 : lengths = _sources.lengths;
521 : 4 : }
522 : :
523 : : //! Getter function for sources called by pdt_plan
524 : 0 : void Parser::get_sources(vector<Src_Abstract*> &sources) {
525 : 0 : sources = _sources.sources_init;
526 : 0 : }
527 : :
528 : : //! Getter function for source types. If mixed type return mixed
529 : 36 : string Parser::get_source_type() {
530 [ + - ]: 36 : if (_sources.unified_type) {
531 [ + + - - ]: 36 : switch (_sources.source_type) {
532 : : case Src_Abstract::Line:
533 [ + + ][ + - ]: 35 : if (_sources.tailored) return "tailored";
534 [ + - ]: 34 : return "line";
535 : : case Src_Abstract::Point:
536 [ + - ]: 1 : return "point";
537 : : case Src_Abstract::CutEnd:
538 [ # # ]: 0 : return "cut-end";
539 : : default:
540 [ # # ]: 0 : return "undefined";
541 : : }
542 [ # # ]: 36 : } else return "mixed";
543 : : }
544 : :
545 : : //! Get the number of valid injection points
546 : 36 : unsigned Parser::get_num_injection_points() {
547 : 36 : return (unsigned) (_injection_points.injection_points.size());
548 : : }
549 : :
550 : : //! Gets the PDT-SPACE tissue properties
551 : 36 : void Parser::get_tissue_properties (vector<double>& dmin, vector<double>& dmax, vector<double>& guard,
552 : : unordered_map<unsigned, string>& names) {
553 : :
554 : 36 : dmin.resize(_materials.size() - 1);
555 : 36 : dmax.resize(_materials.size() - 1);
556 : 36 : guard.resize(_materials.size() - 1);
557 : 36 : names.clear();
558 : :
559 [ + - ][ + - ]: 36 : names[0] = _materials[0].name;
560 : :
561 [ + + ]: 216 : for (unsigned i = 1; i < _materials.size(); i++) {
562 [ + - ][ + - ]: 180 : names[i] = _materials[i].name;
563 : 180 : guard[i - 1] = _materials[i].guardband;
564 : :
565 [ + + ]: 180 : if (_materials[i].is_tumor) {
566 [ - + ]: 36 : if (_materials[i].d_min < 1e-8) {
567 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmMinimum dose threshold on Tumor CANNOT be ZERO! Exiting...\033[0m\n", 31);
568 : 0 : exit(-1);
569 : : }
570 : 36 : dmin[i - 1] = _materials[i].d_min;
571 : :
572 [ - + ]: 36 : if (_materials[i].d_max < 1e-8) {
573 : 0 : dmax[i - 1] = _INFINITY_;
574 : : } else {
575 : 36 : dmax[i - 1] = _materials[i].d_max;
576 : : }
577 : :
578 [ + + ]: 36 : if (guard[i - 1] < 1) {
579 [ + - ]: 1 : fprintf(stderr, "\033[1;%dmWarning: guardband on tumor < 1!\033[0m\n", 33);
580 : : }
581 : : } else {
582 : 144 : dmin[i - 1] = _materials[i].d_min; // Previously hardcoded to 0, keep or not?
583 : 144 : dmax[i - 1] = _materials[i].d_max;
584 : :
585 [ - + ]: 144 : if (guard[i - 1] > 1) {
586 [ # # ]: 0 : fprintf(stderr, "\033[1;%dmWarning: guardband on OAR > 1!\033[0m\n", 33);
587 : : }
588 : : }
589 : : }
590 : 36 : }
591 : :
592 : : //! Gets the tumor region ids in an unordered_set
593 : 58 : void Parser::get_tumor_regions (unordered_set<unsigned>& tumor_regions) {
594 : 58 : tumor_regions.clear();
595 : :
596 [ + + ]: 348 : for (unsigned i = 1; i < _materials.size(); i++) {
597 [ + + ][ + - ]: 290 : if (_materials[i].is_tumor) tumor_regions.insert(_materials[i].id);
598 : : }
599 : 58 : }
600 : :
601 : : //! Gets the map for FullMonte parameters
602 : 36 : unordered_map <string, string>& Parser::get_fm_params() {
603 : 36 : return _fm_params_map;
604 : : }
605 : :
606 : : //! Gets the map for PDT-SPACE parameters
607 : 36 : unordered_map <string, string>& Parser::get_params() {
608 : 36 : return _params_map;
609 : : }
610 : :
611 : : //! Gets the map for SA engine parameters
612 : 4 : unordered_map <string, string>& Parser::get_sa_params() {
613 : 4 : return _sa_params_map;
614 [ + - ][ + - ]: 4 : }
|