61 #define S_STREAM std::istringstream
64 #define S_STREAM std::istrstream
70 static bool EGS_VHP_LOCAL inputSet =
false;
73 EGS_VoxelInfo *EGS_VoxelGeometry::v = 0;
74 int EGS_VoxelGeometry::nv = 0;
76 VHP_OrganData::VHP_OrganData(
const char *fname,
int slice_min,
int slice_max)
77 : nslice(0), ok(false) {
78 ifstream data(fname,ios::binary);
80 egsWarning(
"VHP_OrganData: failed to open file %s for reading\n",
85 data.read(&endian,
sizeof(endian));
87 if (endian != my_endian) {
88 egsWarning(
"VHP_OrganData: wrong endianess. \n"
89 "This machine has endianess %d, data was written on %d\n"
90 "This requires byte swaping, which has not been implemented yet\n",
91 (
int)my_endian,(
int)endian);
94 data.read((
char *)&dx,
sizeof(dx));
95 data.read((
char *)&dy,
sizeof(dy));
96 data.read((
char *)&dz,
sizeof(dz));
97 data.read((
char *)&nslice,
sizeof(nslice));
101 if (slice_max > nslice) {
104 int nwant = slice_max - slice_min;
105 slices =
new VHP_SliceInfo [nwant];
108 for (
int islice=0; islice<nslice; ++islice) {
109 if (islice >= slice_min) {
110 slices[is].readData(data);
112 slices[is++].getSliceDimensions(ni,nj);
124 if (islice == slice_max - 1) {
129 nslice = slice_max - slice_min;
131 egsWarning(
"VHP_OrganData: I/O error while reading data\n");
138 VHP_OrganData::~VHP_OrganData() {
144 void VHP_RowInfo::readData(istream &in) {
146 in.read((
char *)&n,
sizeof(n));
159 pix =
new unsigned short [nbin+1];
160 org =
new unsigned char [nbin];
162 in.read((
char *)pix,(nbin+1)*
sizeof(
unsigned short));
163 in.read((
char *)org,nbin*
sizeof(
unsigned char));
166 void VHP_SliceInfo::readData(istream &in) {
171 in.read((
char *)&firstr,
sizeof(firstr));
172 in.read((
char *)&lastr,
sizeof(lastr));
173 int nrow = lastr-firstr+1;
175 rinfo =
new VHP_RowInfo [nrow];
176 for (
int j=0; j<nrow; ++j) {
177 rinfo[j].readData(in);
183 EGS_VHPGeometry::EGS_VHPGeometry(
const char *phantom_file,
184 const char *media_file,
int slice_min,
int slice_max,
185 const string &Name) :
187 organs =
new VHP_OrganData(phantom_file,slice_min,slice_max);
188 if (!organs->isOK()) {
189 egsWarning(
"EGS_VHPGeometry: failed to construct organ data\n");
194 ifstream med_data(media_file);
196 egsWarning(
"EGS_VHPGeometry: failed to open media data file %s\n",
205 egsWarning(
"EGS_VHPGeometry: %d organs in media data file %s?\n",
212 for (j=0; j<256; ++j) {
214 organ_names[j] =
"Undefined";
218 med_data.getline(buf,1023);
219 for (j=0; j<norg; ++j) {
222 med_data >> iorg >> imed >> c;
223 med_data.getline(buf,1023);
224 if (iorg < 0 || iorg > 255)
225 egsWarning(
"EGS_VHPGeometry: bad organ number %d on line %d\n",
228 organ_media[iorg] = imed;
230 organ_names[iorg] = c;
231 organ_names[iorg] += buf;
235 med_data.getline(buf,1023);
236 vector<string> media_names;
237 vector<int> media_indeces;
238 for (j=0; j<nmed; ++j) {
239 med_data.getline(buf,1023);
241 media_names.push_back(med);
245 for (j=0; j<nmed; ++j) {
247 media_names[j].c_str(),media_indeces[j]);
249 for (j=0; j<256; ++j) {
250 if (organ_media[j] >= 0) {
251 if (organ_media[j] >= nmed) {
252 egsWarning(
"EGS_VHPGeometry: invalid medium index %d\n",
256 organ_media[j] = media_indeces[organ_media[j]];
260 EGS_Float dx, dy, dz;
262 organs->getVoxelSizes(dx,dy,dz);
263 organs->getPhantomDimensions(nx,ny,nz);
264 vg =
new EGS_VoxelGeometry(nx,ny,nz,dx,dy,dz);
267 egsInformation(
"Phantom size in voxels: x=%d y=%d z=%d\n",nx,ny,nz);
271 void EGS_VHPGeometry::setMicros(
EGS_Input *input) {
272 if (!vg || !organs) {
273 egsWarning(
"EGS_VHPGeometry::setMicros: called for an invalid "
278 egsWarning(
"EGS_VHPGeometry::setMicros: no micro matrix definitions\n");
281 vector<EGS_MicroMatrixCluster *> mv;
283 input->
getInput(
"micro matrix folder",dir);
286 const static char *err_msg =
287 "EGS_VHPGeometry::setMicros: wrong/missing '%s' input\n";
288 int err = input->
getInput(
"BSC thickness",t_bsc);
289 if (err || t_bsc < 0) {
293 string tb_medium, bm_medium;
294 err = input->
getInput(
"TB medium",tb_medium);
299 err = input->
getInput(
"BM medium",bm_medium);
305 egsWarning(
"EGS_VHPGeometry::setMicros: wrong/missing inputs found\n"
306 " => no micro matrices set for use\n");
310 vector<string> minput;
311 while (!input->
getInput(
"micro matrix",minput)) {
313 if (minput.size() < 2) {
314 egsWarning(
"EGS_VHPGeometry::setMicros: 'micro matrix' input"
315 " requires at least two inputs => ignored\n");
318 string fname = dir.size() ?
egsJoinPath(dir,minput[0]) : minput[0];
319 EGS_MicroMatrixCluster *mcluster =
new EGS_MicroMatrixCluster(
320 vg->dx,vg->dy,vg->dz,t_bsc,tb_med,bm_med,fname.c_str());
321 if (!mcluster->isValid()) {
322 egsWarning(
"failed to construct micro cluster from %s\n",
329 for (
int i=1; i<minput.size(); ++i) {
330 S_STREAM s(minput[i].c_str());
334 egsWarning(
"EGS_VHPGeometry::setMicros: invalid input %s "
335 "for micro matrix %s\n",minput[i].c_str(),
340 if (org < 0 || org > 255) {
341 egsWarning(
"EGS_VHPGeometry::setMicros: invalid input"
342 " %d for micro matrix %s\n",org,minput[0].c_str());
351 mv.push_back(mcluster);
353 " organs:",fname.c_str());
354 for (
int i=0; i<orgs.size(); ++i) {
356 organ_micro[orgs[i]] = mv.size()-1;
367 for (
int i=0; i<nmicro; ++i) {
373 micros =
new EGS_MicroMatrixCluster* [nmicro];
375 for (
int i=0; i<nmicro; ++i) {
377 int nr = micros[i]->nxy*micros[i]->nz;
378 int nm = micros[i]->mxy*micros[i]->mz;
383 nmacro = vg->nxy*vg->nz;
387 if (ntot > 2147483647)
egsFatal(
"EGS_VHPGeometry::setMicros: "
388 "too many micro regions\n");
389 nreg = nmacro + nmax*nmicro;
392 egsInformation(
"Using regions %d...%d to identify micro voxels\n",
397 EGS_VHPGeometry::~EGS_VHPGeometry() {
405 for (
int j=0; j<nmicro; ++j) {
413 void EGS_VHPGeometry::setMedia(
EGS_Input *,
int,
const int *) {
414 egsWarning(
"EGS_VHPGeometry::setMedia: don't use this method.\n"
415 " Media are fixed by the organ data defining an VHP geometry\n");
418 void EGS_VHPGeometry::printInfo()
const {
429 string EGS_VHPGeometry::type =
"EGS_VHPGeometry";
432 VHPBox EGS_MicroMatrixCluster::bm_boxes[64];
433 bool EGS_MicroMatrixCluster::bm_boxes_initialized =
false;
435 EGS_MicroMatrixCluster::EGS_MicroMatrixCluster(
436 EGS_Float Dx, EGS_Float Dy, EGS_Float Dz, EGS_Float bsc_thickness,
437 int tb_med,
int bm_med,
const char *micro_file) : med_tb(tb_med), med_bm(bm_med),
442 ifstream in(micro_file,ios::binary);
444 egsWarning(
"EGS_MicroMatrixCluster: failed to open file %s\n",
452 unsigned char Mx, My, Mz;
453 in.read((
char *)&Mx,
sizeof(Mx));
454 in.read((
char *)&My,
sizeof(My));
455 in.read((
char *)&Mz,
sizeof(Mz));
461 micros =
new unsigned char *[nmic];
462 in.read((
char *)&Mx,
sizeof(Mx));
463 in.read((
char *)&My,
sizeof(My));
464 in.read((
char *)&Mz,
sizeof(Mz));
469 int nxyz = nxy*nz, j;
472 for (
int j=0; j<nmic; ++j) {
473 micros[j] =
new unsigned char [nxyz];
474 in.read((
char *)micros[j],nxyz*
sizeof(
unsigned char));
476 egsWarning(
"EGS_MicroMatrixCluster: I/O error while reading "
477 "%d'th micto-matrix from file %s\n",j+1,micro_file);
478 for (
int i=0; i<=j; ++i) {
497 EGS_Float ddx = Dx/nx, ddy = Dy/ny, ddz = Dz/nz;
506 vg =
new EGS_VoxelGeometry(nx,ny,nz,ddx,ddy,ddz);
512 if (!bm_boxes_initialized) {
513 bm_boxes_initialized =
true;
514 for (
int ixm=0; ixm<2; ++ixm) {
515 EGS_Float xmin = bsc_thickness*ixm;
516 for (
int ixp=0; ixp<2; ++ixp) {
517 EGS_Float xmax = ddx - bsc_thickness*ixp;
518 for (
int iym=0; iym<2; ++iym) {
519 EGS_Float ymin = bsc_thickness*iym;
520 for (
int iyp=0; iyp<2; ++iyp) {
521 EGS_Float ymax = ddy - bsc_thickness*iyp;
522 for (
int izm=0; izm<2; ++izm) {
523 EGS_Float zmin = bsc_thickness*izm;
524 for (
int izp=0; izp<2; ++izp) {
525 EGS_Float zmax = ddz - bsc_thickness*izp;
526 int ibox = ixm+2*ixp+4*iym+8*iyp+16*izm+32*izp;
527 bm_boxes[ibox].xmin = xmin;
528 bm_boxes[ibox].xmax = xmax;
529 bm_boxes[ibox].ymin = ymin;
530 bm_boxes[ibox].ymax = ymax;
531 bm_boxes[ibox].zmin = zmin;
532 bm_boxes[ibox].zmax = zmax;
550 v_tb =
new EGS_Float [nmic];
551 v_bm =
new EGS_Float [nmic];
552 v_bsc =
new EGS_Float [nmic];
553 double tot_tb = 0, tot_bm = 0, tot_bsc = 0;
554 for (j=0; j<nmic; ++j) {
556 int iy = (j-iz*mxy)/mx;
557 int ix = j-iz*mxy-iy*mx;
582 EGS_Float bsc_vol = 0, bm_vol = 0, tb_vol = 0;
583 for (
int jx=0; jx<nx; ++jx) {
584 for (
int jy=0; jy<ny; ++jy) {
585 for (
int jz=0; jz<nz; ++jz) {
586 int ireg = jx + jy*nx + jz*nxy;
587 if (micros[j][ireg]) {
588 int micxm = !(jx > 0 ? micros[j][ireg-1] :
589 micros[ixm+iy*mx+iz*mxy][nx-1+jy*nx+jz*nxy]);
590 int micxp = !(jx < nx-1 ? micros[j][ireg+1] :
591 micros[ixp+iy*mx+iz*mxy][jy*nx+jz*nxy]);
592 int micym = !(jy > 0 ? micros[j][ireg-nx] :
593 micros[ix+iym*mx+iz*mxy][jx+(ny-1)*nx+jz*nxy]);
594 int micyp = !(jy < ny-1 ? micros[j][ireg+nx] :
595 micros[ix+iyp*mx+iz*mxy][jx+jz*nxy]);
596 int miczm = !(jz > 0 ? micros[j][ireg-nxy] :
597 micros[ix+iy*mx+izm*mxy][jx+jy*nx+(nz-1)*nxy]);
598 int miczp = !(jz < nz-1 ? micros[j][ireg+nxy] :
599 micros[ix+iy*mx+izp*mxy][jx+jy*nx]);
600 if ((micxm && micxp && 2*bsc_thickness>ddx) ||
601 (micym && micyp && 2*bsc_thickness>ddy) ||
602 (miczm && miczp && 2*bsc_thickness>ddz)) {
607 int ibox=micxm+2*micxp+4*micym+8*micyp+
609 micros[j][ireg] = ibox + 2;
615 (bm_boxes[ibox].xmax-bm_boxes[ibox].xmin)*
616 (bm_boxes[ibox].ymax-bm_boxes[ibox].ymin)*
617 (bm_boxes[ibox].zmax-bm_boxes[ibox].zmin);
635 v_tb[j] = tb_vol*ddx*ddy*ddz;
636 v_bm[j] = bm_vol*ddx*ddy*ddz;
637 v_bsc[j] = bsc_vol*ddx*ddy*ddz;
648 EGS_MicroMatrixCluster::~EGS_MicroMatrixCluster() {
652 EGS_TestMicro::EGS_TestMicro(EGS_Float Dx, EGS_Float Dy, EGS_Float Dz,
653 EGS_Float bsc_t,
int tb_med,
int bm_med,
const char *micro_file,
655 micro =
new EGS_MicroMatrixCluster(Dx,Dy,Dz,bsc_t,tb_med,bm_med,micro_file);
656 vg =
new EGS_VoxelGeometry(micro->mx,micro->my,micro->mz,Dx,Dy,Dz);
657 nr = micro->nx*micro->ny*micro->nz;
658 nreg = nr*micro->mx*micro->my*micro->mz;
661 void EGS_TestMicro::setMedia(
EGS_Input *,
int,
const int *) {
662 egsFatal(
"EGS_TestMicro::setMedia(EGS_Input*,int,const int *):\n"
663 " Don't use this method. Media are only set via the micro matrix"
667 EGS_TestMicro::~EGS_TestMicro() {
670 string EGS_TestMicro::type =
"EGS_TestMicro";
672 const static EGS_VHP_LOCAL
char *vhp_error_msg1 =
673 "createGeometry(VHP): wrong/missing %s input for micro_test geometry\n";
677 static void setInputs() {
680 setBaseGeometryInputs(
false);
682 geomBlockInput->getSingleInput(
"library")->setValues({
"egs_vhp_geometry"});
685 geomBlockInput->addSingleInput(
"phantom data",
true,
"The full filepath to the phantom data file, including the extension.");
686 geomBlockInput->addSingleInput(
"media data",
true,
"The full filepath to the media data file, including the extension.");
687 geomBlockInput->addSingleInput(
"slice range",
false,
"Two numbers, slice indices (indexed from 0). The first number must be smaller. Used to select a given slice range instead of using the entire phantom.");
690 geomBlockInput->addSingleInput(
"BSC thickness",
false,
"The thickness of the bone surface cells layer, in cm.");
691 geomBlockInput->addSingleInput(
"TB medium",
false,
"The trabecular bone medium name.");
692 geomBlockInput->addSingleInput(
"BM medium",
false,
"The bone marrow medium name.");
693 geomBlockInput->addSingleInput(
"micro matrix",
false,
"The binary micro matrix filename followed by organ indices (defined in the media data file).");
696 EGS_VHP_EXPORT
string getExample() {
700 # For file format definitions and more inputs, see the documentation.
702 library = egs_vhp_geometry
704 phantom data = phantom_data_file
705 media data = media_data_file
706 slice range = min_slice max_slice
712 EGS_VHP_EXPORT shared_ptr<EGS_BlockInput> getInputs() {
716 return geomBlockInput;
721 int err = input->
getInput(
"type",type);
722 if (!err && type ==
"micro_test") {
724 vector<EGS_Float> vs;
725 err = input->
getInput(
"voxel sizes",vs);
726 if (err || vs.size() != 3) {
731 err = input->
getInput(
"BSC thickness",bsc_t);
736 string tb_medium, bm_medium;
737 int err1 = input->
getInput(
"TB medium",tb_medium);
738 int err2 = input->
getInput(
"BM medium",bm_medium);
749 err = input->
getInput(
"micro data file",micro_data);
751 egsWarning(vhp_error_msg1,
"'micro data file'");
760 tb_med,bm_med,micro_data.c_str());
766 string phantom, media;
767 int err1 = input->
getInput(
"phantom data",phantom);
768 int err2 = input->
getInput(
"media data",media);
769 if (err1)
egsWarning(
"createGeometry(EGS_VHPGeometry): "
770 "missing 'phantom data' input\n");
771 if (err2)
egsWarning(
"createGeometry(EGS_VHPGeometry): "
772 "missing 'media data' input\n");
777 err1 = input->
getInput(
"slice range",srange);
779 if (!err1 && srange.size() == 2 && srange[1] > srange[0]) result =
780 new EGS_VHPGeometry(phantom.c_str(),media.c_str(),srange[0],srange[1]);
784 if (!result->isOK()) {
785 egsWarning(
"createGeometry(EGS_VHPGeometry): failed to construct "
792 result->setMicros(input);
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 Voxelized Human Phantom (VHP) geometry.
Global egspp functions header file.
EGS_GLIB_EXPORT EGS_BaseGeometry * createGeometry(EGS_Input *input)
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.