107 static bool EGS_DOSE_SCORING_LOCAL inputSet =
false;
109 EGS_DoseScoring::EGS_DoseScoring(
const string &Name,
112 norm_u(1.0), nreg(0), nmedia(0), max_dreg(-1), max_medl(0),
113 m_lastCase(-1),score_medium_dose(false), score_region_dose(false), output_dose_file(false) {
114 otype =
"EGS_DoseScoring";
117 EGS_DoseScoring::~EGS_DoseScoring() {
135 if (d_regionString.length() > 0) {
136 getNumberRegions(d_regionString, d_region);
137 getLabelRegions(d_regionString, d_region);
141 nreg =
app->getnRegions();
143 nmedia =
app->getnMedia();
149 for (imed=0; imed < nmedia; imed++) {
150 sprintf(buf,
"%s%n",
app->getMediumName(imed),&count);
151 if (count > max_medl) {
155 if (d_region.size()>nreg)
156 egsWarning(
"\n*********************************************"
158 "\nRequesting %d dose scoring regions, but there"
159 "\nare only %d geometrical regions!"
160 "\nscoring will be done in all regions!"
161 "\n*********************************************",
162 d_region.size(),nreg);
165 if (score_region_dose) {
166 if (d_region.size() && d_region.size() < nreg) {
168 for (vector<int>::iterator it = d_region.begin(); it < d_region.end(); it++) {
169 if (*it > max_dreg) {
173 for (
int j=0; j<nreg; j++) {
174 d_reg_index.push_back(-1);
175 vol.push_back(vol_list[0]);
177 for (
int i=0; i<d_region.size(); i++) {
178 d_reg_index[d_region[i]]=i;
179 if (i < vol_list.size()) {
180 vol[d_region[i]] = vol_list[i];
183 if (score_region_dose) {
189 for (
int j=0; j<nreg; j++) {
190 d_reg_index.push_back(j);
191 if (j < vol_list.size()) {
192 vol.push_back(vol_list[j]);
195 vol.push_back(vol_list[0]);
198 if (score_region_dose) {
204 if (score_medium_dose) {
207 if (!score_region_dose) {
208 if (vol_list.size() == 1) {
209 vol.push_back(vol_list[0]);
212 for (
int j=0; j<nreg; j++) {
213 if (j < vol_list.size()) {
214 vol.push_back(vol_list[j]);
217 vol.push_back(vol_list[0]);
223 if (output_dose_file) {
225 for (
int i=0; i<nreg; i++) {
226 df_reg.push_back(-1);
237 if(globalOffset < 0) {
241 for (
int k=0; k<nz; k++) {
242 for (
int j=0; j<ny; j++) {
243 for (
int i=0; i<nx; i++) {
244 df_reg[globalOffset+count]=count;
254 }
else if(file_type==1 || file_type==2) {
260 egsFatal(
"\nEGS_DoseScoring:: Error: Could not cast %s to EGS_Mesh.\n", dose_geom->
getName().c_str());
264 df_reg[globalOffset+i]=i;
271 description =
"\n*******************************************\n";
275 description +=
"*******************************************\n";
282 description +=
" - Medium dose will be calculated\n";
284 description +=
"\n--------------------------------------\n";
285 sprintf(buf,
"%*s %*s rho/(g/cm^3)\n",max_medl/2,
"medium",max_medl/2,
" ");
287 description +=
"--------------------------------------\n";
288 for (imed=0; imed < nmedia; imed++) {
289 sprintf(buf,
"%-*s",max_medl,
app->getMediumName(imed));
292 sprintf(buf,
"%11.8f",
app->getMediumRho(imed));
296 description +=
"--------------------------------------\n";
298 description +=
" Non-unity user-requested normalization = ";
299 sprintf(buf,
"%g\n",norm_u);
304 if (d_region.size()) {
314 }
else if (file_type==1) {
316 }
else if (file_type==2) {
325 description +=
"\n*******************************************\n\n";
328 void EGS_DoseScoring::getNumberRegions(
const string &str, vector<int> ®s) {
332 void EGS_DoseScoring::getLabelRegions(
const string &str, vector<int> ®s) {
336 void EGS_DoseScoring::reportResults() {
337 egsInformation(
"\n======================================================\n");
339 egsInformation(
"======================================================\n");
340 EGS_Float normD = 1., normE=1.;
341 const double JOULES_PER_MEV = 1.602176634e-13;
343 EGS_Float F =
app->getFluence();
347 normD = JOULES_PER_MEV * 1000. * normE;
348 int irmax_digits = getDigits(max_dreg);
349 if (irmax_digits < 2) {
357 }
else if(file_type == 1 || file_type == 2) {
358 mesh =
dynamic_cast<EGS_Mesh *
>(dose_geom);
360 egsFatal(
"\nEGS_DoseScoring:: Error: Could not cast %s to EGS_Mesh.\n", dose_geom->
getName().c_str());
369 egsInformation(
"\n\n==> Summary of region dosimetry (per particle)\n\n");
371 "%*s %*s %12s %12s Edep (MeV) D (Gy) %n\n",
372 irmax_digits,
"ir",max_medl,
"medium",
"rho (g/cm^3)",
"Volume (cm^3)",&count);
375 egsInformation(
"\n==> Summary of region dosimetry (per fluence)\n");
377 "%*s %*s %12s %12s Edep (MeV*cm^2) D (Gy*cm^2) %n\n",
378 irmax_digits,
"ir",max_medl,
"medium",
"rho (g/cm^3)",
"Volume (cm^3)",&count);
380 line.append(count,
'-');
384 for (
int ireg = 0; ireg < nreg; ireg++) {
385 if (d_reg_index[ireg]>=0) {
399 if(df_reg[ireg] >= 0) {
400 rho = getRealRho(df_reg[ireg]);
401 mass = dose_geom->
getVolume(df_reg[ireg])*rho;
403 rho =
app->getMediumRho(imed);
404 mass = rho*vol[ireg];
406 }
else if(file_type == 1 || file_type == 2) {
408 if(df_reg[ireg] >= 0) {
412 rho =
app->getMediumRho(imed);
413 mass = rho*vol[ireg];
417 rho =
app->getMediumRho(imed);
418 mass = vol[ireg]*rho;
428 egsInformation(
"%*d %-*s %11.8f %13.6f %12.4e +/- %-7.3f%% %10.4e +/- %-7.3f%%\n",
429 irmax_digits,ireg,max_medl,
app->getMediumName(imed),rho,vol[ireg],r*normE,dr*100.,r*normD/mass,dr*100.);
435 vector<EGS_Float> massM(nmedia,0);
439 for (
int ir=0; ir<nreg; ir++) {
450 if(df_reg[ir] >= 0) {
451 massM[imed] += dose_geom->
getVolume(df_reg[ir])*getRealRho(df_reg[ir]);
453 EGS_Float volume = vol.size() > 1 ? vol[ir]:vol[0];
454 massM[imed] +=
app->getMediumRho(imed)*volume;
456 }
else if(file_type == 1 || file_type == 2) {
458 if(df_reg[ir] >= 0) {
461 EGS_Float volume = vol.size() > 1 ? vol[ir]:vol[0];
462 massM[imed] +=
app->getMediumRho(imed)*volume;
466 EGS_Float volume = vol.size() > 1 ? vol[ir]:vol[0];
467 massM[imed] +=
app->getMediumRho(imed)*volume;
473 egsInformation(
"\n\n==> Summary of media dosimetry (per particle)\n");
475 "%*s %*sMass/[g] Edep/[MeV] D/[Gy] %n\n",
476 max_medl/2,
"medium",max_medl/2,
" ",&count);
479 egsInformation(
"\n\n==> Summary of media dosimetry (per fluence)\n");
481 "%*s %*sMass/[g] Edep/[MeV*cm2] D/[Gy*cm2] %n\n",
482 max_medl/2,
"medium",max_medl/2,
" ",&count);
485 line.append(count,
'-');
488 for (
int im=0; im<nmedia; im++) {
493 "%-*s %7.4e %10.4e +/- %-7.3f%% %10.4e +/- %-7.3f%%\n",
494 max_medl,
app->getMediumName(im),massM[im],r*normE,dr*100.,r*normD/massM[im],dr*100.);
501 egsInformation(
"\n EGS_DoseScoring: This is one of a number of parallel jobs. Will only output dose file on combining results.\n");
504 outputDoseFile(normD);
507 egsInformation(
"\n======================================================\n");
510 void EGS_DoseScoring::outputDoseFile(
const EGS_Float &normD) {
519 df_out.open(df_name.c_str());
521 egsFatal(
"\n EGS_DoseScoring: Error: Failed to open file %s\n",df_name.c_str());
529 df_out << nx <<
" " << ny <<
" " << nz <<
"\n";
531 float bound,
dose, doseun;
533 for (
int i=0; i<=nx; i++) {
535 df_out << bound <<
" ";
538 for (
int j=0; j<=ny; j++) {
540 df_out << bound <<
" ";
543 for (
int k=0; k<=nz; k++) {
545 df_out << bound <<
" ";
549 for (
int i=0; i<nx*ny*nz; i++) {
551 EGS_Float mass = dose_geom->
getVolume(i)*getRealRho(i);
553 df_out <<
dose <<
" ";
557 for (
int i=0; i<nx*ny*nz; i++) {
566 df_out << doseun <<
" ";
572 }
else if(file_type==1) {
575 egsFatal(
"\nEGS_DoseScoring:: Error: Could not cast %s to EGS_Mesh.\n", dose_geom->
getName().c_str());
579 df_out.open(df_name.c_str());
581 egsFatal(
"\n EGS_DoseScoring: Error: Failed to open file %s\n",df_name.c_str());
586 df_out << std::setprecision(std::numeric_limits<double>::max_digits10);
588 df_out <<
"# vtk DataFile Version 4.1\n"
591 "DATASET UNSTRUCTURED_GRID\n"
592 "POINTS " << mesh->
num_nodes() <<
" double\n";
595 for (
int i = 0; i < mesh->
num_nodes(); i++) {
597 df_out << node.
x <<
" " << node.
y <<
" " << node.
z <<
"\n";
606 df_out <<
"4 " << node_offsets[0] <<
" " << node_offsets[1] <<
" " <<
607 node_offsets[2] <<
" " << node_offsets[3] <<
"\n";
610 df_out <<
"CELL_TYPES " << mesh->
num_elements() <<
"\n";
619 df_out <<
"FIELD FieldData 2\n";
621 df_out <<
"dose%20[Gy/fluence] 1 " << mesh->
num_elements() <<
" double\n";
624 double e_dep, uncert;
629 df_out << normD *e_dep / mass <<
"\n";
633 df_out <<
"uncertainty%20[%25] 1 " << mesh->
num_elements() <<
" double\n";
635 double e_dep, uncert;
640 df_out << 100.0 <<
"\n";
643 df_out << uncert / e_dep * 100.0 <<
"\n";
647 }
else if(file_type==2) {
650 egsFatal(
"\nEGS_DoseScoring:: Error: Could not cast %s to EGS_Mesh.\n", dose_geom->
getName().c_str());
654 df_out.open(df_name.c_str());
656 egsFatal(
"\n EGS_DoseScoring: Error: Failed to open file %s\n",df_name.c_str());
660 df_out << std::setprecision(std::numeric_limits<double>::max_digits10);
663 df_out <<
"x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4,dose,uncertainty\n";
671 for (
int j = 0; j < 4; j++) {
673 df_out << node.
x <<
"," << node.
y <<
"," << node.
z <<
",";
677 double e_dep, uncert;
681 df_out << normD * e_dep / mass <<
",";
686 df_out << 100.0 <<
"\n";
689 df_out << uncert / e_dep * 100.0 <<
"\n";
693 egsFatal(
"\n EGS_DoseScoring: Warning: Dose output file type not recognized.\n");
697 bool EGS_DoseScoring::storeState(ostream &data)
const {
715 bool EGS_DoseScoring::setState(istream &data) {
731 bool EGS_DoseScoring::addState(istream &data) {
732 int err = addTheStates(data);
739 int EGS_DoseScoring::addTheStates(istream &data) {
747 if (!tmp.setState(data)) {
754 if (!tmpM.setState(data)) {
760 unsigned long numElements = 0;
765 numElements = nx*ny*nz;
766 }
else if(file_type == 1 || file_type == 2) {
772 if (!tmpF.setState(data)) {
780 void EGS_DoseScoring::resetCounter() {
818 static void setInputs() {
821 setBaseAusgabObjectInputs();
823 ausBlockInput->getSingleInput(
"library")->setValues({
"egs_dose_scoring"});
826 ausBlockInput->addSingleInput(
"medium dose",
false,
"Requests the dose deposited in each medium to be scored, default is no", {
"yes",
"no"});
827 ausBlockInput->addSingleInput(
"region dose",
false,
"Requests the dose deposited in each region to be scored, default is yes", {
"yes",
"no"});
828 ausBlockInput->addSingleInput(
"volume",
false,
"Either a single volume, which will be the same for all regions or a list of individual volumes for each region in 'dose regions', default is 1 cm^3");
829 auto dosePtr = ausBlockInput->addSingleInput(
"dose regions",
false,
"A list of individual regions to report the dose in");
830 auto startPtr = ausBlockInput->addSingleInput(
"dose start region",
false,
"For a series of region ranges, list the 'starting region' for each range here (inclusive)");
831 auto stopPtr = ausBlockInput->addSingleInput(
"dose stop region",
false,
"For a series of region ranges, list the 'ending region' for each range here (inclusive)");
833 dosePtr->addDependency(startPtr,
"",
true);
834 dosePtr->addDependency(stopPtr,
"",
true);
835 startPtr->addDependency(dosePtr,
"",
true);
836 stopPtr->addDependency(dosePtr,
"",
true);
839 auto blockPtr = ausBlockInput->addBlockInput(
"output dose file");
840 blockPtr->addSingleInput(
"geometry name",
true,
"The name of a predefined EGS_XYZGeometry");
841 blockPtr->addSingleInput(
"file type",
true,
"The type of file", {
"3ddose"});
844 EGS_DOSE_SCORING_EXPORT
string getExample() {
848 # Example of egs_dose_scoring
849 #:start ausgab object:
850 library = egs_dose_scoring
852 medium dose = yes # no (default)
853 region dose = no # yes (default)
854 volume = v1 ... vn # in cm**3
855 dose regions = ir1 ... irn # individual regions
861 EGS_DOSE_SCORING_EXPORT shared_ptr<EGS_BlockInput> getInputs() {
865 return ausBlockInput;
870 const static char *func =
"createAusgabObject(dose_scoring)";
875 vector <EGS_Float> v_in;
879 vector<string> allowed_mode;
880 allowed_mode.push_back(
"no");
881 allowed_mode.push_back(
"yes");
882 int d_in_medium = input->
getInput(
"medium dose",allowed_mode,0);
883 int d_in_region = input->
getInput(
"region dose",allowed_mode,1);
886 string d_regionsString;
887 vector <int> d_regions;
888 bool using_all_regions=
true;
889 vector <int> d_start, d_stop;
890 if (!input->
getInput(
"dose regions",d_regionsString)&& d_regionsString.length()>0) {
891 using_all_regions =
false;
894 int err1 = input->
getInput(
"dose start region",d_start);
895 int err2 = input->
getInput(
"dose stop region",d_stop);
896 if (!err1 && !err2) {
897 if (d_start.size()==d_stop.size()) {
898 for (
int i=0; i<d_start.size(); i++) {
899 int ir = d_start[i], fr = d_stop[i];
900 for (
int ireg=ir; ireg<=fr; ireg++) {
901 d_regions.push_back(ireg);
904 using_all_regions =
false;
907 "%s: Mismatch in start and stop dose region groups !!!\n"
908 " Calculating dose in ALL regions.\n",func);
911 EGS_Float norma = 1.0;
912 int err04 = input->
getInput(
"normalization",norma);
920 vector <EGS_Float> volin;
922 if (! using_all_regions && v_in.size()== d_start.size()) {
923 for (
int i=0; i<d_start.size(); i++) {
924 int ir = d_start[i], fr = d_stop[i];
925 for (
int ireg=ir; ireg<=fr; ireg++) {
926 volin.push_back(v_in[i]);
935 bool outputdosefile=
false;
942 int err05 = fileinp->
getInput(
"geometry name",gname);
944 egsFatal(
"EGS_DoseScoring: Output dose file: missing/incorrect input for name of geometry.\n");
949 egsFatal(
"EGS_DoseScoring: Output dose file: %s does not name an existing geometry\n",gname.c_str());
951 else if (dgeom->
getType()!=
"EGS_XYZGeometry" && dgeom->
getType()!=
"EGS_Mesh") {
952 egsFatal(
"EGS_DoseScoring: Output dose file: %s is not an EGS_XYZGeometry or EGS_Mesh.\n",gname.c_str());
956 if (fileinp->
getInput(
"file type", str) < 0) {
960 vector<string> allowed_ftype;
961 allowed_ftype.push_back(
"3ddose");
962 allowed_ftype.push_back(
"vtk");
963 allowed_ftype.push_back(
"csv");
964 ftype = fileinp->
getInput(
"file type", allowed_ftype, -1);
966 egsFatal(
"EGS_DoseScoring: Output dose file: Invalid file type. The supported types are: 3ddose, vtk, and csv.\n");
972 if(ftype == 0 && dgeom->
getType()!=
"EGS_XYZGeometry") {
973 egsFatal(
"EGS_DoseScoring: Output dose file: For 3ddose format, the geometry must be of type EGS_XYZGeometry.\n");
974 }
else if ((ftype == 1 || ftype == 2) && dgeom->
getType()!=
"EGS_Mesh") {
975 egsFatal(
"EGS_DoseScoring: Output dose file: For vtk and csv formats, the geometry must be of type EGS_Mesh.\n");
985 if (volin.size()==1) {
986 result->setVol(volin[0]);
988 else if (volin.size()) {
989 result->setVol(volin);
994 if (!using_all_regions) {
995 if (d_regions.size() > 0) {
996 result->setDoseRegions(d_regions);
999 result->setDoseRegions(d_regionsString);
1003 result->setMediumScoring(
true);
1006 result->setRegionScoring(
true);
1008 if (outputdosefile) {
1009 result->setOutputFile(
true,dgeom,ftype);
1013 result->setUserNorm(norma);
Base class for advanced EGSnrc C++ applications.
void getLabelRegions(const string &str, vector< int > ®s)
Gets the regions for the labels in str and pushes onto regs.
int getMedium(int ireg)
Returns the medium index in region ireg using C-style indexing.
int getGlobalRegionOffset(const string geomName)
Get the global region number for the first region in the geometry.
bool isRealRegion(int ireg)
Returns true if ireg is a real region, false otherwise.
const string & getAppDir() const
Returns the absolute path to the user code directory.
void getNumberRegions(const string &str, vector< int > ®s)
Gets numbers out of str and pushes them onto regs.
int getIparallel() const
Returns the job number in a parallel run.
virtual void setApplication(EGS_Application *App)
Set the application this object belongs to.
string description
A short ausgab object description.
EGS_Application * app
The application this object belongs to.
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
virtual const string & getType() const =0
Get the geometry type.
virtual EGS_Float getVolume(int ireg)
Calculates the volume of region ireg.
const string & getName() const
Get the name of this geometry.
virtual int getNRegDir(int idir)
virtual EGS_Float getBound(int idir, int ind)
Returns region boundaries in direction determined by idir.
static EGS_BaseGeometry * getGeometry(const string &Name)
Get a pointer to the geometry named Name.
A dose scoring object: header.
EGS_ScoringArray * doseF
Scoring dose in each region in the specified geometry.
EGS_ScoringArray * doseM
Scoring dose in each medium.
EGS_I64 m_lastCase
The event set via setCurrentCase()
EGS_ScoringArray * dose
Scoring in each dose scoring region.
A tetrahedral mesh geometry.
EGS_Float element_density(int i) const
Returns the density in g/cm3 of element i.
int num_elements() const
Returns the number of mesh elements.
int num_nodes() const
Returns the number of unique mesh nodes.
EGS_Float element_volume(int i) const
Returns the volume in cm3 of element i.
const EGS_Vector & node_coordinates(int node_offset) const
const std::array< int, 4 > & element_node_offsets(int element) const
Given an element offset, return its four node offsets.
void setName(EGS_Input *inp)
Set the name of the object from the information provided by inp.
const string & getObjectName() const
Get the object name.
string name
The object name.
A class for scoring an array of quantities (e.g. a dose distribution) in a Monte Carlo simulation.
int regions() const
Returns the number of regions (or elements or bins, the most appropriate term depending on the way th...
bool storeState(ostream &data)
Stores the state of the scoring array object into the data stream data.
void currentResult(int ireg, double &r, double &dr)
Sets r to the result in region ireg and dr to its statistical uncertainty.
void reset()
Reset the scoring array to a pristine state.
bool setState(istream &data)
Sets the state fof the scoring array object from the data in the input stream data.
A class representing 3D vectors.
A dose scoring ausgab object.
Global egspp functions header file.
Tetrahedral mesh geometry: header.
EGS_RADIATIVE_SPLITTING_EXPORT EGS_AusgabObject * createAusgabObject(EGS_Input *input, EGS_ObjectFactory *f)
bool EGS_EXPORT egsStoreI64(ostream &data, EGS_I64 n)
Writes the 64 bit integer n to the output stream data and returns true on success,...
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.
bool EGS_EXPORT egsGetI64(istream &data, EGS_I64 &n)
Reads a 64 bit integer from the stream data and assigns it to n. Returns true on success,...
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.