diff --git a/nain4/src/n4_run_manager.hh b/nain4/src/n4_run_manager.hh index 0f161b74..7d99e726 100644 --- a/nain4/src/n4_run_manager.hh +++ b/nain4/src/n4_run_manager.hh @@ -149,6 +149,8 @@ private: set_physics& apply_command (const G4String& command ) { ui.apply (command ); return *this; } set_physics& apply_early_macro(const G4String& filename) { ui.run_macro(filename); return *this; } set_physics& apply_cli_early_macro( ) { ui.run_early_macro() ; return *this; } + set_physics& macro_path (const G4String& path ) { ui.prepend_path(path) ; return *this; } + using fn_type = std::function; NEXT_STATE_BASIC(set_geometry, physics, G4VUserPhysicsList) NEXT_CONSTRUCT (set_geometry, physics) diff --git a/nain4/src/n4_ui.cc b/nain4/src/n4_ui.cc index 7664cf0e..431afb4b 100644 --- a/nain4/src/n4_ui.cc +++ b/nain4/src/n4_ui.cc @@ -23,17 +23,20 @@ unsigned parse_beam_on(const std::string& arg) { argparse::ArgumentParser define_args(const std::string& program_name, int argc, char** argv) { argparse::ArgumentParser args{program_name}; - args.add_argument("--beam-on" , "-n", "-b").metavar("N-EVENTS").help("run simulation with given number of events"); - args.add_argument("--early-macro", "-e" ).metavar("FILENAME").help("execute before run manager instantiation"); - args.add_argument( "--late-macro", "-l" ).metavar("FILENAME").help("execute after run manager instantiation"); - args.add_argument( "--vis-macro", "-g" ).metavar("FILENAME").help("switch from batch mode to GUI, executing this macro"); + args.add_argument("--beam-on" , "-n", "-b").metavar("N-EVENTS" ).help("run simulation with given number of events"); + args.add_argument("--early-macro", "-e" ).metavar("FILENAME" ).help("execute before run manager instantiation"); + args.add_argument( "--late-macro", "-l" ).metavar("FILENAME" ).help("execute after run manager instantiation"); + args.add_argument( "--vis-macro", "-g" ).metavar("FILENAME" ).help("switch from batch mode to GUI, executing this macro"); + args.add_argument("--macro-path", "-m" ).metavar("MACRO-PATHS").help("Add directories to Geant4 macro search path") + .nargs(argparse::nargs_pattern::at_least_one) + .append(); try { args.parse_args(argc, argv); } catch(const std::runtime_error& err) { std::cerr << err.what() << std::endl; std::cerr << args; - std::exit(EXIT_FAILURE); + throw err; } return args; @@ -60,6 +63,13 @@ ui::ui(const std::string& program_name, int argc, char** argv, bool warn_empty_r late_macro = args.present( "--late-macro"); vis_macro = args.present( "--vis-macro"); + // Here we use std::string because G4String does not work + auto macro_paths = args.get>("--macro-path"); + for (auto& path : macro_paths) { + prepend_path(path); + } + g4_ui.ParseMacroSearchPath(); + if (warn_empty_run && ! (n_events.has_value() ^ vis_macro.has_value())) { std::cerr << "'" + program_name + "' is not going to do anything interesting without some command-line arguments.\n\n"; std::cerr << args << std::endl; diff --git a/nain4/src/n4_ui.hh b/nain4/src/n4_ui.hh index bd9f726d..13ea3184 100644 --- a/nain4/src/n4_ui.hh +++ b/nain4/src/n4_ui.hh @@ -23,6 +23,9 @@ public: void run_late_macro() { if ( late_macro.has_value()) { run_macro( late_macro.value()); } } void run_vis_macro() { if ( vis_macro.has_value()) { run_macro( vis_macro.value()); } } + void set_path(G4String const& path) { g4_ui.SetMacroSearchPath(path) ;} + void prepend_path(G4String const& path) { set_path(path + ":" + g4_ui.GetMacroSearchPath( ));} + private: argparse::ArgumentParser args; diff --git a/nain4/test/test-run-manager.cc b/nain4/test/test-run-manager.cc index 5cc0d9f3..8501265a 100644 --- a/nain4/test/test-run-manager.cc +++ b/nain4/test/test-run-manager.cc @@ -22,6 +22,8 @@ #include #include #include +#include +#include using Catch::Approx; @@ -153,3 +155,53 @@ TEST_CASE("nain run_manager exactly_one_world_volumes", "[nain][run_manager]") { .actions(do_nothing) .run(); } + +TEST_CASE("test macropath with values", "[nain][run_manager][macropath]") { + auto hush = n4::silence{std::cout}; + + char *argv[] = { (char*)"progname-aaa" + , (char*)"--macro-path" + , (char*)"path-aaa" + , (char*)"--macro-path" + , (char*)"path-bbb" + , (char*)"path-ccc" + , NULL + }; + + auto rm = n4::run_manager::create().ui("progname", 6, argv, false); + + auto search_path = G4UImanager::GetUIpointer() -> GetMacroSearchPath(); + std::cerr << search_path << std::endl; + + CHECK(search_path.find("path-aaa") != std::string::npos); + CHECK(search_path.find("path-bbb") != std::string::npos); + CHECK(search_path.find("path-ccc") != std::string::npos); +} + + +TEST_CASE("test without macropath", "[nain][run_manager][macropath]") { + auto hush = n4::silence{std::cout}; + + char *argv[] = {(char*)"progname-aaa", NULL}; + + auto rm = n4::run_manager::create().ui("progname", 1, argv, false); + + auto search_path = G4UImanager::GetUIpointer() -> GetMacroSearchPath(); + std::cerr << "XXX" << search_path << "XXX" << std::endl; + + CHECK(search_path == ""); +} + + +TEST_CASE("test macropath without value", "[nain][run_manager][macropath]") { + auto hush = n4::silence{std::cout}; + + char *argv[] = {(char*)"progname-aaa", (char*)"--macro-path", NULL}; + + using Catch::Matchers::Contains; + // We tried + // REQUIRE_THROWS_WITH( n4::run_manager::create().ui("progname", 2, argv, false) + // , Contains("Too few arguments") && Contains("--macro-path")); + // and variations on the there but nothing worked sensibly. + REQUIRE_THROWS_AS(n4::run_manager::create().ui("progname", 2, argv, false), std::runtime_error); +} diff --git a/templates/basic/flake/outputs.nix b/templates/basic/flake/outputs.nix index f7b13d24..46830557 100644 --- a/templates/basic/flake/outputs.nix +++ b/templates/basic/flake/outputs.nix @@ -50,7 +50,8 @@ export G4ABLADATA="${g4-data.G4ABLA}/share/Geant4-11.0.4/data/G4ABLA3.1" export G4INCLDATA="${g4-data.G4INCL}/share/Geant4-11.0.4/data/G4INCL1.0" export G4ENSDFSTATEDATA="${g4-data.G4ENSDFSTATE}/share/Geant4-11.0.4/data/G4ENSDFSTATE2.3" - exec CHANGEME-my-n4-prog "$@" + + exec CHANGEME-my-n4-prog --macro-path ${self}/macs $* ''; in { type = "app"; program = "${CHANGEME-wrap-my-package}/bin/CHANGEME-my-app"; }; diff --git a/templates/basic/src/n4app.cc b/templates/basic/src/n4app.cc index 8c4021c7..e7caf399 100644 --- a/templates/basic/src/n4app.cc +++ b/templates/basic/src/n4app.cc @@ -119,9 +119,9 @@ int main(int argc, char* argv[]) { // ANCHOR: create_run_manager n4::run_manager::create() .ui("my-program-name", argc, argv) - + .macro_path("macs") .apply_command("/my/straw_radius 0.5 m") - .apply_early_macro("macs/early-hard-wired.mac") + .apply_early_macro("early-hard-wired.mac") .apply_cli_early_macro() // CLI --early-macro executed at this point // .apply_command(...) // also possible after apply_early_macro @@ -130,7 +130,7 @@ int main(int argc, char* argv[]) { .actions(create_actions(my, n_event)) .apply_command("/my/particle e-") - .apply_late_macro("macs/late-hard-wired.mac") + .apply_late_macro("late-hard-wired.mac") .apply_cli_late_macro() // CLI --late-macro executed at this point // .apply_command(...) // also possible after apply_late_macro