EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_vhp_geometry.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ voxelized human phantom geometry
5 # Copyright (C) 2015 National Research Council Canada
6 #
7 # This file is part of EGSnrc.
8 #
9 # EGSnrc is free software: you can redistribute it and/or modify it under
10 # the terms of the GNU Affero General Public License as published by the
11 # Free Software Foundation, either version 3 of the License, or (at your
12 # option) any later version.
13 #
14 # EGSnrc is distributed in the hope that it will be useful, but WITHOUT ANY
15 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
17 # more details.
18 #
19 # You should have received a copy of the GNU Affero General Public License
20 # along with EGSnrc. If not, see <http://www.gnu.org/licenses/>.
21 #
22 ###############################################################################
23 #
24 # Author: Iwan Kawrakow, 2008
25 #
26 # Contributors: Frederic Tessier
27 # Hubert Ho
28 # Marc Chamberland
29 #
30 ###############################################################################
31 #
32 # A "Voxelized Human Phantom" (VHP) geometry.
33 #
34 # Although a VHP geometry is just a XYZ geometry, due to the huge number of
35 # voxels one has to be more careful with memory use for media indices, etc.
36 # That's why this separate geometry implementation. With Richard Kramer's
37 # phantom data the implementation requires ~12 MB to hold all the organ data
38 # in memory. Richard's ASCII phantom data was also transformed into binary
39 # format with the result that loading them is almost instantaneous.
40 #
41 # For now the implementation only provides the macro geometry, i.e., no
42 # spongiosa micro matrices. Adding the micro matrices is the next step.
43 #
44 ###############################################################################
45 */
46 
47 
53 #include "egs_vhp_geometry.h"
54 #include "egs_input.h"
55 #include "egs_functions.h"
56 
57 #include <vector>
58 #include <fstream>
59 #ifndef NO_SSTREAM
60  #include <sstream>
61  #define S_STREAM std::istringstream
62 #else
63  #include <strstream>
64  #define S_STREAM std::istrstream
65 #endif
66 
67 
68 using namespace std;
69 
70 #ifndef SKIP_DOXYGEN
71 EGS_VoxelInfo *EGS_VoxelGeometry::v = 0;
72 int EGS_VoxelGeometry::nv = 0;
73 
74 VHP_OrganData::VHP_OrganData(const char *fname, int slice_min, int slice_max)
75  : nslice(0), ok(false) {
76  ifstream data(fname,ios::binary);
77  if (!data) {
78  egsWarning("VHP_OrganData: failed to open file %s for reading\n",
79  fname);
80  return;
81  }
82  char endian;
83  data.read(&endian,sizeof(endian));
84  char my_endian = egsGetEndian();
85  if (endian != my_endian) {
86  egsWarning("VHP_OrganData: wrong endianess. \n"
87  "This machine has endianess %d, data was written on %d\n"
88  "This requires byte swaping, which has not been implemented yet\n",
89  (int)my_endian,(int)endian);
90  return;
91  }
92  data.read((char *)&dx, sizeof(dx));
93  data.read((char *)&dy, sizeof(dy));
94  data.read((char *)&dz, sizeof(dz));
95  data.read((char *)&nslice,sizeof(nslice));
96  if (slice_min < 0) {
97  slice_min = 0;
98  }
99  if (slice_max > nslice) {
100  slice_max = nslice;
101  }
102  int nwant = slice_max - slice_min;
103  slices = new VHP_SliceInfo [nwant];
104  nx = 0, ny = 0;
105  int is = 0;
106  for (int islice=0; islice<nslice; ++islice) {
107  if (islice >= slice_min) {
108  slices[is].readData(data);
109  int ni, nj;
110  slices[is++].getSliceDimensions(ni,nj);
111  if (ni > nx) {
112  nx = ni;
113  }
114  if (nj > ny) {
115  ny = nj;
116  }
117  }
118  else {
119  VHP_SliceInfo tmp;
120  tmp.readData(data);
121  }
122  if (islice == slice_max - 1) {
123  break;
124  }
125  }
126  nxy = nx*ny;
127  nslice = slice_max - slice_min;
128  if (data.fail()) {
129  egsWarning("VHP_OrganData: I/O error while reading data\n");
130  }
131  else {
132  ok = true;
133  }
134 }
135 
136 VHP_OrganData::~VHP_OrganData() {
137  if (nslice) {
138  delete [] slices;
139  }
140 }
141 
142 void VHP_RowInfo::readData(istream &in) {
143  unsigned short n;
144  in.read((char *)&n,sizeof(n));
145  if (n != nbin) {
146  if (nbin > 0) {
147  delete [] pix;
148  delete [] org;
149  nbin = 0;
150  }
151  }
152  if (n < 1) {
153  return;
154  }
155  if (!nbin) {
156  nbin = n;
157  pix = new unsigned short [nbin+1];
158  org = new unsigned char [nbin];
159  }
160  in.read((char *)pix,(nbin+1)*sizeof(unsigned short));
161  in.read((char *)org,nbin*sizeof(unsigned char));
162 }
163 
164 void VHP_SliceInfo::readData(istream &in) {
165  if (rinfo) {
166  delete [] rinfo;
167  rinfo = 0;
168  }
169  in.read((char *)&firstr,sizeof(firstr));
170  in.read((char *)&lastr,sizeof(lastr));
171  int nrow = lastr-firstr+1;
172  if (nrow > 0) {
173  rinfo = new VHP_RowInfo [nrow];
174  for (int j=0; j<nrow; ++j) {
175  rinfo[j].readData(in);
176  }
177  }
178 }
179 #endif
180 
181 EGS_VHPGeometry::EGS_VHPGeometry(const char *phantom_file,
182  const char *media_file, int slice_min, int slice_max,
183  const string &Name) :
184  EGS_BaseGeometry(Name), vg(0), micros(0), nmicro(0) {
185  organs = new VHP_OrganData(phantom_file,slice_min,slice_max);
186  if (!organs->isOK()) {
187  egsWarning("EGS_VHPGeometry: failed to construct organ data\n");
188  delete organs;
189  organs = 0;
190  return;
191  }
192  ifstream med_data(media_file);
193  if (!med_data) {
194  egsWarning("EGS_VHPGeometry: failed to open media data file %s\n",
195  media_file);
196  delete organs;
197  organs = 0;
198  return;
199  }
200  int norg;
201  med_data >> norg;
202  if (norg < 1) {
203  egsWarning("EGS_VHPGeometry: %d organs in media data file %s?\n",
204  norg,media_file);
205  delete organs;
206  organs = 0;
207  return;
208  }
209  int j;
210  for (j=0; j<256; ++j) {
211  organ_media[j] = -1;
212  organ_names[j] = "Undefined";
213  organ_micro[j] = -1;
214  }
215  char buf[1024];
216  med_data.getline(buf,1023);
217  for (j=0; j<norg; ++j) {
218  int iorg, imed;
219  char c;
220  med_data >> iorg >> imed >> c;
221  med_data.getline(buf,1023);
222  if (iorg < 0 || iorg > 255)
223  egsWarning("EGS_VHPGeometry: bad organ number %d on line %d\n",
224  iorg,j+2);
225  else {
226  organ_media[iorg] = imed;
227  }
228  organ_names[iorg] = c;
229  organ_names[iorg] += buf;
230  }
231  int nmed;
232  med_data >> nmed;
233  med_data.getline(buf,1023);
234  vector<string> media_names;
235  vector<int> media_indeces;
236  for (j=0; j<nmed; ++j) {
237  med_data.getline(buf,1023);
238  string med(buf);
239  media_names.push_back(med);
240  media_indeces.push_back(EGS_BaseGeometry::addMedium(med));
241  }
242  egsInformation("EGS_VHPGeometry: media information\n");
243  for (j=0; j<nmed; ++j) {
244  egsInformation("Medium %s registered as medium number %d\n",
245  media_names[j].c_str(),media_indeces[j]);
246  }
247  for (j=0; j<256; ++j) {
248  if (organ_media[j] >= 0) {
249  if (organ_media[j] >= nmed) {
250  egsWarning("EGS_VHPGeometry: invalid medium index %d\n",
251  organ_media[j]);
252  }
253  else {
254  organ_media[j] = media_indeces[organ_media[j]];
255  }
256  }
257  }
258  EGS_Float dx, dy, dz;
259  int nx, ny, nz;
260  organs->getVoxelSizes(dx,dy,dz);
261  organs->getPhantomDimensions(nx,ny,nz);
262  vg = new EGS_VoxelGeometry(nx,ny,nz,dx,dy,dz);
263  nreg = nx*ny*nz;
264  nmacro = nreg;
265  egsInformation("Phantom size in voxels: x=%d y=%d z=%d\n",nx,ny,nz);
266  egsInformation("Voxel sizes: dx=%g dy=%g dz=%g\n",dx,dy,dz);
267 }
268 
269 void EGS_VHPGeometry::setMicros(EGS_Input *input) {
270  if (!vg || !organs) {
271  egsWarning("EGS_VHPGeometry::setMicros: called for an invalid "
272  "VHP geometry\n");
273  return;
274  }
275  if (!input->getInputItem("micro matrix")) {
276  egsWarning("EGS_VHPGeometry::setMicros: no micro matrix definitions\n");
277  return;
278  }
279  vector<EGS_MicroMatrixCluster *> mv;
280  string dir;
281  input->getInput("micro matrix folder",dir);
282  EGS_Float t_bsc;
283  bool ok = true;
284  const static char *err_msg =
285  "EGS_VHPGeometry::setMicros: wrong/missing '%s' input\n";
286  int err = input->getInput("BSC thickness",t_bsc);
287  if (err || t_bsc < 0) {
288  egsWarning(err_msg,"BSC thickness");
289  ok = false;
290  }
291  string tb_medium, bm_medium;
292  err = input->getInput("TB medium",tb_medium);
293  if (err) {
294  egsWarning(err_msg,"TB medium");
295  ok = false;
296  }
297  err = input->getInput("BM medium",bm_medium);
298  if (err) {
299  egsWarning(err_msg,"BM medium");
300  ok = false;
301  }
302  if (!ok) {
303  egsWarning("EGS_VHPGeometry::setMicros: wrong/missing inputs found\n"
304  " => no micro matrices set for use\n");
305  return;
306  }
307  int tb_med = addMedium(tb_medium), bm_med = addMedium(bm_medium);
308  vector<string> minput;
309  while (!input->getInput("micro matrix",minput)) {
310  delete input->takeInputItem("micro matrix");
311  if (minput.size() < 2) {
312  egsWarning("EGS_VHPGeometry::setMicros: 'micro matrix' input"
313  " requires at least two inputs => ignored\n");
314  continue;
315  }
316  string fname = dir.size() ? egsJoinPath(dir,minput[0]) : minput[0];
317  EGS_MicroMatrixCluster *mcluster = new EGS_MicroMatrixCluster(
318  vg->dx,vg->dy,vg->dz,t_bsc,tb_med,bm_med,fname.c_str());
319  if (!mcluster->isValid()) {
320  egsWarning("failed to construct micro cluster from %s\n",
321  fname.c_str());
322  delete mcluster;
323  }
324  else {
325  bool ok = true;
326  vector<int> orgs;
327  for (int i=1; i<minput.size(); ++i) {
328  S_STREAM s(minput[i].c_str());
329  int org;
330  s >> org;
331  if (s.fail()) {
332  egsWarning("EGS_VHPGeometry::setMicros: invalid input %s "
333  "for micro matrix %s\n",minput[i].c_str(),
334  minput[0].c_str());
335  ok = false;
336  }
337  else {
338  if (org < 0 || org > 255) {
339  egsWarning("EGS_VHPGeometry::setMicros: invalid input"
340  " %d for micro matrix %s\n",org,minput[0].c_str());
341  ok = false;
342  }
343  else {
344  orgs.push_back(org);
345  }
346  }
347  }
348  if (ok) {
349  mv.push_back(mcluster);
350  egsInformation("Using micro matrix data from\n %s\nfor"
351  " organs:",fname.c_str());
352  for (int i=0; i<orgs.size(); ++i) {
353  egsInformation(" %d",orgs[i]);
354  organ_micro[orgs[i]] = mv.size()-1;
355  }
356  egsInformation("\n");
357  }
358  else {
359  delete mcluster;
360  }
361  }
362  }
363  if (mv.size() > 0) {
364  if (nmicro > 0) {
365  for (int i=0; i<nmicro; ++i) {
366  delete micros[i];
367  }
368  delete [] micros;
369  }
370  nmicro = mv.size();
371  micros = new EGS_MicroMatrixCluster* [nmicro];
372  nmax = 0;
373  for (int i=0; i<nmicro; ++i) {
374  micros[i] = mv[i];
375  int nr = micros[i]->nxy*micros[i]->nz;
376  int nm = micros[i]->mxy*micros[i]->mz;
377  if (nm*nr > nmax) {
378  nmax = nm*nr;
379  }
380  }
381  nmacro = vg->nxy*vg->nz;
382  EGS_I64 ntot = nmax;
383  ntot *= nmicro;
384  ntot += nmacro;
385  if (ntot > 2147483647) egsFatal("EGS_VHPGeometry::setMicros: "
386  "too many micro regions\n");
387  nreg = nmacro + nmax*nmicro;
388  egsInformation("Using regions 0...%d to identify macro voxels\n",
389  nmacro-1);
390  egsInformation("Using regions %d...%d to identify micro voxels\n",
391  nmacro,nreg-1);
392  }
393 }
394 
395 EGS_VHPGeometry::~EGS_VHPGeometry() {
396  if (organs) {
397  delete organs;
398  }
399  if (vg) {
400  delete vg;
401  }
402  if (nmicro > 0) {
403  for (int j=0; j<nmicro; ++j) {
404  delete micros[j];
405  }
406  delete [] micros;
407  }
408 
409 }
410 
411 void EGS_VHPGeometry::setMedia(EGS_Input *,int,const int *) {
412  egsWarning("EGS_VHPGeometry::setMedia: don't use this method.\n"
413  " Media are fixed by the organ data defining an VHP geometry\n");
414 }
415 
416 void EGS_VHPGeometry::printInfo() const {
418  if (isOK()) {
419  egsInformation(" voxel sizes: %g %g %g\n",vg->dx,vg->dy,vg->dz);
420  egsInformation(" phantom size: %d %d %d\n",vg->nx,vg->ny,vg->nz);
421  }
422  else {
423  egsInformation(" undefined VHP geometry\n");
424  }
425 }
426 
427 string EGS_VHPGeometry::type = "EGS_VHPGeometry";
428 
429 #ifndef SKIP_DOXYGEN
430 VHPBox EGS_MicroMatrixCluster::bm_boxes[64];
431 bool EGS_MicroMatrixCluster::bm_boxes_initialized = false;
432 
433 EGS_MicroMatrixCluster::EGS_MicroMatrixCluster(
434  EGS_Float Dx, EGS_Float Dy, EGS_Float Dz, EGS_Float bsc_thickness,
435  int tb_med, int bm_med, const char *micro_file) : med_tb(tb_med), med_bm(bm_med),
436  micros(0), vg(0) {
437  //
438  // *** open micro-matrix file
439  //
440  ifstream in(micro_file,ios::binary);
441  if (!in) {
442  egsWarning("EGS_MicroMatrixCluster: failed to open file %s\n",
443  micro_file);
444  return;
445  }
446 
447  //
448  // *** read data
449  //
450  unsigned char Mx, My, Mz;
451  in.read((char *)&Mx,sizeof(Mx));
452  in.read((char *)&My,sizeof(My));
453  in.read((char *)&Mz,sizeof(Mz));
454  mx = Mx;
455  my = My;
456  mz = Mz;
457  mxy = mx*my;
458  nmic = mxy*mz;
459  micros = new unsigned char *[nmic];
460  in.read((char *)&Mx,sizeof(Mx));
461  in.read((char *)&My,sizeof(My));
462  in.read((char *)&Mz,sizeof(Mz));
463  nx = Mx;
464  ny = My;
465  nz = Mz;
466  nxy = nx*ny;
467  int nxyz = nxy*nz, j;
468  nreg = nxyz;
469  {
470  for (int j=0; j<nmic; ++j) {
471  micros[j] = new unsigned char [nxyz];
472  in.read((char *)micros[j],nxyz*sizeof(unsigned char));
473  if (in.fail()) {
474  egsWarning("EGS_MicroMatrixCluster: I/O error while reading "
475  "%d'th micto-matrix from file %s\n",j+1,micro_file);
476  for (int i=0; i<=j; ++i) {
477  delete [] micros[j];
478  }
479  delete [] micros;
480  micros = 0;
481  return;
482  }
483  }
484  }
485 
486  //
487  // *** initialize micro- and macro-voxel sizes and numbers
488  //
489  dx = Dx;
490  dy = Dy;
491  dz = Dz;
492  dxi = 1/dx;
493  dyi = 1/dy;
494  dzi = 1/dz;
495  EGS_Float ddx = Dx/nx, ddy = Dy/ny, ddz = Dz/nz;
496  egsInformation("Macro voxel sizes: %g %g %g\n",dx,dy,dz);
497  egsInformation("Micro voxel sizes: %g %g %g\n",ddx,ddy,ddz);
498  egsInformation("Number of micros: %d %d %d\n",mx,my,mz);
499  egsInformation("Number of micro-voxles: %d %d %d\n",nx,ny,nz);
500 
501  //
502  // *** create an object for geometry computations
503  //
504  vg = new EGS_VoxelGeometry(nx,ny,nz,ddx,ddy,ddz);
505 
506  //
507  // *** initialize the 64 boxes needed for sub-micro-voxel energy deposition
508  // if needed
509  //
510  if (!bm_boxes_initialized) {
511  bm_boxes_initialized = true;
512  for (int ixm=0; ixm<2; ++ixm) {
513  EGS_Float xmin = bsc_thickness*ixm;
514  for (int ixp=0; ixp<2; ++ixp) {
515  EGS_Float xmax = ddx - bsc_thickness*ixp;
516  for (int iym=0; iym<2; ++iym) {
517  EGS_Float ymin = bsc_thickness*iym;
518  for (int iyp=0; iyp<2; ++iyp) {
519  EGS_Float ymax = ddy - bsc_thickness*iyp;
520  for (int izm=0; izm<2; ++izm) {
521  EGS_Float zmin = bsc_thickness*izm;
522  for (int izp=0; izp<2; ++izp) {
523  EGS_Float zmax = ddz - bsc_thickness*izp;
524  int ibox = ixm+2*ixp+4*iym+8*iyp+16*izm+32*izp;
525  bm_boxes[ibox].xmin = xmin;
526  bm_boxes[ibox].xmax = xmax;
527  bm_boxes[ibox].ymin = ymin;
528  bm_boxes[ibox].ymax = ymax;
529  bm_boxes[ibox].zmin = zmin;
530  bm_boxes[ibox].zmax = zmax;
531  }
532  }
533  }
534  }
535  }
536  }
537  }
538 
539  //
540  // *** process micro data. After this loop the mico-matrices will contain
541  // 0 for TB voxels
542  // 1 for BSC-only voxels (possible if BSC thickness > voxel size/2)
543  // 2 for BM-only voxels (i.e., no TB neighbours)
544  // >2 index of VHPBox corresponding to the BSC layers found in the voxel
545  //
546  // we also compute the TB, BM and BSC volumes
547  //
548  v_tb = new EGS_Float [nmic];
549  v_bm = new EGS_Float [nmic];
550  v_bsc = new EGS_Float [nmic];
551  double tot_tb = 0, tot_bm = 0, tot_bsc = 0;
552  for (j=0; j<nmic; ++j) {
553  int iz = j/mxy;
554  int iy = (j-iz*mxy)/mx;
555  int ix = j-iz*mxy-iy*mx;
556  int ixm = ix-1;
557  if (ixm < 0) {
558  ixm = mx-1;
559  }
560  int ixp = ix+1;
561  if (ixp >= mx) {
562  ixp = 0;
563  }
564  int iym = iy-1;
565  if (iym < 0) {
566  iym = my-1;
567  }
568  int iyp = iy+1;
569  if (iyp >= my) {
570  iyp = 0;
571  }
572  int izm = iz-1;
573  if (izm < 0) {
574  izm = mz-1;
575  }
576  int izp = iz+1;
577  if (izp >= mz) {
578  izp = 0;
579  }
580  EGS_Float bsc_vol = 0, bm_vol = 0, tb_vol = 0;
581  for (int jx=0; jx<nx; ++jx) {
582  for (int jy=0; jy<ny; ++jy) {
583  for (int jz=0; jz<nz; ++jz) {
584  int ireg = jx + jy*nx + jz*nxy;
585  if (micros[j][ireg]) {
586  int micxm = !(jx > 0 ? micros[j][ireg-1] :
587  micros[ixm+iy*mx+iz*mxy][nx-1+jy*nx+jz*nxy]);
588  int micxp = !(jx < nx-1 ? micros[j][ireg+1] :
589  micros[ixp+iy*mx+iz*mxy][jy*nx+jz*nxy]);
590  int micym = !(jy > 0 ? micros[j][ireg-nx] :
591  micros[ix+iym*mx+iz*mxy][jx+(ny-1)*nx+jz*nxy]);
592  int micyp = !(jy < ny-1 ? micros[j][ireg+nx] :
593  micros[ix+iyp*mx+iz*mxy][jx+jz*nxy]);
594  int miczm = !(jz > 0 ? micros[j][ireg-nxy] :
595  micros[ix+iy*mx+izm*mxy][jx+jy*nx+(nz-1)*nxy]);
596  int miczp = !(jz < nz-1 ? micros[j][ireg+nxy] :
597  micros[ix+iy*mx+izp*mxy][jx+jy*nx]);
598  if ((micxm && micxp && 2*bsc_thickness>ddx) ||
599  (micym && micyp && 2*bsc_thickness>ddy) ||
600  (miczm && miczp && 2*bsc_thickness>ddz)) {
601  micros[j][ireg] = 1; // i.e. all BSC
602  bsc_vol += 1;
603  }
604  else {
605  int ibox=micxm+2*micxp+4*micym+8*micyp+
606  16*miczm+32*miczp;
607  micros[j][ireg] = ibox + 2;
608  if (!ibox) {
609  bm_vol += 1;
610  }
611  else {
612  double v =
613  (bm_boxes[ibox].xmax-bm_boxes[ibox].xmin)*
614  (bm_boxes[ibox].ymax-bm_boxes[ibox].ymin)*
615  (bm_boxes[ibox].zmax-bm_boxes[ibox].zmin);
616  v /= (ddx*ddy*ddz);
617  bm_vol += v;
618  bsc_vol += 1 - v;
619  }
620  }
621  }
622  else {
623  tb_vol += 1;
624  }
625  }
626  }
627  }
628  egsInformation("Micro-matrix %d from %s:\n",j+1,micro_file);
629  egsInformation(" TB volume fraction: %g\n",tb_vol/nxyz);
630  egsInformation(" BM volume fraction: %g\n",bm_vol/nxyz);
631  egsInformation(" BSC volume fraction: %g\n",bsc_vol/nxyz);
632  egsInformation(" Total: %g\n",(tb_vol+bm_vol+bsc_vol)/nxyz);
633  v_tb[j] = tb_vol*ddx*ddy*ddz;
634  v_bm[j] = bm_vol*ddx*ddy*ddz;
635  v_bsc[j] = bsc_vol*ddx*ddy*ddz;
636  tot_tb += tb_vol;
637  tot_bm += bm_vol;
638  tot_bsc += bsc_vol;
639  }
640  egsInformation("Average volume fractions:\n");
641  egsInformation(" TB volume fraction: %g\n",tot_tb/(nmic*nxyz));
642  egsInformation(" BM volume fraction: %g\n",tot_bm/(nmic*nxyz));
643  egsInformation(" BSC volume fraction: %g\n",tot_bsc/(nmic*nxyz));
644 }
645 
646 EGS_MicroMatrixCluster::~EGS_MicroMatrixCluster() {
647 }
648 #endif
649 
650 EGS_TestMicro::EGS_TestMicro(EGS_Float Dx, EGS_Float Dy, EGS_Float Dz,
651  EGS_Float bsc_t,int tb_med, int bm_med,const char *micro_file,
652  const string &Name) : EGS_BaseGeometry(Name) {
653  micro = new EGS_MicroMatrixCluster(Dx,Dy,Dz,bsc_t,tb_med,bm_med,micro_file);
654  vg = new EGS_VoxelGeometry(micro->mx,micro->my,micro->mz,Dx,Dy,Dz);
655  nr = micro->nx*micro->ny*micro->nz;
656  nreg = nr*micro->mx*micro->my*micro->mz;
657 }
658 
659 void EGS_TestMicro::setMedia(EGS_Input *, int, const int *) {
660  egsFatal("EGS_TestMicro::setMedia(EGS_Input*,int,const int *):\n"
661  " Don't use this method. Media are only set via the micro matrix"
662  " data\n");
663 }
664 
665 EGS_TestMicro::~EGS_TestMicro() {
666 }
667 
668 string EGS_TestMicro::type = "EGS_TestMicro";
669 
670 const static EGS_VHP_LOCAL char *vhp_error_msg1 =
671  "createGeometry(VHP): wrong/missing %s input for micro_test geometry\n";
672 
673 extern "C" {
674 
675  EGS_VHP_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) {
676  string type;
677  int err = input->getInput("type",type);
678  if (!err && type == "micro_test") {
679  bool ok = true;
680  vector<EGS_Float> vs;
681  err = input->getInput("voxel sizes",vs);
682  if (err || vs.size() != 3) {
683  egsWarning(vhp_error_msg1,"'voxel sizes'");
684  ok = false;
685  }
686  EGS_Float bsc_t;
687  err = input->getInput("BSC thickness",bsc_t);
688  if (err) {
689  egsWarning(vhp_error_msg1,"'BSC thickness'");
690  ok = false;
691  }
692  string tb_medium, bm_medium;
693  int err1 = input->getInput("TB medium",tb_medium);
694  int err2 = input->getInput("BM medium",bm_medium);
695  if (err1) {
696  egsWarning(vhp_error_msg1,"'TB medium'");
697  }
698  if (err2) {
699  egsWarning(vhp_error_msg1,"'BM medium'");
700  }
701  if (err1 || err2) {
702  ok = false;
703  }
704  string micro_data;
705  err = input->getInput("micro data file",micro_data);
706  if (err) {
707  egsWarning(vhp_error_msg1,"'micro data file'");
708  ok = false;
709  }
710  if (!ok) {
711  return 0;
712  }
713  int tb_med = EGS_BaseGeometry::addMedium(tb_medium);
714  int bm_med = EGS_BaseGeometry::addMedium(bm_medium);
715  EGS_TestMicro *result = new EGS_TestMicro(vs[0],vs[1],vs[2],bsc_t,
716  tb_med,bm_med,micro_data.c_str());
717  result->setName(input);
718  result->setBoundaryTolerance(input);
719  result->setLabels(input);
720  return result;
721  }
722  string phantom, media;
723  int err1 = input->getInput("phantom data",phantom);
724  int err2 = input->getInput("media data",media);
725  if (err1) egsWarning("createGeometry(EGS_VHPGeometry): "
726  "missing 'phantom data' input\n");
727  if (err2) egsWarning("createGeometry(EGS_VHPGeometry): "
728  "missing 'media data' input\n");
729  if (err1 || err2) {
730  return 0;
731  }
732  vector<int> srange;
733  err1 = input->getInput("slice range",srange);
734  EGS_VHPGeometry *result;
735  if (!err1 && srange.size() == 2 && srange[1] > srange[0]) result =
736  new EGS_VHPGeometry(phantom.c_str(),media.c_str(),srange[0],srange[1]);
737  else {
738  result = new EGS_VHPGeometry(phantom.c_str(),media.c_str());
739  }
740  if (!result->isOK()) {
741  egsWarning("createGeometry(EGS_VHPGeometry): failed to construct "
742  "geometry");
743  delete result;
744  return 0;
745  }
746  result->setName(input);
747  result->setBoundaryTolerance(input);
748  result->setMicros(input);
749  result->setLabels(input);
750  return result;
751  }
752 
753 }
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
int nreg
Number of local regions in this geometry.
void setName(EGS_Input *inp)
Set the name of the geometry from the input inp.
int setLabels(EGS_Input *input)
Set the labels from an input block.
virtual void printInfo() const
Print information about this geometry.
static int addMedium(const string &medname)
Add a medium or get the index of an existing medium.
void setBoundaryTolerance(EGS_Input *inp)
Set the value of the boundary tolerance from the input inp.
A class for storing information in a tree-like structure of key-value pairs. This class is used throu...
Definition: egs_input.h:182
EGS_Input * takeInputItem(const string &key, bool self=true)
Get the property named key.
Definition: egs_input.cpp:226
EGS_Input * getInputItem(const string &key) const
Same as the previous function but now ownership remains with the EGS_Input object.
Definition: egs_input.cpp:245
int getInput(const string &key, vector< string > &values) const
Assign values to an array of strings from an input identified by key.
Definition: egs_input.cpp:338
A Voxelized Human Phantom (VHP) geometry.
Global egspp functions header file.
EGS_GLIB_EXPORT EGS_BaseGeometry * createGeometry(EGS_Input *input)
Definition: egs_glib.cpp:57
EGS_Input class header file.
Voxelized Human Phantom (VHP) geometry: header.
int egsGetEndian()
Get the endianess of the machine.
EGS_InfoFunction EGS_EXPORT egsInformation
Always use this function for reporting the progress of a simulation and any other type of information...
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
string egsJoinPath(const string &first, const string &second)
Join two path variables (or a path and a file name) using the platform specific directory separator a...
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.