diff --git a/HEN_HOUSE/egs++/egs_functions.cpp b/HEN_HOUSE/egs++/egs_functions.cpp index 013652422..22fd4b7a9 100644 --- a/HEN_HOUSE/egs++/egs_functions.cpp +++ b/HEN_HOUSE/egs++/egs_functions.cpp @@ -205,6 +205,79 @@ string egsJoinPath(const string &first, const string &second) { return result; } +/* Expand first environment variable found anywhere in string aname + + - Checks for Unix or Windows style environment variable + - Expands environment variable in aname appending folder + separator if missing + - Replaces backslashes with slashes + - Checks for duplicate slashes in aname +*/ +string egsExpandPath(const string &aname) { + string str = aname; + string c = "%$"; + // Check for FIRST environment variable anywhere in aname + size_t p1= str.npos; + int i = 0; + while (i < c.size()) { + p1= str.find_first_of(c[i++]); + if (p1 != str.npos) { + break; + } + } + string fs = "%/\\"; + i = 0; + size_t p2 = str.npos; + while (p1 != str.npos && i < fs.size()) { + p2 = str.find_first_of(fs[i++],p1+1); + if (p2 != str.npos) { + break; + } + } + // Did we find an environment variable? + if (p1 != str.npos && p2 != str.npos) { + string envvar = str.substr(p1+1, p2-(p1+1)); + char *envval = getenv(envvar.c_str()); + // Check that env var is defined + string envloc = envval ? string(envval) : string(); + if (!envloc.empty()) { + // Append missing separator + size_t last = envloc.find_last_of("/\\"); + if (last != envloc.size()-1) { + if (envloc[last] == __egs_fs) { + envloc.append("\\"); + } + else { + envloc.append("/"); + } + } + str.replace(p1, p2-p1+1,envloc); + } + else { + if (str[p1] == '$') { + egsWarning("\n\n *** egs++ egsExpandPath: Undefined environment variable $%s \n\n", envvar.c_str()); + } + else { + egsWarning("\n\n *** egs++ egsExpandPath: Undefined environment variable %%%s%% \n\n", envvar.c_str()); + } + } + } + // Replace back slashes with slashes + size_t found = str.find("\\"); + while (found != str.npos) { + str.replace(found,1,"/"); + found = str.find("\\"); + } + // Remove duplicated slashes + found = str.find("//"); + while (found != str.npos) { + str.replace(found,2,"/"); + found = str.find("//"); + } + + return str; +} + string egsStripPath(const string &aname) { int j; for (j=aname.size()-1; j>=0; j--) { diff --git a/HEN_HOUSE/egs++/egs_functions.h b/HEN_HOUSE/egs++/egs_functions.h index 5a361298a..cba648177 100644 --- a/HEN_HOUSE/egs++/egs_functions.h +++ b/HEN_HOUSE/egs++/egs_functions.h @@ -199,6 +199,16 @@ string EGS_EXPORT egsJoinPath(const string &first, const string &second); */ string EGS_EXPORT egsStripPath(const string &fname); +/*! \brief Expands first environment variable found in a file name. + * + * Looks for first Unix or Windows environment variable and expands + * it into its value. Missing folder separator is added, duplicated + * separators are removed. Final file name uses slashes as separators. + * + * \ingroup egspp_main + */ +string EGS_EXPORT egsExpandPath(const string &fname); + /*! \brief Get the name of the host the program is running on. * * \ingroup egspp_main diff --git a/HEN_HOUSE/egs++/egs_spectra.cpp b/HEN_HOUSE/egs++/egs_spectra.cpp index 4aa2e1769..eb71023bd 100644 --- a/HEN_HOUSE/egs++/egs_spectra.cpp +++ b/HEN_HOUSE/egs++/egs_spectra.cpp @@ -1873,6 +1873,8 @@ EGS_BaseSpectrum *EGS_BaseSpectrum::createSpectrum(EGS_Input *input) { else if (inp->compare(stype,"tabulated spectrum")) { string spec_file; err = inp->getInput("spectrum file",spec_file); + // Expands FIRST environment variable found in spec_file + spec_file = egsExpandPath(spec_file); if (!err) { ifstream sdata(spec_file.c_str()); if (!sdata) egsWarning("%s failed to open spectrum file %s\n", diff --git a/HEN_HOUSE/user_codes/cavity/cavity.cpp b/HEN_HOUSE/user_codes/cavity/cavity.cpp index 00eaa63ef..708127f90 100644 --- a/HEN_HOUSE/user_codes/cavity/cavity.cpp +++ b/HEN_HOUSE/user_codes/cavity/cavity.cpp @@ -2822,6 +2822,7 @@ int Cavity_Application::initScoring() { if( err3 ) egsFatal( "\n\n*** Wrong/missing 'muen file' input for a " "HVL calculation\n This is a fatal error\n\n"); + muen_file = egsExpandPath(muen_file); ifstream muen_data(muen_file.c_str()); if( !muen_data ){ egsFatal( diff --git a/HEN_HOUSE/user_codes/egs_cbct/egs_cbct.cpp b/HEN_HOUSE/user_codes/egs_cbct/egs_cbct.cpp index 0e389e6e0..c2bdd2739 100644 --- a/HEN_HOUSE/user_codes/egs_cbct/egs_cbct.cpp +++ b/HEN_HOUSE/user_codes/egs_cbct/egs_cbct.cpp @@ -1145,6 +1145,7 @@ int EGS_CBCT::initScoring() { if( err3 ) egsFatal( "\n\n*** Wrong/missing 'muen file' input for a " "kerma calculation\n This is a fatal error\n\n"); + muen_file = egsExpandPath(muen_file); ifstream muen_data(muen_file.c_str()); if( !muen_data.is_open() ){ egsFatal( @@ -1152,8 +1153,11 @@ int EGS_CBCT::initScoring() { " This is a fatal error\n",muen_file.c_str()); } else{ - egsInformation("\nUsing E*muen file %s for air-kerma calculation\n", - muen_file.c_str()); + egsInformation( + "\n\n=============== Kerma Scoring ===============\n" + "E*muen/rho file: %s\n" + "=============================================\n", + muen_file.c_str()); } int ndat; muen_data >> ndat; if( ndat < 2 || muen_data.fail() ) egsFatal( @@ -1403,7 +1407,7 @@ void EGS_CBCT::initOutput() { scan_type = blank; } else{ - blank_scan = b_scan; + blank_scan = egsExpandPath(b_scan); } /* If no scan file name entry, a warning is issued. @@ -1417,7 +1421,7 @@ void EGS_CBCT::initOutput() { " This is not a proper CBCT calculation.\n\n"); } else{ - real_scan = the_scan; + real_scan = egsExpandPath(the_scan); } /* check what scans are requested by the user real => real scan simulation diff --git a/HEN_HOUSE/user_codes/egs_cbct/example_w5br.egsinp b/HEN_HOUSE/user_codes/egs_cbct/example_w5br.egsinp index a20cf30cb..f059fd9d1 100644 --- a/HEN_HOUSE/user_codes/egs_cbct/example_w5br.egsinp +++ b/HEN_HOUSE/user_codes/egs_cbct/example_w5br.egsinp @@ -31,8 +31,8 @@ # # Projections at other angles can be obtained by modifying input block # :cbct setup: below. One can define the projection angle and angular -# :interval. Negative values of the latter indicate rotation is done -# :counter-clockwise around the indicated axis. +# interval. Negative values of the latter indicate rotation is done +# counter-clockwise around the indicated axis. # # BEWARE: # @@ -43,8 +43,6 @@ # - media information in PEGS4 data file 521icru.pegs4dat distributed # with EGSnrc. # -# - Replace $EGS_HOME string below with the actual value!!! -# # - If the detector resolution is changed, one must recalculate the blank # scan # @@ -183,7 +181,7 @@ rotation = 0 1.570796326794896619 0 :stop transformation: # Uses file provided in the distribution - muen file = /home/mainegra/egsnrc_mp/egs_fac/muen_air.data + muen file = $HEN_HOUSE/user_codes/egs_fac/examples/muen_air.data :stop planar scoring: :stop scoring options: @@ -197,13 +195,13 @@ ############################################### # Use the 2 lines below to produce a blank scan ############################################### - #scan file = /home/mainegra/egsnrc_mp/egs_cbct/blank_coll_64.scan + #scan file = $EGS_HOME/egs_cbct/blank_coll_64.scan #scan type = blank ############################################### # Use the 3 lines below to produce real scans ############################################### - scan file = /home/mainegra/egsnrc_mp/egs_cbct/scan_w5br_coll_64.scan - blank scan = /home/mainegra/egsnrc_mp/egs_cbct/blank_coll_64.scan + scan file = $EGS_HOME/egs_cbct/scan_w5br_coll_64.scan + blank scan = $EGS_HOME/egs_cbct/blank_coll_64.scan scan type = scatter ############################################### :stop scan output: @@ -286,18 +284,20 @@ ######## -# For fast computation one can use KN for Compton scattering. However, -# in realistic phantoms this may cause a 3% discrepancy. +# For fast computation one can assume scattering from free electrons. +# However, in realistic phantoms this may cause a 3% discrepancy. ######## :start MC transport parameter: Global ECUT = 1 - Photon cross sections = xcom # epdl (or xcom) + Photon cross sections = xcom # epdl (or xcom) Bound Compton scattering = off + + Rayleigh scattering = off - Rayleigh scattering= on + Atomic relaxations = off :stop MC transport parameter: diff --git a/HEN_HOUSE/user_codes/egs_fac/egs_fac.cpp b/HEN_HOUSE/user_codes/egs_fac/egs_fac.cpp index ffa8964d6..c32403d68 100644 --- a/HEN_HOUSE/user_codes/egs_fac/egs_fac.cpp +++ b/HEN_HOUSE/user_codes/egs_fac/egs_fac.cpp @@ -955,9 +955,17 @@ int EGS_FACApplication::initScoring() { int err3 = options->getInput("muen file",muen_file); if( err3 ) egsFatal("\n\n*** Wrong/missing 'muen file' input\n" " This is a fatal error\n\n"); + muen_file = egsExpandPath(muen_file); ifstream muen_data(muen_file.c_str()); if( !muen_data ) egsFatal("\n\n*** Failed to open muen file %s\n" " This is a fatal error\n",muen_file.c_str()); + else{ + egsInformation( + "\n\n=============== Kerma Scoring ===============\n" + "E*muen/rho file: %s\n" + "=============================================\n\n", + muen_file.c_str()); + } int ndat; muen_data >> ndat; if( ndat < 2 || muen_data.fail() ) egsFatal( "\n\n*** Failed to read muen dfata file\n"); diff --git a/HEN_HOUSE/user_codes/egs_fac/examples/example_mees_250kV.egsinp b/HEN_HOUSE/user_codes/egs_fac/examples/example_mees_250kV.egsinp index b6d97308a..42c173bf8 100644 --- a/HEN_HOUSE/user_codes/egs_fac/examples/example_mees_250kV.egsinp +++ b/HEN_HOUSE/user_codes/egs_fac/examples/example_mees_250kV.egsinp @@ -29,8 +29,7 @@ # # An example input file for egs_fac. # -# NOTE: Substitute every instance of $HEN_HOUSE for its actual value in this -# file! It is essential to use 'Bound Compton Scattering = norej'. See the MC +# NOTE: It is essential to use 'Bound Compton Scattering = norej'. See the MC # transport parameter input section for more info. See comments accompanying # the various inputs for more details. # @@ -803,7 +802,7 @@ # ignores them (except for the first and last energy, which define the # energy interval). # - muen file = $HEN_HOUSE/user_codes/egs_fac/muen_air.data + muen file = $HEN_HOUSE/user_codes/egs_fac/examples/muen_air.data :stop scoring options: @@ -852,4 +851,4 @@ Bound Compton Scattering = norej Photon cross sections = xcom # (could also be epdl or si) -:stop MC transport parameter: \ No newline at end of file +:stop MC transport parameter: diff --git a/HEN_HOUSE/user_codes/egs_fac/examples/mxr-320-250kVp_tube.egsinp b/HEN_HOUSE/user_codes/egs_fac/examples/mxr-320-250kVp_tube.egsinp index c38b9af5c..f0e5c21e5 100644 --- a/HEN_HOUSE/user_codes/egs_fac/examples/mxr-320-250kVp_tube.egsinp +++ b/HEN_HOUSE/user_codes/egs_fac/examples/mxr-320-250kVp_tube.egsinp @@ -163,9 +163,16 @@ AIRICRU512 :Stop MC Transport Parameter: ######################### + # + # User-defined entries + # + ######################### :Start user inputs: - # phsp output directory = /home/mainegra/egsnrc_mp/phsp/ + # Enter here a custom location for phase-space file output + # For instance users might want to direct the output to a + # device with enough disk space! + # phsp output directory = enter_user_defined_location :Stop user inputs: ######################### diff --git a/HEN_HOUSE/user_codes/egs_kerma/egs_kerma.cpp b/HEN_HOUSE/user_codes/egs_kerma/egs_kerma.cpp index 73cfa8fa8..6e5b159db 100644 --- a/HEN_HOUSE/user_codes/egs_kerma/egs_kerma.cpp +++ b/HEN_HOUSE/user_codes/egs_kerma/egs_kerma.cpp @@ -1312,36 +1312,23 @@ int EGS_KermaApplication::initScoring() { } string emuen_file; - int errKmuen = options->getInput("emuen file",emuen_file); + int errKmuen = options->getInput("emuen file", emuen_file); if (errKmuen) { // Handle legacy option - errKmuen = options->getInput("muen file",emuen_file); + errKmuen = options->getInput("muen file", emuen_file); if (errKmuen) egsFatal( "\n\n*** Wrong/missing 'emuen file' input for a " "Kerma calculation\n This is a fatal error\n\n"); } - //Check for environment variable at beginning of file name - std::size_t p1= emuen_file.find_first_of("$"); - if (p1 != emuen_file.npos) { - string str = emuen_file; - std::size_t p2 = str.find_first_of("/"); - string envvar = str.substr(p1+1,p2-1); - //egsInformation(" Found env var: %s\n",envvar.c_str()); - char *envloc = getenv(envvar.c_str()); - //egsInformation(" %s points to: %s\n",envvar.c_str(),envloc); - emuen_file.replace(p1,p2+1,envloc); - //egsInformation("\n-> Kerma calculated using E*muen/rho file : %s\n\n",emuen_file.c_str()); - } - - //emuen_file = egsExpandPath(emuen_file); + emuen_file = egsExpandPath(emuen_file); ifstream muen_data(emuen_file.c_str()); if (!muen_data) { egsFatal( "\n\n*** Failed to open emuen file %s\n" - " This is a fatal error\n",emuen_file.c_str()); + " This is a fatal error\n", emuen_file.c_str()); } else { egsInformation( diff --git a/HEN_HOUSE/user_codes/egs_kerma/example_40keV_SDD_1m_FD.egsinp b/HEN_HOUSE/user_codes/egs_kerma/example_40keV_SDD_1m_FD.egsinp index d8e667190..0b13579f2 100644 --- a/HEN_HOUSE/user_codes/egs_kerma/example_40keV_SDD_1m_FD.egsinp +++ b/HEN_HOUSE/user_codes/egs_kerma/example_40keV_SDD_1m_FD.egsinp @@ -218,10 +218,8 @@ :stop fluence scoring: ### E*muen file (could also be E*mutr): absolute or relative file path - #emuen file = emuen_icru90_1.5MeV.data ### Use absolute path when submitting parallel jobs!!! - ### $EGS_HOME replaced with its value now - emuen file = $EGS_HOME/egs_kerma/emuen_rho_air_1keV-1.5MeV.data + emuen file = $EGS_HOME/egs_kerma/emuen_icru90_1.5MeV.data ### geometry for forced-detection (if omitted, score ONLY when reaching scoring region) Default FD geometry = sphere