From 37d5b1eb3e2db60c2611a7ebda6caaa6b0723979 Mon Sep 17 00:00:00 2001 From: Jan Kieseler Date: Mon, 11 Sep 2023 08:33:19 +0200 Subject: [PATCH] towards vis --- bind/G4Calo.py | 41 +++++++ bind/bindings.cpp | 17 +-- bind/example.py | 14 +-- exampleB4a.cc | 4 +- include/{SystemBuilder.hh => G4System.hh} | 44 ++++--- src/G4System.cc | 133 ++++++++++++++++++++++ src/SystemBuilder.cc | 68 ----------- 7 files changed, 212 insertions(+), 109 deletions(-) create mode 100644 bind/G4Calo.py rename include/{SystemBuilder.hh => G4System.hh} (81%) create mode 100644 src/G4System.cc delete mode 100644 src/SystemBuilder.cc diff --git a/bind/G4Calo.py b/bind/G4Calo.py new file mode 100644 index 0000000..6d0dc8f --- /dev/null +++ b/bind/G4Calo.py @@ -0,0 +1,41 @@ + +from minicalo import ConstructionWrapper +from minicalo import G4System as _G4System + +import os +import subprocess +from IPython.display import Image, display + + +class G4System(_G4System): + + def run_visualize(self,particleSpec : str, minEnergy: float, maxEnergy:float = -1.): + if maxEnergy < 0: + maxEnergy = minEnergy + super(G4System).run_visualize(particleSpec, minEnergy, maxEnergy) + self.displayEvent() + + def displayEvent(self): + f_to_conv = max(filter(lambda x: x.endswith(".prim"), os.listdir()), + key=os.path.getctime) + # Convert the .prim file to an eps graphic. + subprocess.run(["dawn", + "-d", + f_to_conv], + stderr=subprocess.DEVNULL) + # Convert the eps graphic to png graphic. + subprocess.run(["gs", + "-DEPSCrop", "-dSAFER", "-sDEVICE=png256", + "-r600", + "-o", + "event_raw.png", + f_to_conv.replace(".prim", ".eps")], + stdout=subprocess.DEVNULL) + subprocess.run(["convert", + "event_raw.png", + "-trim", + "event.png" + ]) + display(Image("event.png", width=500)) + + diff --git a/bind/bindings.cpp b/bind/bindings.cpp index 0658f5e..7023f87 100644 --- a/bind/bindings.cpp +++ b/bind/bindings.cpp @@ -4,7 +4,7 @@ #include #include "ConstructionWrapper.hh" -#include "SystemBuilder.hh" +#include "G4System.hh" namespace py = pybind11; @@ -17,16 +17,17 @@ void makeConstructionWrapper(M & m, std::string name){ } template -void makeSystemBuilder(M& m, std::string name){ - py::class_(m, name.data()).def(py::init()) - .def("init", &SystemBuilder::init, py::arg("cw"), py::arg("gui")=false) - .def("run_gui", &SystemBuilder::run_gui) - .def("run_batch", &SystemBuilder::run_batch, py::arg("nEvents"), py::arg("partSpecies"), py::arg("minEnergy"), py::arg("maxEnergy")) - .def("visualize", &SystemBuilder::visualize); +void makeG4System(M& m, std::string name){ + py::class_(m, name.data()).def(py::init()) + .def("init", &G4System::init, py::arg("cw"), py::arg("gui")=false) + .def("run_gui", &G4System::run_gui) + .def("run_batch", &G4System::run_batch, py::arg("nEvents"), py::arg("partSpecies"), py::arg("minEnergy"), py::arg("maxEnergy")) + .def("run_visualize", &G4System::run_visualize, py::arg("partSpecies"), py::arg("minEnergy"), py::arg("maxEnergy")) + .def("applyUICommand", &G4System::applyUICommand, py::arg("command")); } PYBIND11_MODULE(minicalo, m) { m.doc() = "pybind11 plugin"; // optional module docstring makeConstructionWrapper(m, "ConstructionWrapper"); - makeSystemBuilder(m, "SystemBuilder"); + makeG4System(m, "G4System"); } \ No newline at end of file diff --git a/bind/example.py b/bind/example.py index 99be684..80b622e 100644 --- a/bind/example.py +++ b/bind/example.py @@ -1,11 +1,11 @@ -from minicalo import ConstructionWrapper, SystemBuilder +from G4Calo import ConstructionWrapper, G4System -cw = ConstructionWrapper() -cw.addLayer(10,"G4_Si",True) -cw.addLayer(1,"G4_Pb",False) -cw.addLayer(10,"G4_Si",False) +cw = ConstructionWrapper()#the width of the calorimeter is 50 cm times 50 cm (also steerable, but I'd leave it) +cw.addLayer(10,"G4_Si",True) #10 cm of Silicon, active +cw.addLayer(1,"G4_Pb",False) #1 cm of Lead, passive +cw.addLayer(10,"G4_Si",True, 3) #10 cm of Silicon, active, 3x3 segmentation -sb = SystemBuilder() +sb = G4System() sb.init(cw) -sb.run_batch(100, "gamma", 1000, 5000) +sb.run_batch(100, "gamma", 1000, 5000) #100 events, photons, 1000 MeV to 5000 MeV diff --git a/exampleB4a.cc b/exampleB4a.cc index 2b49781..979f3fb 100644 --- a/exampleB4a.cc +++ b/exampleB4a.cc @@ -41,7 +41,7 @@ #include "ConstructionWrapper.hh" -#include "SystemBuilder.hh" +#include "G4System.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... @@ -270,7 +270,7 @@ int main(){ cw.addLayer(4, "G4_Pb", false); cw.addLayer(3, "G4_Si", true, 23); - SystemBuilder builder; + G4System builder; builder.init(cw, true); //builder.run_gui(); builder.run_batch(10000, ((std::string)"e-").data(), 1, 100); diff --git a/include/SystemBuilder.hh b/include/G4System.hh similarity index 81% rename from include/SystemBuilder.hh rename to include/G4System.hh index 663ff07..4d031a0 100644 --- a/include/SystemBuilder.hh +++ b/include/G4System.hh @@ -1,4 +1,7 @@ +#ifndef G4SYSTEM_HH +#define G4SYSTEM_HH + #include "ConstructionWrapper.hh" #include #include "G4RunManagerFactory.hh" @@ -15,11 +18,11 @@ #include "FTFP_BERT.hh" #include "Randomize.hh" -class SystemBuilder{ +class G4System{ public: -SystemBuilder(){}; -~SystemBuilder(){ +G4System(){}; +~G4System(){ if(visManager != nullptr){ delete visManager; delete runManager; @@ -29,32 +32,23 @@ SystemBuilder(){}; void init(ConstructionWrapper &cw, bool gui=false); -void visualize()const{} //TBI +//will use dawn for visualization, also wrap more in python +void run_visualize(const std::string& partSpecies, double minEnergy, double maxEnergy); +//runs the whole gui if available void run_gui(); void run_batch(int nEvents, const std::string& partSpecies, double minEnergy, double maxEnergy); +void applyUICommand(const std::string& command){ + check(); + UImanager->ApplyCommand(command); +} + +void displayEvent()const{}; //just a placeholder, this will be implemented in python + + private: -inline void check(){ - if(runManager == nullptr){ - throw std::runtime_error("runManager not found"); - } - if(detConstruction == nullptr){ - throw std::runtime_error("DetectorConstruction not found"); - } - if(actionInitialization == nullptr){ - throw std::runtime_error("ActionInitialization not found"); - } - if(visManager == nullptr){ - throw std::runtime_error("VisManager not found"); - } - if(UImanager == nullptr){ - throw std::runtime_error("UImanager not found"); - } - if(ui == nullptr){ - throw std::runtime_error("UI not found"); - } - } +void check()const; G4RunManager * runManager=nullptr; @@ -66,6 +60,8 @@ G4UIExecutive * ui=nullptr; }; +#endif + /* diff --git a/src/G4System.cc b/src/G4System.cc new file mode 100644 index 0000000..7e36fa7 --- /dev/null +++ b/src/G4System.cc @@ -0,0 +1,133 @@ + +#include "G4System.hh" + +void G4System::init(ConstructionWrapper &CW, bool gui){ + + char* argv[]={(char*)"dummy"}; + + // Construct the default run manager + // + runManager = + G4RunManagerFactory::CreateRunManager(G4RunManagerType::Default); + runManager->SetNumberOfThreads(1); + + G4String session; + ui = nullptr; + if ( gui ) { + ui = new G4UIExecutive((int)1, argv, session); + } + + // Set mandatory initialization classes + // + detConstruction = new B4::DetectorConstruction(&CW); + + runManager->SetUserInitialization(detConstruction); + + auto physicsList = new FTFP_BERT; + runManager->SetUserInitialization(physicsList); + + actionInitialization = new B4a::ActionInitialization(detConstruction); + runManager->SetUserInitialization(actionInitialization); + + //actionInitialization->setGeneratorProperties(100, 10000, "e-"); + + // Initialize visualization + // + visManager = new G4VisExecutive; + // G4VisExecutive can take a verbosity argument - see /vis/verbose guidance. + // G4VisManager* visManager = new G4VisExecutive("Quiet"); + visManager->Initialize(); + + // Get the pointer to the User Interface manager + UImanager = G4UImanager::GetUIpointer(); + + // Process macro or start UI session + // +} + +void G4System::run_visualize(const std::string& partSpecies, double minEnergy, double maxEnergy){ + //most of it from https://gitlab.etp.kit.edu/Lehre/Teilchenphysik/-/blob/master/ws_2223/Uebung/geant4_simulation/vis.py + // hard coded macro here + + check(); + + std::vector commands={ + "/vis/open DAWNFILE", + "/vis/drawVolume", + "/vis/modeling/trajectories/create/drawByParticleID", + "/vis/modeling/trajectories/drawByParticleID-0/set gamma green", + "/vis/modeling/trajectories/drawByParticleID-0/set e- blue", + "/vis/modeling/trajectories/drawByParticleID-0/set e+ magenta", + "/vis/modeling/trajectories/drawByParticleID-0/set mu- blue", + "/vis/modeling/trajectories/drawByParticleID-0/set mu+ magenta", + "/vis/modeling/trajectories/drawByParticleID-0/set tau- blue", + "/vis/modeling/trajectories/drawByParticleID-0/set tau+ magenta", + "/vis/modeling/trajectories/drawByParticleID-0/set nu_e red", + "/vis/modeling/trajectories/drawByParticleID-0/set anti_nu_e red", + "/vis/modeling/trajectories/drawByParticleID-0/set nu_mu red", + "/vis/modeling/trajectories/drawByParticleID-0/set anti_nu_mu red", + "/vis/modeling/trajectories/drawByParticleID-0/set nu_tau red", + "/vis/modeling/trajectories/drawByParticleID-0/set anti_nu_tau red", + "/vis/modeling/trajectories/drawByParticleID-0/set neutron grey", + "/vis/modeling/trajectories/drawByParticleID-0/set pi- cyan", + "/vis/modeling/trajectories/drawByParticleID-0/set pi+ red", + "/vis/modeling/trajectories/drawByParticleID-0/set kaon+ red", + "/vis/modeling/trajectories/drawByParticleID-0/set kaon- cyan", + "/vis/modeling/trajectories/drawByParticleID-0/set proton red", + "/vis/modeling/trajectories/drawByParticleID-0/set anti_proton cyan", + "/vis/modeling/trajectories/drawByParticleID-0/set alpha red", + "/vis/modeling/trajectories/select drawByParticleID-0", + "/vis/scene/add/trajectories smooth", + "/vis/scene/endOfRunAction refresh", + "/vis/viewer/flush" + }; + + for(const auto& c : commands){ + UImanager->ApplyCommand(c); + } + run_batch(1, partSpecies, minEnergy, maxEnergy); +} + +void G4System::run_gui(){ + if(ui == nullptr){ + throw std::runtime_error("GUI not initialized"); + } + if ( true ) { + // interactive mode : define UI session + UImanager->ApplyCommand("/control/execute init_vis.mac"); + if (ui->IsGUI()) { + UImanager->ApplyCommand("/control/execute gui.mac"); + } + ui->SessionStart(); + } +} + +void G4System::run_batch(int nEvents,const std::string& partSpecies, double minEnergy, double maxEnergy){ + G4String partSpec = partSpecies; + G4cout << "running with particle species " << partSpec << G4endl; + UImanager->ApplyCommand("/run/initialize"); + actionInitialization->setGeneratorProperties(minEnergy, maxEnergy, partSpec); + runManager->BeamOn(nEvents); +} + + +void G4System::check()const{ + if(runManager == nullptr){ + throw std::runtime_error("runManager not found"); + } + if(detConstruction == nullptr){ + throw std::runtime_error("DetectorConstruction not found"); + } + if(actionInitialization == nullptr){ + throw std::runtime_error("ActionInitialization not found"); + } + if(visManager == nullptr){ + throw std::runtime_error("VisManager not found"); + } + if(UImanager == nullptr){ + throw std::runtime_error("UImanager not found"); + } + if(ui == nullptr){ + throw std::runtime_error("UI not found"); + } +} \ No newline at end of file diff --git a/src/SystemBuilder.cc b/src/SystemBuilder.cc deleted file mode 100644 index 111270c..0000000 --- a/src/SystemBuilder.cc +++ /dev/null @@ -1,68 +0,0 @@ - -#include "SystemBuilder.hh" - -void SystemBuilder::init(ConstructionWrapper &CW, bool gui){ - - char* argv[]={(char*)"dummy"}; - - // Construct the default run manager - // - runManager = - G4RunManagerFactory::CreateRunManager(G4RunManagerType::Default); - runManager->SetNumberOfThreads(1); - - G4String session; - ui = nullptr; - if ( gui ) { - ui = new G4UIExecutive((int)1, argv, session); - } - - // Set mandatory initialization classes - // - detConstruction = new B4::DetectorConstruction(&CW); - - runManager->SetUserInitialization(detConstruction); - - auto physicsList = new FTFP_BERT; - runManager->SetUserInitialization(physicsList); - - actionInitialization = new B4a::ActionInitialization(detConstruction); - runManager->SetUserInitialization(actionInitialization); - - //actionInitialization->setGeneratorProperties(100, 10000, "e-"); - - // Initialize visualization - // - visManager = new G4VisExecutive; - // G4VisExecutive can take a verbosity argument - see /vis/verbose guidance. - // G4VisManager* visManager = new G4VisExecutive("Quiet"); - visManager->Initialize(); - - // Get the pointer to the User Interface manager - UImanager = G4UImanager::GetUIpointer(); - - // Process macro or start UI session - // -} - -void SystemBuilder::run_gui(){ - if(ui == nullptr){ - throw std::runtime_error("GUI not initialized"); - } - if ( true ) { - // interactive mode : define UI session - UImanager->ApplyCommand("/control/execute init_vis.mac"); - if (ui->IsGUI()) { - UImanager->ApplyCommand("/control/execute gui.mac"); - } - ui->SessionStart(); - } -} - -void SystemBuilder::run_batch(int nEvents,const std::string& partSpecies, double minEnergy, double maxEnergy){ - G4String partSpec = partSpecies; - G4cout << "running with particle species " << partSpec << G4endl; - UImanager->ApplyCommand("/run/initialize"); - actionInitialization->setGeneratorProperties(minEnergy, maxEnergy, partSpec); - runManager->BeamOn(nEvents); -}