diff --git a/HEN_HOUSE/egs++/Makefile b/HEN_HOUSE/egs++/Makefile index 619662264..d8711d8df 100644 --- a/HEN_HOUSE/egs++/Makefile +++ b/HEN_HOUSE/egs++/Makefile @@ -43,7 +43,7 @@ egspp_files = egs_input egs_base_geometry egs_library egs_transformations \ egs_base_source egs_functions egs_application egs_run_control \ egs_scoring egs_interpolator egs_atomic_relaxations \ egs_ausgab_object egs_particle_track egs_fortran_geometry \ - egs_ensdf + egs_ensdf egs_input_struct egspp_objects = $(addprefix $(DSO1), $(addsuffix .$(obje), $(egspp_files))) config1h = $(IEGS1)$(DSEP)egs_config1.h egs_libconfig.h egs_functions.h @@ -74,6 +74,7 @@ lib_objects = $(addprefix $(DSO1), $(addsuffix .$(obje), $(all_libs))) #****************************************************************************** +#all: $(EGS_BINDIR)egspp$(EXE) $(ABS_DSO)$(libpre)egspp$(libext) $(ABS_DSO)$(libpre)egs_input_struct$(libext) glibs slibs shapes aobjects gtest all: $(EGS_BINDIR)egspp$(EXE) $(ABS_DSO)$(libpre)egspp$(libext) glibs slibs shapes aobjects gtest $(EGS_BINDIR)egspp$(EXE): $(dso) $(DSO1)egspp.$(obje) $(ABS_DSO)$(libpre)egspp$(libext) @@ -86,6 +87,9 @@ $(DSO1)egspp.$(obje): egspp.cpp egs_application.h egs_base_geometry.h egs_vector egs_math.h egs_library.h $(config1h) $(CXX) $(INC1) $(DEF1) $(opt) -c $(COUT)$@ $(notdir $(basename $@)).cpp +#$(ABS_DSO)$(libpre)egs_input_struct$(libext): $(dso) $(DSO1)egs_input_struct.$(obje) $(egspp_objects) +# $(CXX) $(INC1) $(DEFS) $(opt) $(shared) $(DSO1)egs_input_struct.$(obje) $(egspp_objects) $(extra) + $(DSO1)egs_interpolator.$(obje): egs_interpolator.cpp egs_interpolator.h \ $(config1h) @@ -130,7 +134,10 @@ $(DSO1)egs_base_source.$(obje): egs_base_source.cpp egs_base_source.h \ egs_vector.h $(config1h) egs_object_factory.h egs_input.h $(DSO1)egs_ensdf.$(obje): egs_ensdf.cpp egs_ensdf.h \ - $(config1h) egs_functions.h egs_math.h egs_alias_table.h egs_atomic_relaxations.h + $(config1h) egs_math.h egs_alias_table.h egs_atomic_relaxations.h + +$(DSO1)egs_input_struct.$(obje): egs_input_struct.cpp egs_input_struct.h \ + $(config1h) $(DSO1)egs_geometry_tester.$(obje): egs_geometry_tester.cpp \ egs_geometry_tester.h egs_input.h egs_vector.h egs_base_geometry.h \ diff --git a/HEN_HOUSE/egs++/ausgab_objects/egs_dose_scoring/egs_dose_scoring.cpp b/HEN_HOUSE/egs++/ausgab_objects/egs_dose_scoring/egs_dose_scoring.cpp index 39387525f..e874b9484 100644 --- a/HEN_HOUSE/egs++/ausgab_objects/egs_dose_scoring/egs_dose_scoring.cpp +++ b/HEN_HOUSE/egs++/ausgab_objects/egs_dose_scoring/egs_dose_scoring.cpp @@ -27,6 +27,7 @@ # Reid Townson # Hubert Ho # Blake Walters +# Hannah Gallop # ############################################################################### # @@ -96,6 +97,8 @@ #include "egs_input.h" #include "egs_functions.h" +static bool EGS_DOSE_SCORING_LOCAL inputSet = false; + EGS_DoseScoring::EGS_DoseScoring(const string &Name, EGS_ObjectFactory *f) : EGS_AusgabObject(Name,f), dose(0), doseM(0), doseF(0), @@ -589,6 +592,39 @@ void EGS_DoseScoring::resetCounter() { //********************************************************************** extern "C" { + static void setInputs() { + inputSet = true; + + setBaseAusgabObjectInputs(); + + ausBlockInput->getSingleInput("library")->setValues({"EGS_Dose_Scoring"}); + + // Format: name, isRequired, description, vector string of allowed values + ausBlockInput->addSingleInput("medium dose", false, "Requests the dose deposited in each medium to be scored, default is no", {"yes", "no"}); + ausBlockInput->addSingleInput("region dose", false, "Requests the dose deposited in each region to be scored, default is yes", {"yes", "no"}); + ausBlockInput->addSingleInput("volume", false, "Either a unique volume, which will be the same for all regions or a list of individual volumes for each region, default is 1g/cm3"); + auto dosePtr = ausBlockInput->addSingleInput("dose regions", false, "A list of individual regions"); + auto startPtr = ausBlockInput->addSingleInput("dose start region", false, "A list of starts for regions"); + auto stopPtr = ausBlockInput->addSingleInput("dose stop region", false, "A list of stops for regions"); + + dosePtr->addDependency(startPtr, "", true); + dosePtr->addDependency(stopPtr, "", true); + startPtr->addDependency(dosePtr, "", true); + stopPtr->addDependency(dosePtr, "", true); + + // This can only be used if one of the geometries is an EGS_XYZGeometry + auto blockPtr = ausBlockInput->addBlockInput("output dose file"); + blockPtr->addSingleInput("geometry name", true, "The name of a predefined EGS_XYZGeometry"); + blockPtr->addSingleInput("file type", true, "The type of file", {"3ddose"}); + } + + EGS_DOSE_SCORING_EXPORT shared_ptr getInputs() { + if (!inputSet) { + setInputs(); + } + return ausBlockInput; + } + EGS_DOSE_SCORING_EXPORT EGS_AusgabObject *createAusgabObject(EGS_Input *input, EGS_ObjectFactory *f) { const static char *func = "createAusgabObject(dose_scoring)"; diff --git a/HEN_HOUSE/egs++/ausgab_objects/egs_phsp_scoring/egs_phsp_scoring.cpp b/HEN_HOUSE/egs++/ausgab_objects/egs_phsp_scoring/egs_phsp_scoring.cpp index 958a8b71c..d75b5e3dc 100644 --- a/HEN_HOUSE/egs++/ausgab_objects/egs_phsp_scoring/egs_phsp_scoring.cpp +++ b/HEN_HOUSE/egs++/ausgab_objects/egs_phsp_scoring/egs_phsp_scoring.cpp @@ -23,7 +23,7 @@ # # Author: Blake Walters, 2018 # -# Contributors: +# Contributors: Hannah Gallop # ############################################################################### */ @@ -44,6 +44,8 @@ #include "egs_functions.h" #include "iaea_phsp.h" +static bool EGS_PHSP_SCORING_LOCAL inputSet = false; + EGS_PhspScoring::EGS_PhspScoring(const string &Name, EGS_ObjectFactory *f) : EGS_AusgabObject(Name,f), phsp_index(0), store_max(1000), phsp_file(0), @@ -510,190 +512,270 @@ bool EGS_PhspScoring::addState(istream &data) { //********************************************************************** extern "C" { + static void setInputs() { + inputSet = true; + + setBaseAusgabObjectInputs(); + + ausBlockInput->getSingleInput("library")->setValues({"EGS_Phsp_Scoring"}); + + // Format: name, isRequired, description, vector string of allowed values + auto formatPtr = ausBlockInput->addSingleInput("output format", false, "The type of file the data is output to", {"EGSnrc", "IAEA"}); + + auto xPtr = ausBlockInput->addSingleInput("constant X", false, "X values(cm) at which all particles are scored."); + xPtr->addDependency(formatPtr, "IAEA"); + auto yPtr = ausBlockInput->addSingleInput("constant Y", false, "Y values(cm) at which all particles are scored."); + yPtr->addDependency(formatPtr, "IAEA"); + auto zPtr = ausBlockInput->addSingleInput("constant Z", false, "Z values(cm) at which all particles are scored."); + zPtr->addDependency(formatPtr, "IAEA"); + auto muPtr = ausBlockInput->addSingleInput("score mu", false, "Default is no", {"yes", "no"}); + muPtr->addDependency(formatPtr, "IAEA"); + + auto multiPtr = ausBlockInput->addSingleInput("score multiple crossers", false, "Default is no", {"yes", "no"}); + multiPtr->addDependency(formatPtr, "EGSnrc"); + + ausBlockInput->addSingleInput("particle type", true, "The type of particle", {"all", "photons", "charged"}); + ausBlockInput->addSingleInput("output directory", true, "The name of output directory"); + + // Method 1: Score particles on entry to/exit from a predefined geometry + auto spacePtr = ausBlockInput->addSingleInput("phase space geometry", true, "The name of a previously defined geometry"); + auto scorePtr = ausBlockInput->addSingleInput("score particles on", false, "entry, exit, entry and exit", {"entry", "exit", "entry and exit"}); + + // Method 2: Score particles on exiting one region and entering another + auto fromPtr = ausBlockInput->addSingleInput("from regions", true, "A list of exit region numbers"); + auto toPtr = ausBlockInput->addSingleInput("to regions", true, "A list of entry region numbers"); + + // Can only use one method + spacePtr->addDependency(fromPtr, "", true); + spacePtr->addDependency(toPtr, "", true); + scorePtr->addDependency(fromPtr, "", true); + scorePtr->addDependency(toPtr, "", true); + fromPtr->addDependency(spacePtr, "", true); + fromPtr->addDependency(scorePtr, "", true); + toPtr->addDependency(spacePtr, "", true); + toPtr->addDependency(scorePtr, "", true); + } + + EGS_PHSP_SCORING_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_phsp_scoring + #:start ausgab object: + library = egs_phsp_scoring + name = test + from regions = 0 2 + to regions = 3 5 + output format = IAEA + constant Z = 10.0 + particle type = all + score mu = no + :stop ausgab object: + + #:start ausgab object: + library = egs_phsp_scoring + name = test2 + phase space geometry = scoreplane + output format = EGSnrc + particle type = all + score particles on = entry + score multiple crossers = yes + :stop ausgab object: +)"}; + return example; + } + + EGS_PHSP_SCORING_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return ausBlockInput; + } + EGS_PHSP_SCORING_EXPORT EGS_AusgabObject *createAusgabObject(EGS_Input *input, EGS_ObjectFactory *f) { const static char *func = "createAusgabObject(phsp_scoring)"; - if (!input) { - egsWarning("%s: null input?\n",func); - return 0; - } - string str; - EGS_BaseGeometry *phspgeom; - int iscoremc = 0; //default to not score multiple crossers - vector from_reg, to_reg; - int stype = 0; //default is to use scoring geom - int phspouttype; - int ptype; - int sdir=0; - int imuscore = 0; - float xyzconst[3]; - bool xyzisconst[3] = {false, false, false}; - string gname; - string outdir; - int err01 = input->getInput("phase space geometry",gname); - if (err01) { - stype = 1; - } - else { - phspgeom = EGS_BaseGeometry::getGeometry(gname); - if (!phspgeom) { - egsWarning("\nEGS_PhspScoring: %s does not name an existing geometry.\n" - "Will assume you want to use exit/entry region pairs.\n",gname.c_str()); + if (!input) { + egsWarning("%s: null input?\n",func); + return 0; + } + string str; + EGS_BaseGeometry *phspgeom; + int iscoremc = 0; //default to not score multiple crossers + vector from_reg, to_reg; + int stype = 0; //default is to use scoring geom + int phspouttype; + int ptype; + int sdir=0; + int imuscore = 0; + float xyzconst[3]; + bool xyzisconst[3] = {false, false, false}; + string gname; + string outdir; + int err01 = input->getInput("phase space geometry",gname); + if (err01) { stype = 1; } else { - if (input->getInput("score particles on", str) < 0) { - egsInformation("EGS_PhspScoring: No input for scoring direction.\n"); - egsInformation("Will score on entry and exit from phase space geometry.\n"); - sdir = 0; + phspgeom = EGS_BaseGeometry::getGeometry(gname); + if (!phspgeom) { + egsWarning("\nEGS_PhspScoring: %s does not name an existing geometry.\n" + "Will assume you want to use exit/entry region pairs.\n",gname.c_str()); + stype = 1; } else { - //get scoring direction - vector allowed_sdir; - allowed_sdir.push_back("entry and exit"); - allowed_sdir.push_back("entry"); - allowed_sdir.push_back("exit"); - sdir = input->getInput("score particles on",allowed_sdir,-1); - if (sdir < 0) { - egsFatal("\nEGS_PhspScoring: Invalid scoring direction.\n"); + if (input->getInput("score particles on", str) < 0) { + egsInformation("EGS_PhspScoring: No input for scoring direction.\n"); + egsInformation("Will score on entry and exit from phase space geometry.\n"); + sdir = 0; + } + else { + //get scoring direction + vector allowed_sdir; + allowed_sdir.push_back("entry and exit"); + allowed_sdir.push_back("entry"); + allowed_sdir.push_back("exit"); + sdir = input->getInput("score particles on",allowed_sdir,-1); + if (sdir < 0) { + egsFatal("\nEGS_PhspScoring: Invalid scoring direction.\n"); + } } } } - } - if (stype==1) { - // user wants to use exit/entry region pairs - int err05 = input->getInput("from regions",from_reg); - int err06 = input->getInput("to regions",to_reg); - if (err05 || err06) { - egsFatal("\nEGS_PhspScoring: Missing/incorrect input for scoring method\n" - "(scoring geometry or pairs of exit/entry regions)\n"); - } - else { - //run some checks on exit/entry region pairs - vector::iterator p,p1; - if (from_reg.size() > to_reg.size()) { - p = from_reg.begin(); - egsWarning("\nEGS_PhspScoring: Mismatch in no. of exit/entry regions.\n" - "Will only score for matched pairs.\n"); - p += to_reg.size(); - from_reg.erase(p,p+from_reg.size()-to_reg.size()); - } - else if (to_reg.size() > from_reg.size()) { - p = to_reg.begin(); - egsWarning("\nEGS_PhspScoring: Mismatch in no. of exit/entry regions.\n" - "Will only score for matched pairs.\n"); - p += from_reg.size(); - to_reg.erase(p,p+to_reg.size()-from_reg.size()); + if (stype==1) { + // user wants to use exit/entry region pairs + int err05 = input->getInput("from regions",from_reg); + int err06 = input->getInput("to regions",to_reg); + if (err05 || err06) { + egsFatal("\nEGS_PhspScoring: Missing/incorrect input for scoring method\n" + "(scoring geometry or pairs of exit/entry regions)\n"); } - //now go through and look for exit region = entry region - int i=0; - while (i::iterator p,p1; + if (from_reg.size() > to_reg.size()) { + p = from_reg.begin(); + egsWarning("\nEGS_PhspScoring: Mismatch in no. of exit/entry regions.\n" + "Will only score for matched pairs.\n"); + p += to_reg.size(); + from_reg.erase(p,p+from_reg.size()-to_reg.size()); } - else { - //advance counter - i++; + else if (to_reg.size() > from_reg.size()) { + p = to_reg.begin(); + egsWarning("\nEGS_PhspScoring: Mismatch in no. of exit/entry regions.\n" + "Will only score for matched pairs.\n"); + p += from_reg.size(); + to_reg.erase(p,p+to_reg.size()-from_reg.size()); + } + //now go through and look for exit region = entry region + int i=0; + while (igetInput("output format", str) < 0) { - egsInformation("EGS_PhspScoring: No input for output format type. Will default to EGSnrc.\n"); - phspouttype = 0; - } - else { - vector allowed_oformat; - allowed_oformat.push_back("EGSnrc"); - allowed_oformat.push_back("IAEA"); - phspouttype = input->getInput("output format", allowed_oformat, -1); - if (phspouttype < 0) { - egsFatal("\nEGS_PhspScoring: Invalid output format.\n"); + //now get common inputs for both scoring methods + if (input->getInput("output format", str) < 0) { + egsInformation("EGS_PhspScoring: No input for output format type. Will default to EGSnrc.\n"); + phspouttype = 0; } - //see if the user wants to specify constant X/Y/Z for IAEA format - if (phspouttype == 1) { - int err02 = input->getInput("constant X",xyzconst[0]); - int err03 = input->getInput("constant Y",xyzconst[1]); - int err04 = input->getInput("constant Z",xyzconst[2]); - if (!err02) { - xyzisconst[0] = true; - } - if (!err03) { - xyzisconst[1] = true; - } - if (!err04) { - xyzisconst[2] = true; + else { + vector allowed_oformat; + allowed_oformat.push_back("EGSnrc"); + allowed_oformat.push_back("IAEA"); + phspouttype = input->getInput("output format", allowed_oformat, -1); + if (phspouttype < 0) { + egsFatal("\nEGS_PhspScoring: Invalid output format.\n"); } - //see if user wants to score mu (if available) - //default is not to score - if (!input->getInput("score mu", str)) { - vector allowed_muscore; - allowed_muscore.push_back("no"); - allowed_muscore.push_back("yes"); - imuscore = input->getInput("score mu",allowed_muscore,-1); - if (imuscore < 0) { - egsWarning("\nEGS_PhspScoring: Invalid input for mu scoring. Will not score mu.\n"); - imuscore = 0; + //see if the user wants to specify constant X/Y/Z for IAEA format + if (phspouttype == 1) { + int err02 = input->getInput("constant X",xyzconst[0]); + int err03 = input->getInput("constant Y",xyzconst[1]); + int err04 = input->getInput("constant Z",xyzconst[2]); + if (!err02) { + xyzisconst[0] = true; + } + if (!err03) { + xyzisconst[1] = true; + } + if (!err04) { + xyzisconst[2] = true; + } + //see if user wants to score mu (if available) + //default is not to score + if (!input->getInput("score mu", str)) { + vector allowed_muscore; + allowed_muscore.push_back("no"); + allowed_muscore.push_back("yes"); + imuscore = input->getInput("score mu",allowed_muscore,-1); + if (imuscore < 0) { + egsWarning("\nEGS_PhspScoring: Invalid input for mu scoring. Will not score mu.\n"); + imuscore = 0; + } } } } - } - if (phspouttype == 0) { - //see if user wants to score multiple crossers - if (!input->getInput("score multiple crossers", str)) { - vector allowed_scoremc; - allowed_scoremc.push_back("no"); - allowed_scoremc.push_back("yes"); - iscoremc = input->getInput("score multiple crossers",allowed_scoremc,-1); - if (iscoremc < 0) { - egsWarning("\nEGS_PhspScoring: Invalid input for score multiple crossers. Will not score.\n"); - iscoremc = 0; + if (phspouttype == 0) { + //see if user wants to score multiple crossers + if (!input->getInput("score multiple crossers", str)) { + vector allowed_scoremc; + allowed_scoremc.push_back("no"); + allowed_scoremc.push_back("yes"); + iscoremc = input->getInput("score multiple crossers",allowed_scoremc,-1); + if (iscoremc < 0) { + egsWarning("\nEGS_PhspScoring: Invalid input for score multiple crossers. Will not score.\n"); + iscoremc = 0; + } } } - } - if (input->getInput("output directory",outdir) < 0) { - outdir=""; - } - if (input->getInput("particle type", str) < 0) { - egsInformation("EGS_PhspScoring: No input for particle type. Will score all.\n"); - ptype = 0; - } - else { - //get particle type - vector allowed_ptype; - allowed_ptype.push_back("all"); - allowed_ptype.push_back("photons"); - allowed_ptype.push_back("charged"); - ptype = input->getInput("particle type",allowed_ptype,-1); - if (ptype < 0) { - egsFatal("\nEGS_PhspScoring: Invalid particle type.\n"); + if (input->getInput("output directory",outdir) < 0) { + outdir=""; + } + if (input->getInput("particle type", str) < 0) { + egsInformation("EGS_PhspScoring: No input for particle type. Will score all.\n"); + ptype = 0; + } + else { + //get particle type + vector allowed_ptype; + allowed_ptype.push_back("all"); + allowed_ptype.push_back("photons"); + allowed_ptype.push_back("charged"); + ptype = input->getInput("particle type",allowed_ptype,-1); + if (ptype < 0) { + egsFatal("\nEGS_PhspScoring: Invalid particle type.\n"); + } } - } - //================================================= + //================================================= - /* Setup phsp scoring object with input parameters */ - EGS_PhspScoring *result = new EGS_PhspScoring("",f); - result->setName(input); - if (stype==0) { - result->setGeom(phspgeom); - } - else if (stype==1) { - result->setEntryExitReg(from_reg,to_reg); + /* Setup phsp scoring object with input parameters */ + EGS_PhspScoring *result = new EGS_PhspScoring("",f); + result->setName(input); + if (stype==0) { + result->setGeom(phspgeom); + } + else if (stype==1) { + result->setEntryExitReg(from_reg,to_reg); + } + result->setOType(phspouttype); + result->setXYZconst(xyzisconst,xyzconst); + result->setOutDir(outdir); + result->setParticleType(ptype); + result->setScoreDir(sdir); + result->setMuScore(imuscore); + result->setScoreMC(iscoremc); + return result; } - result->setOType(phspouttype); - result->setXYZconst(xyzisconst,xyzconst); - result->setOutDir(outdir); - result->setParticleType(ptype); - result->setScoreDir(sdir); - result->setMuScore(imuscore); - result->setScoreMC(iscoremc); - return result; } -} diff --git a/HEN_HOUSE/egs++/ausgab_objects/egs_radiative_splitting/egs_radiative_splitting.cpp b/HEN_HOUSE/egs++/ausgab_objects/egs_radiative_splitting/egs_radiative_splitting.cpp index fbcd05b52..e00f35b58 100644 --- a/HEN_HOUSE/egs++/ausgab_objects/egs_radiative_splitting/egs_radiative_splitting.cpp +++ b/HEN_HOUSE/egs++/ausgab_objects/egs_radiative_splitting/egs_radiative_splitting.cpp @@ -23,7 +23,7 @@ # # Author: Ernesto Mainegra-Hing, 2018 # -# Contributors: +# Contributors: Hannah Gallop # ############################################################################### # @@ -50,6 +50,8 @@ #include "egs_input.h" #include "egs_functions.h" +static bool EGS_RADIATIVE_SPLITTING_LOCAL inputSet = false; + EGS_RadiativeSplitting::EGS_RadiativeSplitting(const string &Name, EGS_ObjectFactory *f) : nsplit(1) { @@ -95,6 +97,24 @@ void EGS_RadiativeSplitting::setApplication(EGS_Application *App) { //********************************************************************** extern "C" { + static void setInputs() { + inputSet = true; + + setBaseAusgabObjectInputs(); + + ausBlockInput->getSingleInput("library")->setValues({"EGS_Radiative_Splitting"}); + + // Format: name, isRequired, description, vector string of allowed values + ausBlockInput->addSingleInput("splitting", false, "N-split"); + } + + EGS_RADIATIVE_SPLITTING_EXPORT shared_ptr getInputs() { + if (!inputSet) { + setInputs(); + } + return ausBlockInput; + } + EGS_RADIATIVE_SPLITTING_EXPORT EGS_AusgabObject *createAusgabObject(EGS_Input *input, EGS_ObjectFactory *f) { const static char *func = "createAusgabObject(radiative_splitting)"; diff --git a/HEN_HOUSE/egs++/ausgab_objects/egs_track_scoring/egs_track_scoring.cpp b/HEN_HOUSE/egs++/ausgab_objects/egs_track_scoring/egs_track_scoring.cpp index bfcb82721..6b81efd4a 100644 --- a/HEN_HOUSE/egs++/ausgab_objects/egs_track_scoring/egs_track_scoring.cpp +++ b/HEN_HOUSE/egs++/ausgab_objects/egs_track_scoring/egs_track_scoring.cpp @@ -24,6 +24,7 @@ # Author: Iwan Kawrakow, 2009 # # Contributors: Georgi Gerganov +# Hannah Gallop # ############################################################################### */ @@ -38,6 +39,8 @@ #include "egs_input.h" #include "egs_functions.h" +static bool EGS_TRACK_SCORING_LOCAL inputSet = false; + EGS_TrackScoring::EGS_TrackScoring(const string &Name, EGS_ObjectFactory *f) : EGS_AusgabObject(Name,f), m_pts(0), m_start(0), m_stop(1024), m_lastCase(-1), m_nScore(0), m_bufSize(16), m_score(false), m_didScore(false), @@ -117,39 +120,81 @@ void EGS_TrackScoring::reportResults() { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseAusgabObjectInputs(); + + ausBlockInput->getSingleInput("library")->setValues({"EGS_Track_Scoring"}); + + // Format: name, isRequired, description, vector string of allowed values + ausBlockInput->addSingleInput("score photons", false, "Score photons? Default is yes.", {"yes", "no"}); + ausBlockInput->addSingleInput("score electrons", false, "Score the elctrons? Default is yes.", {"yes", "no"}); + ausBlockInput->addSingleInput("score positrons", false, "Score positrons? Default is yes.", {"yes", "no"}); + ausBlockInput->addSingleInput("start scoring", false, "Event_number, default is 0."); + ausBlockInput->addSingleInput("stop scoring", false, "Event_number, default is 1024."); + ausBlockInput->addSingleInput("buffer size", false, "Size, default is 1024."); + ausBlockInput->addSingleInput("file name addition", false, "A string that constructs the output file name"); + } + + EGS_TRACK_SCORING_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_track_scoring + #:start ausgab object: + library = egs_track_scoring + name = my_score + score photons = yes + score electrons = yes + score positrons = yes + start scoring = 0 + stop scoring = 1024 + :stop ausgab object: +)"}; + return example; + } + + EGS_TRACK_SCORING_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return ausBlockInput; + } + EGS_TRACK_SCORING_EXPORT EGS_AusgabObject *createAusgabObject(EGS_Input *input, EGS_ObjectFactory *f) { const static char *func = "createAusgabObject(track_scoring)"; - if (!input) { - egsWarning("%s: null input?\n",func); - return 0; - } - vector sc_options; - sc_options.push_back("no"); - sc_options.push_back("yes"); - bool scph = input->getInput("score photons",sc_options,true); - bool scel = input->getInput("score electrons",sc_options,true); - bool scpo = input->getInput("score positrons",sc_options,true); - if (!scph && !scel && !scpo) { - return 0; + if (!input) { + egsWarning("%s: null input?\n",func); + return 0; + } + vector sc_options; + sc_options.push_back("no"); + sc_options.push_back("yes"); + bool scph = input->getInput("score photons",sc_options,true); + bool scel = input->getInput("score electrons",sc_options,true); + bool scpo = input->getInput("score positrons",sc_options,true); + if (!scph && !scel && !scpo) { + return 0; + } + EGS_I64 first = 0, last = 1024; + input->getInput("start scoring",first); + input->getInput("stop scoring",last); + int bufSize = 1024; + input->getInput("buffer size",bufSize); + string fnExtra; + input->getInput("file name addition",fnExtra); + EGS_TrackScoring *result = new EGS_TrackScoring("",f); + result->setScorePhotons(scph); + result->setScoreElectrons(scel); + result->setScorePositrons(scpo); + result->setFirstEvent(first); + result->setLastEvent(last); + result->setBufferSize(bufSize); + result->setFileNameExtra(fnExtra); + result->setName(input); + return result; } - EGS_I64 first = 0, last = 1024; - input->getInput("start scoring",first); - input->getInput("stop scoring",last); - int bufSize = 1024; - input->getInput("buffer size",bufSize); - string fnExtra; - input->getInput("file name addition",fnExtra); - EGS_TrackScoring *result = new EGS_TrackScoring("",f); - result->setScorePhotons(scph); - result->setScoreElectrons(scel); - result->setScorePositrons(scpo); - result->setFirstEvent(first); - result->setLastEvent(last); - result->setBufferSize(bufSize); - result->setFileNameExtra(fnExtra); - result->setName(input); - return result; - } -} + } diff --git a/HEN_HOUSE/egs++/egs_application.cpp b/HEN_HOUSE/egs++/egs_application.cpp index e638e843f..d340ae448 100644 --- a/HEN_HOUSE/egs++/egs_application.cpp +++ b/HEN_HOUSE/egs++/egs_application.cpp @@ -43,7 +43,6 @@ #include "egs_input.h" #include "egs_base_source.h" #include "egs_rndm.h" -#include "egs_run_control.h" #include "egs_base_source.h" #include "egs_simple_container.h" #include "egs_ausgab_object.h" @@ -100,6 +99,8 @@ static EGS_LOCAL EGS_Application *active_egs_application = 0; int EGS_Application::n_apps = 0; +unique_ptr EGS_Application::inputStructure = unique_ptr(); + EGS_EXPORT EGS_Application *EGS_Application::activeApplication() { return active_egs_application; } diff --git a/HEN_HOUSE/egs++/egs_application.h b/HEN_HOUSE/egs++/egs_application.h index c7842f38b..e2967015f 100644 --- a/HEN_HOUSE/egs++/egs_application.h +++ b/HEN_HOUSE/egs++/egs_application.h @@ -27,6 +27,7 @@ # Ernesto Mainegra-Hing # Blake Walters # Reid Townson +# Hannah Gallop # ############################################################################### */ @@ -44,7 +45,11 @@ #include "egs_base_source.h" #include "egs_simple_container.h" #include "egs_interpolator.h" +#include "egs_input_struct.h" +#include "egs_run_control.h" +#include "egs_scoring.h" +#include #include #include using namespace std; @@ -58,6 +63,47 @@ class EGS_AusgabObject; class EGS_Interpolator; //template class EGS_SimpleContainer; +static void addmcBlock(shared_ptr blockPtr) { + shared_ptr mcBlock = blockPtr->addBlockInput("MC transport parameter"); + mcBlock->addSingleInput("Global ECUT", false, "Global electron transport cutoff"); + mcBlock->addSingleInput("Global PCUT", false, "Global photon transport cutoff"); + mcBlock->addSingleInput("Global SMAX", false, "Global maximum step-size restriction for e-transport"); + mcBlock->addSingleInput("ESTEPE", false, "Default is 0.25"); + mcBlock->addSingleInput("XIMAX", false, "Default is 0.5, maximum value is 1."); + mcBlock->addSingleInput("Boundary crossing algorithm", false, "exact is default", {"exact", "PRESTA-I"}); + mcBlock->addSingleInput("Skin depth for BCA", false, "Default value is 3 for exact boundary crossing"); + mcBlock->addSingleInput("Electron-step algorithm", false, "Default is PRESTA-II", {"PRESTA_II", "PRESTA_I"}); + mcBlock->addSingleInput("Spin effects", false, "Default is On", {"On", "Off"}); + mcBlock->addSingleInput("Brems angular sampling", false, "Default is KM", {"KM", "Simple"}); + mcBlock->addSingleInput("Brems cross sections", false, "Default is BH", {"BH", "NIST"}); + mcBlock->addSingleInput("Pair angular crossing", false, "Default is Simple", {"Simple", "Off", "KM"}); + mcBlock->addSingleInput("Triplet production", false, "Default is On", {"On", "Off"}); + mcBlock->addSingleInput("Electron Impact Ionization", false, "Default is Off", {"On", "Off", "casnati", "kolbenstvedt", "gryzinski"}); + mcBlock->addSingleInput("Bound Compton scattering", false, "Default is norej", {"On", "Off", "Simple", "norej"}); + mcBlock->addSingleInput("Radiative Compton corrections", false, "Default is Off", {"On", "Off"}); + mcBlock->addSingleInput("Rayleigh scattering", false, "Default is off", {"On", "Off", "custom"}); + mcBlock->addSingleInput("Photoelectron angular sampling", false, "Default is on", {"On", "Off"}); + mcBlock->addSingleInput("Atomic relaxations", false, "Default is on", {"On", "Off"}); + mcBlock->addSingleInput("Photon cross sections", false, "Default is xcom, can also be user-supplied", {"si", "epdl", "xcom"}); + mcBlock->addSingleInput("Photon cross-sections output", false, "Default is off", {"On", "Off"}); + mcBlock->addSingleInput("Compton cross sections", false, "User-supplied, default is comp-xsections"); + mcBlock->addSingleInput("Photonuclear attenuation", false, "Default is off", {"On", "Off"}); + mcBlock->addSingleInput("Photonuclear cross sections", false, "Default is default, or is user-supplied", {"default"}); +} + +static void addvrBlock(shared_ptr blockPtr) { + shared_ptr vrBlock = blockPtr->addBlockInput("variance reduction"); + vrBlock->addSingleInput("photon splitting", false, "N_split"); + vrBlock->addSingleInput("TmpPhsp", false, "Score phase space, use once in each geometry"); + vrBlock->addSingleInput("cs enhancement", false, "0 (XCSE off) or >0 (XCSE on)"); + + shared_ptr rangePtr = vrBlock->addBlockInput("range rejection"); + rangePtr->addSingleInput("rejection", false, "N_r"); + rangePtr->addSingleInput("Esave", false, "E_save"); + rangePtr->addSingleInput("cavity geometry", false, "The name of a previously defined geometry"); + rangePtr->addSingleInput("rejection range medium", false, "index of the medium to calculate electron ranges"); +} + /*! \brief A structure holding the information of one particle \ingroup egspp_main */ @@ -1190,8 +1236,8 @@ class EGS_EXPORT EGS_Application { //************************************************************ virtual void setLatch(int latch) {}; + static unique_ptr inputStructure; }; - #define APP_MAIN(app_name) \ int main(int argc, char **argv) { \ app_name app(argc,argv); \ @@ -1216,7 +1262,11 @@ class EGS_EXPORT EGS_Application { APP_EXPORT EGS_Application* createApplication(int argc, char **argv) {\ return new app_name(argc,argv);\ }\ - } - + APP_EXPORT void getAppInputs(shared_ptr inpPtr) {\ + addRunControlBlock(inpPtr);\ + addmcBlock(inpPtr);\ + addvrBlock(inpPtr);\ + addScoringBlock(inpPtr);\ + }\ #endif diff --git a/HEN_HOUSE/egs++/egs_ausgab_object.h b/HEN_HOUSE/egs++/egs_ausgab_object.h index ceeda3275..502c4c2a1 100644 --- a/HEN_HOUSE/egs++/egs_ausgab_object.h +++ b/HEN_HOUSE/egs++/egs_ausgab_object.h @@ -39,6 +39,7 @@ #include "egs_application.h" #include "egs_object_factory.h" +#include "egs_input_struct.h" #include #include @@ -61,6 +62,12 @@ using namespace std; class EGS_Input; class EGS_Application; +static shared_ptr ausBlockInput = make_shared("ausgab object"); +static void setBaseAusgabObjectInputs() { + ausBlockInput->addSingleInput("library", true, "The type of ausgab object, loaded by shared library in egs++/dso."); + ausBlockInput->addSingleInput("name", true, "The user-declared unique name of this ausgab object. This is the name you may refer to elsewhere in the input file."); +} + class EGS_EXPORT EGS_AusgabObject : public EGS_Object { public: diff --git a/HEN_HOUSE/egs++/egs_base_geometry.cpp b/HEN_HOUSE/egs++/egs_base_geometry.cpp index e622679d1..44b95283b 100644 --- a/HEN_HOUSE/egs++/egs_base_geometry.cpp +++ b/HEN_HOUSE/egs++/egs_base_geometry.cpp @@ -1170,3 +1170,5 @@ int EGS_BaseGeometry::setLabels(const string &inp) { return 1; } + + diff --git a/HEN_HOUSE/egs++/egs_base_geometry.h b/HEN_HOUSE/egs++/egs_base_geometry.h index 9bfed973b..ee40a5477 100644 --- a/HEN_HOUSE/egs++/egs_base_geometry.h +++ b/HEN_HOUSE/egs++/egs_base_geometry.h @@ -43,10 +43,12 @@ #define EGS_BASE_GEOMETRY_ #include "egs_vector.h" +#include "egs_input_struct.h" #include #include #include +#include using std::string; using std::vector; @@ -71,6 +73,18 @@ class label { vector regions; }; +static shared_ptr geomBlockInput = make_shared("geometry"); +static void setBaseGeometryInputs(bool includeMediaBlock = true) { + geomBlockInput->addSingleInput("library", true, "The type of geometry, loaded by shared library in egs++/dso."); + geomBlockInput->addSingleInput("name", true, "The user-declared unique name of this geometry. This is the name you may refer to elsewhere in the input file"); + + if (includeMediaBlock) { + shared_ptr mediaBlock = geomBlockInput->addBlockInput("media input"); + mediaBlock->addSingleInput("media", true, "A list of media that are used in this geometry"); + mediaBlock->addSingleInput("set medium", false, "2, 3 or 4 integers defining the medium for a region or range of regions.\nFor 2: region #, medium index from the media list for this geometry (starts at 0). For 3: start region, stop region, medium index. For 4: Same as 3, plus a step size for the region range.\nNeglect this input for a homogeneous geometry of the first medium in the media list. Repeat this input to specify each medium."); + } +} + /*! \brief Base geometry class. Every geometry class must be derived from EGS_BaseGeometry. diff --git a/HEN_HOUSE/egs++/egs_base_source.h b/HEN_HOUSE/egs++/egs_base_source.h index 392eed3d8..0bcb8007a 100644 --- a/HEN_HOUSE/egs++/egs_base_source.h +++ b/HEN_HOUSE/egs++/egs_base_source.h @@ -43,6 +43,7 @@ #include "egs_vector.h" #include "egs_object_factory.h" #include "egs_functions.h" +#include "egs_input_struct.h" #include #include @@ -53,6 +54,69 @@ using namespace std; class EGS_Input; class EGS_RandomGenerator; +static shared_ptr srcBlockInput = make_shared("source"); +static void setBaseSourceInputs(bool isSimpleSource = true, bool includeSpectrumBlock = true) { + srcBlockInput->addSingleInput("library", true, "The type of source, loaded by shared library in egs++/dso."); + srcBlockInput->addSingleInput("name", true, "The user-declared unique name of this source. This is the name you may refer to elsewhere in the input file"); + + if (isSimpleSource) { + includeSpectrumBlock = true; + srcBlockInput->addSingleInput("charge", true, "The type of particle to emit from the source, as defined by the charge. Use 0 for photons, -1 for electrons and 1 for positrons.", {"0", "1", "-1"}); + } + if (includeSpectrumBlock) { + shared_ptr specBlock = srcBlockInput->addBlockInput("spectrum"); + auto typePtr = specBlock->addSingleInput("type", true, "The type of energy distribution for the spectrum.", {"monoenergetic", "Gaussian", "Double Gaussian", "uniform", "tabulated spectrum", "radionuclide"}); + + // Monoenergetic + specBlock->addSingleInput("energy", false, "The kinetic energy of the source particles in MeV.")->addDependency(typePtr, "monoenergetic"); + + // Gaussian & double Gaussian + specBlock->addSingleInput("mean energy", false, "The mean kinetic energy of the source particles in MeV.")->addDependency(typePtr, "Gaussian"); + auto sigmaPtr = specBlock->addSingleInput("sigma", false, "The sigma of the spectrum. For a double Gaussian, input two values."); + sigmaPtr->addDependency(typePtr, "Gaussian"); + sigmaPtr->addDependency(typePtr, "Double Gaussian"); + auto fwhmPtr = specBlock->addSingleInput("fwhm", false, "The full-width-at-half-maximum of the spectrum. For a double Gaussian, input two values."); + fwhmPtr->addDependency(typePtr, "Gaussian"); + fwhmPtr->addDependency(typePtr, "Double Gaussian"); + fwhmPtr->addDependency(sigmaPtr, "", true); + sigmaPtr->addDependency(fwhmPtr, "", true); + + // Uniform + auto rangePtr = specBlock->addSingleInput("range", false, "The minimum and maximum energy for the spectrum, in MeV."); + rangePtr->addDependency(typePtr, "uniform"); + auto minEPtr = specBlock->addSingleInput("minimum energy", false, "The minimum energy for the spectrum, in MeV."); + minEPtr->addDependency(typePtr, "uniform"); + auto maxEPtr = specBlock->addSingleInput("maximum energy", false, "The maximum energy for the spectrum, in MeV."); + maxEPtr->addDependency(typePtr, "uniform"); + minEPtr->addDependency(rangePtr, "", true); + maxEPtr->addDependency(rangePtr, "", true); + rangePtr->addDependency(minEPtr, "", true); + rangePtr->addDependency(maxEPtr, "", true); + + // Tabulated + auto specFilePtr = specBlock->addSingleInput("spectrum file", false, "The full file path to the spectrum file. See documentation for the format of the file."); + specFilePtr->addDependency(typePtr, "tabulated spectrum"); + auto modePtr = specBlock->addSingleInput("spectrum mode", false, "The mode number that denotes how to create the spectrum. Use 0 for histogram counts/bin, 1 for counts/MeV, 2 for a line spectrum and 3 for an interpolated spectrum."); + modePtr->addDependency(typePtr, "tabulated spectrum"); + auto energiesPtr = specBlock->addSingleInput("energies", false, "A list of energies for the spectrum, in MeV. When applicable, this is the upper edge of the bin."); + energiesPtr->addDependency(typePtr, "tabulated spectrum"); + auto probsPtr = specBlock->addSingleInput("probabilities", false, "A list of probabilities for the spectrum. Does not need to be normalized."); + probsPtr->addDependency(typePtr, "tabulated spectrum"); + modePtr->addDependency(specFilePtr, "", true); + energiesPtr->addDependency(specFilePtr, "", true); + probsPtr->addDependency(specFilePtr, "", true); + + // Radionuclide + specBlock->addSingleInput("nuclide", true, "The name of the nuclide to model, e.g. Co-60 or Tc-99m. If the 'ensdf file' input is not specified, then the ENSDF file will be searched for as $HEN_HOUSE/spectra/lnhb/ensdf/nuclide.txt, where nuclide is the text you input. Note that a radionuclide spectrum is ONLY compatible with a radionuclide source.")->addDependency(typePtr, "radionuclide"); + specBlock->addSingleInput("ensdf file", false, "The full path to the ENSDF file to use.")->addDependency(typePtr, "radionuclide"); + specBlock->addSingleInput("relative activity", false, "If multiple radionuclide spectra are specified for a single radionuclide source, this is the relative weight of this spectrum. Defaults to 1.")->addDependency(typePtr, "radionuclide"); + specBlock->addSingleInput("atomic relaxations", false, "The model to use for atomic relaxations resulting from radionuclide decay. Defaults to EADL.", {"eadl", "ensdf", "off"})->addDependency(typePtr, "radionuclide"); + specBlock->addSingleInput("output beta spectra", false, "Whether or not to output as files the beta spectra that are used for sampling beta decay energies. Defaults to No.", {"yes", "no"})->addDependency(typePtr, "radionuclide"); + specBlock->addSingleInput("alpha scoring", false, "The model to use for scoring alpha particles during radionuclide decay. Defaults to Discard.", {"local", "discard"})->addDependency(typePtr, "radionuclide"); + specBlock->addSingleInput("extra transition approximation", false, "Whether or not to use the option that automatically balances transition intensities. Defaults to Off.", {"on","off"})->addDependency(typePtr, "radionuclide"); + } +} + /*! \brief Base source class. All particle sources must be derived from this class. diff --git a/HEN_HOUSE/egs++/egs_input_struct.cpp b/HEN_HOUSE/egs++/egs_input_struct.cpp new file mode 100644 index 000000000..2f15cc860 --- /dev/null +++ b/HEN_HOUSE/egs++/egs_input_struct.cpp @@ -0,0 +1,405 @@ +/* +############################################################################### +# +# EGSnrc egs++ input struct +# Copyright (C) 2015 National Research Council Canada +# +# This file is part of EGSnrc. +# +# EGSnrc is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# EGSnrc is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for +# more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with EGSnrc. If not, see . +# +############################################################################### +# +# Author: Reid Townson, 2019 +# +# Contributors: +# +############################################################################### +*/ + + +/*! \file egs_input_struct.cpp + * \brief The input struct cpp file + * \RT + * + */ + +#include "egs_functions.h" +#include "egs_input_struct.h" + +EGS_InputStruct::EGS_InputStruct() {} + +EGS_InputStruct::~EGS_InputStruct() {} + +shared_ptr EGS_InputStruct::addBlockInput(string blockTit, bool isReq) { + blockInputs.push_back(make_shared(blockTit, isReq, nullptr)); + + return blockInputs.back(); +} + +shared_ptr EGS_InputStruct::addBlockInput(shared_ptr block) { + blockInputs.push_back(block); + + return blockInputs.back(); +} + +void EGS_InputStruct::addBlockInputs(vector> blocks) { + blockInputs.insert(blockInputs.end(), blocks.begin(), blocks.end()); +} + +vector> EGS_InputStruct::getBlockInputs() { + return blockInputs; +} + +shared_ptr EGS_InputStruct::getBlockInput(string title) { + for (auto &block: blockInputs) { + if (egsEquivStr(block->getTitle(), title)) { + return block; + } + } + + return nullptr; +} + +shared_ptr EGS_InputStruct::getLibraryBlock(string blockTitle, string libraryName) { + // Loop through each input block in the structure to find the library with + // the matching name + auto libraryBlock = make_shared(); + for (auto &block : blockInputs) { + libraryBlock = block->getLibraryBlock(blockTitle, libraryName); + if (libraryBlock) { + break; + } + } + return libraryBlock; +} + +vector EGS_InputStruct::getLibraryOptions(string blockTitle) { + // Loop through each input block in the structure to find all the possible + // library options that match the input block type + // E.g. find all the geometry libraries + vector libOptions; + for (auto &block : blockInputs) { + + // We only search the 2nd-level blocks + // i.e. don't look at the geometry definition block, look at the geometries + for (auto &block2 : block->getBlockInputs()) { + if (block2 && (block2->getTitle() == blockTitle)) { + vector libAr = block2->getSingleInput("library")->getValues(); + for (auto &lib : libAr) { + if (lib.size() > 0) { + libOptions.push_back(lib); + } + } + } + } + } + + // If nothing was found on the 2nd level blocks, search the top level ones + // This is the case for shapes + if (libOptions.size() < 1) { + for (auto &block : blockInputs) { + + if (block && (block->getTitle() == blockTitle || + // Handle the special case where "target shape" and "source shape" for egs_collimated_source need to match just "shape". + (egsEquivStr(block->getTitle(), "shape") && (egsEquivStr(blockTitle, "target shape") || egsEquivStr(blockTitle, "source shape"))))) { + vector libAr = block->getSingleInput("library")->getValues(); + for (auto &lib : libAr) { + if (lib.size() > 0) { + libOptions.push_back(lib); + } + } + } + } + } + + return libOptions; +} + + +EGS_BlockInput::EGS_BlockInput() {} + +EGS_BlockInput::EGS_BlockInput(string blockTit, bool isReq, shared_ptr par) { + blockTitle = blockTit; + isRequired = isReq; + parent = par; +} + +EGS_BlockInput::~EGS_BlockInput() {} + +void EGS_BlockInput::setTitle(string blockTit) { + blockTitle = blockTit; +} + +string EGS_BlockInput::getTitle() { + return blockTitle; +} + +shared_ptr EGS_BlockInput::addSingleInput(string inputTag, bool isReq, const string desc, const vector vals) { + singleInputs.push_back(make_shared(inputTag, isReq, desc, vals)); + return singleInputs.back(); +} + +shared_ptr EGS_BlockInput::addBlockInput(string blockTit, bool isReq) { + blockInputs.push_back(make_shared(blockTit, isReq, shared_from_this())); + + return blockInputs.back(); +} + +shared_ptr EGS_BlockInput::addBlockInput(shared_ptr block) { + block->setParent(shared_from_this()); + blockInputs.push_back(block); + + return blockInputs.back(); +} + +vector> EGS_BlockInput::getSingleInputs() { + return singleInputs; +} + +vector> EGS_BlockInput::getSingleInputs(string title) { + if (egsEquivStr(blockTitle, title) || + // Handle the special case where "target shape" and "source shape" for egs_collimated_source need to match just "shape". + (egsEquivStr(blockTitle, "shape") && (egsEquivStr(title, "target shape") || egsEquivStr(title, "source shape")))) { + return singleInputs; + } + else { + for (auto &block: blockInputs) { + auto inp = block->getSingleInputs(title); + if (inp.size() > 0) { + return inp; + } + } + } + + return {}; +} + +vector> EGS_BlockInput::getBlockInputs() { + return blockInputs; +} + +vector> EGS_BlockInput::getBlockInputs(string title) { + if (egsEquivStr(this->getTitle(), title) || + // Handle the special case where "target shape" and "source shape" for egs_collimated_source need to match just "shape". + (egsEquivStr(blockTitle, "shape") && (egsEquivStr(title, "target shape") || egsEquivStr(title, "source shape")))) { + return blockInputs; + } + else { + for (auto &block: blockInputs) { + if (egsEquivStr(block->getTitle(), title)) { + return block->getBlockInputs(); + } + } + } + + return {}; +} + +shared_ptr EGS_BlockInput::getSingleInput(string inputTag) { + for (auto &inp : singleInputs) { + // TODO: this assumes unique inputTag + if (inp && egsEquivStr(inp->getTag(), inputTag)) { + return inp; + } + } + + // If not found in the top level, search recursively + for (auto &block: blockInputs) { + auto inp = block->getSingleInput(inputTag); + if (inp) { + return inp; + } + } + + return nullptr; +} + +shared_ptr EGS_BlockInput::getSingleInput(string inputTag, string title) { + // First search the top-level input block + if (egsEquivStr(blockTitle, title) || + // Handle the special case where "target shape" and "source shape" for egs_collimated_source need to match just "shape". + (egsEquivStr(blockTitle, "shape") && (egsEquivStr(title, "target shape") || egsEquivStr(title, "source shape")))) { + for (auto &inp: singleInputs) { + // TODO: this assumes unique inputTag + if (inp && egsEquivStr(inp->getTag(), inputTag)) { + return inp; + } + } + } + + // If not found, go through input lower level blocks + for (auto &block: blockInputs) { + if (egsEquivStr(block->getTitle(), title)) { + auto inp = block->getSingleInput(inputTag, title); + if (inp) { + return inp; + } + } + } + + return nullptr; +} + +shared_ptr EGS_BlockInput::getBlockInput(string title) { + if (egsEquivStr(blockTitle, title)) { + return shared_from_this(); + } + else { + for (auto &block: blockInputs) { + if (egsEquivStr(block->getTitle(), title)) { + return block; + // Handle the special case where "target shape" and "source shape" for egs_collimated_source need to match just "shape". + } + else if (egsEquivStr(block->getTitle(), "shape") && (egsEquivStr(title, "source shape") || egsEquivStr(title, "target shape"))) { + return block; + } + else { + // Do a recursive search + auto foundBlock = block->getBlockInput(title); + if (foundBlock) { + return foundBlock; + } + } + } + } + + return nullptr; +} + +void EGS_BlockInput::setParent(shared_ptr par) { + parent = par; +} + +shared_ptr EGS_BlockInput::getParent() { + return parent; +} + +shared_ptr EGS_BlockInput::getLibraryBlock(string blockTitle, string libraryName) { + // First search the singleInputs for the library name + for (auto &inp: singleInputs) { + if (!inp) { + continue; + } + if (egsEquivStr(inp->getTag(), "library")) { + if (inp->getValues().size() && egsEquivStr(inp->getValues().front(), libraryName)) { + return shared_from_this(); + } + else { + break; + } + } + } + + // If not found, go through input blocks + for (auto &block: blockInputs) { + auto libraryBlock = block->getLibraryBlock(blockTitle, libraryName); + if (libraryBlock) { + return libraryBlock; + } + } + return nullptr; +} + +bool EGS_BlockInput::contains(string inputTag) { + for (auto &inp: singleInputs) { + if (!inp) { + continue; + } + if (egsEquivStr(inp->getTag(), inputTag)) { + return true; + } + } + return false; +} + +void EGS_BlockInput::addDependency(shared_ptr inp, string val) { + dependencyInp = inp; + dependencyVal = val; +} + +shared_ptr EGS_BlockInput::getDependencyInp() { + return dependencyInp; +} + +string EGS_BlockInput::getDependencyVal() { + return dependencyVal; +} + +EGS_SingleInput::EGS_SingleInput() {} + +EGS_SingleInput::EGS_SingleInput(string inputTag, bool isReq, const string desc, const vector vals) { + tag = inputTag; + isRequired = isReq; + description = desc; + values = vals; +} + +EGS_SingleInput::~EGS_SingleInput() {} + +void EGS_SingleInput::addDependency(shared_ptr inp, string val, bool isAntiDependency) { + dependencyInp.push_back(inp); + dependencyVal.push_back(val); + dependencyAnti.push_back(isAntiDependency); +} + +void EGS_SingleInput::addDependency(shared_ptr block, bool isAntiDependency) { + dependencyBlock = block; + dependencyBlockAnti = isAntiDependency; +} + +vector> EGS_SingleInput::getDependencyInp() { + return dependencyInp; +} + +vector EGS_SingleInput::getDependencyVal() { + return dependencyVal; +} + +vector EGS_SingleInput::getDependencyAnti() { + return dependencyAnti; +} + +shared_ptr EGS_SingleInput::getDependencyBlock() { + return dependencyBlock; +} + +bool EGS_SingleInput::getDependencyBlockAnti() { + return dependencyBlockAnti; +} + +string EGS_SingleInput::getTag() { + return tag; +} + +bool EGS_SingleInput::getRequired() { + return isRequired; +} + +const vector EGS_SingleInput::getValues() { + return values; +} + +void EGS_SingleInput::setValues(const vector vals) { + values = vals; +} + +string EGS_SingleInput::getDescription() { + return description; +} + + + + + diff --git a/HEN_HOUSE/egs++/egs_input_struct.h b/HEN_HOUSE/egs++/egs_input_struct.h new file mode 100644 index 000000000..b1720ade9 --- /dev/null +++ b/HEN_HOUSE/egs++/egs_input_struct.h @@ -0,0 +1,283 @@ +/* +############################################################################### +# +# EGSnrc egs++ input struct headers +# Copyright (C) 2015 National Research Council Canada +# +# This file is part of EGSnrc. +# +# EGSnrc is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# EGSnrc is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for +# more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with EGSnrc. If not, see . +# +############################################################################### +# +# Author: Reid Townson, 2019 +# +# Contributors: +# +# An application has one global scope input struct object. Input blocks are +# then added to contain geometries or sources. Input blocks may contain single +# inputs. +# +############################################################################### +*/ + + +/*! \file egs_input_struct.h + * \brief The input struct header file + * \RT + * + */ + +#ifndef EGS_INPUT_STRUCT_ +#define EGS_INPUT_STRUCT_ + +#include +#include +#include "egs_libconfig.h" +#include + +using namespace std; + +class EGS_BlockInput; + +/*! \brief A class to represent an egsinp single line input. + + \ingroup egspp_main + + The EGS_SingleInput class is used to represent an egsinp input parameter. The class contains the ability to link whether or not this input is required, depending on a different single input parameter or input block. If there are only a few possible options, they can be set so that input values can be validated. A description of the input can also be provided. +*/ +class EGS_EXPORT EGS_SingleInput { + +public: + EGS_SingleInput(); + + /*! \brief Construct a single input \a inputTag. + + The input by the name \a inputTag is optional when \a isReq is false. For cases where the input is only required depending on a different input, leave \a isReq false and then use \a addDependency(). A description can be provided in \a desc. A list of valid values for the input can be provided in \a vals. + */ + EGS_SingleInput(string inputTag, bool isReq, const string desc, const vector vals); + ~EGS_SingleInput(); + + /*! \brief Get the name of the input. */ + string getTag(); + + /*! \brief Get whether or not this input is required. */ + bool getRequired(); + + /*! \brief Add a dependency for this input, by the name of \a inp. + + Optionally, the current input is only required if the dependency input has a value of \a val. If \a isAntiDependency is true, then the current input is required only if \a inp is not set. + */ + void addDependency(shared_ptr inp, string val = "", bool isAntiDependency = false); + + /*! \brief Add a dependency on an input block (there can only be one). */ + void addDependency(shared_ptr block, bool isAntiDependency = false); + + /*! \brief Get a list of all the dependencies for this input. */ + vector> getDependencyInp(); + + /*! \brief Get a list of the required dependency values. */ + vector getDependencyVal(); + + /*! \brief Get a list of whether or not these are anti-dependencies. */ + vector getDependencyAnti(); + + /*! \brief Get the dependency block (can be only one). */ + shared_ptr getDependencyBlock(); + + /*! \brief Get whether or not the block dependency is an anti-dependency. */ + bool getDependencyBlockAnti(); + + /*! \brief Get the list of possible values for this input. */ + const vector getValues(); + + /*! \brief Set the list of possible values for this input. */ + void setValues(const vector vals); + + /*! \brief Get the description for this input. */ + string getDescription(); + +private: + + vector requirements; + string tag; + bool isRequired; + string description; + vector values; + vector> dependencyInp; + vector dependencyVal; + vector dependencyAnti; + shared_ptr dependencyBlock; + bool dependencyBlockAnti; +}; + +/*! \brief A class to represent an egsinp input block. + + \ingroup egspp_main + + The EGS_BlockInput class is used to represent an egsinp input block. An input block has a title, may have a parent that it is nested within, and may contain child single inputs and input blocks. +*/ +class EGS_EXPORT EGS_BlockInput + : public std::enable_shared_from_this { +public: + EGS_BlockInput(); + + /*! \brief Construct a block input \a blockTit. + + The input by the name \a blockTit is optional when \a isReq is false. If this block is always nested, specify the parent with \a par. + */ + EGS_BlockInput(string blockTit, bool isReq = false, shared_ptr par = nullptr); + ~EGS_BlockInput(); + + /*! \brief Set the title of the block. */ + void setTitle(string blockTit); + + /*! \brief Get the title of the block. */ + string getTitle(); + + /*! \brief Add a single input. */ + shared_ptr addSingleInput(string inputTag, bool isReq, const string desc, const vector vals = vector()); + + /*! \brief Add an input block to be nested inside this one. */ + shared_ptr addBlockInput(string blockTit, bool isReq = false); + + /*! \brief Add an already defined input block to be nested inside this one. */ + shared_ptr addBlockInput(shared_ptr block); + + /*! \brief Get a list of the inputs for this input block. */ + vector> getSingleInputs(); + + /*! \brief Get a list of the inputs for the nested input block \a title. */ + vector> getSingleInputs(string title); + + /*! \brief Get a list of the nested input blocks for this input block. */ + vector> getBlockInputs(); + + /*! \brief Get a list of the nested input blocks inside \a title. */ + vector> getBlockInputs(string title); + + /*! \brief Get the input named \a inputTag. */ + shared_ptr getSingleInput(string inputTag); + + /*! \brief Get the input named \a inputTag from the input block \a title. */ + shared_ptr getSingleInput(string inputTag, string title); + + /*! \brief Get the input block \a title. */ + shared_ptr getBlockInput(string title); + + /*! \brief Set the parent to be \a par. */ + void setParent(shared_ptr par); + + /*! \brief Get the parent input block. */ + shared_ptr getParent(); + + /*! \brief Get the input block containing the library tag matching \a libraryName. */ + shared_ptr getLibraryBlock(string blockTitle, string libraryName); + + /*! \brief Check if this input block contains the input \a inputTag. */ + bool contains(string inputTag); + + /*! \brief Add a dependency of this input block on input \a inp being value \a val. */ + void addDependency(shared_ptr inp, string val=""); + + /*! \brief Get the input dependency. */ + shared_ptr getDependencyInp(); + + /*! \brief Get the input dependency required value. */ + string getDependencyVal(); + + +private: + + vector> singleInputs; + vector> blockInputs; + shared_ptr parent; + string blockTitle; + bool isRequired; + const string desc; + shared_ptr dependencyInp; + string dependencyVal; +}; + +/*! \brief A class to represent an egsinp input structure. + + \ingroup egspp_main + + The EGS_InputStruct class is used to represent the top level of the egsinp file structure. + + Example from egs_cylinders.cpp: + + \verbatim + static void setInputs() { + inputSet = true; + + // Get the inputs common to all geometries (name, library, media) + // Builds on the global geometry input block geomBlockInput + setBaseGeometryInputs(); + + // Get the 'library' input, and set the valid values to be only 'EGS_Cylinders' + geomBlockInput->getSingleInput("library")->setValues({"EGS_Cylinders"}); + + // Add the 'type' input, required, and set the valid options for it. + // Note that we save a reference to this input 'typePtr'. + auto typePtr = geomBlockInput->addSingleInput("type", true, "The type of cylinder.", {"EGS_XCylinders", "EGS_YCylinders", "EGS_ZCylinders", "EGS_Cylinders"}); + + // Add other inputs, 'radii' and 'midpoint' + geomBlockInput->addSingleInput("radii", true, "A list of cylinder radii, must be in increasing order"); + geomBlockInput->addSingleInput("midpoint", false, "The position of the midpoint of the cylinder (x, y, z)"); + + // Add the 'axis' input, and save a reference to it 'inpPtr' + auto inpPtr = geomBlockInput->addSingleInput("axis", true, "The unit vector defining the axis along the length of the cylinder."); + + // Set a dependency for 'inpPtr' on 'typePrt' being set to the value 'EGS_Cylinders'. This makes it so that 'axis' is only required if 'type = EGS_Cylinders'. + inpPtr->addDependency(typePtr, "EGS_Cylinders"); + } + \endverbatim +*/ +class EGS_EXPORT EGS_InputStruct { +public: + EGS_InputStruct(); + ~EGS_InputStruct(); + + /*! \brief Add an input block named \a blockTit. */ + shared_ptr addBlockInput(string blockTit, bool isReq = false); + + /*! \brief Add an input block that is already defined as \a block. */ + shared_ptr addBlockInput(shared_ptr block); + + /*! \brief Add a list of input blocks that are already defined as \a blocks */ + void addBlockInputs(vector> blocks); + + /*! \brief Get the list of input blocks. */ + vector> getBlockInputs(); + + /*! \brief Get the input block named \a title. */ + shared_ptr getBlockInput(string title); + + /*! \brief Get the input block \a blockTitle that contains the library \a libraryName. */ + shared_ptr getLibraryBlock(string blockTitle, string libraryName); + + /*! \brief Get the possible values for the library tag for the block \a blockTitle. */ + vector getLibraryOptions(string blockTitle); + +private: + + vector> blockInputs; + vector> generalBlocks; +}; + + +#endif + + diff --git a/HEN_HOUSE/egs++/egs_run_control.h b/HEN_HOUSE/egs++/egs_run_control.h index b27d66c49..4b6ea6e69 100644 --- a/HEN_HOUSE/egs++/egs_run_control.h +++ b/HEN_HOUSE/egs++/egs_run_control.h @@ -40,6 +40,7 @@ #include "egs_libconfig.h" #include "egs_timer.h" +#include "egs_input_struct.h" #include using namespace std; @@ -47,6 +48,16 @@ using namespace std; class EGS_Application; class EGS_Input; +static void addRunControlBlock(shared_ptr blockPtr) { + shared_ptr runBlock = blockPtr->addBlockInput("run control"); + runBlock->addSingleInput("ncase", true, "The number of histories to simulate."); + runBlock->addSingleInput("nbatch", false, "The number of batches to divide the simulation into. After each batch, a checkpoint is created to allow for simulation restarts. Defaults to 10."); + runBlock->addSingleInput("max cpu hours allowed", false, "The number hours after which the simulation will be haulted. Defaults to -1, which is no limit."); + runBlock->addSingleInput("statistical accuracy sought", false, "The statistical uncertainty for a particular quantity of interest, below which the simulation will be haulted. Note that the quantity must be defined by the application (e.g. the cavity dose in egs_chamber), and in general is undefined."); + runBlock->addSingleInput("geometry error limit", false, "The number of geometry errors that will be allowed to occur, before haulting the simulation. Defaults to 0."); + runBlock->addSingleInput("calculation", false, "The calculation type: first (default, runs a new simulation), restart (resumes a terminated simulation), analyze (prints results), combine (combines results from a parallel run). Defaults to 'first'.", {"first", "restart", "analyze", "combine"}); +} + /*! \brief A simple run control object for advanced EGSnrc C++ applications. \ingroup egspp_main diff --git a/HEN_HOUSE/egs++/egs_scoring.h b/HEN_HOUSE/egs++/egs_scoring.h index c526131c1..d9704b01f 100644 --- a/HEN_HOUSE/egs++/egs_scoring.h +++ b/HEN_HOUSE/egs++/egs_scoring.h @@ -40,10 +40,51 @@ #include "egs_libconfig.h" #include "egs_functions.h" #include "egs_math.h" +#include "egs_input_struct.h" #include using namespace std; +static void addScoringBlock(shared_ptr blockPtr) { + shared_ptr scoreBlock = blockPtr->addBlockInput("scoring options"); + scoreBlock->addSingleInput("pulse height regions", false, "A list of regions to score pulse height distributions"); + scoreBlock->addSingleInput("pulse height bins", false, "How many bins to use for each pulse height distribution. This must be either a single input, in which case all pulse height distributions will use this number of bins, or the same number of inputs as pulse height regions."); + scoreBlock->addSingleInput("silent", false, "0 (verbose output) or greater than 0 (short output)"); + scoreBlock->addSingleInput("calculation type", false, "Default is dose", {"Dose", "Awall", "Fano", "FAC", "HVL"}); + + shared_ptr calGeomPtr = scoreBlock->addBlockInput("calculation geometry"); + calGeomPtr->addSingleInput("geometry name", false, "The name of the base geometry"); + calGeomPtr->addSingleInput("cavity regions", true, "A list of cavity region indices"); + calGeomPtr->addSingleInput("cavity mass", true, "The total cavity mass in grams"); + calGeomPtr->addSingleInput("cavity geometry", true, "The name of geometry for range rejection"); + calGeomPtr->addSingleInput("enhance regions", false, "A list of enhancement region indicies"); + calGeomPtr->addSingleInput("enhancement", false, "A list of enhancement factors"); + + auto transPtr = calGeomPtr->addBlockInput("transformation"); + transPtr->addSingleInput("translation", false, "The translation for the geometry (x, y ,z)"); + + scoreBlock->addSingleInput("correlated geometries", false, "A list of geometries"); + + // input loops can also be used so avoid retyping things + auto inpPtr = scoreBlock->addBlockInput("input loop"); + inpPtr->addSingleInput("loop count", true, "The number of times the loop repeats"); + inpPtr->addSingleInput("loop variable", true, "The type (0 for integer, 1 for real, 2 for string), the variable name, then a list of the variable inputs"); + inpPtr->addSingleInput("correlated geometries", false, "A list of geometries"); + + auto geominpPtr = inpPtr->addBlockInput("calculation geometry"); + geominpPtr->addSingleInput("geometry name", false, "The name of the base geometry"); + geominpPtr->addSingleInput("cavity regions", true, "A list of cavity region indices"); + geominpPtr->addSingleInput("cavity mass", true, "The total cavity mass in grams"); + geominpPtr->addSingleInput("cavity geometry", true, "The name of geometry for range rejection"); + geominpPtr->addSingleInput("enhance regions", false, "A list of enhancement region indicies"); + geominpPtr->addSingleInput("enhancement", false, "A list of enhancement factors"); + geominpPtr->addSingleInput("subgeometries", false, "A list of identical geometries with material differences"); + geominpPtr->addSingleInput("sub geom regions", false, "A list of regions where composition changes"); + + auto transinpPtr = geominpPtr->addBlockInput("transformation"); + transinpPtr->addSingleInput("translation", false, "The translation for the geometry (x, y ,z)"); +} + /*! \brief A class for scoring a single quantity of interest in a Monte Carlo simulation. diff --git a/HEN_HOUSE/egs++/egs_shapes.h b/HEN_HOUSE/egs++/egs_shapes.h index dbefb21b0..4a1d0f06e 100644 --- a/HEN_HOUSE/egs++/egs_shapes.h +++ b/HEN_HOUSE/egs++/egs_shapes.h @@ -41,12 +41,43 @@ #include "egs_transformations.h" #include "egs_rndm.h" #include "egs_object_factory.h" +#include "egs_input_struct.h" #include using std::string; class EGS_Input; +static void setShapeInputs(shared_ptr shapePtr) { + auto libPtr = shapePtr->addSingleInput("library", false, "The type of shape, loaded by shared library in egs++/dso."); + auto typePtr = shapePtr->addSingleInput("type", false, "The type of shape - this input includes only a small set of simple shapes. For more options, use the 'library' input instead.", {"point", "box", "sphere", "cylinder"}); + + // Only one of "library" or "type" are allowed + libPtr->addDependency(typePtr, "", true); + typePtr->addDependency(libPtr, "", true); + + // Point + shapePtr->addSingleInput("position", true, "The x, y, z position that the source will emit particles from.")->addDependency(typePtr, "point"); + + // Box + shapePtr->addSingleInput("box size", true, "The side lengths of the box, in cm. Enter 1 number for a cube, or 3 numbers to denote the x, y, and z side lengths.")->addDependency(typePtr, "box"); + + // Sphere + auto radiusPtr = shapePtr->addSingleInput("radius", true, "The radius of the sphere or cylinder, in cm."); + radiusPtr->addDependency(typePtr, "sphere"); + auto midPtr = shapePtr->addSingleInput("midpoint", false, "The x, y and z coordinates of the midpoint of the sphere or cylinder, in cm. Defaults to 0, 0, 0."); + midPtr->addDependency(typePtr, "sphere"); + + // Cylinder + radiusPtr->addDependency(typePtr, "cylinder"); + midPtr->addDependency(typePtr, "cylinder"); + shapePtr->addSingleInput("height", true, "The height of the cylinder, in cm.")->addDependency(typePtr, "cylinder"); + shapePtr->addSingleInput("phi range", false, "The minimum and maximum phi values, in degrees. This allows you restrict the cylinder to a shape like a slice of pie!")->addDependency(typePtr, "cylinder"); + shapePtr->addSingleInput("axis", true, "A unit vector that defines the axis of the cylinder.")->addDependency(typePtr, "cylinder"); + + addTransformationBlock(shapePtr); +} + /*! \defgroup Shapes Shapes \brief Shapes are objects that can pick random points within a certain area or volume. diff --git a/HEN_HOUSE/egs++/egs_spectra.cpp b/HEN_HOUSE/egs++/egs_spectra.cpp index 4b92109a5..462647051 100644 --- a/HEN_HOUSE/egs++/egs_spectra.cpp +++ b/HEN_HOUSE/egs++/egs_spectra.cpp @@ -374,10 +374,10 @@ A spectrum is defined inline as follows: type = tabulated spectrum energies = list of discrete energies or bin edges probabilities = list of probabilities - spectrum type = 0 or 1 or 2 or 3 + spectrum mode = 0 or 1 or 2 or 3 :stop spectrum: \endverbatim -where the meaning of the spectrum type is the same as the mode of a +where the meaning of the spectrum mode is the same as the mode of a spectrum file. */ class EGS_EXPORT EGS_TabulatedSpectrum : public EGS_BaseSpectrum { diff --git a/HEN_HOUSE/egs++/egs_transformations.h b/HEN_HOUSE/egs++/egs_transformations.h index dac540615..aeb49e167 100644 --- a/HEN_HOUSE/egs++/egs_transformations.h +++ b/HEN_HOUSE/egs++/egs_transformations.h @@ -43,6 +43,7 @@ #include "egs_libconfig.h" #include "egs_math.h" #include "egs_functions.h" +#include "egs_input_struct.h" #include @@ -50,6 +51,15 @@ using namespace std; class EGS_Input; +static void addTransformationBlock(shared_ptr blockPtr) { + shared_ptr transBlock = blockPtr->addBlockInput("transformation"); + transBlock->addSingleInput("translation", false, "The x, y, z translation offsets in cm."); + auto vecPtr = transBlock->addSingleInput("rotation vector", false, "Defines a rotation which, when applied to the 3D vector defined by this input, transforms it into a vector along the positive z-axis."); + auto rotPtr = transBlock->addSingleInput("rotation", false, "2, 3 or 9 floating point numbers define a rotation. See the documentation for details."); + vecPtr->addDependency(rotPtr, "", true); + rotPtr->addDependency(vecPtr, "", true); +} + /*! \brief A class for vector rotations. \ingroup egspp_main diff --git a/HEN_HOUSE/egs++/geometry/egs_autoenvelope/egs_autoenvelope.cpp b/HEN_HOUSE/egs++/geometry/egs_autoenvelope/egs_autoenvelope.cpp index c46d9d501..688103a24 100644 --- a/HEN_HOUSE/egs++/geometry/egs_autoenvelope/egs_autoenvelope.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_autoenvelope/egs_autoenvelope.cpp @@ -27,6 +27,7 @@ # Contributors: Marc Chamberland # Rowan Thomson # Dave Rogers +# Hannah Gallop # ############################################################################### # @@ -70,6 +71,7 @@ static char EGS_AENVELOPE_LOCAL transformations_keyword[] = "transformations"; static char EGS_AENVELOPE_LOCAL type_keyword[] = "type"; static char EGS_AENVELOPE_LOCAL transformation_keyword[] = "transformation"; +static bool EGS_AENVELOPE_LOCAL inputSet = false; EGS_AEnvelope::EGS_AEnvelope(EGS_BaseGeometry *base_geom, const vector inscribed, const string &Name, bool debug, string output_vc_file) : @@ -803,7 +805,7 @@ EGS_ASwitchedEnvelope::EGS_ASwitchedEnvelope(EGS_BaseGeometry *base_geom, }; -//TODO: this gets called a lot and is probably quite slow. Instead fo doing a +//TODO: this gets called a lot and is probably quite slow. Instead of doing a //set intersection on every call we can probably do it once when activated //geometries change and cache it vector EGS_ASwitchedEnvelope::getGeomsInRegion(int ireg) { @@ -933,6 +935,32 @@ vector EGS_AEnvelope::createTransforms(EGS_Input *input) extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(false); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_AEnvelope"}); + + // Format: name, isRequired, description, vector string of allowed values + geomBlockInput->addSingleInput("type", false, "The type of auto envelope", {"EGS_ASwitchedEnvelope"}); + + geomBlockInput->addSingleInput("incribed geometries", true, "A list of predefined geometries"); + geomBlockInput->addSingleInput("base geometry", true, "The name of a predefined geometry"); + + auto blockPtr = geomBlockInput->addBlockInput("transformation"); + blockPtr->addSingleInput("translation", false, "The translation for the geometry (x, y ,z)"); + auto rotPtr = blockPtr->addSingleInput("rotation", false, "2, 3, or 9 floating point numbers"); + auto vectPtr = blockPtr->addSingleInput("rotation vector", false, "3 floating point numbers"); + } + + EGS_AENVELOPE_EXPORT shared_ptr getInputs() { + if (!inputSet) { + setInputs(); + } + return geomBlockInput; + } + EGS_AENVELOPE_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { if (!input) { diff --git a/HEN_HOUSE/egs++/geometry/egs_box/Makefile b/HEN_HOUSE/egs++/geometry/egs_box/Makefile index 58b7cd67a..4b34b541e 100644 --- a/HEN_HOUSE/egs++/geometry/egs_box/Makefile +++ b/HEN_HOUSE/egs++/geometry/egs_box/Makefile @@ -36,7 +36,7 @@ DEFS = $(DEF1) -DBUILD_BOX_DLL library = egs_box lib_files = egs_box -my_deps = egs_transformations.h +my_deps = egs_transformations.h egs_input_struct.h extra_dep = $(addprefix $(DSOLIBS), $(my_deps)) include $(SPEC_DIR)egspp_libs.spec diff --git a/HEN_HOUSE/egs++/geometry/egs_box/egs_box.cpp b/HEN_HOUSE/egs++/geometry/egs_box/egs_box.cpp index 32b9a6390..bef8d9c74 100644 --- a/HEN_HOUSE/egs++/geometry/egs_box/egs_box.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_box/egs_box.cpp @@ -24,6 +24,7 @@ # Author: Iwan Kawrakow, 2005 # # Contributors: Frederic Tessier +# Reid Townson # ############################################################################### */ @@ -36,6 +37,7 @@ #include "egs_box.h" #include "egs_input.h" +#include "egs_base_geometry.h" void EGS_Box::printInfo() const { EGS_BaseGeometry::printInfo(); @@ -43,7 +45,8 @@ void EGS_Box::printInfo() const { egsInformation("=======================================================\n"); } -string EGS_Box::type("EGS_Box"); +static string EGS_BOX_LOCAL typeStr("EGS_Box"); +string EGS_Box::type(typeStr); static char EGS_BOX_LOCAL ebox_message1[] = "createGeometry(box): %s\n"; static char EGS_BOX_LOCAL ebox_message2[] = "null input?"; @@ -52,19 +55,73 @@ static char EGS_BOX_LOCAL ebox_message4[] = "expecting 1 or 3 float inputs for 'box size'"; static char EGS_BOX_LOCAL ebox_key1[] = "box size"; +static bool EGS_BOX_LOCAL inputSet = false; + +struct EGS_BOX_LOCAL InputOptions { + vector boxSize; +}; +InputOptions inp; + +// Process inputs from the egsinp file +EGS_BOX_LOCAL int processInputs(EGS_Input *input) { + int err = input->getInput(ebox_key1,inp.boxSize); + if (err && geomBlockInput->getSingleInput(ebox_key1)->getRequired()) { + egsWarning(ebox_message1,ebox_message3); + return 0; + } + + return 1; +} + extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(); + + geomBlockInput->getSingleInput("library")->setValues(vector(1, typeStr)); + + // Format: name, isRequired, description, vector string of allowed values + geomBlockInput->addSingleInput("box size", true, "1 number defining the side-length of a cube, or 3 numbers defining the x, y, and z side-lengths."); + } + + EGS_BOX_EXPORT string getExample() { + string example { + R"( + :start geometry: + library = EGS_Box + name = my_box + box size = 1 2 3 + :start media input: + media = water + :stop media input: + :stop geometry: +)"}; + return example; + } + + EGS_BOX_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } + EGS_BOX_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { if (!input) { egsWarning(ebox_message1,ebox_message2); return 0; } - vector s; - int err = input->getInput(ebox_key1,s); - if (err) { - egsWarning(ebox_message1,ebox_message3); + + if(!processInputs(input)) { + egsWarning("Failed to process the inputs for %s.\n", typeStr.c_str()); return 0; } + + vector s; + s = inp.boxSize; + EGS_AffineTransform *t = EGS_AffineTransform::getTransformation(input); EGS_Box *result; if (s.size() == 1) { @@ -89,5 +146,4 @@ extern "C" { result->setLabels(input); return result; } - } diff --git a/HEN_HOUSE/egs++/geometry/egs_cd_geometry/egs_cd_geometry.cpp b/HEN_HOUSE/egs++/geometry/egs_cd_geometry/egs_cd_geometry.cpp index 718853b39..af6835cfb 100644 --- a/HEN_HOUSE/egs++/geometry/egs_cd_geometry/egs_cd_geometry.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_cd_geometry/egs_cd_geometry.cpp @@ -25,6 +25,7 @@ # # Contributors: Frederic Tessier # Ernesto Mainegra-Hing +# Reid Townson # ############################################################################### */ @@ -46,7 +47,10 @@ #define S_STREAM std::istringstream #endif -string EGS_CDGeometry::type = "EGS_CDGeometry"; +static string EGS_CDGEOMETRY_LOCAL typeStr("EGS_CDGeometry"); +string EGS_CDGeometry::type(typeStr); + +static bool EGS_CDGEOMETRY_LOCAL inputSet = false; void EGS_CDGeometry::setMedia(EGS_Input *,int,const int *) { egsWarning("EGS_CDGeometry::setMedia: don't use this method. Use the\n" @@ -110,6 +114,42 @@ void EGS_CDGeometry::setUpIndexing() { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(false); + + geomBlockInput->getSingleInput("library")->setValues(vector(1, typeStr)); + + // Format: name, isRequired, description, vector string of allowed values + geomBlockInput->addSingleInput("base geometry", true, "The name of the geometry that defines regions for this 'cutting device'. It is within these regions that other geometries will be placed to create a composite geometry."); + geomBlockInput->addSingleInput("set geometry", true, "The region number in the base geometry, followed by the name of the geometry to place in that region. If this geometry extends beyond the region boundaries, it will be cut to size."); + geomBlockInput->addSingleInput("new indexing style", false, "Set to 1 to use a new region numbering algorithm. Defaults to 0, to use the original indexing style."); + } + + EGS_CDGEOMETRY_EXPORT string getExample() { + string example { + R"( + :start geometry: + library = EGS_CDGeometry + name = my_cd + base geometry = my_regions + # set geometry = 1 geom means: + # in region 1 of the basegeometry, use geometry named "geom" + set geometry = 0 my_geom1 + set geometry = 1 my_geom2 + :stop geometry: +)"}; + return example; + } + + EGS_CDGEOMETRY_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } + EGS_CDGEOMETRY_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { if (!input) { egsWarning("createGeometry(CD_Geometry): null input?\n"); @@ -120,8 +160,9 @@ extern "C" { EGS_BaseGeometry::createSingleGeometry(ij); delete ij; } + string bg_name; - int err = input->getInput("base geometry",bg_name); + int err = input->getInput("base geometry", bg_name); if (err) { egsWarning("createGeometry(CD_Geometry): no 'base geometry' input\n"); return 0; diff --git a/HEN_HOUSE/egs++/geometry/egs_cones/egs_cones.cpp b/HEN_HOUSE/egs++/geometry/egs_cones/egs_cones.cpp index b58ec5d8c..20a2939a9 100644 --- a/HEN_HOUSE/egs++/geometry/egs_cones/egs_cones.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_cones/egs_cones.cpp @@ -24,6 +24,7 @@ # Author: Iwan Kawrakow, 2005 # # Contributors: Frederic Tessier +# Reid Townson # ############################################################################### */ @@ -49,6 +50,8 @@ string EGS_ParallelCones::type = "EGS_ParallelCones"; string EGS_ConeSet::type = "EGS_ConeSet"; string EGS_ConeStack::type = "EGS_ConeStack"; +static bool EGS_CONES_LOCAL inputSet = false; + void EGS_ConeStack::clear(bool all) { if (nltot > 0) { if (all) { @@ -244,6 +247,140 @@ void EGS_ConeSet::printInfo() const { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(false); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_Cones"}); + + // Format: name, isRequired, description, vector string of allowed values + auto typePtr = geomBlockInput->addSingleInput("type", true, "The type of cone.", {"EGS_ConeStack", "EGS_SimpleCone", "EGS_ParallelCones", "EGS_ConeSet"}); + + geomBlockInput->addSingleInput("axis", false, "The unit vector defining the axis along the length of the cones. Layers or cones are added sequentially in the vector direction."); + + auto inpPtr = geomBlockInput->addSingleInput("apex", false, "The position of the cone apex (x, y, z). For EGS_ParallelCones, this is the position of the first cone apex."); + inpPtr->addDependency(typePtr, "EGS_SimpleCone"); + inpPtr->addDependency(typePtr, "EGS_ParallelCones"); + inpPtr->addDependency(typePtr, "EGS_ConeSet"); + + // EGS_ConeStack + auto blockPtr = geomBlockInput->addBlockInput("layer"); + blockPtr->addDependency(typePtr, "EGS_ConeStack"); + blockPtr->addSingleInput("thickness", true, "The thickness of the layer."); + blockPtr->addSingleInput("top radii", false, "A list of the top cone radii. If omitted, the top radii are assumed to be the same as a bottom radii from the previous layer. This improves the algorithm efficiency."); + blockPtr->addSingleInput("bottom radii", true, "A list of the bottom cone radii."); + blockPtr->addSingleInput("media", true, "A list of media names, one for each region."); + + // EGS_ConeSet + auto anglesPtr = geomBlockInput->addSingleInput("opening angles", false, "A list of angles in degrees."); + anglesPtr->addDependency(typePtr, "EGS_ConeSet"); + auto anglesRadPtr = geomBlockInput->addSingleInput("opening angles in radian", false, "A list of angles in radians."); + anglesRadPtr->addDependency(typePtr, "EGS_ConeSet"); + // Only one of these inputs two can be included + anglesRadPtr->addDependency(anglesPtr, "", true); + anglesPtr->addDependency(anglesRadPtr, "", true); + geomBlockInput->addSingleInput("flag", false, "0 or 1 or 2. This input affects the region numbering algorithm; see the documentation for details.")->addDependency(typePtr, "EGS_ConeSet"); + + // EGS_SimpleCone + auto anglePtr = geomBlockInput->addSingleInput("opening angle", false, "The opening angle of the cone in degrees."); + anglePtr->addDependency(typePtr, "EGS_SimpleCone"); + anglePtr->addDependency(typePtr, "EGS_ParallelCones"); + geomBlockInput->addSingleInput("height", false, "The height of the cone."); + + // EGS_ParallelCones + geomBlockInput->addSingleInput("apex distances", false, "A list of distances from the first apex."); + } + + EGS_CONES_EXPORT string getExample(string type) { + string example; + example = { + R"( + # Examples of each of the egs_cones types follow + # Simply uncomment the :start line for the example that you + # wish to use + + # EGS_ConeStack example + #:start geometry: + library = egs_cones + type = EGS_ConeStack + name = my_conestack + axis = 1.2417 0 0 -1 0 0 + :start layer: + thickness = 0.0417 + top radii = 0. + bottom radii = 0.0858 + media = water + :stop layer: + :start layer: + thickness = 0.1283 + top radii = 0. 0.0858 + bottom radii = 0.3125 0.35 + media = air water + :stop layer: + :start layer: + thickness = 0.2217 + bottom radii = 0.3125 0.35 + media = air water + :stop layer: + :start layer: + thickness = 2.05 + top radii = 0.050 0.3125 0.35 + bottom radii = 0.050 0.3125 0.35 + media = water air water + :stop layer: + :stop geometry: + + # EGS_SimpleCone example + #:start geometry: + library = egs_cones + type = EGS_SimpleCone + name = my_simple_cone + apex = 0 0 3 + axis = 0 0 -1 + height = 4 + opening angle = 30 # deg + :start media input: + media = water + :stop media input: + :stop geometry: + + # EGS_ParallelCones example + #:start geometry: + library = egs_cones + type = EGS_ParallelCones + name = my_parallel_cones + apex = 0 0 6 + axis = 0 0 -1 + apex distances = 1 2 3 + opening angle = 30 # deg + :stop geometry: + + # EGS_ConeSet example + #:start geometry: + name = my_coneset + library = egs_cones + type = EGS_ConeSet + apex = 0 0 3 + axis = 0 0 -1 + opening angles = 10 20 30 + :start media input: + media = water air water + set medium = 1 1 + set medium = 2 2 + :stop media input: + :stop geometry: +)"}; + return example; + } + + EGS_CONES_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } + EGS_CONES_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { if (!input) { @@ -307,7 +444,7 @@ extern "C" { return 0; } - // adjust lable region numbering in each layer + // adjust label region numbering in each layer int count=0; for (size_t i=0; igetSingleInput("library")->setValues({"EGS_Conez"}); + + // Format: name, description, isRequired, vector string of allowed values + auto typePtr = geomBlockInput->addSingleInput("type", true,"The type of cone", {"EGS_Xconez", "EGS_Yconez", "EGS_Zcones", "EGS_conez"}); + + geomBlockInput->addSingleInput("apex", false, "The position of the cone apex (x, y, z)"); + geomBlockInput->addSingleInput("opening angles", false, "A list of angles in degrees"); + + // EGS_Conez + auto inpPtr = geomBlockInput->addSingleInput("axis", true, "The unit vector defining the length along the conez"); + inpPtr->addDependency(typePtr, "EGS_conez"); + } + + EGS_CONEZ_EXPORT shared_ptr getInputs() { + if (!inputSet) { + setInputs(); + } + return geomBlockInput; + } + EGS_CONEZ_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { // valid input diff --git a/HEN_HOUSE/egs++/geometry/egs_cylinders/egs_cylinders.cpp b/HEN_HOUSE/egs++/geometry/egs_cylinders/egs_cylinders.cpp index 77095519a..48b72507f 100644 --- a/HEN_HOUSE/egs++/geometry/egs_cylinders/egs_cylinders.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_cylinders/egs_cylinders.cpp @@ -24,6 +24,7 @@ # Author: Iwan Kawrakow, 2005 # # Contributors: Frederic Tessier +# Hannah Gallop # ############################################################################### */ @@ -37,8 +38,71 @@ #include "egs_cylinders.h" #include "egs_input.h" +static bool EGS_CYLINDERS_LOCAL inputSet = false; + extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_Cylinders"}); + + // Format: name, isRequired, description, vector string of allowd values + auto typePtr = geomBlockInput->addSingleInput("type", true, "The type of cylinder.", {"EGS_XCylinders", "EGS_YCylinders", "EGS_ZCylinders", "EGS_Cylinders"}); + + geomBlockInput->addSingleInput("radii", true, "A list of cylinder radii, must be in increasing order"); + geomBlockInput->addSingleInput("midpoint", false, "The position of the midpoint of the cylinder (x, y, z)"); + + // EGS_Cylinders + auto inpPtr = geomBlockInput->addSingleInput("axis", true, "The unit vector defining the axis along the length of the cylinder."); + inpPtr->addDependency(typePtr, "EGS_Cylinders"); + } + + EGS_CYLINDERS_EXPORT string getExample(string type) { + string example; + example = { + R"( + # Examples of the egs_cylinders to follow + + # EGS_XCylinder example + #:start geometry: + library = egs_cylinders + type = EGS_XCylinders + name = my_xcylinders + radii = 1 2 3 + midpoint = 0 + :start media input: + media = water air water + set medium = 1 1 + set medium = 2 2 + :stop media input: + :stop geometry: + + # EGS_Cylinder example + #:start geometry: + library = egs_cylinders + type = EGS_Cylinders + name = my_cylinder + radii = 7 + axis = 4 3 2 + midpoint = 0 0 0 + :start media input: + media = water + :stop media input: + :stop geometry: +)"}; + return example; + } + + EGS_CYLINDERS_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } + EGS_CYLINDERS_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { // check for valid input if (!input) { diff --git a/HEN_HOUSE/egs++/geometry/egs_elliptic_cylinders/egs_elliptic_cylinders.cpp b/HEN_HOUSE/egs++/geometry/egs_elliptic_cylinders/egs_elliptic_cylinders.cpp index f98b537e0..90f14469d 100644 --- a/HEN_HOUSE/egs++/geometry/egs_elliptic_cylinders/egs_elliptic_cylinders.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_elliptic_cylinders/egs_elliptic_cylinders.cpp @@ -23,7 +23,7 @@ # # Author: Iwan Kawrakow, 2006 # -# Contributors: +# Contributors: Hannah Gallop # ############################################################################### # @@ -44,10 +44,38 @@ #include "egs_elliptic_cylinders.h" #include "egs_input.h" +static bool EGS_ELLIPTIC_CYLINDERS_LOCAL inputSet = false; + extern "C" { - EGS_ELLIPTIC_CYLINDERS_EXPORT - EGS_BaseGeometry *createGeometry(EGS_Input *input) { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_EllipticCylinders"}); + + // Format: name, isRequired, description, vector string of allowed values + auto typePtr = geomBlockInput->addSingleInput("type", true, "The type of elliptic cylinder", {"EGS_EllipticCylindersXY", "EGS_EllipticCylindersXZ", "EGS_EllipticCylindersYZ", "EGS_EllipticCylinders"}); + + geomBlockInput->addSingleInput("midpoint", false, "The midpoint of the cylinder (x, y, z)"); + geomBlockInput->addSingleInput("x-radii", true, "The x radii of the cylinder"); + geomBlockInput->addSingleInput("y-radii", true, "The y radii of the cylinder"); + + auto xaxPtr = geomBlockInput->addSingleInput("x-axis", true, "The x-axis of the cylider (x, y, z)"); + xaxPtr->addDependency(typePtr, "EGS_EllipticCylinders"); + auto yaxPtr = geomBlockInput->addSingleInput("y-axis", true, "The y-axis of the cylinder (x, y, z)"); + yaxPtr->addDependency(typePtr, "EGS_EllipticCylinders"); + } + + EGS_ELLIPTIC_CYLINDERS_EXPORT shared_ptr getInputs() { + if (!inputSet) { + setInputs(); + } + return geomBlockInput; + } + + EGS_ELLIPTIC_CYLINDERS_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { // check for valid input if (!input) { egsWarning("createGeometry(elliptic cylinders): null input?\n"); diff --git a/HEN_HOUSE/egs++/geometry/egs_genvelope/egs_envelope_geometry.cpp b/HEN_HOUSE/egs++/geometry/egs_genvelope/egs_envelope_geometry.cpp index f94a7f468..87aa01264 100644 --- a/HEN_HOUSE/egs++/geometry/egs_genvelope/egs_envelope_geometry.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_genvelope/egs_envelope_geometry.cpp @@ -25,6 +25,7 @@ # # Contributors: Frederic Tessier # Ernesto Mainegra-Hing +# Hannah Gallop # ############################################################################### */ @@ -46,6 +47,8 @@ using namespace std; string EGS_ENVELOPEG_LOCAL EGS_EnvelopeGeometry::type = "EGS_EnvelopeGeometry"; string EGS_ENVELOPEG_LOCAL EGS_FastEnvelope::type = "EGS_FastEnvelope"; +static bool EGS_ENVELOPEG_LOCAL inputSet = false; + void EGS_EnvelopeGeometry::setMedia(EGS_Input *,int,const int *) { egsWarning("EGS_EnvelopeGeometry::setMedia: don't use this method. Use the\n" " setMedia() methods of the geometry objects that make up this geometry\n"); @@ -358,6 +361,41 @@ static char EGS_ENVELOPEG_LOCAL eeg_keyword2[] = "geometry"; static char EGS_ENVELOPEG_LOCAL eeg_keyword3[] = "inscribed geometries"; extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(false); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_GEnvelope"}); + + // Format: name, isRequired, description, vector string of allowed values + auto typePtr = geomBlockInput->addSingleInput("type", false, "The type of envelope", {"EGS_FastEnvelope"}); + geomBlockInput->addSingleInput("base geometry", true, "The name of a previously defined geometry"); + geomBlockInput->addSingleInput("inscribed geometries", true, "A list of names of previously defined geometries, must be stictly inside the envelope"); + } + + EGS_ENVELOPEG_EXPORT string getExample(string type) { + string example; + example = { + R"( + # Example of egs_genvelope + #:start geometry: + name = my_envelope + library = egs_genvelope + base_geometry = my_box + inscribed geometries: geom1 geom2 + # create geometries geom1 geom2 + #:stop geometry: +)"}; + return example; + } + + EGS_ENVELOPEG_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } EGS_ENVELOPEG_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { if (!input) { diff --git a/HEN_HOUSE/egs++/geometry/egs_glib/egs_glib.cpp b/HEN_HOUSE/egs++/geometry/egs_glib/egs_glib.cpp index e8cf786d9..24db6b099 100644 --- a/HEN_HOUSE/egs++/geometry/egs_glib/egs_glib.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_glib/egs_glib.cpp @@ -27,6 +27,7 @@ # Contributors: Marc Chamberland # Rowan Thomson # Dave Rogers +# Hannah Gallop # ############################################################################### # @@ -50,9 +51,42 @@ #include "egs_functions.h" #include "egs_glib.h" +static bool EGS_GLIB_LOCAL inputSet = false; extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(false); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_Glib"}); + + // Format: name, isRequired, description, vector string of allowed values + geomBlockInput->addSingleInput("include file", true, "The path to some geometry."); + } + + EGS_GLIB_EXPORT string getExample(string type) { + string example; + example = { + R"( + # Example of egs_glib + #:start geometry: + name = my_glib + library = egs_glib + include file = /path to some external file/ + :stop geometry: +)"}; + return example; + } + + EGS_GLIB_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } + /*! createGeometry function for glib shim */ EGS_GLIB_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { diff --git a/HEN_HOUSE/egs++/geometry/egs_gstack/egs_stack_geometry.cpp b/HEN_HOUSE/egs++/geometry/egs_gstack/egs_stack_geometry.cpp index ef48af04a..e7505aa9f 100644 --- a/HEN_HOUSE/egs++/geometry/egs_gstack/egs_stack_geometry.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_gstack/egs_stack_geometry.cpp @@ -26,6 +26,7 @@ # Contributors: Frederic Tessier # Marc Chamberland # Ernesto Mainegra-Hing +# Hannah Gallop # ############################################################################### */ @@ -43,6 +44,8 @@ string EGS_StackGeometry::type = "EGS_StackGeometry"; +static bool EGS_STACKG_LOCAL inputSet = false; + EGS_StackGeometry::EGS_StackGeometry(const vector &geoms, const string &Name) : EGS_BaseGeometry(Name) { if (geoms.size() < 2) egsFatal("EGS_StackGeometry::EGS_StackGeometry: " @@ -122,6 +125,41 @@ void EGS_StackGeometry::setBScaling(EGS_Input *) { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(false); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_GStack"}); + + // Format: name, isRequired, description, vector string of allowed values + geomBlockInput->addSingleInput("geometries", true, "A list of names of previously defined geometries"); + geomBlockInput->addSingleInput("tolerance", false, "A small floating number boundaryTolerance"); + } + + EGS_STACKG_EXPORT string getExample(string type) { + string example; + example = { + R"( + # Example of egs_gstack + :start geometry: + name = my_gstack + library = egs_gstack + geometries = geom1 geom2 + # create geometries called geom1 geom2 + tolerance = 1e-4 + :stop geometry: +)"}; + return example; + } + + EGS_STACKG_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } + EGS_STACKG_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { if (!input) { egsWarning("createGeometry(stack): null input?\n"); diff --git a/HEN_HOUSE/egs++/geometry/egs_gtransformed/egs_gtransformed.cpp b/HEN_HOUSE/egs++/geometry/egs_gtransformed/egs_gtransformed.cpp index f22ba9055..d7de5c544 100644 --- a/HEN_HOUSE/egs++/geometry/egs_gtransformed/egs_gtransformed.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_gtransformed/egs_gtransformed.cpp @@ -26,6 +26,7 @@ # Contributors: Frederic Tessier # Ernesto Mainegra-Hing # Hubert Ho +# Hannah Gallop # ############################################################################### */ @@ -41,6 +42,8 @@ #include "egs_input.h" #include "egs_functions.h" +static bool EGS_GTRANSFORMED_LOCAL inputSet = false; + void EGS_TransformedGeometry::setMedia(EGS_Input *,int,const int *) { egsWarning("EGS_TransformedGeometry::setMedia: don't use this method. Use the\n" " setMedia() methods of the geometry objects that make up this geometry\n"); @@ -68,6 +71,51 @@ void EGS_TransformedGeometry::setBScaling(EGS_Input *) { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(false); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_GTransformed"}); + + // Format: name, isRequired, description, vector string of allowed values + geomBlockInput->addSingleInput("my geometry", true, "The name of a previously defined geometry"); + + auto blockPtr = geomBlockInput->addBlockInput("transformation"); + blockPtr->addSingleInput("translation", false, "The translation for the geometry (x, y ,z)"); + auto rotPtr = blockPtr->addSingleInput("rotation", false, "2, 3, or 9 floating point numbers"); + auto vectPtr = blockPtr->addSingleInput("rotation vector", false, "3 floating point numbers"); + // Can either have "rotation" or "rotation vector" + rotPtr->addDependency(vectPtr, "", true); + vectPtr->addDependency(rotPtr, "", true); + } + + EGS_GTRANSFORMED_EXPORT string getExample(string type) { + string example; + example = { + R"( + # Example of egs_gtransformed + #:start geometry: + name = my_gtransform + library = egs_gtransformed + my geometry = geom + # created a geometry called geom + :start transformation: + translation = 0 0.5 0 + rotation = 0.05 0 -1 + :stop transformation: + :stop geometry: +)"}; + return example; + } + + EGS_GTRANSFORMED_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } + EGS_GTRANSFORMED_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { EGS_BaseGeometry *g = 0; EGS_Input *ij = input->takeInputItem("geometry",false); diff --git a/HEN_HOUSE/egs++/geometry/egs_iplanes/egs_iplanes.cpp b/HEN_HOUSE/egs++/geometry/egs_iplanes/egs_iplanes.cpp index 523028c22..6f5e72828 100644 --- a/HEN_HOUSE/egs++/geometry/egs_iplanes/egs_iplanes.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_iplanes/egs_iplanes.cpp @@ -24,6 +24,7 @@ # Author: Iwan Kawrakow, 2005 # # Contributors: Frederic Tessier +# Hannah Gallop # ############################################################################### */ @@ -47,6 +48,8 @@ using namespace std; string EGS_IPlanes::type = "EGS_IPlanes"; string EGS_RadialRepeater::type = "EGS_RadialRepeater"; +static bool EGS_IPLANES_LOCAL inputSet = false; + EGS_IPlanes::EGS_IPlanes(const EGS_Vector &Xo, const EGS_Vector &A, int np, const EGS_Float *angles, const string &Name, bool degree) : EGS_BaseGeometry(Name), xo(Xo), axis(A) { @@ -257,6 +260,68 @@ void EGS_RadialRepeater::printInfo() const { } extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(false); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_IPlanes"}); + + // Format: name, isRequired, description, vector string of allowed values + auto typePtr = geomBlockInput->addSingleInput("type", false, "The type of iplane", {"EGS_RadialRepeater"}); + + geomBlockInput->addSingleInput("axis", true, "A list of three coordinates of a point on the axis and three direction cosines defining the axis direction"); + + // EGS_IPlane + auto anglesPtr = geomBlockInput->addSingleInput("angles", false, "A list of angles of rotation around the axis for the planes in degrees, must be in increasing order and between 0 and 180"); + auto anglesRadPtr = geomBlockInput->addSingleInput("angles in radian", false, "A list of angles of ratation around the axis for the planes in degrees, in increasing order"); + // Only one of these two inputs can be included + anglesRadPtr->addDependency(anglesPtr, "", true); + anglesRadPtr->addDependency(typePtr, "", true); + anglesPtr->addDependency(anglesRadPtr, "", true); + anglesPtr->addDependency(typePtr, "", true); + + // EGS_RadialRepeater + auto geoPtr = geomBlockInput->addSingleInput("repeated geometry", true, "The exsisting geometry that is repeated"); + geoPtr->addDependency(typePtr, "EGS_RadialRepeater"); + auto numPtr = geomBlockInput->addSingleInput("number of repetitions", true, "The number of times the geometry is repeated"); + numPtr->addDependency(typePtr, "EGS_RadialRepeater"); + auto medPtr = geomBlockInput->addSingleInput("medium", false, "The medium with which the space outside the replicated geometry is filled"); + medPtr->addDependency(typePtr, "EGS_RadialRepeater"); + auto firstanglePtr = geomBlockInput->addSingleInput("first angle", false, "First angle, phi_o"); + firstanglePtr->addDependency(typePtr, "EGS_RadialRepeater"); + } + + EGS_IPLANES_EXPORT string getExample(string type) { + string example; + example = { + R"( + # Example of egs_iplanes + #:start geometry: + library = egs_iplanes + name = my_iplane + axis = 0 0 0 0 0 1 + angles = 0 30 60 90 120 150 + :stop geometry: + + # Example of EGS_RadialRepeater + #:start geometry: + library = egs_iplanes + type = EGS_RadialRepeater + axis = 0 0 1 0 0 1 + number of repetitions = 5 + repeated geometry = my_geom + # use with geometry called my_geom +)"}; + return example; + } + + EGS_IPLANES_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } EGS_IPLANES_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { if (!input) { diff --git a/HEN_HOUSE/egs++/geometry/egs_nd_geometry/egs_nd_geometry.cpp b/HEN_HOUSE/egs++/geometry/egs_nd_geometry/egs_nd_geometry.cpp index 8daf2ca5a..bcc86eb32 100644 --- a/HEN_HOUSE/egs++/geometry/egs_nd_geometry/egs_nd_geometry.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_nd_geometry/egs_nd_geometry.cpp @@ -28,6 +28,7 @@ # Ernesto Mainegra-Hing # Hubert Ho # Randle Taylor +# Hannah Gallop # ############################################################################### */ @@ -1076,494 +1077,634 @@ const char *err_msg1 = "createGeometry(EGS_XYZRepeater)"; #endif -string EGS_NDGeometry::type = "EGS_NDGeometry"; +static string EGS_NDG_LOCAL typeStr("EGS_NDGeometry"); +string EGS_NDGeometry::type(typeStr); + +static bool EGS_NDG_LOCAL inputSet = false; extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_NDGeometry"}); + + // Format: name, isRequired, description, vector string of allowed values + auto typePtr = geomBlockInput->addSingleInput("type", false, "type of nd_geometry", {"EGS_XYZGeometry", "EGS_XYZRepeater"}); + + auto dimPtr = geomBlockInput->addSingleInput("dimensions", true, "A list of previously defined geometries."); + dimPtr->addDependency(typePtr, "", true); + auto hownPtr = geomBlockInput->addSingleInput("hownear method", false, "0(for orthogonal constituent geometries) or 1"); + hownPtr->addDependency(typePtr, "", true); + + // EGS_XYZGeometry + // First method + auto xPtr = geomBlockInput->addSingleInput("x-planes", false, "A list of the x-plane positions"); + xPtr->addDependency(typePtr, "EGS_XYZGeometry"); + auto yPtr = geomBlockInput->addSingleInput("y-planes", false, "A list of the y-plane positions"); + yPtr->addDependency(typePtr, "EGS_XYZGeometry"); + auto zPtr = geomBlockInput->addSingleInput("z-planes", false, "A list of the z-plane positions"); + zPtr->addDependency(typePtr, "EGS_XYZGeometry"); + + // Second method + auto densityPtr = geomBlockInput->addSingleInput("density matrix", false, "Density file"); + densityPtr->addDependency(typePtr, "EGS_XYZGeometry"); + auto ctPtr = geomBlockInput->addSingleInput("ct ramp", false, "Ramp file"); + ctPtr->addDependency(typePtr, "EGS_XYZGeometry"); + auto phantPtr = geomBlockInput->addSingleInput("egsphant file", false, "An egsphant file"); + phantPtr->addDependency(typePtr, "EGS_XYZGeometry"); + + // For second method, must either use "ct ramp" or "egsphant file" + densityPtr->addDependency(phantPtr, "", true); + phantPtr->addDependency(densityPtr, "", true); + + // Third method + auto xslabPtr = geomBlockInput->addSingleInput("x-slabs", false, "Xo Dx Nx"); + xslabPtr->addDependency(typePtr, "EGS_XYZGeometry"); + auto yslabPtr = geomBlockInput->addSingleInput("y-slabs", false, "Yo Dy Ny"); + yslabPtr->addDependency(typePtr, "EGS_XYZGeometry"); + auto zslabPtr = geomBlockInput->addSingleInput("z-slabs", false, "Zo Dz Nz"); + zslabPtr->addDependency(typePtr, "EGS_XYZGeometry"); + + // Can only use one method + xPtr->addDependency(densityPtr, "", true); + yPtr->addDependency(densityPtr, "", true); + zPtr->addDependency(densityPtr, "", true); + xPtr->addDependency(ctPtr, "", true); + yPtr->addDependency(ctPtr, "", true); + zPtr->addDependency(ctPtr, "", true); + xPtr->addDependency(phantPtr, "", true); + yPtr->addDependency(phantPtr, "", true); + zPtr->addDependency(phantPtr, "", true); + xPtr->addDependency(xslabPtr, "", true); + yPtr->addDependency(xslabPtr, "", true); + zPtr->addDependency(xslabPtr, "", true); + xPtr->addDependency(yslabPtr, "", true); + yPtr->addDependency(yslabPtr, "", true); + zPtr->addDependency(yslabPtr, "", true); + xPtr->addDependency(zslabPtr, "", true); + yPtr->addDependency(zslabPtr, "", true); + zPtr->addDependency(zslabPtr, "", true); + densityPtr->addDependency(xPtr, "", true); + ctPtr->addDependency(xPtr, "", true); + phantPtr->addDependency(xPtr, "", true); + densityPtr->addDependency(yPtr, "", true); + ctPtr->addDependency(yPtr, "", true); + phantPtr->addDependency(yPtr, "", true); + densityPtr->addDependency(zPtr, "", true); + ctPtr->addDependency(zPtr, "", true); + phantPtr->addDependency(zPtr, "", true); + densityPtr->addDependency(xslabPtr, "", true); + ctPtr->addDependency(xslabPtr, "", true); + phantPtr->addDependency(xslabPtr, "", true); + densityPtr->addDependency(yslabPtr, "", true); + ctPtr->addDependency(yslabPtr, "", true); + phantPtr->addDependency(yslabPtr, "", true); + densityPtr->addDependency(zslabPtr, "", true); + ctPtr->addDependency(zslabPtr, "", true); + phantPtr->addDependency(zslabPtr, "", true); + xslabPtr->addDependency(xPtr, "", true); + xslabPtr->addDependency(yPtr, "", true); + xslabPtr->addDependency(zPtr, "", true); + xslabPtr->addDependency(densityPtr, "", true); + xslabPtr->addDependency(ctPtr, "", true); + xslabPtr->addDependency(phantPtr, "", true); + yslabPtr->addDependency(xPtr, "", true); + yslabPtr->addDependency(yPtr, "", true); + yslabPtr->addDependency(zPtr, "", true); + yslabPtr->addDependency(densityPtr, "", true); + yslabPtr->addDependency(ctPtr, "", true); + yslabPtr->addDependency(phantPtr, "", true); + zslabPtr->addDependency(xPtr, "", true); + zslabPtr->addDependency(yPtr, "", true); + zslabPtr->addDependency(zPtr, "", true); + zslabPtr->addDependency(densityPtr, "", true); + zslabPtr->addDependency(ctPtr, "", true); + zslabPtr->addDependency(phantPtr, "", true); + + + // EGS_XYZRepeater + auto regeomPtr = geomBlockInput->addSingleInput("repeated geometry", true, "The name of a previously defined geometry"); + regeomPtr->addDependency(typePtr, "EGS_XYZRepeater"); + auto medPtr = geomBlockInput->addSingleInput("medium", false, "The medium the space between xmin..xmax, ymin..ymax, and zmin..zmax is filled with"); + medPtr->addDependency(typePtr, "EGS_XYZRepeater"); + auto rexPtr = geomBlockInput->addSingleInput("repeat x", true, "xmin xmax Nx"); + rexPtr->addDependency(typePtr, "EGS_XYZRepeater"); + auto reyPtr = geomBlockInput->addSingleInput("repeat y", true, "ymin ymax Ny"); + reyPtr->addDependency(typePtr, "EGS_XYZRepeater"); + auto rezPtr = geomBlockInput->addSingleInput("repeat z", true, "zmin zmax Nz"); + rezPtr->addDependency(typePtr, "EGS_XYZRepeater"); + } + + EGS_NDG_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_ndgeometry + #:start geometry: + library = EGS_NDGeometry + name = my_ndgeometry + dimensions = geom1 geom2 + :start media input: + media = water + :stop media input: + :stop geometry: +)"}; + return example; + } + + EGS_NDG_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } EGS_NDG_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { #ifdef EXPLICIT_XYZ const static char *func = "createGeometry(XYZ)"; - string type; - int is_xyz = input->getInput("type",type); - if (!is_xyz && input->compare("EGS_XYZRepeater",type)) { - string base,medium; - vector xr, yr, zr; - int err1 = input->getInput("repeated geometry",base); - int err2 = input->getInput("repeat x",xr); - int err3 = input->getInput("repeat y",yr); - int err4 = input->getInput("repeat z",zr); - int err5 = input->getInput("medium",medium); - EGS_BaseGeometry *g = 0; - if (err1) { - egsWarning("%s: missing 'repeated geometry' input\n",err_msg1); - } - else { - g = EGS_BaseGeometry::getGeometry(base); - if (!g) { - egsWarning("%s: no geometry named %s exists\n",err_msg1, - base.c_str()); + string type; + int is_xyz = input->getInput("type",type); + if (!is_xyz && input->compare("EGS_XYZRepeater",type)) { + string base,medium; + vector xr, yr, zr; + int err1 = input->getInput("repeated geometry",base); + int err2 = input->getInput("repeat x",xr); + int err3 = input->getInput("repeat y",yr); + int err4 = input->getInput("repeat z",zr); + int err5 = input->getInput("medium",medium); + EGS_BaseGeometry *g = 0; + if (err1) { + egsWarning("%s: missing 'repeated geometry' input\n",err_msg1); + } + else { + g = EGS_BaseGeometry::getGeometry(base); + if (!g) { + egsWarning("%s: no geometry named %s exists\n",err_msg1, + base.c_str()); + err1 = 1; + } + } + if (err2 || xr.size() != 3) { err1 = 1; + egsWarning("%s: wrong/missing 'repeat x' input\n",err_msg1); } - } - if (err2 || xr.size() != 3) { - err1 = 1; - egsWarning("%s: wrong/missing 'repeat x' input\n",err_msg1); - } - if (err3 || yr.size() != 3) { - err1 = 1; - egsWarning("%s: wrong/missing 'repeat y' input\n",err_msg1); - } - if (err4 || zr.size() != 3) { - err1 = 1; - egsWarning("%s: wrong/missing 'repeat z' input\n",err_msg1); - } - if (err1) { - return 0; - } - EGS_Float xmin = xr[0], xmax = xr[1]; - int nx = (int)(xr[2]+0.1); - if (xmin >= xmax || nx < 1) { - egsWarning("%s: wrong 'repeat x' input xmin=%g xmax=%g nx=%d\n", - xmin,xmax,nx); - err1 = 1; - } - EGS_Float ymin = yr[0], ymax = yr[1]; - int ny = (int)(yr[2]+0.1); - if (ymin >= ymax || ny < 1) { - egsWarning("%s: wrong 'repeat y' input ymin=%g ymax=%g ny=%d\n", - ymin,ymax,ny); - err1 = 1; - } - EGS_Float zmin = zr[0], zmax = zr[1]; - int nz = (int)(zr[2]+0.1); - if (zmin >= zmax || nz < 1) { - egsWarning("%s: wrong 'repeat z' input zmin=%g zmax=%g nz=%d\n", - zmin,zmax,nz); - err1 = 1; - } - if (err1) { - return 0; - } - - EGS_XYZRepeater *result = - new EGS_XYZRepeater(xmin,xmax,ymin,ymax,zmin,zmax,nx,ny,nz,g); - result->setName(input); - result->setBoundaryTolerance(input); - if (!err5) { - result->setMedium(medium); - } - result->setXYZLabels(input); - result->setLabels(input); - return result; - } - else if (!is_xyz && input->compare("EGS_XYZGeometry",type)) { - string dens_file, ramp_file, egsphant_file, interfile_file; - int ierr1 = input->getInput("density matrix",dens_file); - int ierr2 = input->getInput("ct ramp",ramp_file); - int ierr3 = input->getInput("egsphant file",egsphant_file); - int ierr4 = input->getInput("interfile header",interfile_file); - int dens_or_egsphant_or_interfile = -1; - if (!ierr1) { - dens_or_egsphant_or_interfile = 0; - } - else if (!ierr3) { - dens_or_egsphant_or_interfile = 1; - dens_file = egsphant_file; - } - else if (!ierr4) { - dens_or_egsphant_or_interfile = 2; - dens_file = interfile_file; - } - if (dens_or_egsphant_or_interfile >= 0 || !ierr2) { - if (dens_or_egsphant_or_interfile < 0) { - egsWarning("%s: no 'density matrix', 'egsphant file' or 'interfile header' input\n",func); + if (err3 || yr.size() != 3) { + err1 = 1; + egsWarning("%s: wrong/missing 'repeat y' input\n",err_msg1); + } + if (err4 || zr.size() != 3) { + err1 = 1; + egsWarning("%s: wrong/missing 'repeat z' input\n",err_msg1); + } + if (err1) { return 0; } - if (ierr2) { - egsWarning("%s: no 'ct ramp' input\n",func); + EGS_Float xmin = xr[0], xmax = xr[1]; + int nx = (int)(xr[2]+0.1); + if (xmin >= xmax || nx < 1) { + egsWarning("%s: wrong 'repeat x' input xmin=%g xmax=%g nx=%d\n", + xmin,xmax,nx); + err1 = 1; + } + EGS_Float ymin = yr[0], ymax = yr[1]; + int ny = (int)(yr[2]+0.1); + if (ymin >= ymax || ny < 1) { + egsWarning("%s: wrong 'repeat y' input ymin=%g ymax=%g ny=%d\n", + ymin,ymax,ny); + err1 = 1; + } + EGS_Float zmin = zr[0], zmax = zr[1]; + int nz = (int)(zr[2]+0.1); + if (zmin >= zmax || nz < 1) { + egsWarning("%s: wrong 'repeat z' input zmin=%g zmax=%g nz=%d\n", + zmin,zmax,nz); + err1 = 1; + } + if (err1) { return 0; } - EGS_XYZGeometry *result = - EGS_XYZGeometry::constructGeometry(dens_file.c_str(),ramp_file.c_str(),dens_or_egsphant_or_interfile); - if (result) { - result->setName(input); - result->setBoundaryTolerance(input); - result->setBScaling(input); + EGS_XYZRepeater *result = + new EGS_XYZRepeater(xmin,xmax,ymin,ymax,zmin,zmax,nx,ny,nz,g); + result->setName(input); + result->setBoundaryTolerance(input); + if (!err5) { + result->setMedium(medium); } - + result->setXYZLabels(input); + result->setLabels(input); return result; } - vector xpos, ypos, zpos, xslab, yslab, zslab; - int ix = input->getInput("x-planes",xpos); - int iy = input->getInput("y-planes",ypos); - int iz = input->getInput("z-planes",zpos); - int ix1 = input->getInput("x-slabs",xslab); - int iy1 = input->getInput("y-slabs",yslab); - int iz1 = input->getInput("z-slabs",zslab); - int nx=0, ny=0, nz=0; - if (!ix1) { - if (xslab.size() != 3) { - egsWarning("createGeometry(XYZ): exactly 3 inputs are required" - " when using 'x-slabs' input method\n"); - ix1 = 1; + else if (!is_xyz && input->compare("EGS_XYZGeometry",type)) { + string dens_file, ramp_file, egsphant_file, interfile_file; + int ierr1 = input->getInput("density matrix",dens_file); + int ierr2 = input->getInput("ct ramp",ramp_file); + int ierr3 = input->getInput("egsphant file",egsphant_file); + int ierr4 = input->getInput("interfile header",interfile_file); + int dens_or_egsphant_or_interfile = -1; + if (!ierr1) { + dens_or_egsphant_or_interfile = 0; } - else { - nx = (int)(xslab[2]+0.1); - if (nx < 1) { - egsWarning("createGeometry(XYZ): number of slabs must be" - " positive!\n"); - ix1 = 1; + else if (!ierr3) { + dens_or_egsphant_or_interfile = 1; + dens_file = egsphant_file; + } + else if (!ierr4) { + dens_or_egsphant_or_interfile = 2; + dens_file = interfile_file; + } + if (dens_or_egsphant_or_interfile >= 0 || !ierr2) { + if (dens_or_egsphant_or_interfile < 0) { + egsWarning("%s: no 'density matrix', 'egsphant file' or 'interfile header' input\n",func); + return 0; } - if (xslab[1] <= 0) { - egsWarning("createGeometry(XYZ): slab thickness must be" - " positive!\n"); + if (ierr2) { + egsWarning("%s: no 'ct ramp' input\n",func); + return 0; + } + EGS_XYZGeometry *result = + EGS_XYZGeometry::constructGeometry(dens_file.c_str(),ramp_file.c_str(),dens_or_egsphant_or_interfile); + + if (result) { + result->setName(input); + result->setBoundaryTolerance(input); + result->setBScaling(input); + } + + return result; + } + vector xpos, ypos, zpos, xslab, yslab, zslab; + int ix = input->getInput("x-planes",xpos); + int iy = input->getInput("y-planes",ypos); + int iz = input->getInput("z-planes",zpos); + int ix1 = input->getInput("x-slabs",xslab); + int iy1 = input->getInput("y-slabs",yslab); + int iz1 = input->getInput("z-slabs",zslab); + int nx=0, ny=0, nz=0; + if (!ix1) { + if (xslab.size() != 3) { + egsWarning("createGeometry(XYZ): exactly 3 inputs are required" + " when using 'x-slabs' input method\n"); ix1 = 1; } + else { + nx = (int)(xslab[2]+0.1); + if (nx < 1) { + egsWarning("createGeometry(XYZ): number of slabs must be" + " positive!\n"); + ix1 = 1; + } + if (xslab[1] <= 0) { + egsWarning("createGeometry(XYZ): slab thickness must be" + " positive!\n"); + ix1 = 1; + } + } } - } - if (ix && ix1) { - egsWarning("createGeometry(XYZ): wrong/missing 'x-planes' " - "and 'x-slabs' input\n"); - return 0; - } - if (!iy1) { - if (yslab.size() != 3) { - egsWarning("createGeometry(XYZ): exactly 3 inputs are required" - " when using 'y-slabs' input method\n"); - iy1 = 1; + if (ix && ix1) { + egsWarning("createGeometry(XYZ): wrong/missing 'x-planes' " + "and 'x-slabs' input\n"); + return 0; } - else { - ny = (int)(yslab[2]+0.1); - if (ny < 1) { - egsWarning("createGeometry(XYZ): number of slabs must be" - " positive!\n"); + if (!iy1) { + if (yslab.size() != 3) { + egsWarning("createGeometry(XYZ): exactly 3 inputs are required" + " when using 'y-slabs' input method\n"); iy1 = 1; } - if (yslab[1] <= 0) { - egsWarning("createGeometry(XYZ): slab thickness must be" - " positive!\n"); - iy1 = 1; + else { + ny = (int)(yslab[2]+0.1); + if (ny < 1) { + egsWarning("createGeometry(XYZ): number of slabs must be" + " positive!\n"); + iy1 = 1; + } + if (yslab[1] <= 0) { + egsWarning("createGeometry(XYZ): slab thickness must be" + " positive!\n"); + iy1 = 1; + } } } - } - if (iy && iy1) { - egsWarning("createGeometry(XYZ): wrong/missing 'y-planes' " - "and 'y-slabs' input\n"); - return 0; - } - if (!iz1) { - if (zslab.size() != 3) { - egsWarning("createGeometry(XYZ): exactly 3 inputs are required" - " when using 'z-slabs' input method\n"); - iz1 = 1; + if (iy && iy1) { + egsWarning("createGeometry(XYZ): wrong/missing 'y-planes' " + "and 'y-slabs' input\n"); + return 0; } - else { - nz = (int)(zslab[2]+0.1); - if (nz < 1) { - egsWarning("createGeometry(XYZ): number of slabs must be" - " positive!\n"); + if (!iz1) { + if (zslab.size() != 3) { + egsWarning("createGeometry(XYZ): exactly 3 inputs are required" + " when using 'z-slabs' input method\n"); iz1 = 1; } - if (zslab[1] <= 0) { - egsWarning("createGeometry(XYZ): slab thickness must be" - " positive!\n"); - iz1 = 1; + else { + nz = (int)(zslab[2]+0.1); + if (nz < 1) { + egsWarning("createGeometry(XYZ): number of slabs must be" + " positive!\n"); + iz1 = 1; + } + if (zslab[1] <= 0) { + egsWarning("createGeometry(XYZ): slab thickness must be" + " positive!\n"); + iz1 = 1; + } } } - } - if (iz && iz1) { - egsWarning("createGeometry(XYZ): wrong/missing 'z-planes' " - "and 'z-slabs' input\n"); - return 0; - } - EGS_PlanesX *xp = !ix1 ? - new EGS_PlanesX(xslab[0],xslab[1],nx,"",EGS_XProjector("x-planes")) : - new EGS_PlanesX(xpos,"",EGS_XProjector("x-planes")); - EGS_PlanesY *yp = !iy1 ? - new EGS_PlanesY(yslab[0],yslab[1],ny,"",EGS_YProjector("y-planes")) : - new EGS_PlanesY(ypos,"",EGS_YProjector("y-planes")); - EGS_PlanesZ *zp = !iz1 ? - new EGS_PlanesZ(zslab[0],zslab[1],nz,"",EGS_ZProjector("z-planes")) : - new EGS_PlanesZ(zpos,"",EGS_ZProjector("z-planes")); - EGS_XYZGeometry *result = new EGS_XYZGeometry(xp,yp,zp); - - if (result) { - egsWarning("**********************************************\n"); - EGS_BaseGeometry *g = result; - result->setName(input); - result->setBoundaryTolerance(input); - g->setMedia(input); - result->voxelizeGeometry(input); + if (iz && iz1) { + egsWarning("createGeometry(XYZ): wrong/missing 'z-planes' " + "and 'z-slabs' input\n"); + return 0; + } + EGS_PlanesX *xp = !ix1 ? + new EGS_PlanesX(xslab[0],xslab[1],nx,"",EGS_XProjector("x-planes")) : + new EGS_PlanesX(xpos,"",EGS_XProjector("x-planes")); + EGS_PlanesY *yp = !iy1 ? + new EGS_PlanesY(yslab[0],yslab[1],ny,"",EGS_YProjector("y-planes")) : + new EGS_PlanesY(ypos,"",EGS_YProjector("y-planes")); + EGS_PlanesZ *zp = !iz1 ? + new EGS_PlanesZ(zslab[0],zslab[1],nz,"",EGS_ZProjector("z-planes")) : + new EGS_PlanesZ(zpos,"",EGS_ZProjector("z-planes")); + EGS_XYZGeometry *result = new EGS_XYZGeometry(xp,yp,zp); - // labels - result->setXYZLabels(input); - g->setLabels(input); + if (result) { + egsWarning("**********************************************\n"); + EGS_BaseGeometry *g = result; + result->setName(input); + result->setBoundaryTolerance(input); + g->setMedia(input); + result->voxelizeGeometry(input); + + // labels + result->setXYZLabels(input); + g->setLabels(input); + } + return result; } - return result; - } #endif - vector dims; - EGS_Input *ij; - int error = 0; - while ((ij = input->takeInputItem("geometry",false)) != 0) { - EGS_BaseGeometry *g = EGS_BaseGeometry::createSingleGeometry(ij); - if (g) { - dims.push_back(g); - g->ref(); - } - else { - error++; - } - delete ij; - } - vector gnames; - int err1 = input->getInput("dimensions",gnames); - if (!err1) { - for (unsigned int j=0; j dims; + EGS_Input *ij; + int error = 0; + while ((ij = input->takeInputItem("geometry",false)) != 0) { + EGS_BaseGeometry *g = EGS_BaseGeometry::createSingleGeometry(ij); if (g) { dims.push_back(g); g->ref(); } else { - egsWarning("Geometry %s does not exist\n",gnames[j].c_str()); error++; } + delete ij; + } + vector gnames; + int err1 = input->getInput("dimensions",gnames); + if (!err1) { + for (unsigned int j=0; jref(); + } + else { + egsWarning("Geometry %s does not exist\n",gnames[j].c_str()); + error++; + } + } } - } - if (error) { - egsWarning("createGeometry(ND_Geometry): %d errors while " - "creating/geting geometries defining individual dimensions\n",error); - return 0; - } - if (dims.size() < 2) { - egsWarning("createGeometry(ND_Geometry): why do you want to " - "construct a ND geometry with a single dimension?\n"); - input->print(0,cerr); - for (int j=0; jisConvex()) { - n_concav++; - } - bool is_ok = true; - if (n_concav > 1) { - egsWarning("createGeometry(ND_Geometry): a ND geometry can not have " - " more than one non-convex dimension, yours has %d\n",n_concav); - is_ok = false; - } - else if (n_concav == 1) { - if (dims[dims.size()-1]->isConvex()) { - egsWarning("createGeometry(ND_Geometry): the non-convex " - "dimension must be the last dimension\n"); + if (error) { + egsWarning("createGeometry(ND_Geometry): %d errors while " + "creating/geting geometries defining individual dimensions\n",error); + return 0; + } + if (dims.size() < 2) { + egsWarning("createGeometry(ND_Geometry): why do you want to " + "construct a ND geometry with a single dimension?\n"); + input->print(0,cerr); + for (int j=0; jisConvex()) { + n_concav++; + } + bool is_ok = true; + if (n_concav > 1) { + egsWarning("createGeometry(ND_Geometry): a ND geometry can not have " + " more than one non-convex dimension, yours has %d\n",n_concav); is_ok = false; } - } - if (!is_ok) { - for (int j=0; jderef()) { - delete dims[j]; + else if (n_concav == 1) { + if (dims[dims.size()-1]->isConvex()) { + egsWarning("createGeometry(ND_Geometry): the non-convex " + "dimension must be the last dimension\n"); + is_ok = false; } - return 0; - } - int hn_method=0; - err1 = input->getInput("hownear method",hn_method); - EGS_BaseGeometry *result; - if (!err1 && hn_method == 1) { - result = new EGS_NDGeometry(dims,"",false); - } - else { - result = new EGS_NDGeometry(dims); + } + if (!is_ok) { + for (int j=0; jderef()) { + delete dims[j]; + } + return 0; + } + int hn_method=0; + err1 = input->getInput("hownear method",hn_method); + EGS_BaseGeometry *result; + if (!err1 && hn_method == 1) { + result = new EGS_NDGeometry(dims,"",false); + } + else { + result = new EGS_NDGeometry(dims); + } + result->setName(input); + result->setBoundaryTolerance(input); + result->setMedia(input); + result->setLabels(input); + return result; } - result->setName(input); - result->setBoundaryTolerance(input); - result->setMedia(input); - result->setLabels(input); - return result; - } - void EGS_XYZGeometry::setXYZLabels(EGS_Input *input) { + void EGS_XYZGeometry::setXYZLabels(EGS_Input *input) { - // x,y,z labels - string inp; - int err; + // x,y,z labels + string inp; + int err; - err = input->getInput("set x label", inp); - if (!err) { - xp->setLabels(inp); - } + err = input->getInput("set x label", inp); + if (!err) { + xp->setLabels(inp); + } - err = input->getInput("set y label", inp); - if (!err) { - yp->setLabels(inp); - } + err = input->getInput("set y label", inp); + if (!err) { + yp->setLabels(inp); + } - err = input->getInput("set z label", inp); - if (!err) { - zp->setLabels(inp); + err = input->getInput("set z label", inp); + if (!err) { + zp->setLabels(inp); + } } - } - void EGS_NDGeometry::ndRegions(int r, int dim, int dimk, int k, vector ®s) { + void EGS_NDGeometry::ndRegions(int r, int dim, int dimk, int k, vector ®s) { - // skip looping over selected dimension - if (dim == dimk) { - r += k*n[dimk]; - if (dim == N-1) { - regs.push_back(r); - } - else { - ndRegions(r, dim+1, dimk, k, regs); + // skip looping over selected dimension + if (dim == dimk) { + r += k*n[dimk]; + if (dim == N-1) { + regs.push_back(r); + } + else { + ndRegions(r, dim+1, dimk, k, regs); + } } - } - // last dimension: end recursion and record global region number - else if (dim == N-1) { - for (int j=0; jregions(); j++) { - regs.push_back(r+j*n[dim]); + // last dimension: end recursion and record global region number + else if (dim == N-1) { + for (int j=0; jregions(); j++) { + regs.push_back(r+j*n[dim]); + } } - } - // keep collecting by recursion - else { - for (int j=0; jregions(); j++) { - ndRegions(r + j*n[dim], dim+1, dimk, k, regs); + // keep collecting by recursion + else { + for (int j=0; jregions(); j++) { + ndRegions(r + j*n[dim], dim+1, dimk, k, regs); + } } } - } - void EGS_NDGeometry::getLabelRegions(const string &str, vector ®s) { + void EGS_NDGeometry::getLabelRegions(const string &str, vector ®s) { - // label defined in the sub-geometries - vector local_regs; - for (int i=0; igetLabelRegions(str, local_regs); - } - if (local_regs.size() == 0) { - continue; - } + // label defined in the sub-geometries + vector local_regs; + for (int i=0; igetLabelRegions(str, local_regs); + } + if (local_regs.size() == 0) { + continue; + } - // recurse to collect all global regions comprised in each local region - for (int j=0; j ®s) { + void EGS_XYZGeometry::getLabelRegions(const string &str, vector ®s) { - vector local_regs; + vector local_regs; - // x plane labels - local_regs.clear(); - xp->getLabelRegions(str, local_regs); - for (int i=0; igetLabelRegions(str, local_regs); + for (int i=0; igetLabelRegions(str, local_regs); - for (int j=0; jgetLabelRegions(str, local_regs); + for (int j=0; jgetLabelRegions(str, local_regs); - for (int k=0; kgetLabelRegions(str, local_regs); + for (int k=0; k ®s) { + void EGS_XYZRepeater::getLabelRegions(const string &str, vector ®s) { - vector local_regs; + vector local_regs; - // label in repeated geometry - local_regs.clear(); - g->getLabelRegions(str, local_regs); - for (int i=0; igetLabelRegions(str, local_regs); + for (int i=0; igetXLabelRegions(str, local_regs); - for (int i=0; igetXLabelRegions(str, local_regs); + for (int i=0; igetYLabelRegions(str, local_regs); - for (int j=0; jgetYLabelRegions(str, local_regs); + for (int j=0; jgetZLabelRegions(str, local_regs); - for (int k=0; kgetZLabelRegions(str, local_regs); + for (int k=0; kgetSingleInput("library")->setValues({"EGS_Octree"}); + + // Format: name, isRequired, description, vector string of allowed values + geomBlockInput->addSingleInput("child geometry", true, "The name of child geometry"); + geomBlockInput->addSingleInput("discard child", true, "yes or no"); + geomBlockInput->addSingleInput("prune tree", false, "yes or no"); + + auto blockPtr = geomBlockInput->addBlockInput("octree box"); + blockPtr->addSingleInput("box min", true, "(x, y, z)"); + blockPtr->addSingleInput("box max", true, "(x, y, z)"); + blockPtr->addSingleInput("resolution", true, "A specified resolution (x, y, z)"); + } + + EGS_OCTREE_EXPORT shared_ptr getInputs() { + if (!inputSet) { + setInputs(); + } + return geomBlockInput; + } + EGS_OCTREE_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { EGS_Input *i; diff --git a/HEN_HOUSE/egs++/geometry/egs_planes/egs_planes.cpp b/HEN_HOUSE/egs++/geometry/egs_planes/egs_planes.cpp index 24e4ed8d0..77824581d 100644 --- a/HEN_HOUSE/egs++/geometry/egs_planes/egs_planes.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_planes/egs_planes.cpp @@ -24,6 +24,7 @@ # Author: Iwan Kawrakow, 2005 # # Contributors: Frederic Tessier +# Hannah Gallop # ############################################################################### */ @@ -47,6 +48,8 @@ const string EGS_PLANES_LOCAL yproj_type("EGS_Yplanes"); const string EGS_PLANES_LOCAL zproj_type("EGS_Zplanes"); const string EGS_PLANES_LOCAL proj_type("EGS_Planes"); +static bool EGS_PLANES_LOCAL inputSet = false; + string EGS_PlaneCollection::type = "EGS_PlaneCollection"; EGS_PlaneCollection::EGS_PlaneCollection(int Np, const EGS_Float *pos, @@ -87,6 +90,78 @@ void EGS_PlaneCollection::printInfo() const { } extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(false); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_Planes"}); + + // Format: name, isRequired, description, vector string of allowed values + auto typePtr = geomBlockInput->addSingleInput("type", true, "The type of plane.", {"EGS_XPlanes", "EGS_YPlanes", "EGS_ZPlanes", "EGS_Planes", "EGS_PlaneCollection"}); + + auto posPtr = geomBlockInput->addSingleInput("positions", false, "A list of plane co-ordinates"); + + // EGS_Planes + auto norPtr = geomBlockInput->addSingleInput("normal", true, "The plane normal (x, y, z)"); + norPtr->addDependency(typePtr, "EGS_Planes"); + + // EGS_PlaneCollection + auto normsPtr = geomBlockInput->addSingleInput("normals", true, "3N number inputs For each plane's normal"); + normsPtr->addDependency(typePtr, "EGS_PlaneCollection"); + + // Alternative definition of the plane position + auto fpPtr = geomBlockInput->addSingleInput("first plane", false, "The position of the first plane."); + auto slabPtr = geomBlockInput->addSingleInput("slab thickness", false, "A list of the thickness between each set of planes"); + auto numPtr = geomBlockInput->addSingleInput("number of slabs", false, "A list of the number of slabs"); + + // Either positions or the alternatives must be used, not both + fpPtr->addDependency(posPtr, "", true); + slabPtr->addDependency(posPtr, "", true); + numPtr->addDependency(posPtr, "", true); + posPtr->addDependency(fpPtr, "", true); + posPtr->addDependency(slabPtr, "", true); + posPtr->addDependency(numPtr, "", true); + } + + EGS_PLANES_EXPORT string getExample(string type) { + string example; + example = { + R"( + # Examples of the egs_planes + + # EGS_Plane example + #:start geometry: + library = egs_planes + type = EGS_Planes + name = my_plane + positions = 2 2 2 + normal = 0 + :stop geometry: + + # EGS_PlaneCollection example + #:start geometry: + library = egs_planes + type = EGS_PlaneCollection + name = my_plane_collection + normals = 0 0 1 0.1 -0.1 1 -0.1 -0.3 1 0 0 1 + positions = -5 -2 2 12 + :start media input: + media = air water air + set medium = 1 1 + set medium = 2 2 + :stop media input: + :stop geometry: +)"}; + return example; + } + + EGS_PLANES_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } EGS_PLANES_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { string type; diff --git a/HEN_HOUSE/egs++/geometry/egs_prism/egs_prism.cpp b/HEN_HOUSE/egs++/geometry/egs_prism/egs_prism.cpp index 8dbe78806..c7cee169c 100644 --- a/HEN_HOUSE/egs++/geometry/egs_prism/egs_prism.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_prism/egs_prism.cpp @@ -24,6 +24,7 @@ # Author: Iwan Kawrakow, 2005 # # Contributors: Frederic Tessier +# Hannah Gallop # ############################################################################### */ @@ -45,8 +46,52 @@ static EGS_PRISM_LOCAL string __prismY("EGS_PrismY"); static EGS_PRISM_LOCAL string __prismZ("EGS_PrismZ"); static EGS_PRISM_LOCAL string __prism("EGS_Prism"); +static bool EGS_PRISM_LOCAL inputSet = false; + extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_Prism"}); + + // Format: name, isRequired, description, vector string of allowed values + auto typePtr = geomBlockInput->addSingleInput("type", true, "The type of prism", {"EGS_PrismX", "EGS_PrismY", "EGS_PrismZ", "EGS_Prism"}); + + geomBlockInput->addSingleInput("closed", false, "Two inputs that define the distance from the top and bottom prism plane to the plane used to define the polygon"); + geomBlockInput->addSingleInput("points", true, "A list of 2D or 3D positions."); + } + + EGS_PRISM_EXPORT string getExample(string type) { + string example; + example = { + R"( + # Example of egs_prisms + + # EGS_PrismZ example + #:start geometry: + name = my_prism + library = egs_prism + type = EGS_PrismZ + points = 1 1 -1 1 -1 -1 4 -1 + closed = 1 4 + :start media input: + media = air + :stop media input: + :stop geometry: +)"}; + return example; + } + + EGS_PRISM_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } + EGS_PRISM_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { if (!input) { diff --git a/HEN_HOUSE/egs++/geometry/egs_pyramid/egs_pyramid.cpp b/HEN_HOUSE/egs++/geometry/egs_pyramid/egs_pyramid.cpp index 3b9ef20f6..aef090eb7 100644 --- a/HEN_HOUSE/egs++/geometry/egs_pyramid/egs_pyramid.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_pyramid/egs_pyramid.cpp @@ -24,6 +24,7 @@ # Author: Iwan Kawrakow, 2005 # # Contributors: Frederic Tessier +# Hannah Gallop # ############################################################################### */ @@ -46,6 +47,8 @@ static EGS_PYRAMID_LOCAL string __pyrY = "EGS_PyramidY"; static EGS_PYRAMID_LOCAL string __pyrZ = "EGS_PyramidZ"; static EGS_PYRAMID_LOCAL string __pyr = "EGS_Pyramid"; +static bool EGS_PYRAMID_LOCAL inputSet = false; + template EGS_PyramidT::EGS_PyramidT(T *P, const EGS_Vector &Xo, bool O, const string &Name) : EGS_BaseGeometry(Name), p(P), xo(Xo), @@ -94,6 +97,50 @@ void EGS_PyramidT::printInfo() const { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_Pyramid"}); + + // Format: name, isRequired, description, vector string of allowed values + auto typePtr = geomBlockInput->addSingleInput("type", true, "The type of pyramid", {"EGS_PyramidX", "EGS_PyramidY", "EGS_PyramidZ", "EGS_Pyramid"}); + + geomBlockInput->addSingleInput("points", true, "A list of 2D or 3D positions"); + geomBlockInput->addSingleInput("tip", true, "The 3D position of the tip of the pyramid (x, y ,z)"); + geomBlockInput->addSingleInput("closed", false, "0 (open) or 1 (closed)"); + } + + EGS_PYRAMID_EXPORT string getExample(string type) { + string example; + example = { + R"( + # Example of egs_pyramid + + # EGS_PyramidZ example + #:start geometry: + name = my_pyramid + library = egs_pyramid + type = EGS_PyramidZ + points = 1 1 -1 1 -1 -1 4 -1 + tip = 0 0 7 + closed = 0 + :start media input: + media = air + :stop media input: + :stop geometry: +)"}; + return example; + } + + EGS_PYRAMID_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } + EGS_PYRAMID_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { if (!input) { diff --git a/HEN_HOUSE/egs++/geometry/egs_roundrect_cylinders/egs_roundrect_cylinders.cpp b/HEN_HOUSE/egs++/geometry/egs_roundrect_cylinders/egs_roundrect_cylinders.cpp index 626f5437f..4b51868d3 100644 --- a/HEN_HOUSE/egs++/geometry/egs_roundrect_cylinders/egs_roundrect_cylinders.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_roundrect_cylinders/egs_roundrect_cylinders.cpp @@ -23,7 +23,7 @@ # # Author: Manuel Stoeckl, 2016 # -# Contributors: +# Contributors: Hannah Gallop # ############################################################################### # @@ -41,7 +41,58 @@ #include "egs_roundrect_cylinders.h" #include "egs_input.h" +static bool EGS_ROUNDRECT_CYLINDERS_LOCAL inputSet = false; + extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_RoundRect_Cylinders"}); + + // Format: name, isRequired, description, vector string of allowed inputs + auto typePtr = geomBlockInput->addSingleInput("type", true, "The type of rounded rectangle cylinder", {"EGS_RoundRectCylinders", "EGS_RoundRectCylindersXY", "EGS_RoundRectCylindersYZ", "EGS_RoundRectCylindersXZ"}); + + geomBlockInput->addSingleInput("x-widths", true, "A list of cylinder half-widths in the x-direction, must be in increasing order"); + geomBlockInput->addSingleInput("y-widths", true, "A list of cylinder half-widths in the y-direction, must be in increasing order"); + geomBlockInput->addSingleInput("radii", true, "A list of fillet radii, must be in increasing order"); + geomBlockInput->addSingleInput("midpoint", false, "The position of the midpoint (x, y, z)"); + + // EGS_RoundRectCylinders + auto inpPtr = geomBlockInput->addSingleInput("x-axis", true, "x-axis of rounded rectangle (x, y, z)"); + inpPtr->addDependency(typePtr, "EGS_RoundRectCylinders"); + auto yinpPtr = geomBlockInput->addSingleInput("y-axis", true, "y-axis of rounded rectangle (x, y, z)"); + yinpPtr->addDependency(typePtr, "EGS_RoundRectCylinders"); + } + + EGS_ROUNDRECT_CYLINDERS_EXPORT string getExample(string type) { + string example; + example = { + R"( + # Example of rounded reactangle cylinder + #:start geometry: + name = my_roundedrectcylinder + library = egs_roundrect_cylinders + type = EGS_RoundRectCylindersXY + x-widths = 1 2 + y-widths = 0.5 1 + radii = 0.1 0.5 + :start media input: + media = air water + set medium = 1 1 + :stop media input: + :stop geometry: +)"}; + return example; + } + + EGS_ROUNDRECT_CYLINDERS_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } EGS_ROUNDRECT_CYLINDERS_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { diff --git a/HEN_HOUSE/egs++/geometry/egs_rz/egs_rz.cpp b/HEN_HOUSE/egs++/geometry/egs_rz/egs_rz.cpp index ee02472c0..ffb4937a9 100644 --- a/HEN_HOUSE/egs++/geometry/egs_rz/egs_rz.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_rz/egs_rz.cpp @@ -27,6 +27,7 @@ # Contributors: Marc Chamberland # Rowan Thomson # Dave Rogers +# Hannah Gallop # ############################################################################### # @@ -47,6 +48,7 @@ #include "../egs_cylinders/egs_cylinders.h" #include "../egs_planes/egs_planes.h" +static bool EGS_RZ_LOCAL inputSet = false; string EGS_RZGeometry::RZType = "EGS_RZ"; @@ -225,6 +227,72 @@ bool allIncreasing(vector vec) { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(false); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_RZ"}); + + // Format: name, isRequired, description, vector string of allowed values + auto radPtr = geomBlockInput->addSingleInput("radii", false, "A list of radii, must be in increasing order"); + auto planePtr = geomBlockInput->addSingleInput("z-planes", false, "Input for z-planes"); + + // Or can define using slabs and shells + auto num_shellPtr = geomBlockInput->addSingleInput("number of shells", false, "A list of the number of shells"); + auto shellPtr = geomBlockInput->addSingleInput("shell thickness", false, "A list of shell thicknesses"); + auto firstPtr = geomBlockInput->addSingleInput("first plane", false, "first plane"); + auto num_slabPtr = geomBlockInput->addSingleInput("number of slabs", false, "A list of the number of slabs"); + auto slabPtr = geomBlockInput->addSingleInput("slab thickness", false, "A list of the slab thicknesses"); + + // Can only use one method + radPtr->addDependency(num_shellPtr, "", true); + radPtr->addDependency(shellPtr, "", true); + radPtr->addDependency(firstPtr, "", true); + radPtr->addDependency(num_slabPtr, "", true); + radPtr->addDependency(slabPtr, "", true); + planePtr->addDependency(num_shellPtr, "", true); + planePtr->addDependency(shellPtr, "", true); + planePtr->addDependency(firstPtr, "", true); + planePtr->addDependency(num_slabPtr, "", true); + planePtr->addDependency(slabPtr, "", true); + num_shellPtr->addDependency(radPtr, "", true); + num_shellPtr->addDependency(planePtr, "", true); + shellPtr->addDependency(radPtr, "", true); + shellPtr->addDependency(planePtr, "", true); + firstPtr->addDependency(radPtr, "", true); + firstPtr->addDependency(planePtr, "", true); + num_slabPtr->addDependency(radPtr, "", true); + num_slabPtr->addDependency(planePtr, "", true); + slabPtr->addDependency(radPtr, "", true); + slabPtr->addDependency(planePtr, "", true); + } + + EGS_RZ_EXPORT string getExample(string type) { + string example; + example = { + R"( + # Example of egs_rz + :start geometry: + name = my_rz + library = egs_rz + radii = 1 2 3 + z-planes= -4 -3 -2 -1 0 1 2 3 4 + :start media input: + media = water + :stop media input: + :stop geometry: +)"}; + return example; + } + + EGS_RZ_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } + EGS_RZ_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { if (!input) { diff --git a/HEN_HOUSE/egs++/geometry/egs_smart_envelope/egs_smart_envelope.cpp b/HEN_HOUSE/egs++/geometry/egs_smart_envelope/egs_smart_envelope.cpp index b0e72b53f..be929c694 100644 --- a/HEN_HOUSE/egs++/geometry/egs_smart_envelope/egs_smart_envelope.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_smart_envelope/egs_smart_envelope.cpp @@ -25,6 +25,7 @@ # # Contributors: Frederic Tessier # Ernesto Mainegra-Hing +# Hannah Gallop # ############################################################################### # @@ -65,6 +66,8 @@ using namespace std; string EGS_SMART_ENVELOPE_LOCAL EGS_SmartEnvelope::type = "EGS_SmartEnvelope"; +static bool EGS_SMART_ENVELOPE_LOCAL inputSet = false; + void EGS_SmartEnvelope::setMedia(EGS_Input *,int,const int *) { egsWarning("EGS_SmartEnvelope::setMedia: don't use this method. Use the\n" " setMedia() methods of the geometry objects that make up this geometry\n"); @@ -254,6 +257,25 @@ static char EGS_SMART_ENVELOPE_LOCAL eeg_keyword2[] = "geometry"; extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(false); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_SmartEnvelope"}); + + // Format: name, isRequired, description, vector string of allowed values + geomBlockInput->addSingleInput("base geometry", true, "The name of a previously defined geometry"); + geomBlockInput->addSingleInput("inscribed geometries", true, "A list of previously defined geometries"); + } + + EGS_SMART_ENVELOPE_EXPORT shared_ptr getInputs() { + if (!inputSet) { + setInputs(); + } + return geomBlockInput; + } + EGS_SMART_ENVELOPE_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { if (!input) { egsWarning(eeg_message1,eeg_message2); diff --git a/HEN_HOUSE/egs++/geometry/egs_space/egs_space.cpp b/HEN_HOUSE/egs++/geometry/egs_space/egs_space.cpp index 89678dfb1..afebf785f 100644 --- a/HEN_HOUSE/egs++/geometry/egs_space/egs_space.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_space/egs_space.cpp @@ -24,6 +24,7 @@ # Author: Iwan Kawrakow, 2005 # # Contributors: Frederic Tessier +# Hannah Gallop # ############################################################################### */ @@ -39,8 +40,25 @@ string EGS_Space::type = "EGS_Space"; +static bool EGS_SPACE_LOCAL inputSet = false; + extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(false); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_Space"}); + } + + EGS_SPACE_EXPORT shared_ptr getInputs() { + if (!inputSet) { + setInputs(); + } + return geomBlockInput; + } + EGS_SPACE_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { EGS_Space *g = new EGS_Space(""); g->setName(input); diff --git a/HEN_HOUSE/egs++/geometry/egs_spheres/egs_spheres.cpp b/HEN_HOUSE/egs++/geometry/egs_spheres/egs_spheres.cpp index faa2b6d24..3ef5663d7 100644 --- a/HEN_HOUSE/egs++/geometry/egs_spheres/egs_spheres.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_spheres/egs_spheres.cpp @@ -27,6 +27,7 @@ # Frederic Tessier # Reid Townson # Randle Taylor +# Hannah Gallop # ############################################################################### */ @@ -46,6 +47,8 @@ using std::vector; string EGS_cSpheres::type = "EGS_cSpheres"; +static bool EGS_SPHERES_LOCAL inputSet = false; + // generate the concentric spheres EGS_cSpheres::EGS_cSpheres(int ns, const EGS_Float *radius, const EGS_Vector &position, const string &Name) : @@ -679,6 +682,45 @@ void EGS_cSphericalShell::printInfo() const { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_Spheres"}); + + // Format: name, isRequired, description, vector string of allowed values + geomBlockInput->addSingleInput("radii", true, "A of list of sphere radii in increasing order."); + geomBlockInput->addSingleInput("midpoint", false, "The position of the middle of the sphere (x, y, z)"); + } + + EGS_SPHERES_EXPORT string getExample(string type) { + string example; + example = { + R"( + # Example of egs_spheres + #:start geometry: + name = my_spheres + library = egs_spheres + midpoint = 0 0 0 + radii = 1 2 3 + :start media input: + media = air water air + set medium = 1 1 + set medium = 2 2 + :stop media input: + :stop geometry input: +)"}; + return example; + } + + EGS_SPHERES_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } + EGS_SPHERES_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { if (!input) { egsWarning("createGeometry(spheres): null input?\n"); diff --git a/HEN_HOUSE/egs++/geometry/egs_union/egs_union_geometry.cpp b/HEN_HOUSE/egs++/geometry/egs_union/egs_union_geometry.cpp index ed6d7f7d1..39ac380fa 100644 --- a/HEN_HOUSE/egs++/geometry/egs_union/egs_union_geometry.cpp +++ b/HEN_HOUSE/egs++/geometry/egs_union/egs_union_geometry.cpp @@ -26,6 +26,7 @@ # Contributors: Frederic Tessier # Ernesto Mainegra-Hing # Hubert Ho +# Hannah Gallop # ############################################################################### */ @@ -44,6 +45,8 @@ using namespace std; string EGS_UNIONG_LOCAL EGS_UnionGeometry::type = "EGS_UnionGeometry"; +static bool EGS_UNIONG_LOCAL inputSet = false; + void EGS_UnionGeometry::setMedia(EGS_Input *,int,const int *) { egsWarning("EGS_UnionGeometry::setMedia: don't use this method. Use the\n" " setMedia() methods of the geometry objects that make up this geometry\n"); @@ -167,6 +170,38 @@ void EGS_UnionGeometry::printInfo() const { } extern "C" { + static void setInputs() { + inputSet = true; + + setBaseGeometryInputs(false); + + geomBlockInput->getSingleInput("library")->setValues({"EGS_gunion"}); + + // Format: name, isRequired, description, vector string of allowed values + geomBlockInput->addSingleInput("geometries", true, "A list of names of previously defined geometries"); + geomBlockInput->addSingleInput("priorities", false, "A list of integers defining the geometry priorities"); + } + + EGS_UNIONG_EXPORT string getExample(string type) { + string example; + example = { + R"( + # Example of egs_gunion + #:start geometry: + name = my_union + library = egs_union + geometries = my_box my_sphere + :stop geometry: +)"}; + return example; + } + + EGS_UNIONG_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return geomBlockInput; + } EGS_UNIONG_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { if (!input) { @@ -203,8 +238,8 @@ extern "C" { } } else egsWarning("createGeometry(union): the number of priorities (%d)" - " is not the same as the number of geometries (%d) => ignoring\n", - pri.size(),geoms.size()); + " is not the same as the number of geometries (%d) => ignoring\n", + pri.size(),geoms.size()); } EGS_BaseGeometry *result = new EGS_UnionGeometry(geoms,p); result->setName(input); diff --git a/HEN_HOUSE/egs++/shapes/egs_circle/egs_circle.cpp b/HEN_HOUSE/egs++/shapes/egs_circle/egs_circle.cpp index 2bd369d39..cd9ca06f8 100644 --- a/HEN_HOUSE/egs++/shapes/egs_circle/egs_circle.cpp +++ b/HEN_HOUSE/egs++/shapes/egs_circle/egs_circle.cpp @@ -23,7 +23,7 @@ # # Author: Iwan Kawrakow, 2005 # -# Contributors: +# Contributors: Reid Townson # ############################################################################### */ @@ -38,8 +38,41 @@ #include "egs_input.h" #include "egs_functions.h" +static string EGS_CIRCLE_LOCAL typeStr("EGS_Circle"); +static bool EGS_CIRCLE_LOCAL inputSet = false; +static shared_ptr EGS_CIRCLE_LOCAL shapeBlockInput = make_shared("shape"); + extern "C" { + static void setInputs() { + inputSet = true; + shapeBlockInput->addSingleInput("library", true, "The type of shape, loaded by shared library in egs++/dso.", vector(1, typeStr)); + shapeBlockInput->addSingleInput("radius", false, "The radius of the circle."); + shapeBlockInput->addSingleInput("midpoint", false, "The x, y midpoint of the circle, which is in the x-y plane located at z=0. Use an EGS_AffineTransform block to translate or rotate the shape."); + shapeBlockInput->addSingleInput("inner radius", false, "The inner radius, to define a ring. Points will only be sampled within the ring between the 'inner radius' and 'radius'."); + setShapeInputs(shapeBlockInput); + } + + EGS_CIRCLE_EXPORT string getExample() { + string example { + R"( + :start shape: + library = egs_circle + radius = the circle radius + midpoint = Ox, Oy (optional) + inner radius = the inner radius (optional) + :stop shape: +)"}; + return example; + } + + EGS_CIRCLE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return shapeBlockInput; + } + EGS_CIRCLE_EXPORT EGS_BaseShape *createShape(EGS_Input *input, EGS_ObjectFactory *f) { if (!input) { diff --git a/HEN_HOUSE/egs++/shapes/egs_conical_shell/egs_conical_shell.cpp b/HEN_HOUSE/egs++/shapes/egs_conical_shell/egs_conical_shell.cpp index efe53f5a3..32ed1bcc9 100644 --- a/HEN_HOUSE/egs++/shapes/egs_conical_shell/egs_conical_shell.cpp +++ b/HEN_HOUSE/egs++/shapes/egs_conical_shell/egs_conical_shell.cpp @@ -27,6 +27,7 @@ # Contributors: Marc Chamberland # Rowan Thomson # Dave Rogers +# Hannah Gallop # ############################################################################### # @@ -48,6 +49,8 @@ #include #include +static bool EGS_CONICAL_SHELL_LOCAL inputSet = false; +static shared_ptr EGS_CONICAL_SHELL_LOCAL shapeBlockInput = make_shared("shape"); CSSSLayer::CSSSLayer(EGS_Float t, EGS_Float rit, EGS_Float rot, EGS_Float rib, EGS_Float rob, EGS_Float z): thick(t), ri_top(rit), ro_top(rot), ri_bot(rib), ro_bot(rob), zo(z) { @@ -191,6 +194,58 @@ void EGS_ConicalShellStackShape::setLayerSampler() { extern "C" { + static void setInputs() { + inputSet = true; + + shapeBlockInput->addSingleInput("library", true, "The type of shape, loaded by shared library in egs++/dso.", {"EGS_Conical_Shell"}); + shapeBlockInput->addSingleInput("radius", false, "The radius"); + shapeBlockInput->addSingleInput("midpoint", false, "The midpoint of the concical shell."); + + auto blockPtr = shapeBlockInput->addBlockInput("layer"); + blockPtr->addSingleInput("thickness", true, "The thickness of the layer"); + blockPtr->addSingleInput("top radii", false, "1 (outer radius, inner radius assumed to be 0) or 2 (outer and inner radius) inputs, only required for top layer"); + blockPtr->addSingleInput("bottom radii", true, "1 (outer radius, inner radius assumed to be 0) or 2 (outer and inner radius) inputs"); + + setShapeInputs(shapeBlockInput); + } + + EGS_CONICAL_SHELL_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_conical_shell + #:start shape: + library = egs_conical_shell + midpoint = 0 0 -1 + :start layer: + thickness = 0.5 + top radii = 0 1 + bottom radii = 0.5 2 + :stop layer: + :start layer: + thickness = 0.5 + bottom radii = 0.25 1 + :stop layer: + :start layer: + thickness = 0.5 + bottom radii = 0.5 + :stop layer: + :start layer: + thickness = 0.5 + bottom radii = 2 + :stop layer: + :stop shape: +)"}; + return example; + } + + EGS_CONICAL_SHELL_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return shapeBlockInput; + } + EGS_CONICAL_SHELL_EXPORT EGS_BaseShape *createShape(EGS_Input *input, EGS_ObjectFactory *f) { if (!input) { diff --git a/HEN_HOUSE/egs++/shapes/egs_ellipse/egs_ellipse.cpp b/HEN_HOUSE/egs++/shapes/egs_ellipse/egs_ellipse.cpp index b675e2903..ecf7ddb80 100644 --- a/HEN_HOUSE/egs++/shapes/egs_ellipse/egs_ellipse.cpp +++ b/HEN_HOUSE/egs++/shapes/egs_ellipse/egs_ellipse.cpp @@ -23,7 +23,7 @@ # # Author: Iwan Kawrakow, 2005 # -# Contributors: +# Contributors: Hannah Gallop # ############################################################################### */ @@ -38,8 +38,41 @@ #include "egs_input.h" #include "egs_functions.h" +static bool EGS_ELLIPSE_LOCAL inputSet = false; +static shared_ptr EGS_ELLIPSE_LOCAL shapeBlockInput = make_shared("shape"); + extern "C" { + static void setInputs() { + inputSet = true; + + shapeBlockInput->addSingleInput("library", true, "The type of shape, loaded by shared library in egs++/dso.", {"EGS_Ellipse"}); + shapeBlockInput->addSingleInput("halfaxis", true, "The two half axis of the ellipse."); + shapeBlockInput->addSingleInput("midpoint", false, "The midpoint of the ellipse, (x, y)."); + setShapeInputs(shapeBlockInput); + } + + EGS_ELLIPSE_EXPORT string getExample() { + string example; + example = { + R"( + # Example fo egs_ellipse + #:start shape: + library = egs_ellipse + halfway = the two half axis of the ellipse + midpoint = Ox, Oy (optional) + :stop shape: +)"}; + return example; + } + + EGS_ELLIPSE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return shapeBlockInput; + } + EGS_ELLIPSE_EXPORT EGS_BaseShape *createShape(EGS_Input *input, EGS_ObjectFactory *f) { if (!input) { diff --git a/HEN_HOUSE/egs++/shapes/egs_extended_shape/egs_extended_shape.cpp b/HEN_HOUSE/egs++/shapes/egs_extended_shape/egs_extended_shape.cpp index 92400c69e..1c799aa10 100644 --- a/HEN_HOUSE/egs++/shapes/egs_extended_shape/egs_extended_shape.cpp +++ b/HEN_HOUSE/egs++/shapes/egs_extended_shape/egs_extended_shape.cpp @@ -23,7 +23,7 @@ # # Author: Iwan Kawrakow, 2005 # -# Contributors: +# Contributors: Hannah Gallop # ############################################################################### */ @@ -38,8 +38,42 @@ #include "egs_input.h" #include "egs_functions.h" +static bool EGS_EXTENDED_SHAPE_LOCAL inputSet = false; +static shared_ptr EGS_EXTENDED_SHAPE_LOCAL shapeBlockInput = make_shared("shape"); + extern "C" { + static void setInputs() { + inputSet = true; + shapeBlockInput->addSingleInput("library", true, "The type of shape, loaded by shared library in egs++/dso.", {"EGS_Extended_Shape"}); + shapeBlockInput->addSingleInput("extension", true, "Adds delta z to the z-component of the position vector (z1, z2)"); + + auto shapePtr = shapeBlockInput->addBlockInput("shape"); + setShapeInputs(shapePtr); + } + + EGS_EXTENDED_SHAPE_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_extended_shape + #:start shape: + library = egs_extended_shape + :start shape: + definition of the shape to be 'extended' + :stop shape: + extension = z1 z2 +)"}; + return example; + } + + EGS_EXTENDED_SHAPE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return shapeBlockInput; + } + EGS_EXTENDED_SHAPE_EXPORT EGS_BaseShape *createShape(EGS_Input *input, EGS_ObjectFactory *f) { if (!input) { diff --git a/HEN_HOUSE/egs++/shapes/egs_gaussian_shape/egs_gaussian_shape.cpp b/HEN_HOUSE/egs++/shapes/egs_gaussian_shape/egs_gaussian_shape.cpp index 810b89a34..e86dee9de 100644 --- a/HEN_HOUSE/egs++/shapes/egs_gaussian_shape/egs_gaussian_shape.cpp +++ b/HEN_HOUSE/egs++/shapes/egs_gaussian_shape/egs_gaussian_shape.cpp @@ -23,7 +23,7 @@ # # Author: Iwan Kawrakow, 2005 # -# Contributors: +# Contributors: Hannah Gallop # ############################################################################### */ @@ -38,8 +38,43 @@ #include "egs_input.h" #include "egs_functions.h" +static bool EGS_GAUSSIAN_SHAPE_LOCAL inputSet = false; +static shared_ptr EGS_GAUSSIAN_SHAPE_LOCAL shapeBlockInput = make_shared("shape"); + extern "C" { + static void setInputs() { + inputSet = true; + + shapeBlockInput->addSingleInput("library", true, "The type of shape, loaded by shared library in egs++/dso.", {"EGS_Gaussian_Shape"}); + shapeBlockInput->addSingleInput("sigma", true, "1 or 2 or 3 inputs"); + + auto shapePtr = shapeBlockInput->addBlockInput("shape"); + setShapeInputs(shapePtr); + } + + EGS_GAUSSIAN_SHAPE_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_gaussiam_shape + #:start shape: + library = egs_gaussian_shape + :start shape: + definition of the shape to be smeared + :stop shape: + sigma = 1, 2 or 3 inputs +)"}; + return example; + } + + EGS_GAUSSIAN_SHAPE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return shapeBlockInput; + } + EGS_GAUSSIAN_SHAPE_EXPORT EGS_BaseShape *createShape(EGS_Input *input, EGS_ObjectFactory *f) { if (!input) { diff --git a/HEN_HOUSE/egs++/shapes/egs_line_shape/egs_line_shape.cpp b/HEN_HOUSE/egs++/shapes/egs_line_shape/egs_line_shape.cpp index 47349105a..f789ee0c6 100644 --- a/HEN_HOUSE/egs++/shapes/egs_line_shape/egs_line_shape.cpp +++ b/HEN_HOUSE/egs++/shapes/egs_line_shape/egs_line_shape.cpp @@ -23,7 +23,7 @@ # # Author: Iwan Kawrakow, 2005 # -# Contributors: +# Contributors: Hannah Gallop # ############################################################################### */ @@ -38,6 +38,9 @@ #include "egs_input.h" #include "egs_functions.h" +static bool EGS_LINE_SHAPE_LOCAL inputSet = false; +static shared_ptr EGS_LINE_SHAPE_LOCAL shapeBlockInput = make_shared("shape"); + EGS_LineShape::EGS_LineShape(const vector &points, const string &Name, EGS_ObjectFactory *f) : EGS_BaseShape(Name,f) { int np = points.size(); @@ -63,6 +66,34 @@ EGS_LineShape::EGS_LineShape(const vector &points, extern "C" { + static void setInputs() { + inputSet = true; + + shapeBlockInput->addSingleInput("library", true, "The type of shape, loaded by shared library in egs++/dso.", {"EGS_Line_Shape"}); + shapeBlockInput->addSingleInput("points", true, "A list of 2D positions, at least 2 required"); + setShapeInputs(shapeBlockInput); + } + + EGS_LINE_SHAPE_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_line_shape + :start shape: + library = egs_line_shape + points = list of 2D positions + :stop shape: +)"}; + return example; + } + + EGS_LINE_SHAPE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return shapeBlockInput; + } + EGS_LINE_SHAPE_EXPORT EGS_BaseShape *createShape(EGS_Input *input, EGS_ObjectFactory *f) { if (!input) { diff --git a/HEN_HOUSE/egs++/shapes/egs_polygon_shape/egs_polygon_shape.cpp b/HEN_HOUSE/egs++/shapes/egs_polygon_shape/egs_polygon_shape.cpp index 45ba79e9b..cc81cf839 100644 --- a/HEN_HOUSE/egs++/shapes/egs_polygon_shape/egs_polygon_shape.cpp +++ b/HEN_HOUSE/egs++/shapes/egs_polygon_shape/egs_polygon_shape.cpp @@ -23,7 +23,7 @@ # # Author: Iwan Kawrakow, 2005 # -# Contributors: +# Contributors: Hannah Gallop # ############################################################################### */ @@ -40,6 +40,9 @@ #include "egs_functions.h" #include "egs_math.h" +static bool EGS_POLYGON_SHAPE_LOCAL inputSet = false; +static shared_ptr EGS_POLYGON_SHAPE_LOCAL shapeBlockInput = make_shared("shape"); + EGS_TriangleShape::EGS_TriangleShape(const vector &points, const string &Name, EGS_ObjectFactory *f) : EGS_SurfaceShape(Name,f) { xo = points[0]; @@ -140,6 +143,33 @@ EGS_PolygonShape::EGS_PolygonShape(const vector &points, extern "C" { + static void setInputs() { + inputSet = true; + shapeBlockInput->addSingleInput("library", true, "The type of shape, loaded by shared library in egs++/dso.", {"EGS_Polygon_Shape"}); + shapeBlockInput->addSingleInput("points", true, "A list of at least 3 2D points (at least 6 floating numbers)"); + setShapeInputs(shapeBlockInput); + } + + EGS_POLYGON_SHAPE_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_polygon_shape + #:start shape: + library = egs_polygon_shape + points = list of 2D points + :stop shape: +)"}; + return example; + } + + EGS_POLYGON_SHAPE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return shapeBlockInput; + } + EGS_POLYGON_SHAPE_EXPORT EGS_BaseShape *createShape(EGS_Input *input, EGS_ObjectFactory *f) { if (!input) { diff --git a/HEN_HOUSE/egs++/shapes/egs_rectangle/egs_rectangle.cpp b/HEN_HOUSE/egs++/shapes/egs_rectangle/egs_rectangle.cpp index bac351ce4..633f7a7f5 100644 --- a/HEN_HOUSE/egs++/shapes/egs_rectangle/egs_rectangle.cpp +++ b/HEN_HOUSE/egs++/shapes/egs_rectangle/egs_rectangle.cpp @@ -23,7 +23,7 @@ # # Author: Iwan Kawrakow, 2005 # -# Contributors: +# Contributors: Hannah Gallop # ############################################################################### */ @@ -38,6 +38,9 @@ #include "egs_input.h" #include "egs_functions.h" +static bool EGS_RECTANGLE_LOCAL inputSet = false; +static shared_ptr EGS_RECTANGLE_LOCAL shapeBlockInput = make_shared("shape"); + EGS_RectangularRing::EGS_RectangularRing(EGS_Float xmin, EGS_Float xmax, EGS_Float ymin, EGS_Float ymax, EGS_Float xmin_i, EGS_Float xmax_i, EGS_Float ymin_i, EGS_Float ymax_i, const string &Name, @@ -97,6 +100,33 @@ EGS_RectangularRing::~EGS_RectangularRing() { extern "C" { + static void setInputs() { + inputSet = true; + shapeBlockInput->addSingleInput("library", true, "The type of shape, loaded by shared library in egs++/dso.", {"EGS_Rectangle"}); + shapeBlockInput->addSingleInput("rectangle", true, "x1 y1 x2 y2"); + shapeBlockInput->addSingleInput("inner rectangle", false, "xp1 yp1 xp2 yp2"); + setShapeInputs(shapeBlockInput); + } + + EGS_RECTANGLE_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_rectangle + #:start shape: + library = egs_rectangle + rectangle = -.1 -.1 .1 .1 +)"}; + return example; + } + + EGS_RECTANGLE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return shapeBlockInput; + } + EGS_RECTANGLE_EXPORT EGS_BaseShape *createShape(EGS_Input *input, EGS_ObjectFactory *f) { if (!input) { diff --git a/HEN_HOUSE/egs++/shapes/egs_shape_collection/egs_shape_collection.cpp b/HEN_HOUSE/egs++/shapes/egs_shape_collection/egs_shape_collection.cpp index a029f9403..0e7f72902 100644 --- a/HEN_HOUSE/egs++/shapes/egs_shape_collection/egs_shape_collection.cpp +++ b/HEN_HOUSE/egs++/shapes/egs_shape_collection/egs_shape_collection.cpp @@ -24,6 +24,7 @@ # Author: Iwan Kawrakow, 2005 # # Contributors: Marc Chamberland +# Hannah Gallop # ############################################################################### */ @@ -38,6 +39,9 @@ #include "egs_input.h" #include "egs_functions.h" +static bool EGS_SHAPE_COLLECTION_LOCAL inputSet = false; +static shared_ptr EGS_SHAPE_COLLECTION_LOCAL shapeBlockInput = make_shared("shape"); + EGS_ShapeCollection::EGS_ShapeCollection(const vector &Shapes, const vector &Probs, const string &Name, EGS_ObjectFactory *f) : EGS_BaseShape(Name,f), nshape(0) { @@ -60,6 +64,45 @@ EGS_ShapeCollection::EGS_ShapeCollection(const vector &Shapes, extern "C" { + static void setInputs() { + inputSet = true; + shapeBlockInput->addSingleInput("library", true, "The type of shape, loaded by shared library in egs++/dso.", {"EGS_Shape_Collection"}); + shapeBlockInput->addSingleInput("probabilities", true, "p1 p2 ... pn"); + + auto shapePtr = shapeBlockInput->addBlockInput("shape"); + setShapeInputs(shapePtr); + } + + EGS_SHAPE_COLLECTION_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_shape_collection + #:start shape: + library = egs_shape_collection + :start shape: + definition of the first shape in the collection: + :stop shape: + :start shape: + definition of the second shape in the collection + :stop shape: + ... + :start shape: + definition of the last shape in the collection + :stop shape: + probablities = p1 p2 ... pn + :stop shape: +)"}; + return example; + } + + EGS_SHAPE_COLLECTION_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return shapeBlockInput; + } + EGS_SHAPE_COLLECTION_EXPORT EGS_BaseShape *createShape(EGS_Input *input, EGS_ObjectFactory *f) { if (!input) { @@ -104,7 +147,7 @@ extern "C" { } if (shapes.size() != probs.size()) { egsWarning("createShape(shape collection): the number of shapes (%d)" - " is not the same as the number of input probabilities (%d)\n"); + " is not the same as the number of input probabilities (%d)\n"); ok = false; } for (unsigned int i=0; i EGS_SPHERICAL_SHELL_LOCAL shapeBlockInput = make_shared("shape"); + EGS_SphericalShellShape::EGS_SphericalShellShape(EGS_Float ri, EGS_Float ro, int hemisph, EGS_Float halfangle, const EGS_Vector &Xo, const string &Name,EGS_ObjectFactory *f) : EGS_BaseShape(Name, f), r_inner(ri), r_outer(ro), hemisphere(hemisph), half_angle(halfangle), xo(Xo) { @@ -128,6 +132,42 @@ EGS_Float EGS_SphericalShellShape::area() const { extern "C" { + static void setInputs() { + inputSet = true; + + shapeBlockInput->addSingleInput("library", true, "The type of shape, loaded by shared library in egs++/dso.", {"EGS_Spherical_Shape"}); + shapeBlockInput->addSingleInput("midpoint", true, "The midpoint of the shape, (x y z)"); + shapeBlockInput->addSingleInput("inner radius", true, "The inner radius"); + shapeBlockInput->addSingleInput("outer radius", true, "The outer radius"); + shapeBlockInput->addSingleInput("hemisphere", false, "Hemisphere"); + shapeBlockInput->addSingleInput("hemisphere", false, "The half angle, in degrees"); + setShapeInputs(shapeBlockInput); + } + + EGS_SPHERICAL_SHELL_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_spherical_shell + #:start shape: + library = egs_spherical_shell + midpoint = 0 0 0 + inner radius = 0.5 + outer radius = 1 + hemisphere = 1 + half angle = 35 + :stop shape: +)"}; + return example; + } + + EGS_SPHERICAL_SHELL_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return shapeBlockInput; + } + EGS_SPHERICAL_SHELL_EXPORT EGS_BaseShape *createShape(EGS_Input *input, EGS_ObjectFactory *f) { if (!input) { diff --git a/HEN_HOUSE/egs++/shapes/egs_voxelized_shape/egs_voxelized_shape.cpp b/HEN_HOUSE/egs++/shapes/egs_voxelized_shape/egs_voxelized_shape.cpp index fe091b736..3da274034 100644 --- a/HEN_HOUSE/egs++/shapes/egs_voxelized_shape/egs_voxelized_shape.cpp +++ b/HEN_HOUSE/egs++/shapes/egs_voxelized_shape/egs_voxelized_shape.cpp @@ -24,6 +24,7 @@ # Author: Iwan Kawrakow, 2009 # # Contributors: Frederic Tessier +# Hannah Gallop # ############################################################################### */ @@ -41,6 +42,9 @@ #include using namespace std; +static bool EGS_VOXELIZED_SHAPE_LOCAL inputSet = false; +static shared_ptr EGS_VOXELIZED_SHAPE_LOCAL shapeBlockInput = make_shared("shape"); + void EGS_VoxelizedShape::EGS_VoxelizedShapeFormat0(const char *fname, const string &Name,EGS_ObjectFactory *f) { prob=0; @@ -368,34 +372,62 @@ EGS_VoxelizedShape::~EGS_VoxelizedShape() { extern "C" { + static void setInputs() { + inputSet = true; + + shapeBlockInput->addSingleInput("library", true, "The type of shape, loaded by shared library in egs++/dso.", {"EGS_Voxelized_Shape"}); + shapeBlockInput->addSingleInput("file name", true, "The name of a file that is in binary"); + setShapeInputs(shapeBlockInput); + } + + EGS_VOXELIZED_SHAPE_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_voxelized_shape + #:start shape: + library = egs_voxelized_shape + file name = some_file + :stop shape: +)"}; + return example; + } + + EGS_VOXELIZED_SHAPE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return shapeBlockInput; + } + EGS_VOXELIZED_SHAPE_EXPORT EGS_BaseShape *createShape(EGS_Input *input, EGS_ObjectFactory *f) { static const char *func = "createShape(voxelized shape)"; - if (!input) { - egsWarning("%s: null input?\n",func); - return 0; - } - string fname; - int err = input->getInput("file name",fname); - int file_format; - int err2 = input->getInput("file format",file_format); - if (err) { - egsWarning("%s: missing 'file name' input\n",func); - return 0; - } - if (err2) { - egsInformation("%s: 'file format' input missing. Using default 'binary'" - "file format \n",func); - file_format = 0; - } - EGS_VoxelizedShape *shape = new EGS_VoxelizedShape(file_format, fname.c_str()); - if (!shape->isValid()) { - delete shape; - return 0; + if (!input) { + egsWarning("%s: null input?\n",func); + return 0; + } + string fname; + int err = input->getInput("file name",fname); + int file_format; + int err2 = input->getInput("file format",file_format); + if (err) { + egsWarning("%s: missing 'file name' input\n",func); + return 0; + } + if (err2) { + egsInformation("%s: 'file format' input missing. Using default 'binary'" + "file format \n",func); + file_format = 0; + } + EGS_VoxelizedShape *shape = new EGS_VoxelizedShape(file_format, fname.c_str()); + if (!shape->isValid()) { + delete shape; + return 0; + } + shape->setName(input); + shape->setTransformation(input); + return shape; } - shape->setName(input); - shape->setTransformation(input); - return shape; - } -} + } diff --git a/HEN_HOUSE/egs++/sources/egs_angular_spread/egs_angular_spread_source.cpp b/HEN_HOUSE/egs++/sources/egs_angular_spread/egs_angular_spread_source.cpp index 455ceae83..d57481fcb 100644 --- a/HEN_HOUSE/egs++/sources/egs_angular_spread/egs_angular_spread_source.cpp +++ b/HEN_HOUSE/egs++/sources/egs_angular_spread/egs_angular_spread_source.cpp @@ -23,7 +23,7 @@ # # Author: Iwan Kawrakow, 2009 # -# Contributors: +# Contributors: Hannah Gallop # ############################################################################### */ @@ -38,6 +38,8 @@ #include "egs_input.h" #include "egs_math.h" +static bool EGS_ANGULAR_SPREAD_SOURCE_LOCAL inputSet = false; + EGS_AngularSpreadSource::EGS_AngularSpreadSource(EGS_Input *input, EGS_ObjectFactory *f) : EGS_BaseSource(input,f), source(0), sigma(0) { EGS_Input *isource = input->takeInputItem("source",false); @@ -81,6 +83,41 @@ void EGS_AngularSpreadSource::setUp() { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseSourceInputs(false, false); + + srcBlockInput->getSingleInput("library")->setValues({"EGS_Angular_Spread_Source"}); + + // Format: name, isRequired, description, vector string of allowed values + srcBlockInput->addSingleInput("source name", true, "The name of a previously defined source."); + srcBlockInput->addSingleInput("sigma", false, "Angular spread in degrees."); + } + + EGS_ANGULAR_SPREAD_SOURCE_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_angular_spread_source + #:start source: + library = egs_angular_spread_source + name = my_source + sigma = 10 + source name = my_parallel_source + #create source called my_parallel_source + :stop source: +)"}; + return example; + } + + EGS_ANGULAR_SPREAD_SOURCE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return srcBlockInput; + } + EGS_ANGULAR_SPREAD_SOURCE_EXPORT EGS_BaseSource *createSource(EGS_Input *input, EGS_ObjectFactory *f) { return diff --git a/HEN_HOUSE/egs++/sources/egs_beam_source/egs_beam_source.cpp b/HEN_HOUSE/egs++/sources/egs_beam_source/egs_beam_source.cpp index 813489d2e..265091b44 100644 --- a/HEN_HOUSE/egs++/sources/egs_beam_source/egs_beam_source.cpp +++ b/HEN_HOUSE/egs++/sources/egs_beam_source/egs_beam_source.cpp @@ -27,6 +27,7 @@ # Frederic Tessier # Reid Townson # Ernesto Mainegra-Hing +# Hannah Gallop # ############################################################################### */ @@ -51,6 +52,8 @@ #define F77_NAME(fname,FNAME) STRINGIFY(F77_OBJ(fname,FNAME)) #define F77_NAME_(fname,FNAME) STRINGIFY(F77_OBJ_(fname,FNAME)) +static bool EGS_BEAM_SOURCE_LOCAL inputSet = false; + EGS_BeamSource::EGS_BeamSource(EGS_Input *input, EGS_ObjectFactory *f) : EGS_BaseSource(input,f) { n_reuse_photon = 0; @@ -338,6 +341,45 @@ EGS_BeamSource::~EGS_BeamSource() { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseSourceInputs(false, false); + + srcBlockInput->getSingleInput("library")->setValues({"EGS_Beam_Source"}); + + // Format: name, isRequired, description, vector string of allowed values + srcBlockInput->addSingleInput("beam code", true, "The name of the BEAMnrc user code"); + srcBlockInput->addSingleInput("pegs file", true, "The name of the PEGS file to be used in the BEAMnrc simulation"); + srcBlockInput->addSingleInput("input file", true, "The name of the input file specifying the BEAMnrc simulation"); + srcBlockInput->addSingleInput("cutout", false, "Cutout of a rectangle defined by x1, y1, x2, y2"); + srcBlockInput->addSingleInput("particle type", false, "The type of particle.", {"all", "electrons", "photons", "positrons", "charged"}); + srcBlockInput->addSingleInput("weight window", true, "wmin wmax"); + } + + EGS_BEAM_SOURCE_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_beam_source + #:start source: + library = egs_beam_source + name = my_source + beam code = BEAM_EX10MeVe + pegs file = 521icru + particle type = all + :stop source: +)"}; + return example; + } + + EGS_BEAM_SOURCE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return srcBlockInput; + } + EGS_BEAM_SOURCE_EXPORT EGS_BaseSource *createSource(EGS_Input *input, EGS_ObjectFactory *f) { return diff --git a/HEN_HOUSE/egs++/sources/egs_collimated_source/egs_collimated_source.cpp b/HEN_HOUSE/egs++/sources/egs_collimated_source/egs_collimated_source.cpp index e4c7e1e1d..f5eca51d1 100644 --- a/HEN_HOUSE/egs++/sources/egs_collimated_source/egs_collimated_source.cpp +++ b/HEN_HOUSE/egs++/sources/egs_collimated_source/egs_collimated_source.cpp @@ -24,6 +24,7 @@ # Author: Iwan Kawrakow, 2005 # # Contributors: Hubert Ho +# Hannah Gallop # ############################################################################### */ @@ -37,6 +38,8 @@ #include "egs_collimated_source.h" #include "egs_input.h" +static bool EGS_COLLIMATED_SOURCE_LOCAL inputSet = false; + EGS_CollimatedSource::EGS_CollimatedSource(EGS_Input *input, EGS_ObjectFactory *f) : EGS_BaseSimpleSource(input,f), source_shape(0), target_shape(0), ctry(0), dist(1) { @@ -120,6 +123,57 @@ void EGS_CollimatedSource::setUp() { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseSourceInputs(); + + srcBlockInput->getSingleInput("library")->setValues({"EGS_Collimated_Source"}); + + // Format: name, isRequired, description, vector string of allowed values + auto source_shapePtr = srcBlockInput->addBlockInput("source shape"); + auto target_shapePtr = srcBlockInput->addBlockInput("target shape"); + + setShapeInputs(source_shapePtr); + setShapeInputs(target_shapePtr); + + srcBlockInput->addSingleInput("distance", false, "source-target minimum distance"); + } + + EGS_COLLIMATED_SOURCE_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_collimated_source + #:start source: + library = egs_collimated_source + name = my_source + :start source shape: + type = point + position = 0 0 5 + :stop source shape: + :start target shape: + library = egs_rectangle + rectangle = -1 -1 1 1 + :stop target shape: + distance = 5 + charge = -1 + :start spectrum: + type = monoenergetic + energy = 20 + :stop spectrum: + :stop source: +)"}; + return example; + } + + EGS_COLLIMATED_SOURCE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return srcBlockInput; + } + EGS_COLLIMATED_SOURCE_EXPORT EGS_BaseSource *createSource(EGS_Input *input, EGS_ObjectFactory *f) { return diff --git a/HEN_HOUSE/egs++/sources/egs_dynamic_source/egs_dynamic_source.cpp b/HEN_HOUSE/egs++/sources/egs_dynamic_source/egs_dynamic_source.cpp index 114e44a1f..15b849ebc 100644 --- a/HEN_HOUSE/egs++/sources/egs_dynamic_source/egs_dynamic_source.cpp +++ b/HEN_HOUSE/egs++/sources/egs_dynamic_source/egs_dynamic_source.cpp @@ -23,7 +23,7 @@ # # Author: Blake Walters, 2017 # -# Contributors: +# Contributors: Hannah Gallop # ############################################################################### */ @@ -37,6 +37,8 @@ #include "egs_dynamic_source.h" #include "egs_input.h" +static bool EGS_DYNAMIC_SOURCE_LOCAL inputSet = false; + EGS_DynamicSource::EGS_DynamicSource(EGS_Input *input, EGS_ObjectFactory *f) : EGS_BaseSource(input,f), source(0), valid(true) { EGS_Input *isource = input->takeInputItem("source",false); @@ -180,6 +182,49 @@ int EGS_DynamicSource::getCoord(EGS_Float rand, EGS_ControlPoint &ipt) { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseSourceInputs(false, false); + + srcBlockInput->getSingleInput("library")->setValues({"EGS_Dynamic_Source"}); + + // Format:name, isRequired, description, vector string of allowed + srcBlockInput->addSingleInput("source name", true, "The name of a previously defined source"); + srcBlockInput->addSingleInput("synchronize motion", false, "yes or no", {"yes", "no"}); + + auto motionPtr = srcBlockInput->addBlockInput("motion"); + motionPtr->addSingleInput("control point 1", false, "xiso(1) yiso(1) ziso(1) dsource(1) theta(1) phi(1) phicol(1) mu(1)"); + } + + EGS_DYNAMIC_SOURCE_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_dynamic_source + #:start source: + library = egs_dynamic_source + name = my_source + source name = my_parallel_source + #create a soource called my_parallel_source + :start motion: + control point 1 = 0 0 0 100 0 0 0 0 + control point 2 = 0 0 0 100 360 0 0 0.5 + control point 3 = 0 0 0 100 90 0 0 0.5 + control point 4 = 0 0 0 100 90 360 0 1.0 + :stop motion: + :stop source: +)"}; + return example; + } + + EGS_DYNAMIC_SOURCE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return srcBlockInput; + } + EGS_DYNAMIC_SOURCE_EXPORT EGS_BaseSource *createSource(EGS_Input *input, EGS_ObjectFactory *f) { return diff --git a/HEN_HOUSE/egs++/sources/egs_fano_source/egs_fano_source.cpp b/HEN_HOUSE/egs++/sources/egs_fano_source/egs_fano_source.cpp index db4475f62..2db0c048d 100644 --- a/HEN_HOUSE/egs++/sources/egs_fano_source/egs_fano_source.cpp +++ b/HEN_HOUSE/egs++/sources/egs_fano_source/egs_fano_source.cpp @@ -24,7 +24,7 @@ # Authors: Ernesto Mainegra-Hing, 2016 # Hugo Bouchard, 2016 # -# Contributors: +# Contributors: Hannah Gallop # ############################################################################### */ @@ -41,6 +41,8 @@ #include "egs_math.h" #include +static bool EGS_FANO_SOURCE_LOCAL inputSet = false; + EGS_FanoSource::EGS_FanoSource(EGS_Input *input, EGS_ObjectFactory *f) : EGS_BaseSimpleSource(input,f), shape(0), geom(0), @@ -144,6 +146,55 @@ void EGS_FanoSource::setUp() { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseSourceInputs(); + + srcBlockInput->getSingleInput("library")->setValues({"EGS_Fano_Source"}); + + // Format: name, isRequired, description, vector string of allowed values + auto shapePtr = srcBlockInput->addBlockInput("shape"); + setShapeInputs(shapePtr); + + srcBlockInput->addSingleInput("geometry", true, "The name of a predefined geometry"); + srcBlockInput->addSingleInput("max mass density", true, "The maximum mass density"); + } + + EGS_FANO_SOURCE_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_fano_source + #:start source: + library = egs_fano_source + name = my_fano_source + :start shape: + type = box + box size = 1 2 3 + :start media input: + media = water + :stop media input: + :stop shape: + :start spectrum: + type = monoenergetic + energy = 1 + :stop spectrum: + charge = 0 + max mass density = 1.2 + geometry = some_name + #create a geometry called some_name +)"}; + return example; + } + + EGS_FANO_SOURCE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return srcBlockInput; + } + EGS_FANO_SOURCE_EXPORT EGS_BaseSource *createSource(EGS_Input *input, EGS_ObjectFactory *f) { return createSourceTemplate(input, f, "fano source"); diff --git a/HEN_HOUSE/egs++/sources/egs_isotropic_source/egs_isotropic_source.cpp b/HEN_HOUSE/egs++/sources/egs_isotropic_source/egs_isotropic_source.cpp index 97cd94cbd..05f69ab57 100644 --- a/HEN_HOUSE/egs++/sources/egs_isotropic_source/egs_isotropic_source.cpp +++ b/HEN_HOUSE/egs++/sources/egs_isotropic_source/egs_isotropic_source.cpp @@ -25,6 +25,7 @@ # # Contributors: Long Zhang # Hubert Ho +# Reid Townson # ############################################################################### */ @@ -39,6 +40,9 @@ #include "egs_input.h" #include "egs_math.h" +static string EGS_ISOTROPIC_SOURCE_LOCAL typeStr("EGS_Isotropic_Source"); +static bool EGS_ISOTROPIC_SOURCE_LOCAL inputSet = false; + EGS_IsotropicSource::EGS_IsotropicSource(EGS_Input *input, EGS_ObjectFactory *f) : EGS_BaseSimpleSource(input,f), shape(0), geom(0), regions(0), min_theta(0), max_theta(M_PI), min_phi(0), max_phi(2*M_PI), @@ -149,6 +153,67 @@ void EGS_IsotropicSource::setUp() { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseSourceInputs(); + + srcBlockInput->getSingleInput("library")->setValues(vector(1, typeStr)); + + auto shapePtr = srcBlockInput->addBlockInput("shape"); + /* Commented out because I don't think this input is used + Also at this point dependency of a block on an input hasn't been implemented + auto shapeNamePtr = srcBlockInput->addSingleInput("shape name", false, "..."); + shapeNamePtr->addDependency(shapePtr, true); + shapePtr->addDependency(shapeNamePtr, true);*/ + + setShapeInputs(shapePtr); + + auto geomPtr = srcBlockInput->addSingleInput("geometry", false, "The name of a geometry, used for complex source shapes. Only particles generated inside the geometry or some of its regions are used."); + auto regPtr = srcBlockInput->addSingleInput("region selection", false, "Include or exclude regions from the named geometry, to define a volume for source particle generation.", {"IncludeAll", "ExcludeAll","IncludeSelected","ExcludeSelected"}); + regPtr->addDependency(geomPtr); + auto selPtr = srcBlockInput->addSingleInput("selected regions", false, "If region selection = IncludeSelected or ExcludeSelected, then this is a list of the regions in the named geometry to include or exclude."); + selPtr->addDependency(geomPtr); + selPtr->addDependency(regPtr); + srcBlockInput->addSingleInput("min theta", false, "The minimum theta angle in degrees, to restrict the directions of source particles. Defaults to 0."); + srcBlockInput->addSingleInput("max theta", false, "The maximum theta angle in degrees, to restrict the directions of source particles. Defaults to 180."); + srcBlockInput->addSingleInput("min phi", false, "The minimum phi angle in degrees, to restrict the directions of source particles. Defaults to 0."); + srcBlockInput->addSingleInput("max phi", false, "The maximum phi angle in degrees, to restrict the directions of source particles. Defaults to 360."); + } + + EGS_ISOTROPIC_SOURCE_EXPORT string getExample() { + string example { + R"( + :start source: + name = my_source + library = egs_isotropic_source + charge = 0 + geometry = my_envelope + region selection = IncludeSelected + selected regions = 1 2 + :start shape: + type = box + box size = 1 2 3 + :start media input: + media = H2O521ICRU + :stop media input: + :stop shape: + :start spectrum: + type = monoenergetic + energy = 1 + :stop spectrum: + :stop source: +)"}; + return example; + } + + EGS_ISOTROPIC_SOURCE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return srcBlockInput; + } + EGS_ISOTROPIC_SOURCE_EXPORT EGS_BaseSource *createSource(EGS_Input *input, EGS_ObjectFactory *f) { return diff --git a/HEN_HOUSE/egs++/sources/egs_parallel_beam/egs_parallel_beam.cpp b/HEN_HOUSE/egs++/sources/egs_parallel_beam/egs_parallel_beam.cpp index 09009c9bf..4207b3e1c 100644 --- a/HEN_HOUSE/egs++/sources/egs_parallel_beam/egs_parallel_beam.cpp +++ b/HEN_HOUSE/egs++/sources/egs_parallel_beam/egs_parallel_beam.cpp @@ -23,7 +23,7 @@ # # Author: Iwan Kawrakow, 2005 # -# Contributors: +# Contributors: Hannah Gallop # ############################################################################### */ @@ -37,6 +37,8 @@ #include "egs_parallel_beam.h" #include "egs_input.h" +static bool EGS_PARALLEL_BEAM_LOCAL inputSet = false; + EGS_ParallelBeam::EGS_ParallelBeam(EGS_Input *input, EGS_ObjectFactory *f) : EGS_BaseSimpleSource(input,f), shape(0), uo(0,0,1) { vector dir; @@ -109,6 +111,54 @@ void EGS_ParallelBeam::setUp() { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseSourceInputs(); + + srcBlockInput->getSingleInput("library")->setValues({"EGS_Parallel_Beam"}); + + // Format: name, isRequired, description, vector string of allowed values + auto shapePtr = srcBlockInput->addBlockInput("shape"); + + setShapeInputs(shapePtr); + + srcBlockInput->addSingleInput("direction", true, "Direction of the beam (x, y, z)"); + } + + EGS_PARALLEL_BEAM_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_parallel_beam + #:start source: + library = egs_parallel_beam + name = my_source + :start shape: + type = cylinder + radius = 1 + height = 2 + axis = 0 0 1 + midpoint = 0 + :stop shape: + direction = 0 0 1 + charge = 0 + :start spectrum: + type = monoenergetic + energy = 6 + :stop spectrum: + :stop source: +)"}; + return example; + } + + EGS_PARALLEL_BEAM_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return srcBlockInput; + } + EGS_PARALLEL_BEAM_EXPORT EGS_BaseSource *createSource(EGS_Input *input, EGS_ObjectFactory *f) { return createSourceTemplate(input,f,"parallel beam"); diff --git a/HEN_HOUSE/egs++/sources/egs_phsp_source/egs_phsp_source.cpp b/HEN_HOUSE/egs++/sources/egs_phsp_source/egs_phsp_source.cpp index 26f9904d0..572290dd7 100644 --- a/HEN_HOUSE/egs++/sources/egs_phsp_source/egs_phsp_source.cpp +++ b/HEN_HOUSE/egs++/sources/egs_phsp_source/egs_phsp_source.cpp @@ -26,6 +26,7 @@ # Contributors: Ernesto Mainegra-Hing # Frederic Tessier # Reid Townson +# Hannah Gallop # ############################################################################### */ @@ -41,6 +42,8 @@ #include "egs_functions.h" #include "egs_application.h" +static bool EGS_PHSP_SOURCE_LOCAL inputSet = false; + EGS_PhspSource::EGS_PhspSource(const string &phsp_file, const string &Name, EGS_ObjectFactory *f) : EGS_BaseSource(Name,f) { init(); @@ -503,6 +506,47 @@ void EGS_PhspSource::setFilter(int type, int nbit1, int nbit2, const int *bits) extern "C" { + static void setInputs() { + inputSet = true; + + setBaseSourceInputs(false, false); + + srcBlockInput->getSingleInput("library")->setValues({"EGS_Phsp_Source"}); + + // Format: name, isRequired, description, vector string of allowed values + srcBlockInput->addSingleInput("phase space file", true, "The name of the phase space file."); + srcBlockInput->addSingleInput("particle type", true, "The type of particle", {"all", "charged", "electrons", "positrons", "photons"}); + srcBlockInput->addSingleInput("cutout", false, "A rectangular cutout defined by x1, x2, y1, y2"); + srcBlockInput->addSingleInput("weight window", false, "wmin, wmax, the min and max particle weights to use. If the particle is not in this range, it is rejected."); + srcBlockInput->addSingleInput("recyle photons", false, "The number of time to recycle each photon"); + srcBlockInput->addSingleInput("recycle electrons", false, "The number of times to recycle each electron"); + } + + EGS_PHSP_SOURCE_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_phsp_soure + #:start source: + name = my_source + library = egs_phsp_source + phase space file = ../BEAM_EX16MVp/EX16MVp.egsphsp1 + particle type = all + cutout = -1 1 -2 2 + recycle photons = 10 + recycle electrons = 10 + :stop source: +)"}; + return example; + } + + EGS_PHSP_SOURCE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return srcBlockInput; + } + EGS_PHSP_SOURCE_EXPORT EGS_BaseSource *createSource(EGS_Input *input, EGS_ObjectFactory *f) { return diff --git a/HEN_HOUSE/egs++/sources/egs_point_source/egs_point_source.cpp b/HEN_HOUSE/egs++/sources/egs_point_source/egs_point_source.cpp index d99501c6b..a9d2aca7f 100644 --- a/HEN_HOUSE/egs++/sources/egs_point_source/egs_point_source.cpp +++ b/HEN_HOUSE/egs++/sources/egs_point_source/egs_point_source.cpp @@ -23,7 +23,7 @@ # # Author: Iwan Kawrakow, 2005 # -# Contributors: +# Contributors: Hannah Gallop # ############################################################################### */ @@ -37,6 +37,8 @@ #include "egs_point_source.h" #include "egs_input.h" +static bool EGS_POINT_SOURCE_LOCAL inputSet = false; + EGS_PointSource::EGS_PointSource(EGS_Input *input, EGS_ObjectFactory *f) : EGS_BaseSimpleSource(input,f), xo(), valid(true) { vector pos; @@ -77,6 +79,43 @@ void EGS_PointSource::setUp() { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseSourceInputs(); + + srcBlockInput->getSingleInput("library")->setValues({"EGS_Point_Source"}); + + // Format: name, isRequired, description, vector string of allowed values + srcBlockInput->addSingleInput("position", true, "The position of the point source, (x, y, z)"); + } + + EGS_POINT_SOURCE_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_point_source + #:start source: + library = egs_point_source + name = my_source + position = 0 0 0 + :start spectrum: + type = monoenergetic + energy = 1 + :stop spectrum: + charge = 0 + :stop source: +)"}; + return example; + } + + EGS_POINT_SOURCE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return srcBlockInput; + } + EGS_POINT_SOURCE_EXPORT EGS_BaseSource *createSource(EGS_Input *input, EGS_ObjectFactory *f) { return createSourceTemplate(input,f,"point source"); diff --git a/HEN_HOUSE/egs++/sources/egs_radionuclide_source/egs_radionuclide_source.cpp b/HEN_HOUSE/egs++/sources/egs_radionuclide_source/egs_radionuclide_source.cpp index b56c0a738..865f9d979 100644 --- a/HEN_HOUSE/egs++/sources/egs_radionuclide_source/egs_radionuclide_source.cpp +++ b/HEN_HOUSE/egs++/sources/egs_radionuclide_source/egs_radionuclide_source.cpp @@ -24,6 +24,7 @@ # Author: Reid Townson, 2016 # # Contributors: Martin Martinov +# Hannah Gallop # ############################################################################### */ @@ -39,6 +40,8 @@ #include "egs_math.h" #include "egs_application.h" +static bool EGS_RADIONUCLIDE_SOURCE_LOCAL inputSet = false; + EGS_RadionuclideSource::EGS_RadionuclideSource(EGS_Input *input, EGS_ObjectFactory *f) : EGS_BaseSource(input,f), baseSource(0), q_allowed(0), decays(0), activity(1), sCount(0) { @@ -353,6 +356,83 @@ bool EGS_RadionuclideSource::setState(istream &data) { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseSourceInputs(); + + srcBlockInput->getSingleInput("library")->setValues({"EGS_Radionuclide_Source"}); + + // Format: name, isRequired, description, vector string of allowed values + srcBlockInput->addSingleInput("activity", false, "The total activity of mixture, assumed constant."); + srcBlockInput->addSingleInput("experiment time", false, "Time length of the experiment"); + auto srcPtr = srcBlockInput->addSingleInput("source type", false, "Either isotropic or collimated", {"isotropic", "collimated"}); + + // If source type is isotropic + auto geomPtr = srcBlockInput->addSingleInput("geometry", false, "The name of a geometry, used for complex source shapes. Only particles generated inside the geometry or some of its regions are used."); + geomPtr->addDependency(srcPtr, "isotropic"); + geomPtr->addDependency(srcPtr, ""); + auto regPtr = srcBlockInput->addSingleInput("region selection", false, "Include or exclude regions from the named geometry, to define a volume for source particle generation.", {"IncludeAll", "ExcludeAll","IncludeSelected","ExcludeSelected"}); + regPtr->addDependency(geomPtr); + auto selPtr = srcBlockInput->addSingleInput("selected regions", false, "If region selection = IncludeSelected or ExcludeSelected, then this is a list of the regions in the named geometry to include or exclude."); + selPtr->addDependency(geomPtr); + selPtr->addDependency(regPtr, "IncludeSelected"); + selPtr->addDependency(regPtr, "ExcludeSelected"); + + auto shapePtr = srcBlockInput->addBlockInput("shape"); + shapePtr->addDependency(srcPtr, "isotropic"); + + setShapeInputs(shapePtr); + + // If source is collimated + auto disPtr = srcBlockInput->addSingleInput("distance", false, "The source-target minimum distance"); + disPtr->addDependency(srcPtr, "collimated"); + + auto src_shapePtr = srcBlockInput->addBlockInput("source shape"); + src_shapePtr->addDependency(srcPtr, "collimated"); + auto targetPtr = srcBlockInput->addBlockInput("target shape"); + targetPtr->addDependency(srcPtr, "collimated"); + + setShapeInputs(src_shapePtr); + setShapeInputs(targetPtr); + } + + EGS_RADIONUCLIDE_SOURCE_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_radionuclide_source + #:start source: + name = my_source + library = egs_radionuclide_source + activity = 28e6 + geometry = my_envelope + #create geometry called my_envelope + region selection = IncludeSelected + selected regions = 1 2 + :start shape: + type = box + box size = 1 2 3 + :start media input: + media = H2O521ICRU + :stop media input: + :stop shape: + :start spectrum: + type = radionuclide + nuclide = Ir-192 + :stop spectrum: + :stop source: +)"}; + return example; + } + + EGS_RADIONUCLIDE_SOURCE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return srcBlockInput; + } + EGS_RADIONUCLIDE_SOURCE_EXPORT EGS_BaseSource *createSource(EGS_Input *input, EGS_ObjectFactory *f) { return diff --git a/HEN_HOUSE/egs++/sources/egs_source_collection/egs_source_collection.cpp b/HEN_HOUSE/egs++/sources/egs_source_collection/egs_source_collection.cpp index bc62e07f8..55f31bcc5 100644 --- a/HEN_HOUSE/egs++/sources/egs_source_collection/egs_source_collection.cpp +++ b/HEN_HOUSE/egs++/sources/egs_source_collection/egs_source_collection.cpp @@ -24,6 +24,7 @@ # Author: Iwan Kawrakow, 2005 # # Contributors: Marc Chamberland +# Hannah Gallop # ############################################################################### */ @@ -37,6 +38,8 @@ #include "egs_source_collection.h" #include "egs_input.h" +static bool EGS_SOURCE_COLLECTION_LOCAL inputSet = false; + EGS_SourceCollection::EGS_SourceCollection(EGS_Input *input, EGS_ObjectFactory *f) : EGS_BaseSource(input,f), nsource(0), count(0) { vector s; @@ -132,6 +135,41 @@ void EGS_SourceCollection::setUp(const vector &S, extern "C" { + static void setInputs() { + inputSet = true; + + setBaseSourceInputs(false, false); + + srcBlockInput->getSingleInput("library")->setValues({"EGS_Source_Collection"}); + + // Format: name, isRequired, description, vector string of allowed values + srcBlockInput->addSingleInput("source names", true, "A list of names of previously defined sources."); + srcBlockInput->addSingleInput("weights", true, "A list of weights for the sources"); + } + + EGS_SOURCE_COLLECTION_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_source_collection + :start source: + library = egs_source_collection + name = my_source + source name = p1 p2 + # create sources called p1 and p2 + weights = 0.1 0.9 + :stop source: +)"}; + return example; + } + + EGS_SOURCE_COLLECTION_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return srcBlockInput; + } + EGS_SOURCE_COLLECTION_EXPORT EGS_BaseSource *createSource(EGS_Input *input, EGS_ObjectFactory *f) { return diff --git a/HEN_HOUSE/egs++/sources/egs_transformed_source/egs_transformed_source.cpp b/HEN_HOUSE/egs++/sources/egs_transformed_source/egs_transformed_source.cpp index 752378241..10455e1f4 100644 --- a/HEN_HOUSE/egs++/sources/egs_transformed_source/egs_transformed_source.cpp +++ b/HEN_HOUSE/egs++/sources/egs_transformed_source/egs_transformed_source.cpp @@ -23,7 +23,7 @@ # # Author: Iwan Kawrakow, 2005 # -# Contributors: +# Contributors: Hannah Gallop # ############################################################################### */ @@ -37,6 +37,8 @@ #include "egs_transformed_source.h" #include "egs_input.h" +static bool EGS_TRANSFORMED_SOURCE_LOCAL inputSet = false; + EGS_TransformedSource::EGS_TransformedSource(EGS_Input *input, EGS_ObjectFactory *f) : EGS_BaseSource(input,f), source(0), T(0) { EGS_Input *isource = input->takeInputItem("source",false); @@ -76,6 +78,50 @@ void EGS_TransformedSource::setUp(EGS_AffineTransform *t) { extern "C" { + static void setInputs() { + inputSet = true; + + setBaseSourceInputs(false, false); + + srcBlockInput->getSingleInput("library")->setValues({"EGS_Transformed_Source"}); + + // Format: name, isRequired, description, vector string of allowed values + srcBlockInput->addSingleInput("source name", true, "The name of a previously defined source."); + + auto blockPtr = srcBlockInput->addBlockInput("transformation"); + blockPtr->addSingleInput("translation", false, "The translation for the geometry (x, y ,z)"); + auto rotPtr = blockPtr->addSingleInput("rotation", false, "2, 3, or 9 floating point numbers"); + auto vectPtr = blockPtr->addSingleInput("rotation vector", false, "3 floating point numbers"); + // Can either have "rotation" or "rotation vector" + rotPtr->addDependency(vectPtr, "", true); + vectPtr->addDependency(rotPtr, "", true); + } + + EGS_TRANSFORMED_SOURCE_EXPORT string getExample() { + string example; + example = { + R"( + # Example of egs_transformed_source + #:start source: + library = egs_transformed_source + name = my_source + source name = my_parallel_source + #create source called my_parallel_source + :start transformation: + rotation vector = 0 -1 1 + :stop transformation: + :stop source: +)"}; + return example; + } + + EGS_TRANSFORMED_SOURCE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return srcBlockInput; + } + EGS_TRANSFORMED_SOURCE_EXPORT EGS_BaseSource *createSource(EGS_Input *input, EGS_ObjectFactory *f) { return diff --git a/HEN_HOUSE/egs++/sources/iaea_phsp_source/iaea_phsp_source.cpp b/HEN_HOUSE/egs++/sources/iaea_phsp_source/iaea_phsp_source.cpp index b691b15e6..edb6fc4ed 100644 --- a/HEN_HOUSE/egs++/sources/iaea_phsp_source/iaea_phsp_source.cpp +++ b/HEN_HOUSE/egs++/sources/iaea_phsp_source/iaea_phsp_source.cpp @@ -40,6 +40,8 @@ #include "egs_input.h" #include "egs_functions.h" +static bool IAEA_PHSP_SOURCE_LOCAL inputSet = false; + IAEA_PhspSource::IAEA_PhspSource(const string &phsp_file, const string &Name, EGS_ObjectFactory *f) : EGS_BaseSource(Name,f) { init(); @@ -525,6 +527,47 @@ void IAEA_PhspSource::setFilter(int type, int nbit1, int nbit2, const int *bits) extern "C" { + static void setInputs() { + inputSet = true; + + setBaseSourceInputs(false, false); + + srcBlockInput->getSingleInput("library")->setValues({"IAEA_Phsp_Source"}); + + // Format: name, isRequired, description, vector string of allowed values + srcBlockInput->addSingleInput("iaea phase space file", true, "The path to and name of the phase-space file, no extension. Both the .IAEAphsp and .IAEAheader file must be in the same directory."); + srcBlockInput->addSingleInput("particle type", true, "The type of particle to use from the phase-space", {"all", "charged", "electrons", "positrons", "photons"}); + srcBlockInput->addSingleInput("cutout", false, "A rectangular cutout defined by x1, x2, y1, y2"); + srcBlockInput->addSingleInput("weight window", false, "wmin, wmax; the min and max particle weights to use. If the particle is not in this (inclusive) range, it is rejected."); + srcBlockInput->addSingleInput("recycle photons", false, "The number of time to recycle each photon"); + srcBlockInput->addSingleInput("recycle electrons", false, "The number of times to recycle each electron"); + } + + IAEA_PHSP_SOURCE_EXPORT string getExample() { + string example; + example = { + R"( + # Example of iaea_phsp_soure + #:start source: + name = my_source + library = iaea_phsp_source + iaea phase space file = myPhsp # No extension, both .IAEAphsp and .IAEAheader must be present + particle type = all + cutout = -1 1 -2 2 + recycle photons = 10 + recycle electrons = 10 + :stop source: +)"}; + return example; + } + + IAEA_PHSP_SOURCE_EXPORT shared_ptr getInputs() { + if(!inputSet) { + setInputs(); + } + return srcBlockInput; + } + IAEA_PHSP_SOURCE_EXPORT EGS_BaseSource *createSource(EGS_Input *input, EGS_ObjectFactory *f) { return @@ -532,3 +575,4 @@ extern "C" { } } + diff --git a/HEN_HOUSE/egs++/view/egs_editor.cpp b/HEN_HOUSE/egs++/view/egs_editor.cpp new file mode 100644 index 000000000..e80170f80 --- /dev/null +++ b/HEN_HOUSE/egs++/view/egs_editor.cpp @@ -0,0 +1,1310 @@ +/* +############################################################################### +# +# EGSnrc egs++ egsinp editor +# Copyright (C) 2015 National Research Council Canada +# +# This file is part of EGSnrc. +# +# EGSnrc is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# EGSnrc is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for +# more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with EGSnrc. If not, see . +# +############################################################################### +# +# Author: Reid Townson, 2020 +# +# Contributors: Hannah Gallop +# +############################################################################### +*/ + +#include "egs_editor.h" +#include "egs_functions.h" + +EGS_Editor::EGS_Editor(QWidget *parent) : QPlainTextEdit(parent) { + this->setFrameShape(QFrame::NoFrame); + + // Capture events + installEventFilter(this); + viewport()->installEventFilter(this); + + // Set the font + const QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); + this->setFont(fixedFont); + + // Set the tab width to 4 spaces + const int tabStop = 4; // 4 characters + QFontMetrics metrics(fixedFont); + this->setTabStopWidth(tabStop * metrics.width(' ')); + + // Initialize an area for displaying line numbers + lineNumberArea = new LineNumberArea(this); + updateLineNumberAreaWidth(0); + + // Highlight the line currently selected by the cursor + highlightCurrentLine(); + + // Initialize the auto completion popup + popup = new QListView; + popup->setEditTriggers(QAbstractItemView::NoEditTriggers); + popup->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + popup->setSelectionBehavior(QAbstractItemView::SelectRows); + popup->setSelectionMode(QAbstractItemView::SingleSelection); + popup->setParent(nullptr); + popup->setFocusPolicy(Qt::StrongFocus); + popup->installEventFilter(this); + + + // The Qt::Popup option seems to take control of mouse + key inputs + // essentially locking up the computer, beware! + //popup->setWindowFlag(Qt::Popup); + popup->setWindowFlag(Qt::ToolTip); + + // Init model + model = new QStringListModel(this); + + connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int))); + connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int))); + connect(this, SIGNAL(cursorPositionChanged()), popup, SLOT(hide())); + connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine())); + connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(autoComplete())); + connect(popup, SIGNAL(clicked(QModelIndex)), this, SLOT(insertCompletion(QModelIndex))); + connect(popup, SIGNAL(activated(QModelIndex)), this, SLOT(insertCompletion(QModelIndex))); +// +// QObject::connect(popup->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), +// this, SLOT(_q_completionSelected(QItemSelection))); + //connect(this, SIGNAL(keyboardGrabber()), this, SIGNAL(QAbstractItemView::MoveDown)); + + popupGrabbing = false; +} + +EGS_Editor::~EGS_Editor() { + if (lineNumberArea) { + delete lineNumberArea; + } + if (popup) { + delete popup; + } + if (model) { + delete model; + } +} + +void EGS_Editor::setInputStruct(shared_ptr inp) { + inputStruct = inp; +} + +int EGS_Editor::lineNumberAreaWidth() { + int digits = 1; + int max = qMax(1, blockCount()); + while (max >= 10) { + max /= 10; + ++digits; + } + + int space = 3 + fontMetrics().horizontalAdvance(QLatin1Char('9')) * digits; + + return space; +} + + + +void EGS_Editor::updateLineNumberAreaWidth(int /* newBlockCount */) { + setViewportMargins(lineNumberAreaWidth()+5, 0, 0, 0); +} + + + +void EGS_Editor::updateLineNumberArea(const QRect &rect, int dy) { + if (dy) { + lineNumberArea->scroll(0, dy); + } + else { + lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height()); + } + + if (rect.contains(viewport()->rect())) { + updateLineNumberAreaWidth(0); + } +} + + + +void EGS_Editor::resizeEvent(QResizeEvent *e) { + QPlainTextEdit::resizeEvent(e); + + QRect cr = contentsRect(); + lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height())); +} + + + +void EGS_Editor::highlightCurrentLine() { + QList extraSelections; + + if (!isReadOnly()) { + QTextEdit::ExtraSelection selection; + + QColor lineColor = QColor(Qt::lightGray).lighter(120); + + selection.format.setBackground(lineColor); + selection.format.setProperty(QTextFormat::FullWidthSelection, true); + selection.cursor = textCursor(); + selection.cursor.clearSelection(); + extraSelections.append(selection); + } + + setExtraSelections(extraSelections); +} + +int EGS_Editor::countStartingWhitespace(const QString &s) { + int i, l = s.size(); + for (i = 0; i < l && s[i] == ' ' || s[i] == '\t'; ++i); + return i; +} + +void EGS_Editor::validateEntireInput() { + // This actually validates from the current cursor position, + // but we only call this upon loading the file so the cursor is already at the top + QTextCursor cursor = textCursor(); + for (QTextBlock it = cursor.document()->begin(); it != cursor.document()->end(); it = it.next()) { + cursor.movePosition(QTextCursor::NextBlock); + validateLine(cursor); + } +} + +void EGS_Editor::validateLine(QTextCursor cursor) { + QString selectedText = cursor.block().text().simplified(); + + QString blockTitle; + shared_ptr inputBlockTemplate = getBlockInput(blockTitle, cursor); + + // If we aren't inside an input block, ignore this line + if (blockTitle.size() < 1) { + return; + } + + if (selectedText.startsWith("#")) { + return; + } + + // Check the validity of the inputs + // If this line contains an "=" then it should match a single input + int equalsPos = selectedText.indexOf("="); + if (equalsPos != -1) { + cursor.beginEditBlock(); + + QString inputTag = selectedText.left(equalsPos).simplified(); + QString inputVal = selectedText.right(selectedText.size() - equalsPos - 1).simplified(); +#ifdef EDITOR_DEBUG + egsInformation("EGS_Editor::validateLine: Found equals sign: %s\n",inputTag.toLatin1().data()); +#endif + + // If we found a template for this type of input block, + // check that the input tag (LHS) is valid + if (inputBlockTemplate) { + + QList extraSelections = this->extraSelections(); + QTextEdit::ExtraSelection selection; + selection.cursor = cursor; + selection.cursor.joinPreviousEditBlock(); + + // Select the whole line + selection.cursor.movePosition(QTextCursor::StartOfBlock); + selection.cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); + + // Reset the format to have no red underline + QTextCharFormat format; + format.setUnderlineStyle(QTextCharFormat::NoUnderline); + format.setToolTip(""); + selection.cursor.setCharFormat(format); + + // Check that the input block template contains this type of input + // If the input isn't defined, it will return nullptr + shared_ptr inputPtr = inputBlockTemplate->getSingleInput(inputTag.toStdString(), blockTitle.toStdString()); + if (!inputPtr) { + // Red underline the input tag + // Select the input tag + + selection.cursor.movePosition(QTextCursor::StartOfBlock); + + // If whitespace was trimmed from the start of the line, + // we account for it so only the input tag is underlined + int originalEqualsPos = cursor.block().text().indexOf("="); + int numWhitespace = countStartingWhitespace(cursor.block().text()); + if (numWhitespace > 0) { + selection.cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, numWhitespace); + } + + selection.cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, originalEqualsPos - numWhitespace); + + // Set the format to have a red underline + format.setUnderlineColor(QColor("red")); + format.setUnderlineStyle(QTextCharFormat::SpellCheckUnderline); + } + else { + + // Get the description for this input + string desc = inputPtr->getDescription(); + + bool isRequired = inputPtr->getRequired(); + if (isRequired) { + desc += "\nRequired."; + } + + // Check if this input has any dependencies + // and then confirm that the dependencies are satisfied + if (inputHasDependency(inputPtr)) { + // Add the list of dependencies to the description tooltip + desc += "\nDependencies: "; + auto vals = inputPtr->getDependencyVal(); + int i = 0; + for (auto &inp: inputPtr->getDependencyInp()) { + if (vals[i].size() > 0) { + desc += "'" + inp->getTag() + "=" + vals[i] + "' "; + } + else { + desc += "'" + inp->getTag() + "' "; + } + ++i; + } + auto depBlock = inputPtr->getDependencyBlock(); + if (depBlock) { + desc += "':start " + depBlock->getTitle() + ":'"; + } + + if (inputDependencySatisfied(inputPtr, cursor) == false) { + // Red underline the input tag + // Select the input tag + selection.cursor.movePosition(QTextCursor::StartOfBlock); + + // If whitespace was trimmed from the start of the line, + // we account for it so only the input tag is underlined + int originalEqualsPos = cursor.block().text().indexOf("="); + int numWhitespace = countStartingWhitespace(cursor.block().text()); + if (numWhitespace > 0) { + selection.cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, numWhitespace); + } + + selection.cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, originalEqualsPos - numWhitespace); + + // Set the format to have a red underline + format.setUnderlineColor(QColor("red")); + format.setUnderlineStyle(QTextCharFormat::SpellCheckUnderline); + } + } + + // If the input is valid, add the description as a tooltip + format.setToolTip(QString::fromStdString(desc)); + } + + selection.cursor.setCharFormat(format); + + selection.cursor.endEditBlock(); + extraSelections.append(selection); + setExtraSelections(extraSelections); + } + cursor.endEditBlock(); + } +} + +void EGS_Editor::autoComplete() { + // Get the text of the current line + QTextCursor cursor = textCursor(); + QString selectedText = cursor.block().text().simplified(); + + // Clear the popup string list + model->setStringList(QStringList{}); + popup->setModel(model); + + // If the first character is a "#", ignore this line + if (selectedText.startsWith("#")) { + return; + } + + // Get the input structure + QString blockTitle; + shared_ptr inputBlockTemplate = getBlockInput(blockTitle); + + // If we aren't inside an input block, ignore this line + if (blockTitle.size() < 1) { + return; + } + + // Check the validity of the inputs + // If this line contains an "=" then it should match a single input + int equalsPos = selectedText.indexOf("="); + if (equalsPos != -1) { + QString inputTag = selectedText.left(equalsPos).simplified(); + QString inputVal = selectedText.right(selectedText.size() - equalsPos - 1).simplified(); +#ifdef EDITOR_DEBUG + egsInformation("EGS_Editor::autoComplete: found equals sign: %s\n",inputTag.toLatin1().data()); +#endif + + // Check that the line is valid + validateLine(cursor); + + // Return if the input value (RHS) is already filled + // This way we only offer options for blank inputs + if (inputVal != "") { + return; + } + + // Create a pop-up if there is a list of possible input values + if (inputTag == "library") { + + // Get the list of possible libraries for this type of input block + // I.e. if this is a geometry, only offer geometries as options + vector vals = inputStruct->getLibraryOptions(blockTitle.toStdString()); + + // Populate the popup list + QStringList itemList; + for (auto &v: vals) { + itemList << QString(v.c_str()); + } + if (itemList.size() > 0) { + model->setStringList(itemList); + + + popup->setModel(model); + popup->setFont(this->font()); + + // Get max string length + int strLength = 0; + for (auto &item: itemList) { + if (item.size() > strLength) { + strLength = item.size(); + } + } + + // Create a selection popup + int maxVisibleItems = 6; + int h = (popup->sizeHintForRow(0) * qMin(maxVisibleItems, popup->model()->rowCount()) + 3) + 3; + QScrollBar *hsb = popup->horizontalScrollBar(); + if (hsb && hsb->isVisible()) { + h += popup->horizontalScrollBar()->sizeHint().height(); + } + + QPoint pos = this->viewport()->mapToGlobal(this->cursorRect().bottomRight()); + QFontMetrics fm(popup->font()); + int w = 20 + strLength * fm.horizontalAdvance('9'); + + popup->setGeometry(pos.x(), pos.y(), w, h); + + // Show the popup + if (!popup->isVisible()) { + popup->show(); + } + } + } + else { + + // Return if we couldn't find a template for this input block + if (!inputBlockTemplate) { + return; + } + + // Check for this input tag in the template + shared_ptr inp = inputBlockTemplate->getSingleInput(inputTag.toStdString(), blockTitle.toStdString()); + + // Return if we didn't find this input in the template + if (!inp) { + return; + } + + // Get the possible values + auto vals = inp->getValues(); + + // Return if we don't have a list of values to choose from + if (vals.size() == 0) { + return; + } + + // Populate the popup list + QStringList itemList; + for (auto &v: vals) { + itemList << QString(v.c_str()); + } + if (itemList.size() > 0) { + model->setStringList(itemList); + + + popup->setModel(model); + popup->setFont(this->font()); + + // Get max string length + int strLength = 0; + for (auto &item: itemList) { + if (item.size() > strLength) { + strLength = item.size(); + } + } + + // Create a selection popup + int maxVisibleItems = 6; + int h = (popup->sizeHintForRow(0) * qMin(maxVisibleItems, popup->model()->rowCount()) + 3) + 3; + QScrollBar *hsb = popup->horizontalScrollBar(); + if (hsb && hsb->isVisible()) { + h += popup->horizontalScrollBar()->sizeHint().height(); + } + + QPoint pos = this->viewport()->mapToGlobal(this->cursorRect().bottomRight()); + QFontMetrics fm(popup->font()); + int w = 20 + strLength * fm.horizontalAdvance('9'); + + popup->setGeometry(pos.x(), pos.y(), w, h); + + // Show the popup + if (!popup->isVisible()) { + popup->show(); + } + } + } + + // If this is just an empty line, we can offer suggestions of valid inputs + } + else if (inputBlockTemplate && selectedText == "") { + + vector> singleInputs = inputBlockTemplate->getSingleInputs(blockTitle.toStdString()); + + vector> blockInputs = inputBlockTemplate->getBlockInputs(blockTitle.toStdString()); + + //vector> generalInputs = inputBlockTemplate->getGeneralBlock(blockTitle.toStdString()); + + // Populate the popup list + QStringList itemList; + + // Add all the single inputs for the top level block + for (auto &inp: singleInputs) { + //if(!egsEquivStr(inp->getTag(), "library")) { + // Skip any inputs that have a dependency which is not satisfied + if (inputHasDependency(inp) && inputDependencySatisfied(inp, cursor) == false) { + continue; + } + + itemList << QString((inp->getTag() + " = ").c_str()); + //} + } + + // Store the block titles in a set to remove duplicates + QSet blockTitles; + for (auto &block: blockInputs) { + blockTitles << QString((":start " + block->getTitle() + ":").c_str()); + } + for (auto &title: blockTitles) { + itemList << title; + } + if (itemList.size() > 0) { + model->setStringList(itemList); + + popup->setModel(model); + popup->setFont(this->font()); + + // Get max string length + int strLength = 0; + for (auto &item: itemList) { + if (item.size() > strLength) { + strLength = item.size(); + } + } + + // Create a selection popup + int maxVisibleItems = 6; + int h = (popup->sizeHintForRow(0) * qMin(maxVisibleItems, popup->model()->rowCount()) + 3) + 3; + QScrollBar *hsb = popup->horizontalScrollBar(); + if (hsb && hsb->isVisible()) { + h += popup->horizontalScrollBar()->sizeHint().height(); + } + + QPoint pos = this->viewport()->mapToGlobal(this->cursorRect().bottomRight()); + QFontMetrics fm(popup->font()); + int w = 20 + strLength * fm.horizontalAdvance('9'); + + popup->setGeometry(pos.x(), pos.y(), w, h); + + // Show the popup + if (!popup->isVisible()) { + popup->show(); + } + } + + // If this is the start of an input block, check that it belongs here + } + else if (selectedText.contains(":start ")) { + + // If we're inside another input block that we have a template for, + // Check to this that this is a valid input block to exist here + if (inputBlockTemplate) { + + // Get the block title + QString blockTit; + int pos = selectedText.lastIndexOf(":start "); + pos += 7; + int endPos = selectedText.indexOf(":",pos); + if (endPos > 0) { + blockTit = selectedText.mid(pos, endPos-pos); + } + + QList extraSelections = this->extraSelections(); + QTextEdit::ExtraSelection selection; + selection.cursor = cursor; + selection.cursor.joinPreviousEditBlock(); + + // Select the whole line + selection.cursor.movePosition(QTextCursor::StartOfBlock); + selection.cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); + + // Reset the format to have no red underline + QTextCharFormat format; + format.setUnderlineStyle(QTextCharFormat::NoUnderline); + + auto inputPtr = inputBlockTemplate->getBlockInput(blockTit.toStdString()); + if (!inputPtr) { + // Red underline the input tag + // Select the input tag + selection.cursor.movePosition(QTextCursor::StartOfBlock); + + // If whitespace was trimmed from the start of the line, + // we account for it so only the input tag is underlined + int originalEqualsPos = cursor.block().text().lastIndexOf(":"); + int numWhitespace = countStartingWhitespace(cursor.block().text()); + if (numWhitespace > 0) { + selection.cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, numWhitespace); + } + + selection.cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, originalEqualsPos - numWhitespace); + + // Set the format to have a red underline + format.setUnderlineColor(QColor("red")); + format.setUnderlineStyle(QTextCharFormat::SpellCheckUnderline); + } + + selection.cursor.setCharFormat(format); + + selection.cursor.endEditBlock(); + extraSelections.append(selection); + setExtraSelections(extraSelections); + } + + // For geometry, source and ausgab object blocks that don't contain a library line, + // add 'library =' as an option in the popup + } + else if (selectedText.size() == 0 && (egsEquivStr(blockTitle.toStdString(), "geometry") || egsEquivStr(blockTitle.toStdString(), "source") + || egsEquivStr(blockTitle.toStdString(), "ausgab object"))) { + + // Populate the popup list + QStringList itemList; + itemList << "library = "; + if (itemList.size() > 0) { + model->setStringList(itemList); + + popup->setModel(model); + popup->setFont(this->font()); + + // Get max string length + int strLength = 0; + for (auto &item: itemList) { + if (item.size() > strLength) { + strLength = item.size(); + } + } + + // Create a selection popup + int maxVisibleItems = 6; + int h = (popup->sizeHintForRow(0) * qMin(maxVisibleItems, popup->model()->rowCount()) + 3) + 3; + QScrollBar *hsb = popup->horizontalScrollBar(); + if (hsb && hsb->isVisible()) { + h += popup->horizontalScrollBar()->sizeHint().height(); + } + + QPoint pos = this->viewport()->mapToGlobal(this->cursorRect().bottomRight()); + QFontMetrics fm(popup->font()); + int w = 20 + strLength * fm.horizontalAdvance('9'); + + popup->setGeometry(pos.x(), pos.y(), w, h); + + // Show the popup + if (!popup->isVisible()) { + popup->show(); + } + } + } +} + +void EGS_Editor::insertCompletion(QModelIndex index) { + QTextCursor cursor = textCursor(); + cursor.beginEditBlock(); + this->moveCursor(QTextCursor::EndOfBlock); + insertPlainText(model->data(index).toString()); + cursor.endEditBlock(); + popup->QWidget::releaseKeyboard(); +} + +shared_ptr EGS_Editor::getBlockInput(QString &blockTitle, QTextCursor cursor) { + if (cursor == QTextCursor()) { + cursor = textCursor(); + } + + blockTitle = getBlockTitle(cursor); + if (blockTitle.size() < 1) { + return nullptr; + } + + bool foundTag; + QString library = getInputValue("library", cursor.block(), foundTag); + + // If we couldn't find a library tag in the current block, + // try searching the containing block (if there is one) + if (library.size() < 1) { +#ifdef EDITOR_DEBUG + egsInformation("EGS_Editor::getBlockInput: Searching containing block for library: %s\n", blockTitle.toLatin1().data()); +#endif + + // If we're currently on a :start line, start searching on the next line + // so that we're actually starting within the block + QTextBlock blockEnd; + blockEnd = cursor.block(); + int loopGuard = 10000; + int i = 0; + while (blockEnd.text().contains(":start ")) { + blockEnd = getBlockEnd(blockEnd.next()); + if (++i > loopGuard) { + egsInformation("Warning: Encountered infinite loop while processing the input file. Contact the developers to report this bug.\n"); + break; + } + if (blockEnd.isValid()) { + blockEnd = blockEnd.next(); + } + } + blockEnd = getBlockEnd(blockEnd); + if (blockEnd.isValid()) { + // Go to the line after the end of the current input block + blockEnd = blockEnd.next(); + + // Check for the library tag here + library = getInputValue("library", blockEnd, foundTag); + } + + // If we still didn't find the library, search one block higher + if (library.size() < 1) { +#ifdef EDITOR_DEBUG + egsInformation("EGS_Editor::getBlockInput: Checking up a level...\n"); +#endif + // If we're currently on a :start line, start searching on the next line + // so that we're actually starting within the block + int loopGuard = 10000; + int i = 0; + while (blockEnd.text().contains(":start ")) { + blockEnd = getBlockEnd(blockEnd.next()); + if (++i > loopGuard) { + egsInformation("Warning: Encountered infinite loop while processing the input file. Contact the developers to report this bug.\n"); + break; + } + if (blockEnd.isValid()) { + blockEnd = blockEnd.next(); + } + } + blockEnd = getBlockEnd(blockEnd); + if (blockEnd.isValid()) { + // Go to the line after the end of the current input block + blockEnd = blockEnd.next(); + + // Check for the library tag here + library = getInputValue("library", blockEnd, foundTag); + } + } + } + + // If we got the library tag, we can directly look up this input block structure + if (library.size() > 0) { + shared_ptr inputBlock = inputStruct->getLibraryBlock(blockTitle.toStdString(), library.toStdString()); + if (inputBlock) { +#ifdef EDITOR_DEBUG + egsInformation("EGS_Editor::getBlockInput: Found library: %s\n", library.toLatin1().data()); +// vector> singleInputs = inputBlock->getSingleInputs(); +// for (auto &inp : singleInputs) { +// const vector vals = inp->getValues(); +// egsInformation(" single %s\n", inp->getTag().c_str()); +// for (auto&& val : vals) { +// egsInformation(" %s\n", val.c_str()); +// } +// } +// vector> inputBlocks = inputBlock->getBlockInputs(); +// for (auto &block : inputBlocks) { +// singleInputs = inputBlock->getSingleInputs(); +// for (auto &inp : singleInputs) { +// const vector vals = inp->getValues(); +// egsInformation(" single %s\n", inp->getTag().c_str()); +// for (auto&& val : vals) { +// egsInformation(" %s\n", val.c_str()); +// } +// } +// } +#endif + return inputBlock; + } + } + + // If we didn't get the library tag, we might be in a top-level block + // like a geometry definition. Just return the block with the matching title + shared_ptr inputBlock = inputStruct->getBlockInput(blockTitle.toStdString()); + +#ifdef EDITOR_DEBUG + egsInformation("EGS_Editor::getBlockInput: No library found, assuming '%s' is top-level block\n", blockTitle.toLatin1().data()); +#endif + + return inputBlock; +} + +QString EGS_Editor::getBlockTitle(QTextCursor cursor) { + if (cursor == QTextCursor()) { + cursor = textCursor(); + } + + vector innerList; + QString blockTitle; + bool withinOtherBlock = false; + + // Starting at the current line, starting iterating in reverse through + // the previous lines + for (QTextBlock block = cursor.block(); block.isValid(); block = block.previous()) { + QString line = block.text().simplified(); + + // Get block title + int pos = line.lastIndexOf(":start "); + if (pos >= 0) { + pos += 7; + int endPos = line.indexOf(":",pos); + if (endPos > 0) { + blockTitle = line.mid(pos, endPos-pos); + if (innerList.size() > 0 && blockTitle == innerList.back()) { + innerList.pop_back(); + blockTitle.clear(); + withinOtherBlock = false; + } + else { + break; + } + } + } + + // Save a vector of blocks that have already been closed + // This means both a matching :start and :stop are above the cursor + // so we're not inside the block + pos = line.lastIndexOf(":stop "); + if (pos >= 0) { + pos += 6; + int endPos = line.indexOf(":",pos); + if (endPos > 0) { + QString stopTitle = line.mid(pos, endPos-pos); + innerList.push_back(stopTitle); + withinOtherBlock = true; + } + } + } + + return blockTitle; +} + +QString EGS_Editor::getInputValue(QString inp, QTextBlock currentBlock, bool &foundTag) { + QString value; + vector innerList; + bool withinOtherBlock = false; + foundTag = false; + + // Get the last textblock in this input block + // so that we search all the inputs in the block + QTextBlock blockEnd = getBlockEnd(currentBlock); + if (!blockEnd.isValid()) { + return ""; + } + + // Starting at the last line, start iterating in reverse through + // the previous lines + blockEnd = blockEnd.previous(); + for (QTextBlock block = blockEnd; block.isValid(); block = block.previous()) { + QString line = block.text().simplified(); + + // Get block library for input blocks based on a shared library + // e.g. geometries and sources + // Only look for the library tag if we're not in a sub-block + int pos; + if (!withinOtherBlock) { + pos = line.lastIndexOf(inp); + if (pos >= 0) { + int pos2 = line.lastIndexOf("="); + if (pos2 > pos) { + QString tag = line.left(pos2).simplified(); + if (egsEquivStr(tag.toStdString(), inp.simplified().toStdString())) { + foundTag = true; + value = line.right(line.size()-pos2-1).simplified(); + break; + } + } + } + } + + // Get block title + pos = line.lastIndexOf(":start "); + if (pos >= 0) { + pos += 7; + int endPos = line.indexOf(":",pos); + if (endPos > 0) { + QString blockTitle = line.mid(pos, endPos-pos); + if (innerList.size() > 0 && blockTitle == innerList.back()) { + innerList.pop_back(); + if (innerList.size() == 0) { + withinOtherBlock = false; + } + } + else { + // If we got to the start of the block, + // then we failed to find the input + return ""; + } + } + } + + // Save a vector of blocks that have already been closed + // This means both a matching :start and :stop are above the cursor + // so we're not inside the block + pos = line.lastIndexOf(":stop "); + if (pos >= 0) { + pos += 6; + int endPos = line.indexOf(":",pos); + if (endPos > 0) { + QString stopTitle = line.mid(pos, endPos-pos); + innerList.push_back(stopTitle); + withinOtherBlock = true; + } + } + } + + return value; +} + +QTextBlock EGS_Editor::getBlockEnd(QTextBlock currentBlock) { + vector innerList; + bool withinOtherBlock = false; + + // Starting at the current line, starting iterating in forward through + // the next lines + for (QTextBlock block = currentBlock; block.isValid(); block = block.next()) { + QString line = block.text().simplified(); + + // Save a vector of blocks that are contained within this input block + // This means both a matching :start and :stop are below the cursor + // so we're not inside the block + int pos = line.lastIndexOf(":start "); + if (pos >= 0) { + pos += 7; + int endPos = line.indexOf(":",pos); + if (endPos > 0) { + QString startTitle = line.mid(pos, endPos-pos); + innerList.push_back(startTitle); + withinOtherBlock = true; + } + } + + // Save a vector of blocks that are contained within this input block + // so that we can skip them + pos = line.lastIndexOf(":stop "); + if (pos >= 0) { + pos += 6; + int startPos = line.indexOf(":",pos); + if (startPos > 0) { + QString blockTitle = line.mid(pos, startPos-pos); + if (innerList.size() > 0 && blockTitle == innerList.back()) { + innerList.pop_back(); + blockTitle.clear(); + withinOtherBlock = false; + } + else { + return block; + } + } + } + } + + return QTextBlock(); +} + +bool EGS_Editor::inputHasDependency(shared_ptr inp) { + auto dependencyInp = inp->getDependencyInp(); + auto dependencyBlock = inp->getDependencyBlock(); + if (dependencyInp.size() < 1 && !dependencyBlock) { + return false; + } + else { + return true; + } +} + +bool EGS_Editor::inputDependencySatisfied(shared_ptr inp, QTextCursor cursor) { + if (cursor == QTextCursor()) { + cursor = textCursor(); + } + bool satisfied = true; + + // This is a list of inputs that the current input depends on + auto dependencyInp = inp->getDependencyInp(); + + // This is a list of values, that each of the dependencies above must match + // These are like the required input parameters that we are checking against + auto dependencyVal = inp->getDependencyVal(); + auto dependencyAnti = inp->getDependencyAnti(); + + // Loop through the dependencies + vector previousSatisfied; + string previousTag; + for (size_t i = 0; i < dependencyInp.size(); ++i) { + if (!satisfied) { + break; + } + + string depTag = dependencyInp[i]->getTag(); + + // Get the value from the input file + bool foundTag; + QString val = getInputValue(QString::fromStdString(depTag), cursor.block(), foundTag); + + if (foundTag && !dependencyAnti[i]) { + if (dependencyVal[i].size() > 0) { + if (egsEquivStr(val.toLatin1().data(), dependencyVal[i])) { + satisfied = true; + } + else { + satisfied = false; + } + } + else { + satisfied = true; + } + } + else { + // If this is an anti dependency, then we didn't want to find the tag + // Note that we don't check the value, only whether or not the input tag is used + if (!foundTag && dependencyAnti[i]) { + satisfied = true; + } + else { + satisfied = false; + } + } + // Look ahead, if the following inputs have the same tag as this one (i) + for (size_t j = i+1; j < dependencyInp.size(); ++j) { + if (egsEquivStr(dependencyInp[j]->getTag(), depTag)) { + // If we already were satisfied by the first one, just skip + // ahead. + // This is because dependencies with the same tag are treated + // with an OR operation + if (satisfied) { + // If we hit the end because all the tags matched, reset i + if (j == dependencyInp.size()-1) { + i = j; + } + continue; + } + else { + if (egsEquivStr(val.toLatin1().data(), dependencyVal[j])) { + satisfied = true; + // If we hit the end because all the tags matched, reset i + if (j == dependencyInp.size()-1) { + i = j; + } + continue; + } + } + } + else { + i = j-1; + break; + } + } + } + + // Check for any input blocks that this input depends on + // We are doing an AND between the input-type dependencies and the block-type ones + // So we can skip this section if the input-type dependencies failed + if (satisfied) { + auto dependencyBlock = inp->getDependencyBlock(); + + if (dependencyBlock) { + auto dependencyBlockAnti = inp->getDependencyBlockAnti(); + + QTextBlock depBlock = findSiblingBlock(QString::fromStdString(dependencyBlock->getTitle()), cursor.block()); + + if (depBlock.isValid()) { + if (dependencyBlockAnti) { + satisfied = false; + } + else { + satisfied = true; + } + } + else { + if (dependencyBlockAnti) { + satisfied = true; + } + else { + satisfied = false; + } + } + } + } + + return satisfied; +} + +QTextBlock EGS_Editor::findSiblingBlock(QString title, QTextBlock currentBlock) { + vector innerList; + bool withinOtherBlock = false; + + // Get the last textblock in this input block + // so that we search all the inputs in the block + QTextBlock blockEnd = getBlockEnd(currentBlock); + if (!blockEnd.isValid()) { + return QTextBlock(); + } + + // Starting at the last line, start iterating in reverse through + // the previous lines + blockEnd = blockEnd.previous(); + for (QTextBlock block = blockEnd; block.isValid(); block = block.previous()) { + QString line = block.text().simplified(); + + // Find a sibling block with the title we're looking for + // Here we expect to be within another block because the start line counts as inside the block + int pos; + if (withinOtherBlock) { + pos = line.lastIndexOf(":start " + title + ":"); + if (pos >= 0) { + return block; + } + } + + // Get block title + pos = line.lastIndexOf(":start "); + if (pos >= 0) { + pos += 7; + int endPos = line.indexOf(":",pos); + if (endPos > 0) { + QString blockTitle = line.mid(pos, endPos-pos); + if (innerList.size() > 0 && blockTitle == innerList.back()) { + innerList.pop_back(); + if (innerList.size() == 0) { + withinOtherBlock = false; + } + } + else { + // If we got to the start of the current block, + // then we failed to find the target block + return QTextBlock(); + } + } + } + + // Save a vector of blocks that have already been closed + // This means both a matching :start and :stop are above the cursor + // so we're not inside the block + pos = line.lastIndexOf(":stop "); + if (pos >= 0) { + pos += 6; + int endPos = line.indexOf(":",pos); + if (endPos > 0) { + QString stopTitle = line.mid(pos, endPos-pos); + innerList.push_back(stopTitle); + withinOtherBlock = true; + } + } + } + + return QTextBlock(); +} + +void EGS_Editor::lineNumberAreaPaintEvent(QPaintEvent *event) { + QPainter painter(lineNumberArea); + //painter.fillRect(event->rect(), QColor(Qt::lightGray).lighter(110)); + + + QTextBlock block = firstVisibleBlock(); + int blockNumber = block.blockNumber(); + int top = static_cast(blockBoundingGeometry(block).translated(contentOffset()).top()); + int bottom = top + static_cast(blockBoundingRect(block).height()); + + while (block.isValid() && top <= event->rect().bottom()) { + if (block.isVisible() && bottom >= event->rect().top()) { + QString number = QString::number(blockNumber + 1); + painter.setPen(Qt::black); + painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(), + Qt::AlignRight, number); + } + + block = block.next(); + top = bottom; + bottom = top + static_cast(blockBoundingRect(block).height()); + ++blockNumber; + } +} + +bool EGS_Editor::eventFilter(QObject *obj, QEvent *event) { + + if (event->type() == QEvent::MouseButtonRelease) { + QMouseEvent *mouseEvent = static_cast(event); + + // track `Ctrl + Click` in the text edit + if ((obj == this->viewport()) && + (mouseEvent->button() == Qt::LeftButton) && + (QGuiApplication::keyboardModifiers() == Qt::ControlModifier)) { + // open the link (if any) at the current position + //openLinkAtCursorPosition(); + return true; + } + } + else if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + + // Insert 4 spaces instead of tabs + if (keyEvent->key() == Qt::Key_Tab) { + if (!popup->isVisible()) { + insertPlainText(" "); + return true; + } + } + else if (keyEvent->key() == Qt::Key_Backtab) { + // Delete 4 spaces from the front of the line + QTextCursor cursor = textCursor(); + QString line = cursor.block().text(); + if (line.startsWith(" ")) { + cursor.movePosition(QTextCursor::StartOfBlock); + cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 4); + cursor.removeSelectedText(); + } + else if (line.startsWith("\t")) { + cursor.movePosition(QTextCursor::StartOfBlock); + cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 1); + cursor.removeSelectedText(); + } + return true; + } + else if (keyEvent->key() == Qt::Key_Return) { + if (!popup->isVisible()) { + + QTextCursor cursor = textCursor(); + QString line = cursor.block().text(); + + // Get the current indentation amount + QString indentation; + for (size_t i = 0; i < line.size(); ++i) { + if (line.at(i) == ' ') { + indentation += ' '; + } + else if (line.at(i) == '\t') { + indentation += " "; + } + else { + break; + } + } + + QString stopLine; + int pos = line.lastIndexOf(":start "); + int posInBlock = cursor.positionInBlock(); + if (pos > -1 && posInBlock > pos) { + stopLine = line.replace(pos, 7, ":stop "); + } + + // If we inserted the ":stop" line, then also insert a line between + // and leave the cursor there + if (stopLine.size() > 0) { + insertPlainText("\n" + indentation + " "); + insertPlainText("\n" + stopLine); + cursor.movePosition(QTextCursor::PreviousBlock); + cursor.movePosition(QTextCursor::EndOfBlock); + setTextCursor(cursor); + + // Normally, we just insert a new line with matching indentation + } + else { + insertPlainText("\n" + indentation); + } + + // Skip the usual return event! So we have to handle it here + return true; + } + } + else if (keyEvent->key() == Qt::Key_Escape) { + popup->hide(); + popup->QWidget::releaseKeyboard(); + } + else if (keyEvent->key() == Qt::Key_Right) { + if (popup->isVisible()) { + popupGrabbing = true; + popup->QWidget::grabKeyboard(); + return true; + } + } +// } else if(event->type() == QEvent::FocusOut || event->type() == QEvent::Move || event->type() == QEvent::Resize || event->type() == QEvent::Scroll || event->type() == QEvent::WindowDeactivate) { + + //} else if(event->type() == QEvent::Wheel || event->type() == QEvent::WindowDeactivate) { + } + else if (event->type() == QEvent::Wheel || event->type() == QEvent::FocusOut) { + if (!popupGrabbing) { + popup->hide(); + popup->QWidget::releaseKeyboard(); + } + } + else if (obj == popup && event->type() == QEvent::FocusIn) { + popupGrabbing = false; + } + + return QPlainTextEdit::eventFilter(obj, event); +} + +//bool EGS_Editor::openLinkAtCursorPosition() { +// QTextCursor cursor = this->textCursor(); +// int clickedPosition = cursor.position(); + +// // select the text in the clicked block and find out on +// // which position we clicked +// cursor.movePosition(QTextCursor::StartOfBlock); +// int positionFromStart = clickedPosition - cursor.position(); +// cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); + +// QString selectedText = cursor.selectedText(); + +// // find out which url in the selected text was clicked +// QString urlString = getMarkdownUrlAtPosition(selectedText, +// positionFromStart); +// QUrl url = QUrl(urlString); +// bool isRelativeFileUrl = urlString.startsWith("file://.."); + +// qDebug() << __func__ << " - 'emit urlClicked( urlString )': " +// << urlString; + +// emit urlClicked(urlString); + +// if ((url.isValid() && isValidUrl(urlString)) || isRelativeFileUrl) { +// // ignore some schemata +// if (!(_ignoredClickUrlSchemata.contains(url.scheme()) || +// isRelativeFileUrl)) { +// // open the url +// openUrl(urlString); +// } + +// return true; +// } + +// return false; +//} + diff --git a/HEN_HOUSE/egs++/view/egs_editor.h b/HEN_HOUSE/egs++/view/egs_editor.h new file mode 100644 index 000000000..960a222ac --- /dev/null +++ b/HEN_HOUSE/egs++/view/egs_editor.h @@ -0,0 +1,110 @@ +/* +############################################################################### +# +# EGSnrc egs++ egsinp editor +# Copyright (C) 2015 National Research Council Canada +# +# This file is part of EGSnrc. +# +# EGSnrc is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# EGSnrc is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for +# more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with EGSnrc. If not, see . +# +############################################################################### +# +# Author: Reid Townson, 2020 +# +# Contributors: +# +############################################################################### +*/ + +#ifndef EGS_EDITOR_H +#define EGS_EDITOR_H + +#include +#include +#include +#include +#include + +#include "egs_input_struct.h" + +class QPaintEvent; +class QResizeEvent; +class QSize; +class QWidget; + +class LineNumberArea; + +class EGS_Editor : public QPlainTextEdit { + Q_OBJECT + +public: + EGS_Editor(QWidget *parent = 0); + ~EGS_Editor(); + + void lineNumberAreaPaintEvent(QPaintEvent *event); + int lineNumberAreaWidth(); + void setInputStruct(shared_ptr inp); + void validateEntireInput(); + +protected: + void resizeEvent(QResizeEvent *event) override; + bool eventFilter(QObject *obj, QEvent *event); + +private slots: + void updateLineNumberAreaWidth(int newBlockCount); + void highlightCurrentLine(); + void validateLine(QTextCursor line); + void autoComplete(); + void insertCompletion(QModelIndex index); + void updateLineNumberArea(const QRect &, int); + +private: + shared_ptr getBlockInput(QString &blockTitle, QTextCursor cursor = QTextCursor()); + QString getBlockTitle(QTextCursor cursor = QTextCursor()); + QString getInputValue(QString inp, QTextBlock currentBlock, bool &foundTag); + QTextBlock getBlockEnd(QTextBlock currentBlock); + bool inputHasDependency(shared_ptr inp); + bool inputDependencySatisfied(shared_ptr inp, QTextCursor cursor = QTextCursor()); + QTextBlock findSiblingBlock(QString title, QTextBlock currentBlock); + int countStartingWhitespace(const QString &s); + + QWidget *lineNumberArea; + shared_ptr inputStruct; + QListView *popup; + QStringListModel *model; + bool popupGrabbing; +}; + + +class LineNumberArea : public QWidget { +public: + LineNumberArea(EGS_Editor *editor) : QWidget(editor) { + egsEditor = editor; + } + + QSize sizeHint() const override { + return QSize(egsEditor->lineNumberAreaWidth(), 0); + } + +protected: + void paintEvent(QPaintEvent *event) override { + egsEditor->lineNumberAreaPaintEvent(event); + } + +private: + EGS_Editor *egsEditor; +}; + +#endif // EGS_EDITOR_H diff --git a/HEN_HOUSE/egs++/view/egs_highlighter.cpp b/HEN_HOUSE/egs++/view/egs_highlighter.cpp new file mode 100644 index 000000000..6cb12704a --- /dev/null +++ b/HEN_HOUSE/egs++/view/egs_highlighter.cpp @@ -0,0 +1,124 @@ +/* +############################################################################### +# +# EGSnrc egs++ input highlighter +# Copyright (C) 2015 National Research Council Canada +# +# This file is part of EGSnrc. +# +# EGSnrc is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# EGSnrc is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for +# more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with EGSnrc. If not, see . +# +############################################################################### +# +# Author: Reid Townson, 2019 +# +# Contributors: +# +############################################################################### +*/ + +#include "egs_highlighter.h" + +EGS_Highlighter::EGS_Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) { + + HighlightingRule rule; + + keywordFormat.setForeground(Qt::darkRed); + keywordFormat.setFontWeight(QFont::Bold); + + QStringList keywordPatterns; + keywordPatterns << ":(start|stop).*\\S:"; + + foreach (const QString &pattern, keywordPatterns) { + rule.pattern = QRegularExpression(pattern); + rule.format = keywordFormat; + highlightingRules.append(rule); + } + + attributeFormat.setForeground(Qt::darkBlue); + rule.pattern = QRegularExpression(".*="); + rule.format = attributeFormat; + highlightingRules.append(rule); + + numberFormat.setForeground(Qt::darkGreen); + rule.pattern = QRegularExpression("[+-]?(\\d*\\.)?\\d"); + rule.format = numberFormat; + highlightingRules.append(rule); + + definitionFormat.setForeground(Qt::darkMagenta); + definitionFormat.setFontWeight(QFont::Bold); + rule.pattern = QRegularExpression(":(start|stop).*(definition|MC transport parameter|run control|scoring options):"); + rule.format = definitionFormat; + highlightingRules.append(rule); + + nameFormat.setForeground(Qt::darkBlue); + nameFormat.setFontWeight(QFont::Bold); + rule.pattern = QRegularExpression("( )*name( )*=.*"); + rule.format = nameFormat; + highlightingRules.append(rule); + + quotationFormat.setForeground(Qt::darkRed); + rule.pattern = QRegularExpression("\".*\""); + rule.format = quotationFormat; + highlightingRules.append(rule); + + squotationFormat.setForeground(Qt::red); + rule.pattern = QRegularExpression("\'.*\'"); + rule.format = squotationFormat; + highlightingRules.append(rule); + + // Comment highlighting must come last + singleLineCommentFormat.setForeground(Qt::gray); + rule.pattern = QRegularExpression("(#|//|!)[^\n]*"); + rule.format = singleLineCommentFormat; + highlightingRules.append(rule); + + // For multi-line comments + multiLineCommentFormat.setForeground(Qt::gray); + commentStartExpression = QRegularExpression("/\\*"); + commentEndExpression = QRegularExpression("\\*/"); +} + +void EGS_Highlighter::highlightBlock(const QString &text) { + foreach (const HighlightingRule &rule, highlightingRules) { + QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); + while (matchIterator.hasNext()) { + QRegularExpressionMatch match = matchIterator.next(); + setFormat(match.capturedStart(), match.capturedLength(), rule.format); + } + } + setCurrentBlockState(0); + + //For multi-line comments + int startIndex = 0; + if (previousBlockState() != 1) { + startIndex = text.indexOf(commentStartExpression); + } + + while (startIndex >= 0) { + QRegularExpressionMatch match = commentEndExpression.match(text, startIndex); + int endIndex = match.capturedStart(); + int commentLength = 0; + if (endIndex == -1) { + setCurrentBlockState(1); + commentLength = text.length() - startIndex; + } + else { + commentLength = endIndex - startIndex + + match.capturedLength(); + } + setFormat(startIndex, commentLength, multiLineCommentFormat); + startIndex = text.indexOf(commentStartExpression, startIndex + commentLength); + } +} diff --git a/HEN_HOUSE/egs++/view/egs_highlighter.h b/HEN_HOUSE/egs++/view/egs_highlighter.h new file mode 100644 index 000000000..a6eadc49e --- /dev/null +++ b/HEN_HOUSE/egs++/view/egs_highlighter.h @@ -0,0 +1,75 @@ +/* +############################################################################### +# +# EGSnrc egs++ input highlighter +# Copyright (C) 2015 National Research Council Canada +# +# This file is part of EGSnrc. +# +# EGSnrc is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# EGSnrc is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for +# more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with EGSnrc. If not, see . +# +############################################################################### +# +# Author: Reid Townson, 2019 +# +# Contributors: +# +############################################################################### +*/ + +#ifndef EGS_HIGHLIGHTER_H +#define EGS_HIGHLIGHTER_H + +#include +#include +#include + +class QTextDocument; + +class EGS_Highlighter : public QSyntaxHighlighter { + Q_OBJECT +public: + explicit EGS_Highlighter(QTextDocument *parent = nullptr); + +protected: + void highlightBlock(const QString &text) override; + +private: + struct HighlightingRule { + QRegularExpression pattern; + QTextCharFormat format; + }; + QVector highlightingRules; + + QRegularExpression commentStartExpression, + commentEndExpression; + + QTextCharFormat keywordFormat, + attributeFormat, + numberFormat, + definitionFormat, + nameFormat, + singleLineCommentFormat, + multiLineCommentFormat, + quotationFormat, + squotationFormat, + functionFormat; + +signals: + +public slots: + +}; + +#endif // EGS_HIGHLIGHTER_H diff --git a/HEN_HOUSE/egs++/view/view.pro b/HEN_HOUSE/egs++/view/view.pro index af1a8c9ce..f899d73f5 100644 --- a/HEN_HOUSE/egs++/view/view.pro +++ b/HEN_HOUSE/egs++/view/view.pro @@ -37,11 +37,15 @@ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets HEADERS += egs_visualizer.h image_window.h egs_light.h \ clippingplanes.h viewcontrol.h geometryview.ui.h \ saveimage.h egs_user_color.h egs_track_view.h \ - renderworker.h + renderworker.h \ + egs_highlighter.h \ + egs_editor.h SOURCES += main.cpp egs_visualizer.cpp egs_track_view.cpp \ saveimage.cpp clippingplanes.cpp viewcontrol.cpp \ - renderworker.cpp image_window.cpp + renderworker.cpp image_window.cpp \ + egs_highlighter.cpp \ + egs_editor.cpp FORMS = saveimage.ui clippingplanes.ui viewcontrol.ui @@ -72,7 +76,7 @@ unix { message( "Static build ..." ) DESTDIR = ../../pieces/linux #LIBS += -L../dso/$$my_machine -Wl,-rpath,$$hhouse/egs++/dso/$$my_machine -legspp # Fixes path to library - LIBS += -L$$hhouse/egs++/dso/$$my_machine -legspp # Relies on LD_LIBRARY_PATH + LIBS += -L../dso/$$my_machine -legspp # Relies on LD_LIBRARY_PATH UNAME = $$system(getconf LONG_BIT) contains( UNAME, 64 ){ message( "-> 64 bit ($$SNAME)" ) @@ -88,7 +92,7 @@ unix { } # Debug options -#DEFINES += VIEW_DEBUG +#DEFINES += VIEW_DEBUG EDITOR_DEBUG #QMAKE_CXXFLAGS+="-fsanitize=address -fno-omit-frame-pointer" #QMAKE_CXXFLAGS+="-ggdb3" #QMAKE_LFLAGS+="-fsanitize=address" @@ -103,5 +107,3 @@ greaterThan(QMAKE_GCC_MAJOR_VERSION, 4) { UI_DIR = .ui/$$my_machine MOC_DIR = .moc/$$my_machine OBJECTS_DIR = .obj/$$my_machine - - diff --git a/HEN_HOUSE/egs++/view/viewcontrol.cpp b/HEN_HOUSE/egs++/view/viewcontrol.cpp index 5d3bd48ab..1234f5921 100644 --- a/HEN_HOUSE/egs++/view/viewcontrol.cpp +++ b/HEN_HOUSE/egs++/view/viewcontrol.cpp @@ -19,7 +19,7 @@ # You should have received a copy of the GNU Affero General Public License # along with EGSnrc. If not, see . # -############################################################################### +####################################################################8########### # # Author: Iwan Kawrakow, 2005 # @@ -27,6 +27,7 @@ # Ernesto Mainegra-Hing # Manuel Stoeckl # Reid Townson +# Hannah Gallop # ############################################################################### */ @@ -39,11 +40,14 @@ #include "egs_libconfig.h" #include "egs_functions.h" #include "egs_base_geometry.h" +#include "egs_shapes.h" #include "egs_visualizer.h" #include "egs_timer.h" #include "egs_input.h" #include "egs_ausgab_object.h" #include "ausgab_objects/egs_dose_scoring/egs_dose_scoring.h" +#include "egs_library.h" +#include "egs_input_struct.h" #include #include @@ -56,6 +60,7 @@ #include #include #include +#include #include #include @@ -68,6 +73,29 @@ using namespace std; #define M_PI 3.14159265358979323846 #endif +typedef EGS_Application *(*createAppFunction)(int argc, char **argv); +typedef EGS_BaseGeometry *(*createGeomFunction)(); +typedef EGS_BaseSource *(*createSourceFunction)(); +typedef EGS_BaseShape *(*createShapeFunction)(); +typedef EGS_AusgabObject *(*createAusgabObjectFunction)(); +typedef void (*getAppInputsFunction)(shared_ptr inpPtr); +typedef shared_ptr (*getInputsFunction)(); +typedef string(*getExampleFunction)(); + +#ifdef WIN32 + #ifdef CYGWIN + const char fs = '/'; + #else + const char fs = '\\'; + #endif + string lib_prefix = ""; + string lib_suffix = ".dll"; +#else + const char fs = '/'; + string lib_prefix = "lib"; + string lib_suffix = ".so"; +#endif + static unsigned char standard_red[] = { 255, 0, 0, 0, 255, 255, 128, 0, 0, 0, 128, 128, 191, 80, 0, 0, 0, 0, 85, 255, 192, 128 @@ -165,6 +193,9 @@ GeometryViewControl::GeometryViewControl(QWidget *parent, const char *name) connect(gview, SIGNAL(leftMouseClick(int,int)), this, SLOT(reportViewSettings(int,int))); connect(gview, SIGNAL(leftDoubleClick(EGS_Vector)), this, SLOT(setRotationPoint(EGS_Vector))); connect(gview, SIGNAL(tracksLoaded(vector)), this, SLOT(updateTracks(vector))); + connect(global_transparency, SIGNAL(sliderReleased()), this, SLOT(endTransformation())); + connect(global_transparency, SIGNAL(sliderPressed()), this, SLOT(startTransformation())); + connect(global_transparency, SIGNAL(valueChanged(int)), this, SLOT(changeGlobalTransparency(int))); save_image = new SaveImage(this,"save image"); @@ -175,8 +206,325 @@ GeometryViewControl::GeometryViewControl(QWidget *parent, const char *name) // Add the clipping planes widget to the designated layout clipLayout->addWidget(cplanes); - // set the widget to show near the left-upper corner of the screen - move(QPoint(25,25)); + // Initialize the editor and syntax highlighter + egsinpEdit = new EGS_Editor(); + editorLayout->addWidget(egsinpEdit); + highlighter = new EGS_Highlighter(egsinpEdit->document()); + +// TODO: This is an example of how to load an application for egs_editor inputs +// // Load an egs++ application to parse the input file +// string app_name; + int appc = 5; + char *appv[] = { "egspp", "-a", "tutor7pp", "-i", "tracks1.egsinp", "-p", "tutor_data"}; +// +// // Appv: %s -a application [-p pegs_file] [-i input_file] [-o output_file] [-b] [-P number_of_parallel_jobs] [-j job_index] +// if (!EGS_Application::getArgument(appc,appv,"-a","--application",app_name)) { +// egsFatal("test fail\n\n"); +// } +// +// string lib_dir; +// EGS_Application::checkEnvironmentVar(appc,appv,"-e","--egs-home","EGS_HOME",lib_dir); +// lib_dir += "bin"; +// lib_dir += fs; +// lib_dir += CONFIG_NAME; +// lib_dir += fs; +// +// // Load the application library +// // We don't require the application to be compiled, just give a warning if it isn't. +// EGS_Library app_lib(app_name.c_str(),lib_dir.c_str()); +// bool app_loaded = true; +// if (!app_lib.load()) { +// egsWarning("\n%s: Failed to load the %s application library from %s\n\n", appv[0],app_name.c_str(),lib_dir.c_str()); +// app_loaded = false; +// } else { +// createAppFunction createApp = (createAppFunction) app_lib.resolve("createApplication"); +// if (!createApp) { +// egsWarning("\n%s: Failed to resolve the address of the 'createApplication' function in the application library %s\n\n",appv[0],app_lib.libraryFile()); +// app_loaded = false; +// } else { +// EGS_Application *app = createApp(appc,appv); +// if (!app) { +// egsWarning("\n%s: Failed to construct the application %s\n\n",appv[0],app_name.c_str()); +// app_loaded = false; +// } +// egsInformation("Testapp %f\n",app->getRM()); +// delete app; +// } +// } + + + + + // Get a list of all the libraries in the dso directory + string dso_dir; + EGS_Application::checkEnvironmentVar(appc,appv,"-H","--hen-house","HEN_HOUSE",dso_dir); + dso_dir += "egs++"; + dso_dir += fs; + dso_dir += "dso"; + dso_dir += fs; + dso_dir += CONFIG_NAME; + dso_dir += fs; + + QDir directory(dso_dir.c_str()); + QStringList libraries = directory.entryList(QStringList() << (lib_prefix+"*"+lib_suffix).c_str(), QDir::Files); + + // Create an examples drop down menu on the editor tab + QMenuBar *menuBar = new QMenuBar(); + QMenu *exampleMenu = new QMenu("Insert example..."); + menuBar->addMenu(exampleMenu); + QMenu *geomMenu = exampleMenu->addMenu("Geometries"); + QMenu *sourceMenu = exampleMenu->addMenu("Sources"); + QMenu *shapeMenu = exampleMenu->addMenu("Shapes"); + QMenu *ausgabMenu = exampleMenu->addMenu("Ausgab/Output"); + QMenu *mediaMenu = exampleMenu->addMenu("Media"); + QMenu *runMenu = exampleMenu->addMenu("Run Control"); + QMenu *appMenu = exampleMenu->addMenu("Applications"); + editorLayout->setMenuBar(menuBar); + + // The input template structure + inputStruct = make_shared(); + +// // Get the application level input blocks +// if(app_loaded) { +// getAppInputsFunction getAppInputs = (getAppInputsFunction) app_lib.resolve("getAppInputs"); +// if(getAppInputs) { +// getAppInputs(inputStruct); +// if(inputStruct) { +// vector> inputBlocks = inputStruct->getBlockInputs(); +// for (auto &block : inputBlocks) { +// egsInformation(" block %s\n", block->getTitle().c_str()); +// vector> singleInputs = block->getSingleInputs(); +// for (auto &inp : singleInputs) { +// const vector vals = inp->getValues(); +// egsInformation(" single %s\n", inp->getTag().c_str()); +// for (auto&& val : vals) { +// egsInformation(" %s\n", val.c_str()); +// } +// } +// } +// } +// } +// } + + // Geometry definition block + auto geomDefPtr = inputStruct->addBlockInput("geometry definition"); + geomDefPtr->addSingleInput("simulation geometry", true, "The name of the geometry that will be used in the simulation, or to be viewed in egs_view. If you have created a composite geometry using many other geometries, name the final composite geometry here. Note that in some applications, the calculation geometry input block overrides this input, but it is still required."); + + // Source definition block + auto srcDefPtr = inputStruct->addBlockInput("source definition"); + srcDefPtr->addSingleInput("simulation source", true, "The name of the source that will be used in the simulation. If you have created a composite source using many other sources, name the final composite source here."); + + // Ausgab Object definition block + auto ausDefPtr = inputStruct->addBlockInput("ausgab object definition"); + +#ifdef EDITOR_DEBUG + egsInformation("Loading libraries for egs_editor...\n"); +#endif + + // For each library, try to load it and determine if it is geometry or source + for (const auto &lib : libraries) { + // Remove the extension + QString libName = lib.left(lib.lastIndexOf(".")); + // Remove the prefix (EGS_Library adds it automatically) + libName = libName.right(libName.length() - lib_prefix.length()); + +#ifdef EDITOR_DEBUG + egsInformation("Trying %s\n", libName.toLatin1().data()); +#endif + // Skip any library files that start with Qt + // For dynamic builds, there may be QtCore, QtWidgets, etc. files in the dso directory + if (lib.startsWith("Qt")) { + continue; + } + + EGS_Library egs_lib(libName.toLatin1().data(),dso_dir.c_str()); + if (!egs_lib.load()) { + continue; + } + + // Geometries + createGeomFunction isGeom = (createGeomFunction) egs_lib.resolve("createGeometry"); + if (isGeom) { +#ifdef EDITOR_DEBUG + egsInformation(" Geometry %s\n",libName.toLatin1().data()); +#endif + + getInputsFunction getInputs = (getInputsFunction) egs_lib.resolve("getInputs"); + if (getInputs) { + + shared_ptr geom = getInputs(); + if (geom) { + geomDefPtr->addBlockInput(geom); + + vector> singleInputs = geom->getSingleInputs(); + for (auto &inp : singleInputs) { + const vector vals = inp->getValues(); +// egsInformation(" single %s\n", inp->getTag().c_str()); +// for (auto&& val : vals) { +// egsInformation(" %s\n", val.c_str()); +// } + } + + vector> inputBlocks = geom->getBlockInputs(); + for (auto &block : inputBlocks) { + //egsInformation(" block %s\n", block->getTitle().c_str()); + vector> singleInputs = block->getSingleInputs(); + for (auto &inp : singleInputs) { + const vector vals = inp->getValues(); +// egsInformation(" single %s\n", inp->getTag().c_str()); +// for (auto&& val : vals) { +// egsInformation(" %s\n", val.c_str()); +// } + } + } + } + } + getExampleFunction getExample = (getExampleFunction) egs_lib.resolve("getExample"); + if (getExample) { + QAction *action = geomMenu->addAction(libName); + action->setData(QString::fromStdString(getExample())); + connect(action, &QAction::triggered, this, [this] { insertInputExample(); }); + } + } + + // Sources + createSourceFunction isSource = (createSourceFunction) egs_lib.resolve("createSource"); + if (isSource) { +#ifdef EDITOR_DEBUG + egsInformation(" Source %s\n",libName.toLatin1().data()); +#endif + + getInputsFunction getInputs = (getInputsFunction) egs_lib.resolve("getInputs"); + if (getInputs) { + + shared_ptr src = getInputs(); + if (src) { + srcDefPtr->addBlockInput(src); + + vector> singleInputs = src->getSingleInputs(); + for (auto &inp : singleInputs) { + const vector vals = inp->getValues(); +// egsInformation(" single %s\n", inp->getTag().c_str()); +// for (auto&& val : vals) { +// egsInformation(" %s\n", val.c_str()); +// } + } + + vector> inputBlocks = src->getBlockInputs(); + for (auto &block : inputBlocks) { + //egsInformation(" block %s\n", block->getTitle().c_str()); + vector> singleInputs = block->getSingleInputs(); + for (auto &inp : singleInputs) { + const vector vals = inp->getValues(); +// egsInformation(" single %s\n", inp->getTag().c_str()); +// for (auto&& val : vals) { +// egsInformation(" %s\n", val.c_str()); +// } + } + } + } + } + + getExampleFunction getExample = (getExampleFunction) egs_lib.resolve("getExample"); + if (getExample) { + QAction *action = sourceMenu->addAction(libName); + action->setData(QString::fromStdString(getExample())); + connect(action, &QAction::triggered, this, [this] { insertInputExample(); }); + } + } + + // Shapes + createShapeFunction isShape = (createShapeFunction) egs_lib.resolve("createShape"); + if (isShape) { +#ifdef EDITOR_DEBUG + egsInformation(" Shape %s\n",libName.toLatin1().data()); +#endif + + getInputsFunction getInputs = (getInputsFunction) egs_lib.resolve("getInputs"); + if (getInputs) { + + shared_ptr shape = getInputs(); + if (shape) { + inputStruct->addBlockInput(shape); + + vector> singleInputs = shape->getSingleInputs(); + for (auto &inp : singleInputs) { + const vector vals = inp->getValues(); +// egsInformation(" single %s\n", inp->getTag().c_str()); +// for (auto&& val : vals) { +// egsInformation(" %s\n", val.c_str()); +// } + } + + vector> inputBlocks = shape->getBlockInputs(); + for (auto &block : inputBlocks) { + //egsInformation(" block %s\n", block->getTitle().c_str()); + vector> singleInputs = block->getSingleInputs(); + for (auto &inp : singleInputs) { + const vector vals = inp->getValues(); +// egsInformation(" single %s\n", inp->getTag().c_str()); +// for (auto&& val : vals) { +// egsInformation(" %s\n", val.c_str()); +// } + } + } + } + } + + getExampleFunction getExample = (getExampleFunction) egs_lib.resolve("getExample"); + if (getExample) { + QAction *action = shapeMenu->addAction(libName); + action->setData(QString::fromStdString(getExample())); + connect(action, &QAction::triggered, this, [this] { insertInputExample(); }); + } + } + + // Ausgab Objects + createAusgabObjectFunction isAusgabObject = (createAusgabObjectFunction) egs_lib.resolve("createAusgabObject"); + if (isAusgabObject) { +#ifdef EDITOR_DEBUG + egsInformation(" Ausgab %s\n",libName.toLatin1().data()); +#endif + + getInputsFunction getInputs = (getInputsFunction) egs_lib.resolve("getInputs"); + if (getInputs) { + + shared_ptr aus = getInputs(); + if (aus) { + ausDefPtr->addBlockInput(aus); + + vector> singleInputs = aus->getSingleInputs(); + for (auto &inp : singleInputs) { + const vector vals = inp->getValues(); +// egsInformation(" single %s\n", inp->getTag().c_str()); +// for (auto&& val : vals) { +// egsInformation(" %s\n", val.c_str()); +// } + } + + vector> inputBlocks = aus->getBlockInputs(); + for (auto &block : inputBlocks) { + //egsInformation(" block %s\n", block->getTitle().c_str()); + vector> singleInputs = block->getSingleInputs(); + for (auto &inp : singleInputs) { + const vector vals = inp->getValues(); +// egsInformation(" single %s\n", inp->getTag().c_str()); +// for (auto&& val : vals) { +// egsInformation(" %s\n", val.c_str()); +// } + } + } + } + } + getExampleFunction getExample = (getExampleFunction) egs_lib.resolve("getExample"); + if (getExample) { + QAction *action = ausgabMenu->addAction(libName); + action->setData(QString::fromStdString(getExample())); + connect(action, &QAction::triggered, this, [this] { insertInputExample(); }); + } + } + } + egsinpEdit->setInputStruct(inputStruct); } GeometryViewControl::~GeometryViewControl() { @@ -195,6 +543,12 @@ GeometryViewControl::~GeometryViewControl() { delete EGS_AusgabObject::getObject(i); } } + if (egsinpEdit) { + delete egsinpEdit; + } + if (highlighter) { + delete highlighter; + } } void GeometryViewControl::selectInput() { @@ -225,7 +579,7 @@ bool GeometryViewControl::loadInput(bool reloading, EGS_BaseGeometry *simGeom) { // check that the file (still) exists QFile file(filename); if (!file.exists()) { - egsWarning("\nFile %s does not exist anymore!\n\n",filename.toUtf8().constData()); + egsWarning("\nInput file %s does not exist!\n\n",filename.toUtf8().constData()); return false; } @@ -411,6 +765,12 @@ bool GeometryViewControl::loadInput(bool reloading, EGS_BaseGeometry *simGeom) { // See if any of the dose checkboxes are checked doseCheckbox_toggled(); + // Load the egsinp file into the editor + if (file.open(QFile::ReadOnly | QFile::Text)) { + egsinpEdit->setPlainText(file.readAll()); + egsinpEdit->validateEntireInput(); + } + return true; } @@ -688,6 +1048,8 @@ void GeometryViewControl::loadConfig(QString configFilename) { } // Load the particle track options + label_particles->hide(); + label_particle_colours->hide(); EGS_Input *iTracks = input->takeInputItem("tracks"); if (iTracks) { int show; @@ -725,9 +1087,26 @@ void GeometryViewControl::loadConfig(QString configFilename) { showPositronsCheckbox->setCheckState(Qt::Unchecked); } } - delete iTracks; } + else { + label_particles->show(); + spin_tmaxp->hide(); + showPositronsCheckbox->hide(); + showPhotonsCheckbox->hide(); + showElectronsCheckbox->hide(); + spin_tminp->hide(); + spin_tmine->hide(); + spin_tmaxe->hide(); + spin_tminpo->hide(); + spin_tmaxpo->hide(); + + label_particle_colours->show(); + cPhotonsButton->hide(); + cElectronsButton->hide(); + cPositronsButton->hide(); + energyScalingCheckbox->hide(); + } // Load the overlay options EGS_Input *iOverlay = input->takeInputItem("overlay"); @@ -908,6 +1287,22 @@ void GeometryViewControl::loadConfig(QString configFilename) { // Load the clipping planes EGS_Input *iClip = input->takeInputItem("clipping planes"); + // Set default clipped planes, along each axis + cplanes->setCell(0,0,1); + cplanes->setCell(0,1, 0); + cplanes->setCell(0,2,0); + cplanes->setCell(0,3,0); + cplanes->setCell(0,4,Qt::Unchecked); + cplanes->setCell(1,0,0); + cplanes->setCell(1,1,1); + cplanes->setCell(1,2,0); + cplanes->setCell(1,3,0); + cplanes->setCell(1,4,Qt::Unchecked); + cplanes->setCell(2,0,0); + cplanes->setCell(2,1,0); + cplanes->setCell(2,2,1); + cplanes->setCell(2,3,0); + cplanes->setCell(2,4,Qt::Unchecked); if (iClip) { for (int i=0; inumPlanes(); i++) { EGS_Input *iPlane = iClip->takeInputItem("plane"); @@ -922,6 +1317,9 @@ void GeometryViewControl::loadConfig(QString configFilename) { if (!err) { cplanes->setCell(i,0,ax); } + /*else if (i == 0) { + cplanes->setCell(0, 0, 1); + }*/ else { cplanes->clearCell(i,0); } @@ -1074,6 +1472,26 @@ void GeometryViewControl::loadConfig(QString configFilename) { updateView(true); } +void GeometryViewControl::saveEgsinp() { +#ifdef VIEW_DEBUG + egsWarning("In saveEgsinp()\n"); +#endif + + // Prompt the user for a filename and open the file for writing + QString newFilename = QFileDialog::getSaveFileName(this, "Save input file as...", filename); + QFile egsinpFile(newFilename); + if (!egsinpFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + return; + } + QTextStream out(&egsinpFile); + + // Write the text from the editor window + out << egsinpEdit->toPlainText() << flush; + + // Reload the input so that the changes are recognized + reloadInput(); +} + void GeometryViewControl::setFilename(QString str) { filename = str; } @@ -1716,6 +2134,16 @@ void GeometryViewControl::changeTransparency(int t) { updateView(true); } +void GeometryViewControl::changeGlobalTransparency(int t) { + int test = materialCB->count(); + for (int i = 0; i <= test; i++) { + int med = materialCB->count() - i; + QRgb c = m_colors[med]; + m_colors[med] = qRgba(qRed(c), qGreen(c), qBlue(c), t); + } + updateView(true); +} + void GeometryViewControl::changeDoseTransparency(int t) { #ifdef VIEW_DEBUG egsWarning("In changeDoseTransparency(%d)\n",t); @@ -1895,7 +2323,6 @@ void GeometryViewControl::loadTracksDialog() { if (filename_tracks.isEmpty()) { return; } - gview->loadTracks(filename_tracks); } @@ -1907,6 +2334,22 @@ void GeometryViewControl::updateTracks(vector ntracks) { #ifdef VIEW_DEBUG egsWarning("In updateTracks(%d %d %d)\n",ntracks[0], ntracks[1], ntracks[2]); #endif + label_particles->hide(); + spin_tmaxp->show(); + showPositronsCheckbox->show(); + showPhotonsCheckbox->show(); + showElectronsCheckbox->show(); + spin_tminp->show(); + spin_tmine->show(); + spin_tmaxe->show(); + spin_tminpo->show(); + spin_tmaxpo->show(); + + label_particle_colours->hide(); + cPhotonsButton->show(); + cElectronsButton->show(); + cPositronsButton->show(); + energyScalingCheckbox->show(); // Update maximum values for the track selection spin_tminp->setMaximum(ntracks[0]); @@ -2354,39 +2797,38 @@ int GeometryViewControl::setGeometry( axesmax = pmax + EGS_Vector(size, size, size)*0.3; - if (!justReloading) { - distance = size*3.5; // ~2*sqrt(3); - look_at = center; - look_at_home = look_at; - setLookAtLineEdit(); - if (distance > 60000) { - egsWarning("too big: %g\n",size); - distance = 9999; - } - else { - zoomlevel = -112; - } - setProjectionLineEdit(); - //p_light = look_at+EGS_Vector(s_theta*s_phi,s_theta*s_phi,c_theta)*distance; - p_light = look_at+EGS_Vector(s_theta*s_phi,s_theta*s_phi,c_theta)*3*distance; - setLightLineEdit(); - camera = p_light; - screen_xo = look_at-EGS_Vector(s_theta*s_phi,s_theta*s_phi,c_theta)*distance; - screen_v1 = EGS_Vector(c_phi,-s_phi,0); - screen_v2 = EGS_Vector(c_theta*s_phi,c_theta*c_phi,-s_theta); + // Set or reset the viewing window + distance = size*3.5; // ~2*sqrt(3); + look_at = center; + look_at_home = look_at; + setLookAtLineEdit(); + if (distance > 60000) { + egsWarning("too big: %g\n",size); + distance = 9999; + } + else { + zoomlevel = -112; + } + setProjectionLineEdit(); + //p_light = look_at+EGS_Vector(s_theta*s_phi,s_theta*s_phi,c_theta)*distance; + p_light = look_at+EGS_Vector(s_theta*s_phi,s_theta*s_phi,c_theta)*3*distance; + setLightLineEdit(); + camera = p_light; + screen_xo = look_at-EGS_Vector(s_theta*s_phi,s_theta*s_phi,c_theta)*distance; + screen_v1 = EGS_Vector(c_phi,-s_phi,0); + screen_v2 = EGS_Vector(c_theta*s_phi,c_theta*c_phi,-s_theta); - // camera orientation vectors (same as the screen vectors) - camera_v1 = screen_v1; - camera_v2 = screen_v2; + // camera orientation vectors (same as the screen vectors) + camera_v1 = screen_v1; + camera_v2 = screen_v2; - // save camera home position - camera_home = camera; - camera_home_v1 = camera_v1; - camera_home_v2 = camera_v2; - zoomlevel_home = zoomlevel; + // save camera home position + camera_home = camera; + camera_home_v1 = camera_v1; + camera_home_v2 = camera_v2; + zoomlevel_home = zoomlevel; - setCameraLineEdit(); - } + setCameraLineEdit(); updateView(); @@ -2932,6 +3374,8 @@ void GeometryViewControl::enlargeFont() { controlsText->selectAll(); controlsText->setFontPointSize(controlsFont.pointSize() + 1); controlsText->setTextCursor(cursor); + + egsinpEdit->zoomIn(); } void GeometryViewControl::shrinkFont() { @@ -2946,6 +3390,8 @@ void GeometryViewControl::shrinkFont() { controlsText->selectAll(); controlsText->setFontPointSize(controlsFont.pointSize() - 1); controlsText->setTextCursor(cursor); + + egsinpEdit->zoomOut(); } void GeometryViewControl::setFontSize(int size) { @@ -2962,3 +3408,11 @@ void GeometryViewControl::setFontSize(int size) { controlsText->setTextCursor(cursor); } +void GeometryViewControl::insertInputExample() { + QAction *pAction = qobject_cast(sender()); + + QTextCursor cursor(egsinpEdit->textCursor()); + egsinpEdit->insertPlainText(pAction->data().toString()); +} + + diff --git a/HEN_HOUSE/egs++/view/viewcontrol.h b/HEN_HOUSE/egs++/view/viewcontrol.h index 13c7d0e76..f0a1c3888 100644 --- a/HEN_HOUSE/egs++/view/viewcontrol.h +++ b/HEN_HOUSE/egs++/view/viewcontrol.h @@ -38,6 +38,9 @@ #include #include "egs_user_color.h" #include "egs_vector.h" +#include "egs_highlighter.h" +#include "egs_editor.h" +#include "egs_advanced_application.h" #include @@ -84,6 +87,7 @@ public slots: virtual void loadDose(); virtual void loadConfig(); virtual void saveConfig(); + virtual void saveEgsinp(); virtual void updateSimulationGeometry(int ind); virtual void checkboxAxes(bool toggle); virtual void checkboxAxesLabels(bool toggle); @@ -105,6 +109,7 @@ public slots: virtual void phiRotation(int Phi); virtual void changeAmbientLight(int alight); virtual void changeTransparency(int t); + virtual void changeGlobalTransparency(int t); virtual void moveLightChanged(int toggle); virtual void setLightPosition(); virtual void setLookAt(); @@ -143,6 +148,7 @@ public slots: virtual void changeTrackMaxE(int t); virtual void changeTrackMaxPo(int t); virtual void updateTracks(vector ntracks); + virtual void insertInputExample(); private: @@ -199,7 +205,13 @@ public slots: energyScaling; vector> scoreArrays; vector geometryNames; + vector inputExamples; EGS_BaseGeometry *origSimGeom; + EGS_Editor *egsinpEdit; + EGS_Highlighter *highlighter; + EGS_AdvancedApplication *egsApp; + shared_ptr inputStruct; + QMenu *exampleMenu; protected slots: diff --git a/HEN_HOUSE/egs++/view/viewcontrol.ui b/HEN_HOUSE/egs++/view/viewcontrol.ui index bec3933d2..a283f8258 100644 --- a/HEN_HOUSE/egs++/view/viewcontrol.ui +++ b/HEN_HOUSE/egs++/view/viewcontrol.ui @@ -65,7 +65,7 @@ 0 - + 0 @@ -91,7 +91,7 @@ 0 0 671 - 563 + 567 @@ -155,7 +155,7 @@ - Simulation geometry + View geometry @@ -184,123 +184,6 @@ - - - - - 0 - 0 - - - - - 0 - 120 - - - - - 16777215 - 16777215 - - - - Particle tracks - - - - - - 1 - - - 1 - - - - - - - Positrons - - - true - - - - - - - Photons - - - true - - - - - - - Electrons - - - true - - - - - - - 1 - - - 1 - - - - - - - 1 - - - 1 - - - - - - - 1 - - - 1 - - - - - - - 1 - - - 1 - - - - - - - 1 - - - 1 - - - - - - @@ -380,6 +263,155 @@ + + + + + 0 + 0 + + + + + 0 + 120 + + + + + 16777215 + 16777215 + + + + Use egs_track_scoring to output a ptracks file + + + Particle tracks + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + 3 + + + + + Electrons + + + true + + + + + + + 1 + + + 1 + + + + + + + 1 + + + 1 + + + + + + + 1 + + + 1 + + + + + + + 1 + + + 1 + + + + + + + Photons + + + true + + + + + + + Positrons + + + true + + + + + + + 1 + + + 1 + + + + + + + 1 + + + 1 + + + + + + + + + No particle tracks found + + + Qt::AlignCenter + + + + + + @@ -408,16 +440,31 @@ 6 - - - 100 - - - 50 - - - Qt::Horizontal + + + Opacity + + + + + 100 + + + 50 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + + @@ -425,12 +472,20 @@ - QFrame::Box + QFrame::NoFrame true + + + 0 + 0 + 301 + 155 + + @@ -440,7 +495,7 @@ - No ausgab objects found + No dose files found Qt::AlignCenter @@ -543,7 +598,7 @@ - Transparency + Opacity @@ -568,6 +623,34 @@ + + + + Global Opacity + + + + + + 255 + + + 255 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 25 + + + + + + @@ -699,6 +782,16 @@ + + + + No particle tracks found + + + Qt::AlignCenter + + + @@ -1638,15 +1731,15 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Cantarell'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Rotate: </span><span style=" font-size:10pt;">hold left MB</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Zoom:</span><span style=" font-size:10pt;"> scroll or hold middle MB</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Pan: </span><span style=" font-size:10pt;">Ctrl + left MB</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Roll:</span><span style=" font-size:10pt;"> Shift + left MB</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Set rotation point:</span><span style=" font-size:10pt;"> double left MB</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Home:</span><span style=" font-size:10pt;"> Home</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Set home:</span><span style=" font-size:10pt;"> Alt + Home</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Look along X (Y or Z): </span><span style=" font-size:10pt;">x (y or z)</span></p></body></html> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell'; font-size:10pt; font-weight:600;">Rotate: </span><span style=" font-family:'Cantarell'; font-size:10pt;">hold left MB</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell'; font-size:10pt; font-weight:600;">Zoom:</span><span style=" font-family:'Cantarell'; font-size:10pt;"> scroll or hold middle MB</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell'; font-size:10pt; font-weight:600;">Pan: </span><span style=" font-family:'Cantarell'; font-size:10pt;">Ctrl + left MB</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell'; font-size:10pt; font-weight:600;">Roll:</span><span style=" font-family:'Cantarell'; font-size:10pt;"> Shift + left MB</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell'; font-size:10pt; font-weight:600;">Set rotation point:</span><span style=" font-family:'Cantarell'; font-size:10pt;"> double left MB</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell'; font-size:10pt; font-weight:600;">Home:</span><span style=" font-family:'Cantarell'; font-size:10pt;"> Home</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell'; font-size:10pt; font-weight:600;">Set home:</span><span style=" font-family:'Cantarell'; font-size:10pt;"> Alt + Home</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell'; font-size:10pt; font-weight:600;">Look along X (Y or Z): </span><span style=" font-family:'Cantarell'; font-size:10pt;">x (y or z)</span></p></body></html> @@ -1657,6 +1750,18 @@ p, li { white-space: pre-wrap; } + + + + 0 + 0 + + + + Editor (experimental) + + + @@ -1673,7 +1778,7 @@ p, li { white-space: pre-wrap; } 0 0 675 - 25 + 21 @@ -1685,6 +1790,7 @@ p, li { white-space: pre-wrap; } + @@ -1704,7 +1810,7 @@ p, li { white-space: pre-wrap; } - &Open... + &Open egsinp... Ctrl+O @@ -1720,7 +1826,7 @@ p, li { white-space: pre-wrap; } - Save &image... + Save &image Ctrl+I @@ -1728,10 +1834,10 @@ p, li { white-space: pre-wrap; } - &Save settings... + Save settin&gs - Ctrl+S + Ctrl+G @@ -1768,7 +1874,7 @@ p, li { white-space: pre-wrap; } - Open &dose... + Open 3d&dose... Ctrl+D @@ -1776,12 +1882,20 @@ p, li { white-space: pre-wrap; } - Open trac&ks... + Open ptrac&ks... Ctrl+K + + + &Save egsinp + + + Ctrl+S + + @@ -2174,6 +2288,22 @@ p, li { white-space: pre-wrap; } + + actionSave_egsinp + triggered() + GeometryViewControl + saveEgsinp() + + + -1 + -1 + + + 20 + 20 + + + showPhotonsCheckbox toggled(bool)