51#include "egs_run_control.h"
74 return firstElem.
tlen > secondElem.
tlen;
78 return firstElem.
edep > secondElem.
edep;
85 for (std::string::iterator it = text.begin(); it != text.end(); ++it) {
106 app(parent), tlen_score(0), edep_score(0),
107 prim_score(0), sscat_score(0), mscat_score(0),
113 geometry(geom), global_regions(global_regions) {
128 EGS_Particle *p =
static_cast<EGS_Particle *
>(data);
134 if (ir < 0 || ir >=
geometry->regions()) {
135 egsFatal(
"bad %d \n", ir);
171 for (
int i=0; i<end; i++) {
185 for (
int i=0; i<end; i++) {
197 regs.push_back(it->first);
260 string output_volcor) {
262 if (output_voxinfo ==
"text" || output_voxinfo ==
"gzip") {
266 if (output_volcor ==
"text" || output_volcor ==
"gzip") {
276 if (
can_write_3ddose && (output_3ddose ==
"text" || output_3ddose ==
"gzip")) {
280 if (
can_write_3ddose && (output_egsphant==
"text" || output_egsphant ==
"gzip")) {
287 return geometry->getRelativeRho(ireg)*the_media->rho[med];
306 EGS_Float volume =
geometry->getVolume(ireg);
351 score->currentResult(ireg, r, dr);
352 dr = r > 0 ? dr/r: 1;
363 if (type ==
"tlen") {
365 }
else if (type ==
"edep") {
380 vector<RegionResult> region_results;
383 for (
int ireg = 0; ireg < nreg; ireg++) {
385 double result=0, dr=0;
390 double result_edep=0, result_edep_dr=0;
398 RegionResult regr = { ireg, volume, dv, result, dr, result_edep, result_edep_dr };
399 region_results.push_back(regr);
403 return region_results;
410 int nreg = score->regions();
412 EGS_Float avg_dose=0,
421 avg_dose_gt_20_err=0,
443 EGS_Float max_dose = 0;
445 for (
int i=0; i < nreg; i++) {
448 max_dose = max(max_dose, r);
452 for (
int i=0; i < nreg; i++) {
454 EGS_Float dose, dose_err;
456 getResult(score, i, type, dose, dose_err);
472 avg_vol_err += vol_err;
476 avg_vol_err_0 += vol_err;
481 if (dose > 0 && (vol_cor / vol_nom <= 0.500)){
483 avg_vol_err_50 += vol_err;
486 if (dose > 0 && (vol_cor / vol_nom <= 0.01)){
488 avg_vol_err_99 += vol_err;
495 avg_dose_err += dose_err;
496 avg_tot_err += sqrt(dose_err*dose_err + vol_err*vol_err);
501 avg_dose_gt_0 += dose;
502 avg_dose_gt_0_err += dose_err;
503 avg_tot_gt_0_err += sqrt(dose_err*dose_err + vol_err*vol_err);
507 if (dose >= max_dose*0.20) {
509 avg_dose_gt_20 += dose;
510 avg_dose_gt_20_err += dose_err;
511 avg_tot_gt_20_err += sqrt(dose_err*dose_err + vol_err*vol_err);
513 avg_vol_err_d20 += vol_err;
520 string units =
"Gy/hist";
521 if (type ==
"pr" || type ==
"ss" || type ==
"ms" || type ==
"to") {
523 egsInformation(
"\n Total radiant energy = %.3G MeV\n",
total_radiant_e);
526 egsInformation(
"\n Dose Scaling = %.3G\n",
dose_scale);
528 egsInformation(
"\n # of voxels with vol corrections = %d / %d (%.3F%)\n", n_vol_cor, nreg, 100.*n_vol_cor/nreg);
529 egsInformation(
" # of voxels with vol correction & D > 0 = %d / %d (%.3F%)\n", n_vol_cor_0, nreg, 100.*n_vol_cor_0/nreg);
530 egsInformation(
" # of voxels with vol correction & D = 0 = %d / %d (%.3F%)\n", n_vol_cor_no_dose, nreg, 100.*n_vol_cor_no_dose/nreg);
532 egsInformation(
" Average error on vol correction where:\n");
533 egsInformation(
" D > 0 & at least 0%% of voxel covered = %.2F% (%d voxels)\n",
534 n_vol_cor_0 > 0 ? 100.*avg_vol_err_0/n_vol_cor_0 : 0, n_vol_cor_0);
535 egsInformation(
" Average error on vol corrections where:\n");
536 egsInformation(
" D > 0 & at least 50%% of voxel covered = %.2F% (%d voxels)\n",
537 n_vol_cor_50 > 0 ? 100.*avg_vol_err_50/n_vol_cor_50 : 0, n_vol_cor_50);
538 egsInformation(
" Average error on vol corrections where:\n");
539 egsInformation(
" D > 0 & at least 99%% of voxel covered = %.2F% (%d voxels)\n",
540 n_vol_cor_99 > 0 ? 100.*avg_vol_err_99/n_vol_cor_99 : 0, n_vol_cor_99);
542 egsInformation(
"\n Max dose = %.5E %s\n", max_dose, units.c_str());
543 egsInformation(
" # of voxels with D > 0 = %d / %d (%.3G%)\n", n_gt_0, nreg, 100.*n_gt_0/nreg);
544 egsInformation(
" # of voxels with D = 0 = %d / %d (%.3G%)\n", nreg - n_gt_0, nreg, 100.*(nreg - n_gt_0)/nreg);
545 egsInformation(
" Average dose for D > 0 = %.5E %s\n", avg_dose_gt_0 / n_gt_0, units.c_str());
546 egsInformation(
" Average dose for D >= 0 = %.5E %s\n", avg_dose / nreg, units.c_str());
547 egsInformation(
" Average error on dose for D > 0 = %.2F%\n",
548 n_gt_0 ? 100.*avg_dose_gt_0_err / n_gt_0 : 0);
549 egsInformation(
" Average error on vol cors for D > 0 = %.2F% (%d voxels)\n",
550 n_vol_cor_0 ? 100.*avg_vol_err_0 / n_vol_cor_0 : 0, n_vol_cor_0);
551 egsInformation(
" Average total error on dose for D > 0 = %.2F%\n",
552 n_gt_0 ? 100.*avg_tot_gt_0_err / n_gt_0 : 0);
554 egsInformation(
"\n 20%% of Dmax = %.5E %s\n", 0.2*max_dose, units.c_str());
555 egsInformation(
" # of voxels with D >= 20%%*Dmax = %d / %d (%.3G%)\n", n_gt_20, nreg, 100.*n_gt_20/nreg);
556 egsInformation(
" Average dose for D > 20%%*Dmax = %.5E %s\n", avg_dose_gt_20 / n_gt_20, units.c_str());
557 egsInformation(
" Average error on doses for D >= 20%%*Dmax = %.2F%\n",
558 n_gt_20 ? 100.*avg_dose_gt_20_err / n_gt_20 : 0);
559 egsInformation(
" Average error on vol cors for D >= 20%%*Dmax = %.2F% (%d voxels)\n",
560 n_vol_cor_d20 ? 100.*avg_vol_err_d20 / n_vol_cor_d20 : 0, n_vol_cor_d20);
561 egsInformation(
" Average total error on dose for D >= 20%%*Dmax = %.2F%\n",
562 n_gt_20 ? 100.*avg_tot_gt_20_err / n_gt_20 : 0);
569 top_n = min(top_n,
geometry->regions());
571 string fmt =
"\n\nTop %d dose results for geometry named '%s'";
576 egsInformation((fmt+
"\n").c_str(), top_n, (
geometry->getName()).c_str());
579 " Region Med # Volume (Nominal) / cm^3 Tracklength Dose / Gy/hist (Derr, Verr) "
580 "Interaction Dose / Gy/hist (Derr, Verr)\n"
582 egsInformation(
"%s\n",
string(title.size()-1,
'=').c_str());
583 egsInformation(title.c_str());
585 string sep(title.size()-1,
'-');
586 egsInformation((sep+
"\n").c_str());
589 vector<RegionResult> top_results(top_n);
591 partial_sort_copy(region_results.begin(), region_results.end(), top_results.begin(), top_results.end(),
594 partial_sort_copy(region_results.begin(), region_results.end(), top_results.begin(), top_results.end(),
598 for (vector<RegionResult>::iterator rrit=top_results.begin(); rrit!=top_results.end(); rrit++) {
611 if (total_tlen_unc > 0.001){
612 fmt =
"%7d %5d %11.3E(%8.3E) +/- %6.2f%% %12.3E +/- %6.2f%% (%6.2f%%, %6.2f%%) %10.3E +/- %6.2f%% (%6.2f%%, %6.2f%%)\n";
614 fmt =
"%7d %5d %11.3E(%8.3E) +/- %6.3f%% %11.4E +/- %6.3f%% (%6.3f%%, %6.3f%%) %10.4E +/- %7.3f%% (%6.3f%%, %6.3f%%)\n";
637 vector<string> &descriptions) {
641 types.push_back(
"tlen");
642 descriptions.push_back(
"tracklength");
647 types.push_back(
"edep");
648 descriptions.push_back(
"energy deposition");
656 types.push_back(
"to");
657 types.push_back(
"pr");
658 types.push_back(
"ss");
659 types.push_back(
"ms");
660 descriptions.push_back(
"total primary + scattered");
661 descriptions.push_back(
"primary");
662 descriptions.push_back(
"single scattered");
663 descriptions.push_back(
"multiple scattered");
690 vector<EGS_ScoringArray *> scores;
691 vector<string> types;
692 vector<string> descriptions;
695 egsInformation(
"\nDose Output Files for %s\n%s\n",
geometry->getName().c_str(),
string(80,
'=').c_str());
696 for (
size_t s=0; s < scores.size(); s++) {
698 string type = types[s];
700 string sep = type ==
"tlen" ?
"" :
"."+type;
702 extension += (format ==
"gzip") ?
".gz" :
"";
703 string fname =
app->constructIOFileName(extension.c_str(),
true);
705 "\nWriting %s dose to %s%s:",
706 descriptions[s].c_str(),
707 app->getOutputFile().c_str(),
712 if (format ==
"gzip") {
714 out.
open(fname.c_str());
721 out.open(fname.c_str());
741 out << nx <<
" " << ny <<
" " << nz <<
"\n";
743 for (
int dir=
XDIR; dir <=
ZDIR; dir++) {
745 int nbounds =
geometry->getNRegDir(dir) + 1;
748 out << -999 <<
"\t" << 999 <<
"\n";
750 for (
int idx=0; idx < nbounds; idx++) {
751 string delim = (idx == nbounds - 1) ?
"\n" :
"\t";
752 out<<
geometry->getBound(dir, idx) << delim ;
762 for (
int loop = 0; loop < 2; loop++) {
763 for (
int ireg=0; ireg < score->regions(); ireg++) {
765 double result, dr, dv;
766 getResult(score, ireg, type, result, dr);
769 out << result <<
"\t";
772 out << sqrt(dr*dr + dv*dv) <<
"\t";
783 int nmed = EGS_BaseGeometry::nMedia();
786 for (
int i=0; i < nmed; i++) {
787 out << EGS_BaseGeometry::getMediumName(i) <<
"\n";
790 for (
int i=0; i < nmed; i++) {
791 out << the_etcontrol->estepe <<
"\t";
802 for (
int loop = 0; loop < 2; loop++) {
803 for (
int kk=0; kk < nz; kk++) {
804 for (
int jj=0; jj < ny; jj++) {
805 for (
int ii=0; ii < nx; ii++) {
806 int ireg = ii + jj*nx + kk*nx*ny;
810 out << char(49 + nreg + (nreg>8?7:0) + (nreg>34?6:0));
825 string medIdx =
"123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
826 if (medium >= medIdx.length()){
827 egsFatal(
"Too many media to write egsPhant");
830 return string(1, medIdx[medium]);
835 egsInformation(
"\nEGSPhant Output File for %s\n%s\n",
geometry->getName().c_str(),
string(80,
'=').c_str());
838 extension += (format ==
"gzip") ?
".gz" :
"";
839 string out_name =
app->getOutputFile()+extension;
840 string fname =
app->constructIOFileName(extension.c_str(),
true);
842 egsInformation(
"Writing egsphant file to %s\n", (out_name).c_str());
844 if (format ==
"gzip") {
849 ofstream out(fname.c_str());
859 for (nreg = 0; nreg <
geometry->regions(); nreg++) {
862 return nreg > 0 ? total / nreg : 0;
867 out << std::setprecision(6) << std::scientific;
869 "Region, Volume / cm^3, Nominal Volume / cm^3, Vol Cor Unc, Mass / g, Density / g/cm^3, Med, "
870 "Dose (tracklength) / Gy/hist, Total Dose Unc (tracklength), Dose Unc (tracklength)"
873 header +=
", Dose (interaction) / Gy/hist, Total Dose Unc (interaction), Dose Unc (interaction)";
875 out << header <<
"\n";
877 for (
int i=0; i <
geometry->regions(); i++) {
878 EGS_Float r=0, dr=0, r_edep, dr_edep, dv;
889 out << r <<
", " << sqrt(dr*dr + dv*dv) <<
", " << dr;
891 out <<
", " << r_edep <<
", " << sqrt(dr_edep*dr_edep + dv*dv) <<
", " << dr_edep;
899 egsInformation(
"\nVoxel Info File Output File for %s\n%s\n",
geometry->getName().c_str(),
string(80,
'=').c_str());
901 extension += (format ==
"gzip") ?
".gz" :
"";
902 string fname =
app->constructIOFileName(extension.c_str(),
true);
905 "Writing voxel info file to %s\n",
906 (
app->getOutputFile() + extension).c_str()
909 if (format ==
"gzip") {
911 out.
open(fname.c_str());
916 out.open(fname.c_str());
925 out << nrecords <<
"\n";
927 for (
int i=0; i <
geometry->regions(); i++) {
936 egsInformation(
"\nVolume Correction Output File for %s\n%s\n",
geometry->getName().c_str(),
string(80,
'=').c_str());
938 extension += (format ==
"gzip") ?
".gz" :
"";
939 string fname =
app->constructIOFileName(extension.c_str(),
true);
943 "Writing volume correction file for %s to %s file %s\n",
944 gname.c_str(), format.c_str(), (
app->getOutputFile()+
"."+gname+
".volcor").c_str());
946 if (format ==
"gzip") {
952 out.open(fname.c_str());
962 vector<EGS_ScoringArray *> scores;
965 vector<EGS_ScoringArray *>::iterator it = scores.begin();
966 for (; it != scores.end(); ++it) {
967 bool ok = (*it)->storeState(*ofile);
982 vector<EGS_ScoringArray *> scores;
985 vector<EGS_ScoringArray *>::iterator it = scores.begin();
986 for (; it != scores.end(); ++it) {
987 bool ok = (*it)->setState(*ifile);
998 EGS_Float total_radiant_e_tmp;
999 data >> total_radiant_e_tmp;
1002 vector<EGS_ScoringArray *> scores, tmp_scores;
1005 vector<EGS_ScoringArray *>::iterator it = scores.begin();
1006 for (; it != scores.end(); ++it) {
1008 EGS_ScoringArray tmp((*it)->regions());
1010 bool ok = tmp.setState(data);
1025 vector<EGS_ScoringArray *> scores;
1028 vector<EGS_ScoringArray *>::iterator it = scores.begin();
1029 for (; it != scores.end(); ++it) {
@ YDIR
YDIR=1 y dir for rectilinear, r dir for cylindrical.
@ XDIR
XDIR=0 x dir for rectilinear, r dir for spherical, z dir for cylindrical.
@ ZDIR
ZDIR=2 z dir for rectilinear.
void getResult(EGS_ScoringArray *, int ireg, string type, EGS_Float &r, EGS_Float &dr)
get result for region from scoring array and normalize based on the type requested.
void outputEGSPhant(string)
initialize and write an egsphant file for this phantom
void scoreTlen(int ir, EGS_Float dose, EGS_Particle *p)
add tracklength dose to region ir
void output3ddoseResults(string)
write the phantom boundaries, doses and uncertainties to 3ddose file
void outputVoxelInfo(string format)
write voxel volumes, mass, desnity etc
std::map< int, double > volume_uncertainty
int global_reg_stop
ending global region index for this phantom
void update(EB_Message message, void *data)
bool can_write_3ddose
this phantom can output 3ddose files
EGS_Float getUncorrectedVolume(int ireg)
get corrected volume for a given region
EGS_BaseGeometry * geometry
the phantom geometry object
void getCurrentScore(int ireg, double &sum, double &sum2)
get current tlen score for region
void output3DDoses(ostream &out, EGS_ScoringArray *score, string type)
write input scoring array to 3ddose file
vector< int > getRegionsWithCorrections()
return a vector of all regions which were corrected
double getTlenNorm(int ireg)
int global_reg_start
starting global region index for this phantom
EGS_Float effective_histories
void outputTopDoses(int top_n, vector< RegionResult > region_results)
write the top_n doses to console
EGS_Float getRealRho(int ireg)
return actual density for region
void writeVolumeCorrection(ostream &)
write voxel volumes to file
void setEffectiveHistories(EGS_Float current_case)
set number of effective histories for normalizing scoring arrays
void enableScatterScoring()
enableInteractionScoring must be called before simulation begins if you want to score dose with inter...
void setHistory(EGS_I64 current_case)
set current history on scoring arrays for proper statistics
bool needs_user_geoms
this phantom requires user specified geometries
EB_Phantom(EGS_Application *, EGS_BaseGeometry *, set< int > global_regions, int nsource, Publisher *publisher)
EB_Phantom constructor.
static const string threeddose_geom_types[]
int readData(istream *ifile)
void scoreEdep(int ir, EGS_Float dose)
add energy deposition dose to region ir
EGS_Float getRealMass(int ireg)
return (corrected) real mass for region
static const string autovol_phantom_geom_types[]
EGS_Application * app
Parent application instance. Required for constructing filenames.
EGS_ScoringArray * sscat_score
Tracklenth scored dose from single scattered particles.
vector< RegionResult > getRegionResults()
create a vector of RegionResult structs which can then be sorted by dose value. used for output routi...
EGS_Float total_radiant_e
void setCorrectedVolume(int ir, double fraction, double unc=0)
Allow user to tell phantom what the actual volume of a region is.
void getScoringArrays(vector< EGS_ScoringArray * > &scores, vector< string > &types, vector< string > &descriptions)
get all active scoring arrays, their types and descriptions
string medIndex(int medium)
get medium index 1-9A-Z
EGS_ScoringArray * mscat_score
Tracklenth scored dose from multiple scattered particles.
static bool canWrite3ddose(const string &geom_type)
function for checking whether a given geometry type can output 3ddose files
void outputResults(int top_n=20, string output_3ddose="text", string output_egsphant="text", string output_voxinfo="text", string output_volcor="text")
tell phantom to output its results.
int addState(istream &ifile)
EGS_ScoringArray * prim_score
Tracklenth scored dose from primary particles.
void writeEGSPhant(ostream &)
write actual egsphant data to file for this phantom
void getEGSdatScoringArrays(vector< EGS_ScoringArray * > &scores)
get all active scoring arrays for writing to egsdat file
void enableTLenScoring()
enableTLenScoring must be called before simulation begins if you want to score dose with tracklength ...
void outputDoseStats(EGS_ScoringArray *score, string type)
write some stats about dose arrays
EGS_ScoringArray * tlen_score
Tracklength dose scoring array.
std::map< int, double > corrected_volumes
Corrected volume in a given region.
void outputVolumeCorrection(string format)
intialize and output write voxel volumes to file
void output3DBounds(ostream &out)
write the phantom bounds to 3ddose file
EGS_Float getCorrectedVolume(int ireg)
get uncorrected volume for a given region
void setDoseScale(EGS_Float)
set dose scaling factor for output
static bool needsUserVolumes(const string &geom_type)
function for checking whether a given geometry type requires user specified volumes
void writeVoxelInfo(ostream &)
write voxel info file
int outputData(ostream *ofile)
set< int > global_regions
the set of all global regions contained in this phantom
EGS_Float getUncorrectedMass(int ireg)
return uncorrected for region
EGS_Float getVolumeUncertainty(int ireg)
get volume unc
void enableInteractionScoring()
enableInteractionScoring must be called before simulation begins if you want to score dose with inter...
EGS_Float avgVoxelVol()
return average voxel volume
EGS_ScoringArray * edep_score
Interaction scored dose scoring array.
static bool isMultScat(int latch)
static bool isPrimary(int latch)
static bool isSingleScat(int latch)
void subscribe(Subscriber *s, EB_Message message)
void open(const char *name, int open_mode=std::ios::out)
handle particles latch bits for egs_brachy
string space2underscore(std::string text)
bool tlenRegTopResultCompare(const RegionResult &firstElem, const RegionResult &secondElem)
bool edepRegTopResultCompare(const RegionResult &firstElem, const RegionResult &secondElem)
Header file for phantom objects.
@ PARTICLE_ESCAPING_SOURCE