gui
Loading...
Searching...
No Matches
gui.cc
Go to the documentation of this file.
1// gui
2#include "gui.h"
3#include "gtree.h"
4#include "g4SceneProperties.h"
5
6// geant4
7#include "G4UImanager.hh"
8
9// c++
10#include <algorithm>
11
12
13namespace {
14void resetSceneBeforeGeometryReload(G4UImanager* g4uim) {
15 if (!g4uim) { return; }
16
17 g4uim->ApplyCommand("/vis/viewer/set/autoRefresh false");
18 g4uim->ApplyCommand("/vis/scene/endOfEventAction accumulate 0");
19 g4uim->ApplyCommand("/vis/scene/endOfRunAction refresh");
20 g4uim->ApplyCommand("/vis/scene/removeModel all");
21 g4uim->ApplyCommand("/vis/viewer/clearTransients");
22 g4uim->ApplyCommand("/vis/viewer/clear");
23 g4uim->ApplyCommand("/vis/viewer/set/autoRefresh true");
24 g4uim->ApplyCommand("/vis/viewer/flush");
25 g4uim->ApplyCommand("/vis/viewer/clearTransients");
26}
27
28void resetEventDrawingBeforeRun(G4UImanager* g4uim) {
29 if (!g4uim) { return; }
30
31 g4uim->ApplyCommand("/vis/viewer/set/autoRefresh false");
32 g4uim->ApplyCommand("/vis/scene/endOfEventAction accumulate 0");
33 g4uim->ApplyCommand("/vis/scene/endOfRunAction refresh");
34 g4uim->ApplyCommand("/vis/viewer/clearTransients");
35 g4uim->ApplyCommand("/vis/viewer/clear");
36 g4uim->ApplyCommand("/vis/viewer/flush");
37 g4uim->ApplyCommand("/vis/viewer/clearTransients");
38}
39
40void restoreSceneModels(G4UImanager* g4uim, const std::shared_ptr<GOptions>& gopts, bool includeEventModels) {
41 if (!g4uim) { return; }
42
43 const auto g4view = g4display::getG4View(gopts);
44 G4SceneProperties g4SceneProperties(gopts);
45
46 g4uim->ApplyCommand("/vis/viewer/set/autoRefresh false");
47 g4uim->ApplyCommand("/vis/scene/removeModel all");
48 g4uim->ApplyCommand("/vis/viewer/clearTransients");
49 g4uim->ApplyCommand("/vis/viewer/clear");
50 g4uim->ApplyCommand("/vis/drawVolume");
51 g4uim->ApplyCommand("/vis/viewer/set/background " + g4view.background);
52 g4uim->ApplyCommand("/vis/viewer/set/numberOfCloudPoints " + std::to_string(g4view.cloudPoints));
53 for (const auto& command : g4SceneProperties.addSceneDecorations(gopts)) { g4uim->ApplyCommand(command); }
54 for (const auto& command : g4SceneProperties.addSceneTexts(gopts)) { g4uim->ApplyCommand(command); }
55 if (includeEventModels) {
56 const auto decorations = g4display::getG4Decorations(gopts);
57 g4uim->ApplyCommand("/vis/scene/add/trajectories smooth");
58 g4uim->ApplyCommand("/vis/modeling/trajectories/create/drawByCharge");
59 g4uim->ApplyCommand("/vis/modeling/trajectories/drawByCharge-0/default/setDrawStepPts true");
60 g4uim->ApplyCommand("/vis/modeling/trajectories/drawByCharge-0/default/setStepPtsSize 2");
61 g4uim->ApplyCommand("/vis/scene/add/hits");
62 g4uim->ApplyCommand("/vis/scene/endOfEventAction accumulate 10000");
63 if (decorations.eventID) {
64 g4uim->ApplyCommand("/vis/scene/add/eventID " + std::to_string(decorations.eventIDSize));
65 }
66 }
67 g4uim->ApplyCommand("/vis/viewer/set/autoRefresh true");
68 g4uim->ApplyCommand("/vis/viewer/flush");
69}
70}
71
72
73GemcGUI::GemcGUI(std::shared_ptr<GOptions> gopts,
74 std::shared_ptr<EventDispenser> ed,
76 bool viewerAlreadyInitialized,
77 QWidget* parent) :
78 QWidget(parent),
80 guiOptions(gopts),
81 detectorConstruction(dc),
82 viewerInitialized(viewerAlreadyInitialized) {
83
84 // Create the left navigation pane first; right content initialization uses it to sync selection state.
85 createLeftButtons(); // instantiates leftButtons
86
87 // The board is a long-lived widget attached to this GUI; it is used by other pages (e.g. dialog).
88 auto* gboard = new GBoard(gopts, this);
89
90 // Session object ties together options and the board; it is kept alive for the GUI lifetime.
91 guiSession = std::make_unique<GUI_Session>(gopts, gboard);
92
93 // Create the right stacked content pages (display, dialog, setup, tree) and synchronize default selection.
94 createRightContent(gopts, dc, gboard); // instantiates rightContent: g4control, g4dialog, etc
95
96 // Top row control buttons (run controls and counters).
97 auto* topLayout = new QHBoxLayout;
98 createTopButtons(topLayout);
99
100 // Bottom row contains left navigation and right content; stretch factor favors the content area.
101 auto* bottomLayout = new QHBoxLayout;
102 bottomLayout->setContentsMargins(0, 0, 0, 0);
103 bottomLayout->setSpacing(6);
104 // second argument is stretch factor. Right content can have 10 times more space.
105 bottomLayout->addWidget(leftButtons, 1);
106 bottomLayout->addWidget(rightContent, 10);
107
108 // Main layout: top controls, bottom panes, and board.
109 auto* mainLayout = new QVBoxLayout;
110 mainLayout->setContentsMargins(6, 6, 6, 6);
111 mainLayout->setSpacing(6);
112 mainLayout->addLayout(topLayout);
113 mainLayout->addLayout(bottomLayout, 1);
114 mainLayout->addWidget(gboard, 0);
115
116 setLayout(mainLayout);
117 setWindowTitle(tr("GEMC: Geant4 Monte-Carlo"));
118 setFixedWidth(1000);
119 setMinimumHeight(760);
120 resize(1000, std::max(sizeHint().height(), 760));
121 QTimer::singleShot(0, this, [this]() {
122 adjustSize();
123 const int preferredHeight = std::max(sizeHint().height(), 760);
124 setMinimumHeight(preferredHeight);
125 resize(1000, preferredHeight);
126 });
127
128 // Timer used for cycle mode; timeouts are connected to cycleBeamOn().
129 gtimer = new QTimer(this);
130 connect(gtimer, SIGNAL(timeout()), this, SLOT(cycleBeamOn()));
131
132 // Page switching: left button selection drives the stacked widget page index.
133 connect(leftButtons->buttonsWidget,
134 SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem*)),
135 this, SLOT(change_page(QListWidgetItem *, QListWidgetItem*)));
136}
137
138
139void GemcGUI::updateGui() {
140 // Parse the current label text and increment by the amount run in the most recent batch.
141 std::vector<std::string> sBefore = gutilities::getStringVectorFromString(eventNumberLabel->text().toStdString());
142
143 int nThatWasRun = nEvents->text().toInt();
144 int nBefore = stoi(sBefore[2]);
145
146 QString newNEvents("Event Number: ");
147 newNEvents.append(std::to_string(nBefore + nThatWasRun).c_str());
148
149 eventNumberLabel->setText(newNEvents);
150}
151
152
153void GemcGUI::resetVisualizationBeforeGeometryReload() {
154 resetSceneBeforeGeometryReload(G4UImanager::GetUIpointer());
155}
156
157void GemcGUI::refreshVisualizationFromOptions() {
158 if (!detectorConstruction || !detectorConstruction->has_built_geometry()) { return; }
159
160 auto* g4uim = G4UImanager::GetUIpointer();
161 if (!g4uim) { return; }
162
163 restoreSceneModels(g4uim, guiOptions, false);
164 visualizationNeedsRunRestore = true;
165}
166
167void GemcGUI::refreshGeometryTree() {
168 if (!rightContent || !detectorConstruction || !guiOptions || !geometryTree) { return; }
169
170 geometryReloadedSinceRun = true;
171
172 const int treeIndex = rightContent->indexOf(geometryTree);
173 if (treeIndex < 0) { return; }
174
175 const int currentIndex = rightContent->currentIndex();
176 auto* g4uim = G4UImanager::GetUIpointer();
177 if (!g4uim) { return; }
178
179 const auto g4volumes = detectorConstruction->has_built_geometry()
180 ? detectorConstruction->get_g4volumes_map()
181 : std::unordered_map<std::string, G4Volume*>{};
182 const auto gvolumes = detectorConstruction->has_built_geometry()
183 ? detectorConstruction->get_gvolumes_flat_map()
184 : std::unordered_map<std::string, const GVolume*>{};
185 auto* refreshedTree = new GTree(guiOptions, g4volumes, gvolumes);
186
187 rightContent->removeWidget(geometryTree);
188 geometryTree->deleteLater();
189 geometryTree = refreshedTree;
190 rightContent->insertWidget(treeIndex, geometryTree);
191 rightContent->setCurrentIndex(currentIndex == treeIndex ? treeIndex : currentIndex);
192
193 if (g4volumes.size() > 1) {
194 if (!viewerInitialized) {
195 // First geometry load: no viewer exists yet; create the named scene and open one.
196 G4SceneProperties g4SceneProperties(guiOptions);
197 auto commands = g4SceneProperties.scene_commands(guiOptions);
198 for (const auto& command : commands) { g4uim->ApplyCommand(command); }
199 viewerInitialized = true;
200 }
201
202 restoreSceneModels(g4uim, guiOptions, false);
203 }
204}
205
206void GemcGUI::prepareGeometryForBeamOn() {
207 if ((!geometryReloadedSinceRun && !visualizationNeedsRunRestore) || !detectorConstruction) { return; }
208 if (!detectorConstruction->has_built_geometry()) { return; }
209
210 auto* g4uim = G4UImanager::GetUIpointer();
211 resetEventDrawingBeforeRun(g4uim);
212
213 if (geometryReloadedSinceRun) {
214 detectorConstruction->prepare_geometry_for_run();
215 if (eventDispenser) {
216 eventDispenser->resetRunContext();
217 }
218 }
219
220 // Restore visualization models after geometry reinitialization.
221 // The run reinitialization can replace the world volume, so restore the same
222 // persistent models used by refreshGeometryTree() before BeamOn draws events.
223 restoreSceneModels(g4uim, guiOptions, true);
224
225 geometryReloadedSinceRun = false;
226 visualizationNeedsRunRestore = false;
227}
228
229
231 // All widgets are owned via Qt parent/child relationships once placed into the layout hierarchy.
232 // Rely on Qt to destroy children when GemcGUI is destroyed.
233}
234
235
236void GemcGUI::change_page(QListWidgetItem* current, QListWidgetItem* previous) {
237
238 // Qt may emit selection changes with a null current item; fall back to the previous selection.
239 if (!current)
240 current = previous;
241
242 // The left button widget provides the active page index; apply it to the stacked widget.
243 int thisIndex = leftButtons->button_pressed();
244 rightContent->setCurrentIndex(thisIndex);
245}
std::unordered_map< std::string, const GVolume * > get_gvolumes_flat_map() const
std::unordered_map< std::string, G4Volume * > get_g4volumes_map() const
bool has_built_geometry() const
QListWidget * buttonsWidget
int button_pressed() const
GemcGUI(std::shared_ptr< GOptions > gopts, std::shared_ptr< EventDispenser > ed, GDetectorConstruction *dc, bool viewerAlreadyInitialized=false, QWidget *parent=nullptr)
Construct the main GUI widget.
Definition gui.cc:73
~GemcGUI() override
Destroy the GUI widget and release explicitly owned resources.
Definition gui.cc:230
G4View getG4View(const std::shared_ptr< GOptions > &gopts)
G4Decorations getG4Decorations(const std::shared_ptr< GOptions > &gopts)
vector< std::string > getStringVectorFromString(const std::string &input)