EGS Brachy
An egs++ user code for rapid brachytherapy calculations
Loading...
Searching...
No Matches
/Users/marc/Developer/EGSnrc/HEN_HOUSE/user_codes/egs_brachy/egs_brachy/ginfo.cpp
Go to the documentation of this file.
1/*
2################################################################################
3#
4# egs_brachy ginfo.cpp
5# Copyright (C) 2016 Rowan Thomson, Dave Rogers, Randle Taylor, and Marc
6# Chamberland
7#
8# This file is part of egs_brachy
9#
10# egs_brachy is free software: you can redistribute it and/or modify it
11# under the terms of the GNU Affero General Public License as published
12# by the Free Software Foundation, either version 3 of the License, or
13# (at your option) any later version.
14#
15# egs_brachy is distributed in the hope that it will be useful, but
16# WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18# Affero General Public License for more details:
19# <http://www.gnu.org/licenses/>.
20#
21################################################################################
22#
23# When egs_brachy is used for publications, please cite our paper:
24# M. J. P. Chamberland, R. E. P. Taylor, D. W. O. Rogers, and R. M. Thomson,
25# egs brachy: a versatile and fast Monte Carlo code for brachytherapy,
26# Phys. Med. Biol. 61, 8214-8231 (2016).
27#
28################################################################################
29#
30# Author: Randle Taylor, 2016
31#
32# Contributors: Marc Chamberland
33# Dave Rogers
34# Rowan Thomson
35#
36################################################################################
37*/
38
43#include "ginfo.h"
44#include <limits>
45#include <algorithm>
46#include <sstream>
47
48typedef pair <string, vector<int> > CDGeomRegType;
49
50// comarison function for sorting CD 'set geometry' region definitions
51bool pairCompare(const CDGeomRegType &firstElem, const CDGeomRegType &secondElem) {
52 return firstElem.second[0] < secondElem.second[0];
53}
54
55// simple string join routine
56string join(const vector<string> &v, string delim) {
57
58 string s="";
59
60 for (vector<string>::const_iterator p = v.begin(); p != v.end(); ++p) {
61 s += *p;
62 if (p != v.end() - 1) {
63 s += delim;
64 }
65 }
66 return s;
67}
68
69
70// build up our geometry tree based from composite geometries
71Node GeomInfo::build_tree(string root, vector<Node> &children) {
72
73 for (size_t i =0; i < gmap[root].children.size(); i++) {
74 string child = gmap[root].children[i];
75 vector<Node> empty;
76 children.push_back(build_tree(child, empty));
77 }
78
79 return Node(root, children);
80}
81
82// parse the input geometry definition and figures out which geometries are inscribed in others
83// and then builds up a tree of nodes that can be used for figuring out the egs++ region
84// numbers assigned to each geometry
85int GeomInfo::initializeFromInput(EGS_Input *input) {
86
87 int err = input->getInput("simulation geometry", sim_geom_name);
88 if (err) {
89 egsWarning("GeomInfo::initializeFromInput: missing keyword 'simulation geometry'\n");
90 return 1;
91 }
92
93 input->getInput("source envelope geometry", source_envelope_name);
94
95 err = input->getInput("phantom geometries", phantom_names);
96 if (err) {
97 egsWarning("GeomInfo::initializeFromInput: missing keyword 'phantom geometries'\n");
98 return 1;
99 }
100 sort(phantom_names.begin(), phantom_names.end());
101
102 err = input->getInput("source geometries", source_names);
103 if (err) {
104 egsWarning("GeomInfo::initializeFromInput: missing keyword 'source geometries'\n");
105 return 1;
106 }
107
108 // keep track of the the items we're taking so we can add them back to the input
109 // for the actual geometry creation routinte to use
110 vector<EGS_Input *> items;
111
112 EGS_Input *ij;
113 while ((ij = input->takeInputItem("geometry")) != 0) {
114
115 items.push_back(ij);
116
117 string name("");
118 int err = ij->getInput("name", name);
119 if (err) {
120 egsWarning("GeomInfo::initializeFromInput: Found geometry with no name. All geometries must be named.\n");
121 return 1;
122 }
123
124 gmap[name].children = getChildren(name, ij);
125
126 }
127
128 // now add them back to the geometry input
129 for (vector<EGS_Input *>::iterator item = items.begin(); item != items.end(); item++) {
130 input->addInputItem(**item);
131 delete *item;
132 }
133
134
135 // we've got all geometries in the input. Now we need build up a tree of geometries with
136 // the simulation geometry as the root node. This allows the setGeometryIndexes method
137 // to figure out the order of geometries and starting/ending regions in egs++
138 // by traversing the tree
139 vector<Node> empty; // need a default empty vector
140 geom_tree = new Node(build_tree(sim_geom_name, empty));
141
142 return 0;
143
144}
145
146
147/* counts the number of transformation blocks for an auto envelope geometry
148 * and hence counts the number of inscribed geometries in an envelope
149 */
150size_t countAutoEnvelopeInscribed(EGS_Input *input) {
151
152 EGS_Input *inscribedInp = input->getInputItem("inscribed geometry");
153 if (!inscribedInp) {
154 return 0;
155 }
156
157 EGS_Input *transformInp = inscribedInp->getInputItem("transformations");
158 if (!transformInp) {
159 return 1;
160 }
161
162 vector<EGS_Input *> items;
163 EGS_Input *ij;
164 size_t count = 0;
165
166 while ((ij = transformInp->takeInputItem("transformation")) != 0) {
167 count++;
168 items.push_back(ij);
169 }
170
171 // now add them back to the geometry input
172 for (vector<EGS_Input *>::iterator item = items.begin(); item != items.end(); item++) {
173 transformInp->addInputItem(**item);
174 delete *item;
175 }
176
177 return count;
178}
179
180
181// return base geometrty name for egs_genvelope or egs_autoenvelope geometry
182string getGeomBaseName(EGS_Input *input) {
183 string base;
184 input->getInput("base geometry", base);
185 return base;
186}
187
188
189// return a vector of all the names of the inscribed geometries in an EGS_AutoEnvelope input
190vector<string> getAutoEnvelopeChildren(EGS_Input *input) {
191
192 vector<string> children;
193 children.push_back(getGeomBaseName(input));
194
195 EGS_Input *inscribed_inp = input->getInputItem("inscribed geometry");
196 if (!inscribed_inp) {
197 return children;
198 }
199
200 string inscribed_name;
201 inscribed_inp->getInput("inscribed geometry name", inscribed_name);
202
203 size_t ninscribed = countAutoEnvelopeInscribed(input);
204 for (size_t i=0; i < ninscribed; i++) {
205 children.push_back(inscribed_name);
206 }
207
208 return children;
209}
210
211
212// return a vector of all the names of the inscribedd geometries in an egs_genvelope input
213vector<string> getGEnvelopeChildren(EGS_Input *input) {
214 vector<string> children;
215 input->getInput("inscribed geometries", children);
216 children.insert(children.begin(), getGeomBaseName(input));
217 return children;
218}
219
220
221// return a vector of all the names of the inscribed geometries in an egs_cdgeometry input
222vector<string> getCDChildren(EGS_Input *input) {
223 vector<string> children;
224 string name;
225 input->getInput("name", name);
226
227 //children.push_back(getGeomBaseName(input));
228
229 vector<EGS_Input *> items;
230 EGS_Input *ij;
231
232 vector<int> start_regs, stop_regs;
233 vector<string> names;
234 vector<CDGeomRegType> regs;
235
236 while ((ij = input->takeInputItem("set geometry")) != 0) {
237 items.push_back(ij);
238
239 vector<string> aux;
240 ij->getInput("set geometry", aux);
241
242 int start_reg, stop_reg;
243 string name;
244
245 if (aux.size() == 2) {
246 start_reg = atoi(aux[0].c_str());
247 stop_reg = start_reg;
248 name = aux[1];
249 } else if (aux.size() == 3) {
250 start_reg = atoi(aux[0].c_str());
251 stop_reg = atoi(aux[1].c_str());
252 name = aux[2];
253 }
254
255 vector<int> start_stop_regs;
256 start_stop_regs.push_back(start_reg);
257 start_stop_regs.push_back(stop_reg);
258 regs.push_back(CDGeomRegType(name, start_stop_regs));
259
260 }
261
262
263 // now add them back to the geometry input
264 for (vector<EGS_Input *>::iterator item = items.begin(); item != items.end(); item++) {
265 input->addInputItem(**item);
266 delete *item;
267 }
268
269 sort(regs.begin(), regs.end(), pairCompare);
270 for (size_t i=0; i< regs.size(); i++) {
271 for (int g = regs[i].second[0]; g <= regs[i].second[1]; g++) {
272 children.push_back(regs[i].first);
273 }
274 }
275
276 return children;
277}
278
279
280// return a vector of all the names of the inscribedd geometries in an egs_genvelope input
281vector<string> getNDChildren(EGS_Input *input) {
282
283 vector<string> children;
284
285 string type;
286 input->getInput("type", type);
287
288 if (type == "EGS_XYZGeometry") {
289 return children;
290 }
291
292 input->getInput("dimensions", children);
293 return children;
294}
295
296
297// return a vector of all the names of the inscribedd geometries in an egs_genvelope input
298vector<string> getUnionChildren(EGS_Input *input) {
299 vector<string> children;
300 input->getInput("geometries", children);
301 return children;
302}
303
304
305// return a vector of all the names of the inscribedd geometries in an egs_genvelope input
306vector<string> getGStackChildren(EGS_Input *input) {
307 vector<string> children;
308 input->getInput("geometries", children);
309 return children;
310}
311
312// return a vector of all the names of the inscribedd geometries in an egs_gtransformed input
313vector<string> getGTransformedChildren(EGS_Input *input) {
314 vector<string> children;
315 input->getInput("my geometry", children);
316 return children;
317}
318
319
320
321/* return a vector of the names of all the direct children for a given geometry input
322 * currently works for:
323 * egs_autoenvelope
324 * egs_genvelope
325 * egs_cdgeometry
326 * egs_ndgeometry
327 * egs_gunion
328 * egs_gstack
329 * egs_gtransformed
330 *
331 * */
332vector<string> GeomInfo::getChildren(string name, EGS_Input *input) {
333
334 string library;
335 int err = input->getInput("library", library);
336
337 vector<string> children;
338 if (err) {
339 return children;
340 }
341
342 if (library == "egs_autoenvelope") {
343 children = getAutoEnvelopeChildren(input);
344 } else if (library == "egs_genvelope") {
345 children = getGEnvelopeChildren(input);
346 } else if (library == "egs_cdgeometry") {
347 children = getCDChildren(input);
348 } else if (library == "egs_ndgeometry") {
349 children = getNDChildren(input);
350 } else if (library == "egs_gunion") {
351 children = getUnionChildren(input);
352 } else if (library == "egs_gstack") {
353 children = getGStackChildren(input);
354 } else if (library == "egs_gtransformed") {
355 children = getGTransformedChildren(input);
356 }
357
358 return children;
359}
360
361
362// return the index of the geometry name in the the given input vector or -1 if not found
363int findGeomInVec(EGS_BaseGeometry *geom, vector<string> geoms) {
364 for (size_t p=0; p < geoms.size(); p++) {
365 if (geoms[p] == geom->getName()) {
366 return p;
367 }
368 }
369
370 return -1;
371}
372
373
374// return the maximum number of regions for the input geometry names
375int maxNRegOfGeoms(vector<string> gnames, int start) {
376 int max = 0;
377 for (size_t i = start; i < gnames.size(); i++) {
378 int nreg = EGS_BaseGeometry::getGeometry(gnames[i])->regions();
379 max = nreg > max ? nreg : max;
380 }
381 return max;
382}
383
384
385// return the number of regions in the subdivision at index idx of a composite geometry
386int nregForSubDiv(GeomRegionInfo gri, int idx) {
387
388 EGS_BaseGeometry *geom = EGS_BaseGeometry::getGeometry(gri.name);
389
390 if (gri.type == "EGS_AEnvelope" ||
391 gri.type == "EGS_ASwitchedEnvelope" ||
392 gri.type == "EGS_EnvelopeGeometry" ||
393 gri.type == "EGS_FastEnvelope") {
394
395 if (idx == 0) {
396 EGS_BaseGeometry *base = EGS_BaseGeometry::getGeometry(gri.children[idx]);
397 return base->regions();
398 }
399
400 return maxNRegOfGeoms(gri.children, 1);
401
402 } else if (gri.type == "EGS_CDGeometry") {
403 return maxNRegOfGeoms(gri.children, 0);
404 } else if (gri.type == "EGS_NDGeometry") {
405 return EGS_BaseGeometry::getGeometry(gri.children[idx])->regions();
406 } else if (gri.type == "EGS_UnionGeometry") {
407 return maxNRegOfGeoms(gri.children, 0);
408 } else if (gri.type == "EGS_StackGeometry") {
409 return maxNRegOfGeoms(gri.children, 0);
410 }
411
412 return geom->regions();
413}
414
415
416// traverse tree and set geometry start/end regions for a given geometry
417void GeomInfo::getGeomRegs(Node root, vector<GeomRegionInfo> &ordered, int start) {
418
419 EGS_BaseGeometry *g = EGS_BaseGeometry::getGeometry(root.name);
420 int nreg = g->regions();
421 gmap[root.name].name = root.name;
422 gmap[root.name].type = g->getType();
423 gmap[root.name].start = start;
424 gmap[root.name].end = start + nreg - 1;
425 gmap[root.name].nreg = nreg;
426
427 ordered.push_back(gmap[root.name]);
428 for (size_t i=0; i < gmap[root.name].children.size(); i++) {
429 getGeomRegs(root.children[i], ordered, start);
430 start += nregForSubDiv(gmap[root.name], i);
431 }
432
433}
434
435
436// set up all arrays required to decide which geometry/phantom a region
437// is in and whether or not we are scoring dose in it.
438// To do this we loop through all geometries, decide whether it is a phantom
439// or not, then loop through each region in the geometry and set the local
440// region number phantom index etc
441void GeomInfo::setGeometryIndexes(EGS_BaseGeometry *geom) {
442
444
445 nreg_total = EGS_BaseGeometry::getGeometry(sim_geom_name)->regions();
446 ngeom = ordered_geom_data.size();
447
448 for (int rr = 0; rr < nreg_total; rr++) {
449 global_ir_to_geom.push_back(NULL); // region number to parent geometry
450 global_ir_to_phant.push_back(-1); // IF is phantom THEN phantom index else -1
451 global_ir_to_source.push_back(-1); // IF is phantom THEN phantom index else -1
452 global_ir_to_local_ir.push_back(-1); // global region to local region number
453 }
454
455 for (int gg=0; gg < ngeom; gg++) {
456
458 EGS_BaseGeometry *geom = EGS_BaseGeometry::getGeometry(ginfo.name);
459
460 geom_to_regioninfo[geom] = ginfo;
461
462 int phant_idx = findGeomInVec(geom, phantom_names);
463 int source_idx = findGeomInVec(geom, source_names);
464
465 for (int rr = ginfo.start; rr <= ginfo.end; rr++) {
466 global_ir_to_geom[rr] = geom; // region number to parent geometry
467 if (global_ir_to_phant[rr] == -1 || phant_idx > -1) {
468 global_ir_to_phant[rr] = phant_idx; // IF is phantom THEN phantom index else -1
469 }
470 if (global_ir_to_source[rr] == -1 || source_idx > -1) {
471 global_ir_to_source[rr] = source_idx; // IF is source THEN source index else -1
472 }
473 global_ir_to_local_ir[rr] = rr - ginfo.start; // global region to local region number
474 }
475 }
476}
477
478
480 if (ir < 0) {
481 return GeomRegT(0,0);
482 }
484}
485
486
488 return ir >= 0 && ir < nreg_total ? global_ir_to_local_ir[ir] : -1;
489}
490
491
493 GeomRegionInfo gri = geom_to_regioninfo[local.first];
494 return gri.start + local.second;
495}
496
497
499 return ir >= 0 && ir < nreg_total && global_ir_to_phant[ir] >= 0;
500}
501
502
503bool GeomInfo::isSource(int ir) {
504 return ir >= 0 && ir < nreg_total && global_ir_to_source[ir] >= 0;
505}
506
507
509 return ir >= 0 && ir < nreg_total ? global_ir_to_phant[ir] : -1;
510}
511
512
514
515 egsInformation("Total number of geometries = %d\n", ngeom);
516 egsInformation("Total number of regions = %d\n", nreg_total);
517 egsInformation("Simulation geometry = %s\n", sim_geom_name.c_str());
518 egsInformation("Envelope containing sources = %s\n", source_envelope_name.c_str());
519 string sgnames = join(source_names, ", ");
520 egsInformation("Source geometries = %s\n", sgnames.c_str());
521
522 egsInformation("\nName | First Reg Idx | Last Reg Idx | Nreg \n%s\n",string(80,
523 '-').c_str());
524 for (int gg=0; gg < ngeom; gg++) {
526 egsInformation("%-30s | %13d | %13d | %12d \n", gr.name.c_str(), gr.start, gr.end, gr.nreg);
527 }
528 egsInformation("%s\n",string(80, '-').c_str());
529}
map< EGS_BaseGeometry *, GeomRegionInfo > geom_to_regioninfo
Definition ginfo.h:151
void getGeomRegs(Node, vector< GeomRegionInfo > &, int)
Definition ginfo.cpp:417
string source_envelope_name
Definition ginfo.h:131
vector< int > global_ir_to_local_ir
pointer for the geometry it belongs to
Definition ginfo.h:111
GeomRegionInfoMapT gmap
Definition ginfo.h:118
vector< GeomRegionInfo > ordered_geom_data
Definition ginfo.h:149
vector< EGS_BaseGeometry * > global_ir_to_geom
the source geometry index or -1 if not a source
Definition ginfo.h:108
bool isSource(int ir)
Definition ginfo.cpp:503
int phantomFromRegion(int ir)
return the phantom index for this region number or -1 if region is not in a phantom
Definition ginfo.cpp:508
int localToGlobal(GeomRegT)
Definition ginfo.cpp:492
int initializeFromInput(EGS_Input *input)
Initialize the GeomInfo structure (ginfo) This function reads the geometry input block,...
Definition ginfo.cpp:85
Node build_tree(string root, vector< Node > &children)
Definition ginfo.cpp:71
vector< int > global_ir_to_source
the phantoms geometry index or -1 if not a phant
Definition ginfo.h:104
string sim_geom_name
Definition ginfo.h:130
int ngeom
total number of geometries created
Definition ginfo.h:138
bool isPhantom(int ir)
Definition ginfo.cpp:498
void setGeometryIndexes(EGS_BaseGeometry *sim_geom)
Setup all arrays required to decide which geometry/phantom a region is in and whether or not we are s...
Definition ginfo.cpp:441
vector< int > global_ir_to_phant
array of size nreg mapping global region number to
Definition ginfo.h:101
void printInfo()
Definition ginfo.cpp:513
GeomRegT globalToLocal(int ir)
convert global region number to (EGS_BaseGeometry, local_reg_num) pair
Definition ginfo.cpp:479
int nreg_total
total number of regions in the simulation geometry
Definition ginfo.h:139
Node * geom_tree
Definition ginfo.h:136
int globalToLocalReg(int ir)
convert global region number to local_reg_num
Definition ginfo.cpp:487
vector< string > getChildren(string name, EGS_Input *inp)
Definition ginfo.cpp:332
vector< string > source_names
Definition ginfo.h:134
vector< string > phantom_names
Definition ginfo.h:132
Definition ginfo.h:58
vector< Node > children
Definition ginfo.h:61
vector< string > getUnionChildren(EGS_Input *input)
Definition ginfo.cpp:298
vector< string > getAutoEnvelopeChildren(EGS_Input *input)
Definition ginfo.cpp:190
vector< string > getGEnvelopeChildren(EGS_Input *input)
Definition ginfo.cpp:213
vector< string > getGTransformedChildren(EGS_Input *input)
Definition ginfo.cpp:313
string join(const vector< string > &v, string delim)
Definition ginfo.cpp:56
pair< string, vector< int > > CDGeomRegType
Definition ginfo.cpp:48
int nregForSubDiv(GeomRegionInfo gri, int idx)
Definition ginfo.cpp:386
int maxNRegOfGeoms(vector< string > gnames, int start)
Definition ginfo.cpp:375
bool pairCompare(const CDGeomRegType &firstElem, const CDGeomRegType &secondElem)
Definition ginfo.cpp:51
vector< string > getCDChildren(EGS_Input *input)
Definition ginfo.cpp:222
vector< string > getNDChildren(EGS_Input *input)
Definition ginfo.cpp:281
string getGeomBaseName(EGS_Input *input)
Definition ginfo.cpp:182
int findGeomInVec(EGS_BaseGeometry *geom, vector< string > geoms)
Definition ginfo.cpp:363
vector< string > getGStackChildren(EGS_Input *input)
Definition ginfo.cpp:306
size_t countAutoEnvelopeInscribed(EGS_Input *input)
Definition ginfo.cpp:150
ginfo contains classes for organizing information about the geometries present in an egs_brachy simul...
pair< EGS_BaseGeometry *, int > GeomRegT
pair of geometry and local region number
Definition ginfo.h:79
a struct to contain elementary information aboud a geometry
Definition ginfo.h:83
vector< string > children
Definition ginfo.h:87
string type
Definition ginfo.h:86
string name
Definition ginfo.h:85