Import Geant4 11.3.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2024-06-28 13:08:51 +02:00
parent f7b23877ed
commit e58e650b32
5232 changed files with 239416 additions and 244360 deletions
+132 -1
View File
@@ -6,10 +6,141 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2024-03-18 Gabriele Cosmo (visman-V11-01-33)
## 2024-06-04 John Allison (visman-V11-02-12)
- G4VisManager:
- Implement EventReadyForVis, used by G4SubEvtRunManager.
- Restructure EndOfEvent functions to accommodate this, and avoid
code duplication. This involved introducing:
- Relinquishable, EndOfEventKernel and EndOfEventCleanup.
- Correct the use of KeepForPostProcessing/PostProcessingFinished.
## 2024-05-30 Guy Barrand (visman-V11-02-11)
- G4VisExecutive.icc: Qt6: restore vis/OGL as default driver.
## 2024-03-18 Gabriele Cosmo (visman-V11-02-10)
- G4VisExecutive.icc: fixed use of static symbol 'fVerbosity' and replaced
with call to dedicated static method, to avoid linkage problems on Windows.
## 2024-03-04 John Allison (visman-V11-02-09)
- G4VViewer.cc: Coverity fix.
- Add return statement after G4Exception(...FatalException...) so Coverity
does not think a null pointer might be being allowed.
- This is a fix to a fix in visman-V11-02-07.
## 2024-02-05 John Allison (visman-V11-02-08)
- G4VisCommandsTouchable.cc:
- "/vis/touchable/dump" and "findPath" do not need a scene handler nor a
viewer. Move them to the beginning of G4VisCommandsTouchable::SetNewValue,
before the check on scene handler and viewer.
- This allows the user to "/vis/touchable/dump" even if he/she has
not yet opened a viewer.
## 2024-02-03 John Allison (visman-V11-02-07)
- G4VViewer.cc: Coverity fix.
- A previous tag changed class G4VViewer::SceneTreeScene to require a
G4PhysicalVolumeModel*. Previous to that, it was programmed for a
general G4VModel*, which required a check on the type. That check
inadvertently remained, even though now not necessary. It seems to
confuse Coverity - something to do with the fact that it is called
in a virtual function, which has already involved a de-referencing,
whereas my checks implied the pointer could be null. It now *must*
be valid by construction, so I have removed the checks, and, just
to be sure, added a G4Exception on null pointer in the constructor.
## 2024-02-02 John Allison (visman-V11-02-06)
- G4VSceneHandler.cc:
- Coverity fix: "const auto&" instead of "auto" to prevent copying.
## 2024-01-23 John Allison (visman-V11-02-05)
- Rationalisation, simplification and much tidying of visman-V11-02-04.
- G4VViewer:
- Check validity of arguments in SceneTreeScene constructor.
- Pre-calculation of quantities in SceneTreeScene constructor.
- Avoids repeated calculations in ProcessVolume.
- More logical order of some functions.
G4VSceneHandler.cc:
- Specify the G4PhysicalVolumeModel for construction of scene tree scene.
## 2024-01-22 John Allison (visman-V11-02-04)
- Co-works with modeling-V11-02-01, interfaces-V11-02-01 and greps-V11-02-00.
- Limit the number of scene tree items.
- For complex geometries, the scene tree can take up a lot of space, and,
anyway, not easy to navigate. This tag suppresses the scene tree if the
number of touchables exceeds 10,000 (equivalent to about 20 MB).
- Better to suppress altogether than create a partial tree?
- G4VViewer:
- Pre-calculate number of touchables. If >10,000, suppress them in the
scene tree and add some information about it to the model item so that
it pops up as a tooltip in the GUI.
- Some tidying and rationalisation.
- G4VSceneHandler:
- Simplify loop over models, add some printing (verbosity >= confirmations).
- Some tidying and rationalisation.
- G4VisCommandsViewer.cc:
- Use GetSceneTree (const) rather than AccessSceneTree when not necessary.
## 2024-01-17 John Allison (visman-V11-02-03)
- G4VSceneHandler:
- Print number of touchables by depth (if verbosity >= confirmations).
- Print problematic volumes (if verbosity >= confirmations).
- G4VisCommandsTouchable.cc:
- Protect polyhedron pointer in /vis/touchable/dump.
## 2024-01-16 John Allison (visman-V11-02-02)
- Co-works with modeling-V11-02-00 and interfaces-V11-02-00
- Improve identification of scene tree models - use full description, including
embedded blanks.
- G4VisCommandScene.cc:
- G4VisCommandSceneActivateModel::SetNewValue:
- Need to handle the possibility that the search string
contains embedded blanks within quotation marks.
(This arises if the search string is automatically generated from the
global description, as in G4UIQt, clicking on check box.)
- Tidy model searches.
- G4VisCommandSceneAdd.cc:
- Text and Text2D: Use single quote (') to delineate actual text in description.
- This is so that normal quotes can be used in G4VisCommandSceneActivateModel.
## 2024-01-12 John Allison (visman-V11-02-01)
- G4VisExecutive.icc:
- Trap use of run-time vis driver choice - not allowed in batch mode.
- And (if using run-time choice) insist UI session is instantiated
*before* G4VisExecutive.
- G4VisManager.cc:
- Improve messaging.
- G4VSceneHandler.cc:
- Minor typo.
## 2023-12-31 John Allison (visman-V11-02-00)
- Delay determination of the run-time-chosen default driver (see visman-V11-01-26).
- This run-time-chosen default driver is not actually used until the first
use of /vis/open or /vis/sceneHandler/create without driver parameter,
so we delay to this point.
- This catches the situation when the user instantiates the UI session
*after* instantiating the vis manager.
- This choice depends on whether or not the user instantiates a
UI session, and, indeed, if instantiated, what type, so in this case
we *have* to delay.
- Note that Geant4 recommends instantiating the UI session as early as
possible in order to capture output streams. However, this is not
enforceable and even some of our examples do not follow this.
- G4VisExecutive:
- Keep argc, argv and user-specified system, if specified, for delayed use.
- Move informational (G4warn) from G4VisManager.
- G4VisManager:
- Make GetDefaultGraphicsSystemName() virtual and non const.
- It has to be virtual so that the derived class (G4VisExecutive) can
override it.
- And non-const because on first pass it may/should determine
these run-time-chosen defaults.
- The code for choosing a default driver *has to be* in user space, i.e.,
in G4VisExecutive, so that it has access to use flags. Hence we have to
use the virtual function mechanism.
- Modify the informational (G4warn) in PrintAvailableGraphicsSystems to give
advice and point to further information to be given after /vis/open.
- G4VViewer.cc:
- Minor, purely cosmetic improvement.
## 2023-11-12 John Allison (visman-V11-01-32)
- G4VisExecutive.icc:
- Add single line message "VTK: OpenGL-based drivers suppressed".
@@ -45,6 +45,8 @@
#include "G4THitsMap.hh"
#include "G4PseudoScene.hh"
#include <map>
class G4Scene;
class G4VGraphicsSystem;
class G4AttHolder;
@@ -451,6 +453,7 @@ protected:
G4int fNestingDepth; // For Begin/EndPrimitives.
const G4VisAttributes* fpVisAttribs; // Working vis attributes.
const G4Transform3D fIdentityTransformation;
std::map<G4VPhysicalVolume*,G4String> fProblematicVolumes;
private:
@@ -171,25 +171,25 @@ public: // With description
class SceneTreeScene: public G4PseudoScene {
// G4PhysicalVolumeModel sends touchables to this scene
public:
SceneTreeScene() = default;
SceneTreeScene(G4VViewer*, G4PhysicalVolumeModel*);
~SceneTreeScene() = default;
void SetViewer(G4VViewer* pViewer) {fpViewer = pViewer;}
void SetModel(G4VModel* pModel); // ...and more (see .cc)
private:
void ProcessVolume(const G4VSolid& solid) override;
std::list<G4SceneTreeItem>::iterator FindOrInsertModel
(const G4String& modelType,const G4String& modelID);
std::list<G4SceneTreeItem>::iterator FindOrInsertTouchable
(const G4String& modelID, G4SceneTreeItem& mother,
G4int depth, const G4String& partialPathString, const G4String& fullPathString);
G4VViewer* fpViewer = nullptr;
G4VModel* fpModel = nullptr;
G4int fMaximumExpandedDepth = 0; // To be calculated in SetModel
G4PhysicalVolumeModel* fpPVModel = nullptr;
std::list<G4SceneTreeItem>::iterator fModelIter; // Points to scene tree item for this model
G4int fMaximumExpandedDepth = 0; // To be calculated in constructor
const G4int fMaximumExpanded = 30; // So as not to swamp the GUI
};
SceneTreeScene& AccessSceneTreeScene() {return fSceneTreeScene;}
void InsertModelInSceneTree(G4VModel*);
const G4SceneTreeItem& GetSceneTree() {return fSceneTree;}
G4SceneTreeItem& AccessSceneTree() {return fSceneTree;}
void UpdateGUISceneTree(); // A utility
const G4int fMaxNTouchables = 10000; // Limits memory to about 50 MB
G4bool fCurtailDescent = false; // Flag to curtail descent into PV model for scene tree
//////////////////////////////////////////////////////////////
// Access functions.
@@ -258,7 +258,6 @@ protected:
G4ViewParameters fDefaultVP; // Default view parameters.
G4double fKernelVisitElapsedTimeSeconds = 999.; // Default to a large number
// Note: fKernelVisitElapsedTimeSeconds is measured in ProcessView().
SceneTreeScene fSceneTreeScene; // G4PhysicalVolumeModel sends touchables to this scene
G4SceneTreeItem fSceneTree;
//////////////////////////////////////////////////////////////
@@ -126,15 +126,19 @@ public: // With description
private:
const G4String& GetDefaultGraphicsSystemName() override;
void SetDefaultsByArgument(const G4String& system);
void SetDefaultsByEnvironment();
void SetDefaultsByFile(int argc, char** argv);
void SetDefaultsByBatch();
void SetDefaultsByBuildFlags();
G4bool fSelected;
void RegisterGraphicsSystems();
void RegisterModelFactories();
int fUserArgc;
char** fUserArgv;
G4String fUserSpecifiedSystem;
G4bool fSelected;
void RegisterGraphicsSystems() override;
void RegisterModelFactories() override;
};
@@ -149,6 +149,8 @@
#include <cstdlib>
#include <sstream>
#define G4warn G4cout
// The inline keyword prevents the compiler making an external
// reference even though they cannot actually be inlined since they
// are virtual functions. This prevents a "multiple definition" error
@@ -160,31 +162,54 @@
inline
G4VisExecutive::G4VisExecutive(int argc, char** argv, const G4String& system,
const G4String& verbosityString):
const G4String& verbosityString):
G4VisManager(verbosityString),
fSelected(false)
{
if (!fSelected) SetDefaultsByArgument(system);
if (!fSelected) SetDefaultsByEnvironment();
if (!fSelected) SetDefaultsByFile(argc, argv);
if (!fSelected) SetDefaultsByBatch();
if (!fSelected) SetDefaultsByBuildFlags();
fUserArgc = argc;
fUserArgv = argv;
fUserSpecifiedSystem = system;
}
inline
G4VisExecutive::G4VisExecutive (const G4String& verbosityString):
G4VisManager(verbosityString),
fSelected(false)
G4VisManager(verbosityString)
, fUserArgc(0) // >0 if argc is provided by the user...
, fUserArgv(nullptr)
, fSelected(false)
{}
inline
const G4String& G4VisExecutive::GetDefaultGraphicsSystemName ()
{
if (!fSelected) SetDefaultsByEnvironment();
if (!fSelected) SetDefaultsByBatch();
if (!fSelected) SetDefaultsByBuildFlags();
if (fSelected) return fDefaultGraphicsSystemName;
if (fUserArgc > 0) SetDefaultsByArgument(fUserSpecifiedSystem);
if (!fSelected) SetDefaultsByEnvironment();
if (!fSelected && fUserArgc > 0) SetDefaultsByFile(fUserArgc, fUserArgv);
if (!fSelected) { SetDefaultsByBatch();
if (fSelected) { // No UI session
// Deal with this later - the user may have specified a system
// on the command line - see G4VisCommandSceneHandlerCreate.
return fDefaultGraphicsSystemName;
}
}
if (!fSelected) SetDefaultsByBuildFlags();
if (GetVerbosity() >= warnings) {
G4warn << "Default graphics system is: " << fDefaultGraphicsSystemName
<< " (based on " << fDefaultGraphicsSystemBasis << ")."
<< "\nDefault window size hint is: " << fDefaultXGeometryString
<< " (based on " << fDefaultXGeometryStringBasis << ")."
<< "\nNote: Parameters specified on the command line will override these defaults."
<< "\n Use \"vis/open\" without parameters to get these defaults."
<< G4endl;
}
return fDefaultGraphicsSystemName;
}
inline
void G4VisExecutive::SetDefaultsByArgument(const G4String& system)
{
// 1st priority: selection by G4VisExecuitive argument
// 1st priority: selection by G4VisExecutive argument
if (!system.empty()) {
fDefaultGraphicsSystemName = system;
fDefaultGraphicsSystemBasis = "G4VisExecuitive argument";
@@ -277,10 +302,10 @@ void G4VisExecutive::SetDefaultsByBatch()
G4UIsession* session = G4UImanager::GetUIpointer()->GetBaseSession();
if (session == nullptr // Usual case - pure batch
|| dynamic_cast<G4UIbatch*>(session)) { // From a macro from batch
// Choose an offscreen or file-writing system
fDefaultGraphicsSystemName = "TSG_OFFSCREEN";
fDefaultGraphicsSystemBasis = "batch session";
fSelected = true;
// Actually, in this case, we wish to force the user to specify a driver
fDefaultGraphicsSystemName = "NO_UI_SESSION";
fDefaultGraphicsSystemBasis = "no UI session";
fSelected = true; // To prevent any further selection
}
}
@@ -311,8 +336,8 @@ void G4VisExecutive::SetDefaultsByBuildFlags()
fSelected = true;
}
inline void
G4VisExecutive::RegisterGraphicsSystems () {
inline
void G4VisExecutive::RegisterGraphicsSystems () {
// Graphics Systems not needing external packages or libraries...
RegisterGraphicsSystem (new G4ASCIITree);
@@ -331,7 +356,6 @@ G4VisExecutive::RegisterGraphicsSystems () {
// super-abbreviated names and fallback names where approproiate.
#ifdef G4VIS_USE_OPENGLQT
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
G4VGraphicsSystem* ogliqt = new G4OpenGLImmediateQt;
G4VGraphicsSystem* oglsqt = new G4OpenGLStoredQt;
RegisterGraphicsSystem(ogliqt);
@@ -340,7 +364,6 @@ G4VisExecutive::RegisterGraphicsSystems () {
oglsqt->AddNickname("OGL");
oglsqt->AddNickname("OGLS");
#endif
#endif
#ifdef G4VIS_USE_OPENGLXM
G4VGraphicsSystem* oglixm = new G4OpenGLImmediateXm;
@@ -482,12 +505,6 @@ G4VisExecutive::RegisterGraphicsSystems () {
#ifdef G4VIS_USE_TOOLSSG_QT_GLES
tsg_qt_gles->AddNickname("TSG");
# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
if (GetVerbosity() >= startup) {
G4cout << " Qt6: Asking ToolsSG to stand in for OpenGL" << G4endl;
tsg_qt_gles->AddNickname("OGL");
}
# endif
#elif defined(G4VIS_USE_TOOLSSG_XT_GLES)
tsg_xt_gles->AddNickname("TSG");
#elif defined(G4VIS_USE_TOOLSSG_X11_GLES)
@@ -338,6 +338,10 @@ public: // With description
virtual void SetUpForAThread();
// This method is invoked by G4WorkerRunManager
virtual void EventReadyForVis(const G4Event*);
// This is invoked by G4SubEvtRunManager.
// The event is passed to EndOfEventKernel.
static G4ThreadFunReturnType G4VisSubThread(G4ThreadFunArgType);
// Vis sub-thread function.
@@ -362,6 +366,11 @@ private:
// This is called on change of state (G4ApplicationState). It is
// used to draw hits, digis and trajectories if included in the
// current scene at the end of event, as required.
G4bool Relinquishable (G4int eventID, G4int nKeptEvents, G4int nRequests);
void EndOfEventKernel (const G4Event* event);
void EndOfEventCleanup
(const G4Event* currentEvent,
G4int eventID); // See EndOfEventKernel: can be == -2?
void EndOfRun ();
@@ -402,6 +411,8 @@ public: // With description
G4bool GetTransientsDrawnThisEvent () const;
G4bool GetDrawEventOnlyIfToBeKept () const;
const G4Event* GetRequestedEvent () const;
G4int GetNKeepForPostProcessingRequests () const;
G4int GetNKeepTheEventRequests () const;
G4int GetNKeepRequests () const;
G4bool GetReviewingKeptEvents () const;
G4bool GetAbortReviewKeptEvents () const;
@@ -412,7 +423,10 @@ public: // With description
G4int GetMaxEventQueueSize () const;
G4bool GetWaitOnEventQueueFull () const;
#endif
const G4String& GetDefaultGraphicsSystemName() const;
virtual const G4String& GetDefaultGraphicsSystemName();
// The above has to be virtual so that the derived class, G4VisExecutive,
// can override and non-const because on first pass it may/should
// determine these defaults.
const G4String& GetDefaultXGeometryString () const;
const G4String& GetDefaultGraphicsSystemBasis() const;
const G4String& GetDefaultXGeometryStringBasis() const;
@@ -484,19 +498,18 @@ protected:
void RegisterMessengers (); // Command messengers.
const G4int fVerbose;
const G4int fVerbose;
// No longer used. Use fVerbosity and access functions instead.
// fVerbose is kept for backwards compatibility for some user
// examples. (It is used in the derived user vis managers to print
// available graphics systems.) It is initialised to 1 in the
// constructor and cannot be changed.
static Verbosity fVerbosity;
static Verbosity fVerbosity;
G4String fDefaultGraphicsSystemName;
G4String fDefaultXGeometryString;
G4String fDefaultGraphicsSystemBasis;
G4String fDefaultXGeometryStringBasis;
G4String fDefaultGraphicsSystemName;
G4String fDefaultXGeometryString;
G4String fDefaultGraphicsSystemBasis;
G4String fDefaultXGeometryStringBasis;
private:
@@ -538,7 +551,8 @@ private:
G4bool fTransientsDrawnThisRun;
G4bool fTransientsDrawnThisEvent;
G4int fNoOfEventsDrawnThisRun;
G4int fNKeepRequests;
G4int fNKeepForPostProcessingRequests;
G4int fNKeepTheEventRequests;
G4bool fEventKeepingSuspended;
G4bool fDrawEventOnlyIfToBeKept;
const G4Event* fpRequestedEvent; // If non-zero, scene handler uses.
@@ -98,8 +98,12 @@ inline const G4Event* G4VisManager::GetRequestedEvent() const {
return fpRequestedEvent;
}
inline G4int G4VisManager::GetNKeepRequests () const {
return fNKeepRequests;
inline G4int G4VisManager::GetNKeepForPostProcessingRequests () const {
return fNKeepForPostProcessingRequests;
}
inline G4int G4VisManager::GetNKeepTheEventRequests () const {
return fNKeepTheEventRequests;
}
inline G4bool G4VisManager::GetReviewingKeptEvents() const {
@@ -134,7 +138,7 @@ inline G4bool G4VisManager::GetWaitOnEventQueueFull () const {
#endif
inline const G4String& G4VisManager::GetDefaultGraphicsSystemName () const {
inline const G4String& G4VisManager::GetDefaultGraphicsSystemName () {
return fDefaultGraphicsSystemName;
}
@@ -94,8 +94,6 @@
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include <set>
#define G4warn G4cout
G4VSceneHandler::G4VSceneHandler (G4VGraphicsSystem& system, G4int id, const G4String& name):
@@ -602,29 +600,30 @@ void G4VSceneHandler::RequestPrimitives (const G4VSolid& solid)
break;
} else { // Print warnings and drop through to cloud
G4VisManager::Verbosity verbosity = G4VisManager::GetVerbosity();
static std::set<const G4VSolid*> problematicSolids;
if (verbosity >= G4VisManager::errors &&
problematicSolids.find(&solid) == problematicSolids.end()) {
problematicSolids.insert(&solid);
G4warn <<
"ERROR: G4VSceneHandler::RequestPrimitives"
"\n Polyhedron not available for " << solid.GetName ();
G4PhysicalVolumeModel* pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
if (pPVModel) {
G4warn << "\n Touchable path: " << pPVModel->GetFullPVPath();
auto pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
if (pPVModel) {
auto problematicVolume = pPVModel->GetCurrentPV();
if (fProblematicVolumes.find(problematicVolume) == fProblematicVolumes.end()) {
fProblematicVolumes[problematicVolume] = "Null polyhedron";
if (verbosity >= G4VisManager::errors) {
G4warn <<
"ERROR: G4VSceneHandler::RequestPrimitives"
"\n Polyhedron not available for " << solid.GetName ();
G4warn << "\n Touchable path: " << pPVModel->GetFullPVPath();
static G4bool explanation = false;
if (!explanation) {
explanation = true;
G4warn <<
"\n This means it cannot be visualized in the usual way on most systems."
"\n 1) The solid may not have implemented the CreatePolyhedron method."
"\n 2) For Boolean solids, the BooleanProcessor, which attempts to create"
"\n the resultant polyhedron, may have failed."
"\n Try RayTracer. It uses Geant4's tracking algorithms instead.";
}
}
G4warn << "\n Drawing solid with cloud of points.";
G4warn << G4endl;
}
static G4bool explanation = false;
if (!explanation) {
explanation = true;
G4warn <<
"\n This means it cannot be visualized in the usual way on most systems."
"\n 1) The solid may not have implemented the CreatePolyhedron method."
"\n 2) For Boolean solids, the BooleanProcessor, which attempts to create"
"\n the resultant polyhedron, may have failed."
"\n Try RayTracer. It uses Geant4's tracking algorithms instead.";
}
G4warn << "\n Drawing solid with cloud of points.";
G4warn << G4endl;
}
}
}
@@ -708,27 +707,31 @@ void G4VSceneHandler::ProcessScene()
const std::vector<G4Scene::Model>& runDurationModelList =
fpScene->GetRunDurationModelList();
if(runDurationModelList.size())
{
if(verbosity >= G4VisManager::confirmations)
{
if(runDurationModelList.size()) {
if(verbosity >= G4VisManager::confirmations) {
G4cout << "Traversing scene data..." << G4endl;
static G4int first = true;
if (first) {
first = false;
G4cout <<
"(This could happen more than once - in fact, up to three times"
"\nper rebuild, for opaque, transparent and non-hidden markers.)"
<< G4endl;
}
}
// Reset visibility of all objects to false - visible objects will then set to true
fpViewer->AccessSceneTree().ResetVisibility();
BeginModeling();
// Create modeling parameters from view parameters...
G4ModelingParameters* pMP = CreateModelingParameters();
for(std::size_t i = 0; i < runDurationModelList.size(); ++i)
{
if(runDurationModelList[i].fActive)
{
fpModel = runDurationModelList[i].fpModel;
fpModel->SetModelingParameters(pMP);
for(std::size_t i = 0; i < runDurationModelList.size(); ++i) {
if(runDurationModelList[i].fActive) {
fpModel = runDurationModelList[i].fpModel;
fpModel->SetModelingParameters(pMP);
// Describe to the current scene handler
fpModel->DescribeYourselfTo(*this);
@@ -737,17 +740,44 @@ void G4VSceneHandler::ProcessScene()
// uncomment the next line and DrawExtent in namespace above.
// DrawExtent(fpModel);
// Enter models in the scene tree, and for PV models, describe
// Enter models in the scene tree. Then for PV models, describe
// the model to the scene tree, i.e., enter all the touchables.
auto& sceneTreeScene = fpViewer->AccessSceneTreeScene();
sceneTreeScene.SetViewer(fpViewer);
sceneTreeScene.SetModel(fpModel);
if (dynamic_cast<G4PhysicalVolumeModel*>(fpModel)) {
fpViewer->InsertModelInSceneTree(fpModel);
auto pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
if (pPVModel) {
G4VViewer::SceneTreeScene sceneTreeScene(fpViewer, pPVModel);
fpModel->DescribeYourselfTo(sceneTreeScene);
}
// Reset modeling parameters pointer
fpModel->SetModelingParameters(0);
fpModel->SetModelingParameters(0);
}
}
// Some printing
if(verbosity >= G4VisManager::confirmations) {
for (const auto& model: runDurationModelList) {
if (model.fActive) {
auto pvModel = dynamic_cast<G4PhysicalVolumeModel*>(model.fpModel);
if (pvModel) {
G4int nTouchables = 0;
G4cout << "Numbers of touchables by depth in model \""
<< pvModel->GetGlobalDescription() << "\":";
for (const auto& dn : pvModel->GetNumberOfTouchables()) {
G4cout << "\n Depth " << dn.first << ": " << dn.second;
nTouchables += dn.second;
}
G4cout << "\n Total number of touchables: " << nTouchables << G4endl;
}
}
}
if (fProblematicVolumes.size() > 0) {
G4cout << "Problematic volumes:";
for (const auto& prob: fProblematicVolumes) {
G4cout << "\n " << prob.first->GetName() << " (" << prob.second << ')';
}
G4cout << G4endl;
}
}
@@ -755,7 +785,7 @@ void G4VSceneHandler::ProcessScene()
delete pMP;
EndModeling();
}
}
fReadyForTransients = true;
@@ -854,9 +884,7 @@ void G4VSceneHandler::DrawEvent(const G4Event* event)
fpModel -> DescribeYourselfTo (*this);
// Enter models in the scene tree
auto& sceneTreeScene = fpViewer->AccessSceneTreeScene();
sceneTreeScene.SetViewer(fpViewer);
sceneTreeScene.SetModel(fpModel);
fpViewer->InsertModelInSceneTree(fpModel);
// Reset modeling parameters pointer
fpModel -> SetModelingParameters(0);
@@ -884,9 +912,7 @@ void G4VSceneHandler::DrawEndOfRunModels()
fpModel -> DescribeYourselfTo (*this);
// Enter models in the scene tree
auto& sceneTreeScene = fpViewer->AccessSceneTreeScene();
sceneTreeScene.SetViewer(fpViewer);
sceneTreeScene.SetModel(fpModel);
fpViewer->InsertModelInSceneTree(fpModel);
// Reset modeling parameters pointer
fpModel -> SetModelingParameters(0);
@@ -1072,7 +1098,7 @@ G4DisplacedSolid* G4VSceneHandler::CreateCutawaySolid()
break;
}
G4Exception("G4VSceneHandler::CreateCutawaySolid", "visman107", JustWarning,
G4Exception("G4VSceneHandler::CreateCutawaySolid", "visman0107", JustWarning,
"Not programmed for more than 3 cutaway planes");
return nullptr;
}
+110 -92
View File
@@ -64,6 +64,7 @@ G4VViewer::G4VViewer(G4VSceneHandler& sceneHandler, G4int id, const G4String& na
fDefaultVP = fVP;
fSceneTree.SetType(G4SceneTreeItem::root);
fSceneTree.SetDescription(fName);
}
G4VViewer::~G4VViewer()
@@ -231,73 +232,129 @@ void G4VViewer::UpdateGUISceneTree()
if (uiWindow) uiWindow->UpdateSceneTree(fSceneTree);
}
void G4VViewer::SceneTreeScene::SetModel(G4VModel* pModel)
void G4VViewer::InsertModelInSceneTree(G4VModel* model)
{
fpModel = pModel;
auto modelType = model->GetType();
auto modelDescription = model->GetGlobalDescription();
// Insert in tree (if not already inserted)
auto& modelType = fpModel->GetType();
auto& modelID = fpModel->GetGlobalDescription();
FindOrInsertModel(modelType, modelID);
auto type = G4SceneTreeItem::model;
auto pvModel = dynamic_cast<G4PhysicalVolumeModel*>(model);
if (pvModel) type = G4SceneTreeItem::pvmodel;
auto pvModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
fCurtailDescent = false; // This is used later in SceneTreeScene::ProcessVolume
G4String furtherInfo;
if (pvModel) {
// Limit the expanded depth to limit the number expanded so as not to swamp the GUI
G4int expanded = 0;
for (const auto& dn : pvModel->GetNumberOfTouchables()) {
expanded += dn.second;
if (fMaximumExpandedDepth < dn.first) fMaximumExpandedDepth = dn.first;
if (expanded > fMaximumExpanded) break;
struct : public G4PseudoScene {
void ProcessVolume(const G4VSolid&) {++fNTotalTouchables;}
G4int fNTotalTouchables = 0;
} counter;
pvModel->DescribeYourselfTo(counter); // Calls ProcessVolume for every touchable
if (counter.fNTotalTouchables > fMaxNTouchables) {
std::ostringstream oss;
oss << counter.fNTotalTouchables << " touchables - too many for scene tree";
furtherInfo = oss.str();
if (G4VisManager::GetInstance()->GetVerbosity() >= G4VisManager::warnings) {
G4ExceptionDescription ed;
ed << pvModel->GetGlobalDescription() <<
":\n Too many touchables (" << counter.fNTotalTouchables
<< ") for scene tree. Scene tree for this model will be empty.";
G4Exception("G4VViewer::InsertModelInSceneTree", "visman0404", JustWarning, ed);
}
fCurtailDescent = true; // This is used later in SceneTreeScene::ProcessVolume
}
}
}
std::list<G4SceneTreeItem>::iterator
G4VViewer::SceneTreeScene::FindOrInsertModel(const G4String& modelType, const G4String& modelID)
{
G4SceneTreeItem::Type type = G4SceneTreeItem::unidentified;
if (dynamic_cast<G4PhysicalVolumeModel*>(fpModel)) {
type = G4SceneTreeItem::pvmodel;
}
else {
type = G4SceneTreeItem::model;
}
auto& rootItem = fpViewer->fSceneTree;
rootItem.SetDescription(fpViewer->GetName());
// Find appropriate model
auto& modelItems = rootItem.AccessChildren();
auto& modelItems = fSceneTree.AccessChildren();
auto modelIter = modelItems.begin();
auto pvModelIter = modelItems.end();
for (; modelIter != modelItems.end(); ++modelIter) {
if (modelIter->GetType() == G4SceneTreeItem::pvmodel) {
pvModelIter = modelIter; // Last PV model
pvModelIter = modelIter; // Last pre-existing PV model (if any)
}
if (modelIter->GetModelDescription() == modelID) break;
if (modelIter->GetModelDescription() == modelDescription) break;
}
if (modelIter == modelItems.end()) {
// Model not seen before
if (modelIter == modelItems.end()) { // Model not seen before
G4SceneTreeItem modelItem(type);
modelItem.SetDescription("model");
modelItem.SetModelType(modelType);
modelItem.SetModelDescription(modelID);
modelItem.SetModelDescription(modelDescription);
modelItem.SetFurtherInfo(furtherInfo);
if (pvModelIter != modelItems.end() && // There was pre-existing PV Model...
type == G4SceneTreeItem::pvmodel)
{ // ...and the new model is also PV...
modelIter = rootItem.InsertChild(++pvModelIter, modelItem); // ...insert after, else...
type == G4SceneTreeItem::pvmodel) { // ...and the new model is also PV...
fSceneTree.InsertChild(++pvModelIter, modelItem); // ...insert after, else...
} else {
fSceneTree.InsertChild(modelIter, modelItem); // ...insert at end
}
else {
modelIter = rootItem.InsertChild(modelIter, modelItem); // ...insert at end
}
}
else {
// Existing model - mark visible == active
} else { // Existing model - mark visible == active
modelIter->AccessVisAttributes().SetVisibility(true);
}
}
return modelIter;
G4VViewer::SceneTreeScene::SceneTreeScene(G4VViewer* pViewer, G4PhysicalVolumeModel* pPVModel)
: fpViewer (pViewer)
, fpPVModel(pPVModel)
{
if (fpPVModel == nullptr) {
G4Exception("G4VViewer::SceneTreeScene::SceneTreeScene", "visman0405", FatalException,
"G4PhysicalVolumeModel pointer is null");
return; // To keep Coverity happy
}
// Describe the model to an empty scene simply to get the numbers of touchables
struct : public G4PseudoScene {
void ProcessVolume(const G4VSolid&) {}
} counter;
fpPVModel->DescribeYourselfTo(counter); // Calls ProcessVolume for every touchable
// Limit the expanded depth to limit the number expanded so as not to swamp the GUI
G4int expanded = 0;
for (const auto& dn : fpPVModel->GetNumberOfTouchables()) {
expanded += dn.second;
if (fMaximumExpandedDepth < dn.first) fMaximumExpandedDepth = dn.first;
if (expanded > fMaximumExpanded) break;
}
// Find appropriate model and its iterator
const auto& modelID = fpPVModel->GetGlobalDescription();
auto& modelItems = fpViewer->fSceneTree.AccessChildren();
fModelIter = modelItems.begin();
for (; fModelIter != modelItems.end(); ++fModelIter) {
if (fModelIter->GetModelDescription() == modelID) break;
}
if (fModelIter == modelItems.end()) {
G4Exception("G4VViewer::SceneTreeScene::SceneTreeScene", "visman0406", JustWarning,
"Model not found");
}
}
void G4VViewer::SceneTreeScene::ProcessVolume(const G4VSolid&)
{
if (fpViewer->fCurtailDescent) {
fpPVModel->CurtailDescent();
return;
}
const auto& modelID = fpPVModel->GetGlobalDescription();
std::ostringstream oss;
oss << fpPVModel->GetFullPVPath(); // of this volume
G4String fullPathString(oss.str()); // Has a leading space
// Navigate scene tree and find or insert touchables one by one
// Work down the path - "name id", then "name id name id", etc.
const auto& nodeIDs = fpPVModel->GetFullPVPath();
G4String partialPathString;
auto currentIter = fModelIter;
G4int depth = 0;
for (const auto& nodeID : nodeIDs) {
std::ostringstream oss1;
oss1 << nodeID;
partialPathString += ' ' + oss1.str();
currentIter =
FindOrInsertTouchable(modelID, *currentIter, ++depth, partialPathString, fullPathString);
}
}
// clang-format off
@@ -305,12 +362,6 @@ std::list<G4SceneTreeItem>::iterator G4VViewer::SceneTreeScene::FindOrInsertTouc
(const G4String& modelID, G4SceneTreeItem& mother,
G4int depth, const G4String& partialPathString, const G4String& fullPathString)
{
auto pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
if (pPVModel == nullptr) {
G4ExceptionDescription ed;
ed << fpModel->GetType() << ": not a Physical VolumeModel";
G4Exception("G4VViewer::SceneTreeScene::FindOrInsertTouchable", "visman0404", FatalException, ed);
}
auto& children = mother.AccessChildren();
auto childIter = children.begin();
for (; childIter != children.end(); ++childIter) {
@@ -328,13 +379,13 @@ std::list<G4SceneTreeItem>::iterator G4VViewer::SceneTreeScene::FindOrInsertTouc
// Partial path string refers to the actual volume so it's a touchable
childIter->SetType(G4SceneTreeItem::touchable);
// Populate with information
childIter->SetDescription(fpModel->GetCurrentTag());
childIter->SetModelType(fpModel->GetType());
childIter->SetDescription(fpPVModel->GetCurrentTag());
childIter->SetModelType(fpPVModel->GetType());
childIter->SetModelDescription(modelID);
childIter->SetPVPath(partialPathString);
if (fpVisAttributes) childIter->SetVisAttributes(*fpVisAttributes);
if (pPVModel) childIter->SetAttDefs(pPVModel->GetAttDefs());
if (pPVModel) childIter->SetAttValues(pPVModel->CreateCurrentAttValues());
childIter->SetAttDefs(fpPVModel->GetAttDefs());
childIter->SetAttValues(fpPVModel->CreateCurrentAttValues());
} // Partial path string refers to an ancester - do nothing
} else {
@@ -359,13 +410,13 @@ std::list<G4SceneTreeItem>::iterator G4VViewer::SceneTreeScene::FindOrInsertTouc
// Insert new touchable item
G4SceneTreeItem touchable(G4SceneTreeItem::touchable);
touchable.SetExpanded(depth > fMaximumExpandedDepth? false: true);
touchable.SetDescription(fpModel->GetCurrentTag());
touchable.SetModelType(fpModel->GetType());
touchable.SetDescription(fpPVModel->GetCurrentTag());
touchable.SetModelType(fpPVModel->GetType());
touchable.SetModelDescription(modelID);
touchable.SetPVPath(partialPathString);
if (fpVisAttributes) touchable.SetVisAttributes(*fpVisAttributes);
if (pPVModel) touchable.SetAttDefs(pPVModel->GetAttDefs());
if (pPVModel) touchable.SetAttValues(pPVModel->CreateCurrentAttValues());
touchable.SetAttDefs(fpPVModel->GetAttDefs());
touchable.SetAttValues(fpPVModel->CreateCurrentAttValues());
childIter = mother.InsertChild(childIter,touchable);
} else {
@@ -380,7 +431,7 @@ std::list<G4SceneTreeItem>::iterator G4VViewer::SceneTreeScene::FindOrInsertTouc
std::ostringstream oss;
oss << name << ':' << copyNo;
ghost.SetDescription(oss.str());
ghost.SetModelType(fpModel->GetType());
ghost.SetModelType(fpPVModel->GetType());
ghost.SetModelDescription(modelID);
ghost.SetPVPath(partialPathString);
ghost.AccessVisAttributes().SetVisibility(false);
@@ -392,39 +443,6 @@ std::list<G4SceneTreeItem>::iterator G4VViewer::SceneTreeScene::FindOrInsertTouc
}
// clang-format on
void G4VViewer::SceneTreeScene::ProcessVolume(const G4VSolid&)
{
auto& modelType = fpModel->GetType();
auto& modelID = fpModel->GetGlobalDescription();
auto modelIter = FindOrInsertModel(modelType, modelID);
auto pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
if (pPVModel) { // G4PhysicalVolumeModel
std::ostringstream oss;
oss << pPVModel->GetFullPVPath();
G4String fullPathString(oss.str()); // Has a leading space - OK
// Navigate scene tree and find or insert touchables one by one
const auto& nodeIDs = pPVModel->GetFullPVPath(); // std::vector<G4PhysicalVolumeNodeID>
// Work down the path - "name id", then "name id name id", etc.
G4String partialPathString;
auto currentIter = modelIter;
G4int depth = 0;
for (const auto& nodeID : nodeIDs) {
std::ostringstream oss1;
oss1 << nodeID;
partialPathString += ' ' + oss1.str(); // Has a leading space - OK
currentIter =
FindOrInsertTouchable(modelID, *currentIter, ++depth, partialPathString, fullPathString);
}
}
else {
// Orphan solid - what to do? Push an empty scene tree item????????????????????????
}
}
#ifdef G4MULTITHREADED
void G4VViewer::DoneWithMasterThread()
@@ -93,7 +93,34 @@ void G4VisCommandSceneActivateModel::SetNewValue (G4UIcommand*,
G4String searchString, activateString;
std::istringstream is (newValue);
is >> searchString >> activateString;
// Need to handle the possibility that the search string
// contains embedded blanks within quotation marks.
// (This arises if the search string is automatically generated from the
// global description, as in G4UIQt, clicking on check box.)
auto lastQuotationMark = newValue.find_last_of('"');
if (lastQuotationMark != std::string::npos) { // We have at least one quotation mark
auto firstQuotationMark = newValue.find_first_of('"');
if (lastQuotationMark != firstQuotationMark) { // We have at least two quotations marks
// Note: there must not be more quotation marks - it upsets the command system.
searchString = newValue.substr
(firstQuotationMark + 1, lastQuotationMark - firstQuotationMark - 1);
activateString = newValue.substr(lastQuotationMark + 2);
// Perhaps we ought to check number of quotation marks
G4int nQuotes = 0;
for (auto c : newValue) {
if (c == '"') nQuotes++;
}
if (nQuotes > 2) {
G4ExceptionDescription ed;
ed << "More than 2 quotation marks in search string: " << searchString;
G4Exception("G4VisCommandSceneActivateModel::SetNewValue", "visman0301", JustWarning, ed);
}
}
}
else {
// None or one quotation marks - just input two strings
is >> searchString >> activateString;
}
G4bool activate = G4UIcommand::ConvertToBool(activateString);
G4Scene* pScene = fpVisManager->GetCurrentScene();
@@ -127,10 +154,8 @@ void G4VisCommandSceneActivateModel::SetNewValue (G4UIcommand*,
std::vector<G4Scene::Model>& runDurationModelList =
pScene->SetRunDurationModelList();
for (size_t i = 0; i < runDurationModelList.size(); i++) {
const G4String& modelName =
runDurationModelList[i].fpModel->GetGlobalDescription();
if (searchString == "all" || modelName.find(searchString)
!= std::string::npos) {
const G4String& modelName = runDurationModelList[i].fpModel->GetGlobalDescription();
if (searchString == "all" || modelName.find(searchString) != std::string::npos) {
any = true;
runDurationModelList[i].fActive = activate;
if (verbosity >= G4VisManager::warnings) {
@@ -145,10 +170,8 @@ void G4VisCommandSceneActivateModel::SetNewValue (G4UIcommand*,
std::vector<G4Scene::Model>& endOfEventModelList =
pScene->SetEndOfEventModelList();
for (size_t i = 0; i < endOfEventModelList.size(); i++) {
const G4String& modelName =
endOfEventModelList[i].fpModel->GetGlobalDescription();
if (searchString == "all" || modelName.find(searchString)
!= std::string::npos) {
const G4String& modelName = endOfEventModelList[i].fpModel->GetGlobalDescription();
if (searchString == "all" || modelName.find(searchString) != std::string::npos) {
any = true;
endOfEventModelList[i].fActive = activate;
if (verbosity >= G4VisManager::warnings) {
@@ -163,10 +186,8 @@ void G4VisCommandSceneActivateModel::SetNewValue (G4UIcommand*,
std::vector<G4Scene::Model>& endOfRunModelList =
pScene->SetEndOfRunModelList();
for (size_t i = 0; i < endOfRunModelList.size(); i++) {
const G4String& modelName =
endOfRunModelList[i].fpModel->GetGlobalDescription();
if (searchString == "all" || modelName.find(searchString)
!= std::string::npos) {
const G4String& modelName = endOfRunModelList[i].fpModel->GetGlobalDescription();
if (searchString == "all" || modelName.find(searchString) != std::string::npos) {
any = true;
endOfRunModelList[i].fActive = activate;
if (verbosity >= G4VisManager::warnings) {
@@ -2643,8 +2643,8 @@ void G4VisCommandSceneAddText::SetNewValue (G4UIcommand*, G4String newValue) {
G4bool successful = pScene -> AddRunDurationModel (model, warn);
if (successful) {
if (verbosity >= G4VisManager::confirmations) {
G4cout << "Text \"" << text
<< "\" has been added to scene \"" << currentSceneName << "\"."
G4cout << "Text '" << text
<< "' has been added to scene \"" << currentSceneName << "\"."
<< G4endl;
}
}
@@ -2731,8 +2731,8 @@ void G4VisCommandSceneAddText2D::SetNewValue (G4UIcommand*, G4String newValue) {
model->SetType("Text2D");
model->SetGlobalTag("Text2D");
std::ostringstream oss;
oss << "Text2D: \"" << g4text.GetText()
<< "\" at " << g4text.GetPosition().x() << ',' << g4text.GetPosition().y()
oss << "Text2D: '" << g4text.GetText()
<< "' at " << g4text.GetPosition().x() << ',' << g4text.GetPosition().y()
<< " with size " << g4text.GetScreenSize()
<< " with offsets " << g4text.GetXOffset() << ',' << g4text.GetYOffset();
model->SetGlobalDescription(oss.str());
@@ -2740,8 +2740,8 @@ void G4VisCommandSceneAddText2D::SetNewValue (G4UIcommand*, G4String newValue) {
G4bool successful = pScene -> AddRunDurationModel (model, warn);
if (successful) {
if (verbosity >= G4VisManager::confirmations) {
G4cout << "2D text \"" << text
<< "\" has been added to scene \"" << currentSceneName << "\"."
G4cout << "2D text '" << text
<< "' has been added to scene \"" << currentSceneName << "\"."
<< G4endl;
}
}
@@ -150,7 +150,7 @@ G4VisCommandSceneHandlerCreate::G4VisCommandSceneHandlerCreate (): fId (0) {
parameter -> SetCurrentAsDefault(true);
const G4GraphicsSystemList& gslist =
fpVisManager -> GetAvailableGraphicsSystems ();
G4String candidates;
G4String candidates = "NO_UI_SESSION "; // A dummy candidate to catch issue
for (const auto gs: gslist) {
const G4String& name = gs -> GetName ();
candidates += name + ' ';
@@ -212,7 +212,7 @@ void G4VisCommandSceneHandlerCreate::SetNewValue (G4UIcommand* command,
" no graphics systems available."
"\n Did you instantiate any in"
" YourVisManager::RegisterGraphicsSystems()?";
command->CommandFailed(JustWarning,ed);
command->CommandFailed(ed);
return;
}
std::size_t iGS; // Selector index.
@@ -237,6 +237,23 @@ void G4VisCommandSceneHandlerCreate::SetNewValue (G4UIcommand* command,
}
}
if (!found) {
if (graphicsSystem == "NO_UI_SESSION") {
G4Exception
("G4VisCommandSceneHandlerCreate::SetNewValue","visman1001",JustWarning,
"This looks like an attempt to use run-time vis driver selection."
"\nYou have issued \"/vis/open\" or \"/vis/sceneHandler/create\" without"
"\na parameter for the vis driver. This is allowed only if you instantiate"
"\na UI session, and only if it is instantiated *before* the first"
"\n\"/vis/open\" command. So:"
"\na) It is not allowed in batch mode. If you really want to create"
"\n some graphics with a file-writing driver in batch mode, you must"
"\n request a specific driver on the \"/vis/open\" command line, e.g.,"
"\n \"/vis/open TSG_OFFSCREEN\". See, examples/basic/B1/tsg_offscreen.mac."
"\nb) If you want to exploit this feature in interactive mode, simply move"
"\n the instantiation of the UI session earlier. In any case, this is good"
"\n practice in order to capture output in a GUI session.");
return;
}
// Shouldn't happen, since graphicsSystem should be a candidate
G4ExceptionDescription ed;
ed <<
@@ -246,7 +263,7 @@ void G4VisCommandSceneHandlerCreate::SetNewValue (G4UIcommand* command,
<< "\" requested."
<< "\n Candidates are:";
fpVisManager->PrintAvailableGraphicsSystems(verbosity,ed);
command->CommandFailed(JustWarning,ed);
command->CommandFailed(ed);
return;
}
@@ -274,9 +291,11 @@ void G4VisCommandSceneHandlerCreate::SetNewValue (G4UIcommand* command,
if (iGS >= nSystems || loopCounter >=3) {
G4ExceptionDescription ed;
ed << "\"" << gsl[iGSBeingTested]->GetNickname()
<< "\" is not compatible with your chosen session,"
" and no fallback system found.";
command->CommandFailed(JustWarning,ed);
<< "\" is not compatible with the session,"
"\nand no fallback system found. Make sure your session is"
"\ninstantiated _before_ you create a graphics system.";
G4Exception("G4VisCommandSceneHandlerCreate::SetNewValue",
"visman1002", JustWarning, ed);
return;
}
// A fallback system found...but go back and check this too.
@@ -312,7 +331,7 @@ void G4VisCommandSceneHandlerCreate::SetNewValue (G4UIcommand* command,
ed <<
"ERROR: Scene handler \"" << newName
<< "\" already exists.";
command->CommandFailed(JustWarning,ed);
command->CommandFailed(ed);
return;
}
}
@@ -349,7 +368,7 @@ void G4VisCommandSceneHandlerCreate::SetNewValue (G4UIcommand* command,
<< "\" is not the new name \""
<< newName
<< "\".\n Please report to vis coordinator.";
command->CommandFailed(JustWarning,ed);
command->CommandFailed(ed);
return;
}
@@ -176,6 +176,81 @@ void G4VisCommandsTouchable::SetNewValue
return;
}
if (command == fpCommandDump) {
G4PhysicalVolumeModel::TouchableProperties properties =
G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath);
if (properties.fpTouchablePV) {
// To handle parameterisations we have to set the copy number
properties.fpTouchablePV->SetCopyNo(properties.fCopyNo);
G4PhysicalVolumeModel tempPVModel
(properties.fpTouchablePV,
G4PhysicalVolumeModel::UNLIMITED,
properties.fTouchableGlobalTransform,
nullptr, // Modelling parameters (not used)
true, // use full extent (prevents calculating own extent, which crashes)
properties.fTouchableBaseFullPVPath);
const std::map<G4String,G4AttDef>* attDefs = tempPVModel.GetAttDefs();
std::vector<G4AttValue>* attValues = tempPVModel.CreateCurrentAttValues();
G4cout << G4AttCheck(attValues,attDefs);
delete attValues;
const auto lv = properties.fpTouchablePV->GetLogicalVolume();
const auto polyhedron = lv->GetSolid()->GetPolyhedron();
if (polyhedron) {
polyhedron->SetVisAttributes(lv->GetVisAttributes());
G4cout << "\nLocal polyhedron coordinates:\n" << *polyhedron;
const G4Transform3D& transform = tempPVModel.GetCurrentTransform();
polyhedron->Transform(transform);
G4cout << "\nGlobal polyhedron coordinates:\n" << *polyhedron;
}
} else {
G4warn << "Touchable not found." << G4endl;
}
return;
} else if (command == fpCommandFindPath) {
G4String pvName;
G4int copyNo;
std::istringstream iss(newValue);
iss >> pvName >> copyNo;
std::vector<G4PhysicalVolumesSearchScene::Findings> findingsVector;
std::vector<G4VPhysicalVolume*>::iterator iterWorld =
transportationManager->GetWorldsIterator();
for (size_t i = 0; i < nWorlds; ++i, ++iterWorld) {
G4PhysicalVolumeModel searchModel (*iterWorld); // Unlimited depth.
G4ModelingParameters mp; // Default - no culling.
searchModel.SetModelingParameters (&mp);
// Find all instances at any position in the tree
G4PhysicalVolumesSearchScene searchScene (&searchModel, pvName, copyNo);
searchModel.DescribeYourselfTo (searchScene); // Initiate search.
for (const auto& findings: searchScene.GetFindings()) {
findingsVector.push_back(findings);
}
}
for (const auto& findings: findingsVector) {
G4cout
<< findings.fFoundBasePVPath
<< ' ' << findings.fpFoundPV->GetName()
<< ' ' << findings.fFoundPVCopyNo
<< " (mother logical volume: "
<< findings.fpFoundPV->GetMotherLogical()->GetName()
<< ')'
<< G4endl;
}
if (findingsVector.size()) {
G4cout
<< "Use this to set a particular touchable with \"/vis/set/touchable <path>\""
<< "\nor to see overlaps: \"/vis/drawLogicalVolume <mother-logical-volume-name>\""
<< G4endl;
} else {
G4warn << pvName;
if (copyNo >= 0) G4warn << ':' << copyNo;
G4warn << " not found" << G4endl;
}
return;
}
G4VViewer* currentViewer = fpVisManager -> GetCurrentViewer ();
if (!currentViewer) {
if (verbosity >= G4VisManager::errors) {
@@ -310,36 +385,6 @@ void G4VisCommandsTouchable::SetNewValue
}
return;
} else if (command == fpCommandDump) {
G4PhysicalVolumeModel::TouchableProperties properties =
G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath);
if (properties.fpTouchablePV) {
// To handle parameterisations we have to set the copy number
properties.fpTouchablePV->SetCopyNo(properties.fCopyNo);
G4PhysicalVolumeModel tempPVModel
(properties.fpTouchablePV,
G4PhysicalVolumeModel::UNLIMITED,
properties.fTouchableGlobalTransform,
nullptr, // Modelling parameters (not used)
true, // use full extent (prevents calculating own extent, which crashes)
properties.fTouchableBaseFullPVPath);
const std::map<G4String,G4AttDef>* attDefs = tempPVModel.GetAttDefs();
std::vector<G4AttValue>* attValues = tempPVModel.CreateCurrentAttValues();
G4cout << G4AttCheck(attValues,attDefs);
delete attValues;
const auto lv = properties.fpTouchablePV->GetLogicalVolume();
const auto polyhedron = lv->GetSolid()->GetPolyhedron();
polyhedron->SetVisAttributes(lv->GetVisAttributes());
G4cout << "\nLocal polyhedron coordinates:\n" << *polyhedron;
const G4Transform3D& transform = tempPVModel.GetCurrentTransform();
polyhedron->Transform(transform);
G4cout << "\nGlobal polyhedron coordinates:\n" << *polyhedron;
} else {
G4warn << "Touchable not found." << G4endl;
}
return;
} else if (command == fpCommandExtentForField) {
G4PhysicalVolumeModel::TouchableProperties properties =
@@ -363,48 +408,6 @@ void G4VisCommandsTouchable::SetNewValue
}
return;
} else if (command == fpCommandFindPath) {
G4String pvName;
G4int copyNo;
std::istringstream iss(newValue);
iss >> pvName >> copyNo;
std::vector<G4PhysicalVolumesSearchScene::Findings> findingsVector;
std::vector<G4VPhysicalVolume*>::iterator iterWorld =
transportationManager->GetWorldsIterator();
for (size_t i = 0; i < nWorlds; ++i, ++iterWorld) {
G4PhysicalVolumeModel searchModel (*iterWorld); // Unlimited depth.
G4ModelingParameters mp; // Default - no culling.
searchModel.SetModelingParameters (&mp);
// Find all instances at any position in the tree
G4PhysicalVolumesSearchScene searchScene (&searchModel, pvName, copyNo);
searchModel.DescribeYourselfTo (searchScene); // Initiate search.
for (const auto& findings: searchScene.GetFindings()) {
findingsVector.push_back(findings);
}
}
for (const auto& findings: findingsVector) {
G4cout
<< findings.fFoundBasePVPath
<< ' ' << findings.fpFoundPV->GetName()
<< ' ' << findings.fFoundPVCopyNo
<< " (mother logical volume: "
<< findings.fpFoundPV->GetMotherLogical()->GetName()
<< ')'
<< G4endl;
}
if (findingsVector.size()) {
G4cout
<< "Use this to set a particular touchable with \"/vis/set/touchable <path>\""
<< "\nor to see overlaps: \"/vis/drawLogicalVolume <mother-logical-volume-name>\""
<< G4endl;
} else {
G4warn << pvName;
if (copyNo >= 0) G4warn << ':' << copyNo;
G4warn << " not found" << G4endl;
}
return;
} else if (command == fpCommandLocalAxes) {
G4PhysicalVolumeModel::TouchableProperties properties =
@@ -1079,7 +1079,7 @@ void G4VisCommandViewerCreate::SetNewValue (G4UIcommand* command, G4String newVa
if (existingViewer) {
// ...bring view parameters up to date...
fExistingVP = existingViewer->GetViewParameters();
fExistingSceneTree = existingViewer->AccessSceneTree();
fExistingSceneTree = existingViewer->GetSceneTree();
}
}
@@ -1112,7 +1112,7 @@ void G4VisCommandViewerCreate::SetNewValue (G4UIcommand* command, G4String newVa
fThereWasAViewer = true;
auto viewer = fpVisManager->GetCurrentViewer();
fExistingVP = viewer->GetViewParameters();
fExistingSceneTree = viewer->AccessSceneTree();
fExistingSceneTree = viewer->GetSceneTree();
} else {
G4ExceptionDescription ed;
if (newViewer) {
@@ -113,7 +113,8 @@ G4VisManager::G4VisManager (const G4String& verbosityString)
, fTransientsDrawnThisRun (false)
, fTransientsDrawnThisEvent (false)
, fNoOfEventsDrawnThisRun (0)
, fNKeepRequests (0)
, fNKeepForPostProcessingRequests (0)
, fNKeepTheEventRequests (0)
, fEventKeepingSuspended (false)
, fDrawEventOnlyIfToBeKept (false)
, fpRequestedEvent (0)
@@ -1735,7 +1736,7 @@ void G4VisManager::PrintAvailableGraphicsSystems
for (const auto& gs: fAvailableGraphicsSystems) {
const G4String& name = gs->GetName();
const std::vector<G4String>& nicknames = gs->GetNicknames();
if (verbosity <= warnings) {
if (verbosity >= warnings) {
// Brief output
out << " " << name << " (";
for (std::size_t i = 0; i < nicknames.size(); ++i) {
@@ -1751,15 +1752,20 @@ void G4VisManager::PrintAvailableGraphicsSystems
}
out << std::endl;
}
out << "Default graphics system is: " << fDefaultGraphicsSystemName
<< " (based on " << fDefaultGraphicsSystemBasis << ")."
<< "\nDefault window size hint is: " << fDefaultXGeometryString
<< " (based on " << fDefaultXGeometryStringBasis << ")."
<< "\nNote: Parameters specified on the command line will override these defaults."
<< "\n Use \"vis/open\" without parameters to get these defaults."
out <<
"You may choose a graphics system (driver) with a parameter of"
"\nthe command \"/vis/open\" or \"/vis/sceneHandler/create\","
"\nor you may omit the driver parameter and choose at run time:"
"\n- by argument in the construction of G4VisExecutive;"
"\n- by environment variable \"G4VIS_DEFAULT_DRIVER\";"
"\n- by entry in \"~/.g4session\";"
"\n- by build flags."
"\n- Note: This feature is not allowed in batch mode."
"\nFor further information see \"examples/basic/B1/exampleB1.cc\""
"\nand \"vis.mac\"."
<< std::endl;
} else {
out << " NONE!!! None registered - yet! Mmmmm!" << G4endl;
out << " NONE!!! None registered - yet! Mmmmm!" << std::endl;
}
}
@@ -1983,14 +1989,14 @@ G4ThreadFunReturnType G4VisManager::G4VisSubThread(G4ThreadFunArgType p)
// Then pop and release event
G4MUTEXLOCK(&mtVisSubThreadMutex);
mtVisEventQueue.pop_front();
event->PostProcessingFinished();
pVisManager->EndOfEventCleanup(event, event->GetEventID());
eventQueueSize = mtVisEventQueue.size();
G4MUTEXUNLOCK(&mtVisSubThreadMutex);
// G4cout << "Event queue size (B): " << eventQueueSize << G4endl;
}
G4MUTEXLOCK(&mtVisSubThreadMutex);
G4int runInProgress = mtRunInProgress;
G4bool runInProgress = mtRunInProgress;
G4MUTEXUNLOCK(&mtVisSubThreadMutex);
if (!runInProgress) {
// EndOfRun on master thread has signalled end of run. There is
@@ -2018,6 +2024,10 @@ namespace {
#endif
namespace {
G4bool isSubEventRunManagerType = false;
}
void G4VisManager::BeginOfRun ()
{
if (fIgnoreStateChanges) return;
@@ -2029,12 +2039,20 @@ void G4VisManager::BeginOfRun ()
// << G4Threading::G4GetThreadId() << G4endl;
G4RunManager* runManager = G4RunManagerFactory::GetMasterRunManager();
G4RunManager::RMType rmType = runManager->GetRunManagerType();
isSubEventRunManagerType =
(rmType == G4RunManager::subEventMasterRM) ||
(rmType == G4RunManager::subEventWorkerRM);
// If sub-event active, ignore if invoked from worker thread
if(isSubEventRunManagerType && G4Threading::IsWorkerThread()) return;
// For a fake run...
G4int nEventsToBeProcessed = runManager->GetNumberOfEventsToBeProcessed();
if (nEventsToBeProcessed == 0) return;
fNKeepRequests = 0;
fNKeepForPostProcessingRequests = 0;
fNKeepTheEventRequests = 0;
fEventKeepingSuspended = false;
fTransientsDrawnThisRun = false;
if (fpSceneHandler) fpSceneHandler->SetTransientsDrawnThisRun(false);
@@ -2082,6 +2100,8 @@ void G4VisManager::BeginOfEvent ()
if (!GetConcreteInstance()) return;
if (isSubEventRunManagerType) return;
// G4cout << "G4VisManager::BeginOfEvent: thread: "
// << G4Threading::G4GetThreadId() << G4endl;
@@ -2093,19 +2113,38 @@ void G4VisManager::BeginOfEvent ()
#endif
}
#ifdef G4MULTITHREADED
void G4VisManager::EventReadyForVis(const G4Event* event)
// This is invoked by G4SubEvtRunManager.
// The event is passed to EndOfEventKernel.
{
if (fIgnoreStateChanges) return;
if (!GetConcreteInstance()) return;
G4bool valid = fpSceneHandler && IsValidView();
if (!valid) return;
G4AutoLock al(&visEndOfEventMutex);
EndOfEventKernel(event);
}
#endif
void G4VisManager::EndOfEvent ()
{
if (fIgnoreStateChanges) return;
if (!GetConcreteInstance()) return;
// G4cout << "G4VisManager::EndOfEvent: thread: "
// << G4Threading::G4GetThreadId() << G4endl;
if (isSubEventRunManagerType) return;
// G4cout << "G4VisManager::EndOfEvent: thread: "
// << G4Threading::G4GetThreadId() << G4endl;
#ifdef G4MULTITHREADED
G4AutoLock al(&visEndOfEventMutex);
// Testing.
// std::this_thread::sleep_for(std::chrono::seconds(5));
// std::this_thread::sleep_for(std::chrono::seconds(5));
#endif
// Don't call IsValidView unless there is a scene handler. This
@@ -2124,10 +2163,81 @@ void G4VisManager::EndOfEvent ()
const G4Event* currentEvent = eventManager->GetConstCurrentEvent();
if (!currentEvent) return;
// Call kernel
EndOfEventKernel(currentEvent);
}
G4bool G4VisManager::Relinquishable (G4int eventID, G4int nKeptEvents, G4int nRequests)
// Figures out if event is relinquishable, i.e., the run manager(s) may delete.
// If _not_ relinquishable, KeepCurrentEvent is called as soon as event is recieved.
// If relinquishable, PostProcesssingFinshed is called when drawing finished.
// nKeptEvents is number of events currently kept by the run manager.
// nRequests is the number of requests for keeping made by the vis maanager.
{
G4bool relinquishable = false;
G4RunManager* runManager = G4RunManagerFactory::GetMasterRunManager();
G4int nEventsToBeProcessed = runManager->GetNumberOfEventsToBeProcessed();
if (fpScene->GetRefreshAtEndOfEvent()) {
// Unless last event (in which case wait end of run)...
if (eventID < nEventsToBeProcessed - 1) {
relinquishable = true;
} else { // Last event - relinquish too if user has kept some
if (nKeptEvents > 0) {
relinquishable = true;
}
}
fpSceneHandler->SetMarkForClearingTransientStore(true);
} else { // Accumulating events...
G4int maxNumberOfKeptEvents = fpScene->GetMaxNumberOfKeptEvents();
if (maxNumberOfKeptEvents >= 0 &&
nRequests >= maxNumberOfKeptEvents) {
fEventKeepingSuspended = true;
static G4bool warned = false;
if (!warned) {
if (fVerbosity >= warnings) {
G4warn <<
"WARNING: G4VisManager::EndOfEvent: Automatic event keeping suspended."
<< G4endl;
if (maxNumberOfKeptEvents > 0) {
G4warn <<
"\n The number of events exceeds the maximum, "
<< maxNumberOfKeptEvents <<
", that may be kept by\n the vis manager."
<< G4endl;
}
}
warned = true;
}
relinquishable = true;
} else if (maxNumberOfKeptEvents != 0) { // i.e., indefinite keeping
// Relinquish anyway if disabled or suspended
if (!GetConcreteInstance() || fEventKeepingSuspended) {
relinquishable = true;
}
}
}
return relinquishable;
}
void G4VisManager::EndOfEventKernel (const G4Event* currentEvent)
{
G4RunManager* runManager = G4RunManagerFactory::GetMasterRunManager();
const G4Run* currentRun = runManager->GetCurrentRun();
G4EventManager* eventManager = G4EventManager::GetEventManager();
// Discard event if fDrawEventOnlyIfToBeKept flag is set unless the
// user has requested the event to be kept.
if (fDrawEventOnlyIfToBeKept) {
if (!currentEvent->ToBeKept()) return;
if (!currentEvent->KeepTheEventFlag()) return;
}
if (G4Threading::IsMultithreadedApplication()) {
@@ -2138,12 +2248,12 @@ void G4VisManager::EndOfEvent ()
G4MUTEXLOCK(&mtVisSubThreadMutex);
std::size_t eventQueueSize = mtVisEventQueue.size();
G4MUTEXUNLOCK(&mtVisSubThreadMutex);
// G4cout << "Event queue size (1): " << eventQueueSize << G4endl;
// G4cout << "Event queue size (1): " << eventQueueSize << G4endl;
G4bool eventQueueFull = false;
while (fMaxEventQueueSize > 0 && (G4int)eventQueueSize >= fMaxEventQueueSize) {
// G4cout << "Event queue size (2): " << eventQueueSize << G4endl;
// G4cout << "Event queue size (2): " << eventQueueSize << G4endl;
if (fWaitOnEventQueueFull) {
static G4bool warned = false;
if (!warned) {
@@ -2192,24 +2302,25 @@ void G4VisManager::EndOfEvent ()
}
if (!eventQueueFull) {
G4MUTEXLOCK(&mtVisSubThreadMutex);
// Keep event for processing and put event on vis event queue
// Make sure the event is not deleted by the run manager while in the vis queue
currentEvent->KeepForPostProcessing();
if (fpScene->GetRefreshAtEndOfEvent()) {
// Keep one event (cannot know which is last so any will do)
if (fNKeepRequests == 0) {
eventManager->KeepTheCurrentEvent();
fNKeepRequests++;
}
fNKeepForPostProcessingRequests++;
if (!Relinquishable(currentEvent->GetEventID(),
(G4int)currentRun->GetEventVector()->size(),
fNKeepTheEventRequests)) {
eventManager->KeepTheCurrentEvent();
fNKeepTheEventRequests++; // Counts number of calls to KeepTheCurrentEvent
}
G4MUTEXLOCK(&mtVisSubThreadMutex);
// Put event on vis queue
mtVisEventQueue.push_back(currentEvent);
G4MUTEXUNLOCK(&mtVisSubThreadMutex);
}
// G4MUTEXLOCK(&mtVisSubThreadMutex);
// G4int eQS = mtVisEventQueue.size();
// G4MUTEXUNLOCK(&mtVisSubThreadMutex);
// G4cout << "Event queue size (5): " << eQS << G4endl;
// G4MUTEXLOCK(&mtVisSubThreadMutex);
// G4int eQS = mtVisEventQueue.size();
// G4MUTEXUNLOCK(&mtVisSubThreadMutex);
// G4cout << "Event queue size (5): " << eQS << G4endl;
#endif
@@ -2217,14 +2328,9 @@ void G4VisManager::EndOfEvent ()
// Sequential mode
G4int nEventsToBeProcessed = 0;
G4int nKeptEvents = 0;
G4int eventID = -2; // (If no run manager, triggers ShowView as normal.)
if (currentRun) {
nEventsToBeProcessed = runManager->GetNumberOfEventsToBeProcessed();
eventID = currentEvent->GetEventID();
const std::vector<const G4Event*>* events = currentRun->GetEventVector();
if (events) nKeptEvents = (G4int)events->size();
}
// We are about to draw the event (trajectories, etc.), but first we
@@ -2237,69 +2343,45 @@ void G4VisManager::EndOfEvent ()
// See, for example, G4HepRepFileSceneHandler::ClearTransientStore.
ClearTransientStoreIfMarked();
// Keep - but relinquish (PostProcessingFinished) later if not needed
currentEvent->KeepForPostProcessing();
if (!Relinquishable(currentEvent->GetEventID(),
(G4int)currentRun->GetEventVector()->size(),
fNKeepTheEventRequests)) {
eventManager->KeepTheCurrentEvent();
fNKeepTheEventRequests++; // Counts number of calls to KeepTheCurrentEvent
}
// Now draw the event...
fpSceneHandler->DrawEvent(currentEvent);
++fNoOfEventsDrawnThisRun;
if (fpScene->GetRefreshAtEndOfEvent()) {
EndOfEventCleanup(currentEvent,eventID);
}
}
// Unless last event (in which case wait end of run)...
if (eventID < nEventsToBeProcessed - 1) {
// ShowView guarantees the view is flushed to the screen. It also
// triggers other features such picking (if enabled) and allows
// file-writing viewers to close the file.
fpViewer->ShowView();
} else { // Last event...
// Keep, but only if user has not kept any...
if (nKeptEvents == 0) {
eventManager->KeepTheCurrentEvent();
fNKeepRequests++;
}
}
fpSceneHandler->SetMarkForClearingTransientStore(true);
}
void G4VisManager::EndOfEventCleanup
(const G4Event* currentEvent,
G4int eventID) // See EndOfEventKernel: can be == -2?
{
G4RunManager* runManager = G4RunManagerFactory::GetMasterRunManager();
G4int nKeptEvents = 0;
const G4Run* currentRun = runManager->GetCurrentRun();
if (currentRun) {
const std::vector<const G4Event*>* events = currentRun->GetEventVector();
if (events) nKeptEvents = (G4int)events->size();
}
// Both modes - sequential and MT
if (!(fpScene->GetRefreshAtEndOfEvent())) {
// Accumulating events...
G4int maxNumberOfKeptEvents = fpScene->GetMaxNumberOfKeptEvents();
if (maxNumberOfKeptEvents >= 0 &&
fNKeepRequests >= maxNumberOfKeptEvents) {
fEventKeepingSuspended = true;
static G4bool warned = false;
if (!warned) {
if (fVerbosity >= warnings) {
G4warn <<
"WARNING: G4VisManager::EndOfEvent: Automatic event keeping suspended."
<< G4endl;
if (maxNumberOfKeptEvents > 0) {
G4warn <<
"\n The number of events exceeds the maximum, "
<< maxNumberOfKeptEvents <<
", that may be kept by\n the vis manager."
<< G4endl;
}
}
warned = true;
}
} else if (maxNumberOfKeptEvents != 0) {
// If not disabled nor suspended.
if (GetConcreteInstance() && !fEventKeepingSuspended) {
// G4cout <<
// "Requesting keeping event " << currentEvent->GetEventID()
// << G4endl;
eventManager->KeepTheCurrentEvent();
fNKeepRequests++;
}
// Seems to relinquish every event - probably becuase it doesn't get here soon enough.
// In fact, it makes sense to do this - immediate post processing is finished,
// and a user-requested number of events have been kept. So great!
if (Relinquishable(eventID, nKeptEvents, fNKeepForPostProcessingRequests)) {
currentEvent->PostProcessingFinished();
if (fpScene->GetRefreshAtEndOfEvent()) { // && eventID == -2?
// ShowView guarantees the view is flushed to the screen. It also
// triggers other features such picking (if enabled) and allows
// file-writing viewers to close the file.
fpViewer->ShowView();
}
}
}
@@ -2366,17 +2448,17 @@ void G4VisManager::EndOfRun ()
if (nKeptEvents == 1) G4warn << " event has";
else G4warn << " events have";
G4warn << " been kept for refreshing and/or reviewing." << G4endl;
if (nKeptEvents != fNKeepRequests) {
if (nKeptEvents != fNKeepTheEventRequests) {
G4warn << " (Note: ";
if (fNKeepRequests == 0) {
if (fNKeepTheEventRequests == 0) {
G4warn << "No keep requests were";
} else if (fNKeepRequests == 1) {
} else if (fNKeepTheEventRequests == 1) {
G4warn << "1 keep request was";
} else {
G4warn << fNKeepRequests << " keep requests were";
G4warn << fNKeepTheEventRequests << " keep requests were";
}
G4warn << " made by the vis manager.";
if (fNKeepRequests == 0) {
if (fNKeepTheEventRequests == 0) {
G4warn <<
"\n The kept events are those you have asked to be kept in your user action(s).)";
} else {