Import Geant4 11.3.0 source tree

This commit is contained in:
Gabriele Cosmo
2024-12-06 11:11:40 +01:00
parent e58e650b32
commit 32390e802b
1984 changed files with 98713 additions and 83996 deletions
+56
View File
@@ -6,6 +6,62 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2024-09-13 John Allison (opengl-V11-02-09)
- G4OpenGLStoredQtSceneHandler.cc:
- G4OpenGLStoredQtSceneHandler::ClearStore():
- Commented out some code related to the old scene tree. The old scene
tree is currently (partially) disabled, but this code somehow affects
the view in rare cases, e.g., after twinkling the volume does not return
to its original colour. So I have disabled this, pending a review of
the old scene tree.
## 2024-10-25 John Allison (opengl-V11-02-08)
- G4OpenGLQtViewer.cc:
- G4OpenGLQtViewer::currentTabActivated(): Fix compilation error, see Bug Report 2633.
- Use .data().
## 2024-09-13 John Allison (opengl-V11-02-07)
- G4OpenGLQtViewer.cc:
- Comment out code that refers to the old scene tree because it adversely impacts
the new scene tree.
- I would like to extract the old scene tree code completely, but so far I have
found it difficult, since it is so entangled with other code. So my efforts so
far have been to bop problems on the head as they arise. Not satisfactory, I
know, and I will continue to work on it.
## 2024-08-13 John Allison (opengl-V11-02-06)
- G4OpenGLQtViewer:
- Resolve the timing issues around switching to the vis sub-thread with the
use of G4CONDITIONWAITLAMBDA.
- Fix small memory leak in G4OpenGLQtViewer::DrawText.
## 2024-07-24 Guy Barrand (opengl-V11-02-05)
- G4OpenGLImmediateQtViewer, G4OpenGLStoredQtViewer::ShowView: Qt6: do a:
((QApplication*)G4Qt::getInstance ())->processEvents();
so that a:
/vis/viewer/interpolate viewfiles/movie-1
produces truly an animation.
## 2024-07-12 Guy Barrand (opengl-V11-02-04)
- G4OpenGLQtViewer: Qt6: implement ReadyToDraw(). It permits to avoid a crash in case
of /run/beamOn in vis.mac at startup (especially on macOS).
- G4OpenGLImmediateQtViewer, G4OpenGLStoredQtViewer: Qt5: in Initialise(), displace
makeCurrent() after CreateMainWindow(). It avoids a crash in case of /run/beamOn
in vis.mac at startup.
- G4OpenGLQtViewer: Qt5, Qt6: in DoneWithVisSubThread(), SwitchToMasterThread() protect
against a possible null qGLW->context(). It permits to avoid a crash in case of
doing /run/beamOn in vis.mac at startup.
- G4OpenGLQtViewer, G4OpenGLImmediateQtViewer, G4OpenGLStoredQtViewer: Qt6:
remove unused fields: fHasToRepaint, fUpdateGLLock, fQGLWidgetInitialiseCompleted
and fPaintEventLock.
- G4OpenGLImmediateQtViewer, G4OpenGLStoredQtViewer: Qt6: remove no more needed
initializeGL() and showEvent() methods.
- G4OpenGLImmediateQtViewer, G4OpenGLStoredQtViewer: Qt6: displace setExportImageFormat("jpg")
in Initialise().
## 2024-06-21 Ben Morgan (opengl-V11-02-03)
- Use runtime checks for MT mode where possible.
## 2024-05-30 Guy Barrand (opengl-V11-02-02)
- G4OpenGLImmediateQtViewer, G4OpenGLStoredQtViewer: Qt6: remove the usage of a paintEvent(),
the paintGL() should be sufficient. Having an extra paintEvent() is confusing.
@@ -47,7 +47,9 @@ public:
const G4String& name = "");
~G4OpenGLImmediateQtViewer ();
void Initialise ();
#if QT_VERSION < 0x060000
void initializeGL ();
#endif
void DrawView ();
void resizeGL(int width,int height);
void paintGL();
@@ -66,7 +68,9 @@ public:
}
#endif
protected:
#if QT_VERSION < 0x060000
void showEvent(QShowEvent * event );
#endif
void wheelEvent(QWheelEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
@@ -97,7 +97,17 @@ public:
G4OpenGLQtViewer (G4OpenGLSceneHandler& scene);
virtual ~G4OpenGLQtViewer ();
#ifdef G4MULTITHREADED
// In MT mode these functions are called in the following order for each run:
// For switching threads in MT mode
// Note: the order of calling of MovingToVisSubThread and SwitchToVisSubThread
// is undefined, so we have to use mutexes to ensure required information,
// namely the vis sub-thread address, is available before moving objects.
// To summarise, the order of calling is
// DoneWithMasterThread
// MovingToVisSubThread ) or ( SwitchToVisSubThread
// SwitchToVisSubThread ) ( MovingToVisSubThread
// DoneWithVisSubThread
// MovingToMasterThread
// SwitchToMasterThread
// Called on the master thread before starting the vis sub-thread.
virtual void DoneWithMasterThread ();
// Called on the master thread after starting the vis sub-thread.
@@ -116,6 +126,7 @@ private:
G4OpenGLQtViewer (const G4OpenGLQtViewer&);
G4OpenGLQtViewer& operator= (const G4OpenGLQtViewer&);
public:
virtual G4bool ReadyToDraw();
virtual void updateQWidget()=0;
void updateSceneTreeWidget();
void updateViewerPropertiesTableWidget();
@@ -194,10 +205,12 @@ protected:
void savePPMToTemp();
int fRecordFrameNumber;
#if QT_VERSION < 0x060000
bool fHasToRepaint;
bool fUpdateGLLock;
bool fQGLWidgetInitialiseCompleted;
bool fPaintEventLock;
#endif
// Flag to indicate that action was initiated by interaction (mouse
// click) on the scene tree. It is used and reset in
@@ -265,15 +278,6 @@ private:
std::string parseSceneTreeElementAndSaveState(QTreeWidgetItem* item, unsigned int level);
QString GetCommandParameterList (const G4UIcommand *aCommand);
void changeColorAndTransparency(GLuint index, G4Color color);
#ifdef G4MULTITHREADED
inline void SetQGLContextVisSubThread(QThread *th) {
fQGLContextVisSubThread = th;
}
inline void SetQGLContextMainThread(QThread *th) {
fQGLContextMainThread = th;
}
#endif
QMenu *fContextMenu;
QPoint fLastPos1;
@@ -386,12 +390,6 @@ private:
#ifdef G4MULTITHREADED
QThread* fQGLContextVisSubThread;
QThread* fQGLContextMainThread;
G4Mutex fmWaitForVisSubThreadQtOpenGLContextMoved;
G4Mutex fmWaitForVisSubThreadQtOpenGLContextInitialized;
G4Condition fc1_VisSubThreadQtOpenGLContextInitialized;
G4Condition fc2_VisSubThreadQtOpenGLContextMoved;
G4AutoLock* flWaitForVisSubThreadQtOpenGLContextInitialized;
G4AutoLock* flWaitForVisSubThreadQtOpenGLContextMoved;
#endif
public Q_SLOTS :
@@ -49,7 +49,9 @@ public:
const G4String& name = "");
~G4OpenGLStoredQtViewer ();
void Initialise ();
#if QT_VERSION < 0x060000
void initializeGL ();
#endif
void DrawView ();
void resizeGL(int width,int height);
void paintGL();
@@ -78,7 +80,9 @@ protected:
G4bool POSelected(size_t POListIndex);
G4bool TOSelected(size_t TOListIndex);
#if QT_VERSION < 0x060000
void showEvent(QShowEvent * event );
#endif
void wheelEvent(QWheelEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
@@ -54,10 +54,8 @@ public:
virtual ~G4OpenGLXViewer ();
void SetView ();
void ShowView ();
#ifdef G4MULTITHREADED
void SwitchToVisSubThread();
void SwitchToMasterThread();
#endif
void DrawText(const G4Text&);
protected:
@@ -82,9 +80,7 @@ protected:
XSetWindowAttributes swa;
GLXDrawable win;
GLXContext cxMaster;
#ifdef G4MULTITHREADED
GLXContext cxVisSubThread;
#endif
XEvent event;
G4int *attributeList,
errorBase,
@@ -33,12 +33,12 @@
#include "G4OpenGLImmediateSceneHandler.hh"
#include "G4ios.hh"
#ifdef G4MULTITHREADED
#include "G4Threading.hh"
#endif
#include <qapplication.h>
#include <qtabwidget.h>
#if 0x060000 <= QT_VERSION
#include "G4Qt.hh"
#endif
G4OpenGLImmediateQtViewer::G4OpenGLImmediateQtViewer
(G4OpenGLImmediateSceneHandler& sceneHandler,
@@ -48,6 +48,7 @@ G4OpenGLImmediateQtViewer::G4OpenGLImmediateQtViewer
G4OpenGLQtViewer (sceneHandler),
G4OpenGLImmediateViewer (sceneHandler)
{
#if QT_VERSION < 0x060000
fQGLWidgetInitialiseCompleted = false;
setFocusPolicy(Qt::StrongFocus); // enable keybord events
@@ -56,19 +57,20 @@ G4OpenGLImmediateQtViewer::G4OpenGLImmediateQtViewer
fUpdateGLLock = false;
if (fViewId < 0) return; // In case error in base class instantiation.
#else
setFocusPolicy(Qt::StrongFocus); // enable keybord events
#endif
}
G4OpenGLImmediateQtViewer::~G4OpenGLImmediateQtViewer() {
// makeCurrent(); // Not sure why this - commented out 12-Apr-2021 JA
}
G4OpenGLImmediateQtViewer::~G4OpenGLImmediateQtViewer() {}
void G4OpenGLImmediateQtViewer::Initialise() {
#if QT_VERSION < 0x060000
makeCurrent();
fQGLWidgetInitialiseCompleted = false;
CreateMainWindow (this,QString(GetName()));
makeCurrent();
glDrawBuffer (GL_BACK);
// set the good tab active
@@ -81,16 +83,13 @@ void G4OpenGLImmediateQtViewer::Initialise() {
fQGLWidgetInitialiseCompleted = true;
#else
fQGLWidgetInitialiseCompleted = false;
CreateMainWindow (this,QString(GetName()));
if(G4QGLWidgetType::isValid()) { //G.Barrand: macOS: isValid() needed at startup.
makeCurrent();
glDrawBuffer (GL_BACK);
}
fQGLWidgetInitialiseCompleted = true;
// Set jpg as default export format for Qt viewer
setExportImageFormat("jpg");
#endif
}
#if QT_VERSION < 0x060000
void G4OpenGLImmediateQtViewer::initializeGL () {
InitializeGLView ();
@@ -113,6 +112,7 @@ void G4OpenGLImmediateQtViewer::initializeGL () {
// Set jpg as default export format for Qt viewer
setExportImageFormat("jpg");
}
#endif
void G4OpenGLImmediateQtViewer::DrawView() {
@@ -123,22 +123,20 @@ void G4OpenGLImmediateQtViewer::DrawView() {
return;
}
#endif
#ifdef G4MULTITHREADED
if (G4Threading::G4GetThreadId() == G4Threading::MASTER_ID) {
if (G4Threading::IsMasterThread()) {
updateQWidget();
}
#else
updateQWidget();
#endif
}
void G4OpenGLImmediateQtViewer::ComputeView () {
#if QT_VERSION < 0x060000
makeCurrent();
// If a double buffer context has been forced upon us, ignore the
// back buffer for this OpenGLImmediate view.
// glDrawBuffer (GL_FRONT);
#endif
G4ViewParameters::DrawingStyle dstyle = GetViewParameters().GetDrawingStyle();
@@ -160,7 +158,9 @@ void G4OpenGLImmediateQtViewer::ComputeView () {
savePPMToTemp();
}
#if QT_VERSION < 0x060000
fHasToRepaint = true;
#endif
}
/**
@@ -173,10 +173,10 @@ void G4OpenGLImmediateQtViewer::resizeGL(
if ((aWidth > 0) && (aHeight > 0)) {
#if QT_VERSION < 0x060000
ResizeWindow(aWidth,aHeight);
fHasToRepaint = sizeHasChanged();
#else
ResizeWindow(devicePixelRatio()*aWidth,devicePixelRatio()*aHeight);
#endif
fHasToRepaint = sizeHasChanged();
}
}
@@ -189,6 +189,7 @@ void G4OpenGLImmediateQtViewer::paintGL()
//G.Barrand: don't do any change in the GUI here, just "paint" this widget!
#endif
#if QT_VERSION < 0x060000
if (fPaintEventLock) {
// return ;
}
@@ -200,7 +201,6 @@ void G4OpenGLImmediateQtViewer::paintGL()
return;
}
#if QT_VERSION < 0x060000
// DO NOT RESIZE IF SIZE HAS NOT CHANGE
if ( !fHasToRepaint) {
// L. Garnier : Trap to get the size with mac OSX 10.6 and Qt 4.6(devel)
@@ -223,11 +223,14 @@ void G4OpenGLImmediateQtViewer::paintGL()
}
}
}
#else
if ((getWinWidth() == 0) && (getWinHeight() == 0)) return; //G.Barrand: needed?
#endif
#if QT_VERSION < 0x060000
#else
InitializeGLView ();
glDrawBuffer (GL_BACK);
#endif
SetView();
@@ -235,9 +238,11 @@ void G4OpenGLImmediateQtViewer::paintGL()
ClearView (); //ok, put the background correct
ComputeView();
#if QT_VERSION < 0x060000
fHasToRepaint = false; // could be set to false by ComputeView
fPaintEventLock = false;
#endif
}
void G4OpenGLImmediateQtViewer::mousePressEvent(QMouseEvent *event)
@@ -260,13 +265,14 @@ void G4OpenGLImmediateQtViewer::wheelEvent (QWheelEvent * event)
G4wheelEvent(event);
}
#if QT_VERSION < 0x060000
void G4OpenGLImmediateQtViewer::showEvent (QShowEvent *)
{
if (fQGLWidgetInitialiseCompleted) {
fHasToRepaint = true;
}
}
#endif
/**
* This function was build in order to make a zoom on double clic event.
@@ -313,6 +319,7 @@ void G4OpenGLImmediateQtViewer::paintEvent(QPaintEvent *) {
void G4OpenGLImmediateQtViewer::updateQWidget() {
#if QT_VERSION < 0x060000
if (fUpdateGLLock) {
return;
}
@@ -323,23 +330,25 @@ void G4OpenGLImmediateQtViewer::updateQWidget() {
fUpdateGLLock = true;
fHasToRepaint= true;
#if QT_VERSION < 0x060000
repaint();
updateViewerPropertiesTableWidget();
updateSceneTreeWidget();
fUpdateGLLock= false;
#else
//if (!isCurrentWidget()) return; //G.Barrand: Qt must know if it has to activate paintGL() if the widget is not visible.
//G.Barrand: don't do any change in the GUI here, just ask to "paint" this widget!
update();
#endif
fUpdateGLLock= false;
}
void G4OpenGLImmediateQtViewer::ShowView (
)
//////////////////////////////////////////////////////////////////////////////
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
void G4OpenGLImmediateQtViewer::ShowView ()
{
#if QT_VERSION < 0x060000
fHasToRepaint = true;
activateWindow();
#else
activateWindow();
((QApplication*)G4Qt::getInstance ())->processEvents();
#endif
}
@@ -112,9 +112,6 @@ void G4OpenGLQtViewer::CreateMainWindow (
if(fGLWidget) return; //Done.
fGLWidget = glWidget ;
// fGLWidget->makeCurrent();
G4Qt* interactorManager = G4Qt::getInstance ();
#if QT_VERSION < 0x060000
ResizeWindow(fVP.GetWindowSizeHintX(),fVP.GetWindowSizeHintY());
@@ -144,6 +141,7 @@ void G4OpenGLQtViewer::CreateMainWindow (
bool isTabbedView = false;
if ( fUiQt) {
if (!fBatchMode) {
G4Qt* interactorManager = G4Qt::getInstance ();
if (!interactorManager->IsExternalApp()) {
// INIT size
fWinSize_x = fVP.GetWindowSizeHintX();
@@ -272,15 +270,6 @@ G4OpenGLQtViewer::G4OpenGLQtViewer (
,fLastHighlightName(0)
,fIsDeleting(false)
{
#ifdef G4MULTITHREADED
flWaitForVisSubThreadQtOpenGLContextInitialized
= new G4AutoLock(fmWaitForVisSubThreadQtOpenGLContextInitialized,
std::defer_lock);
flWaitForVisSubThreadQtOpenGLContextMoved
= new G4AutoLock(fmWaitForVisSubThreadQtOpenGLContextMoved,
std::defer_lock);
#endif
// launch Qt if not
if (QCoreApplication::instance () == NULL) {
fBatchMode = true;
@@ -525,12 +514,18 @@ G4OpenGLQtViewer::~G4OpenGLQtViewer (
G4cout <<removeTempFolder().toStdString().c_str() <<G4endl; //G.Barrand: with Qt6, it crashes at exit if the viewer is in a detached dialog window.
#endif
#ifdef G4MULTITHREADED
delete flWaitForVisSubThreadQtOpenGLContextInitialized;
delete flWaitForVisSubThreadQtOpenGLContextMoved;
#endif
}
G4bool G4OpenGLQtViewer::ReadyToDraw() {
#if QT_VERSION < 0x060000
return true;
#else
if(!fGLWidget) return false;
auto* qGLW = dynamic_cast<G4QGLWidgetType*>(fGLWidget);
if (!qGLW) return false;
return qGLW->isValid();
#endif
}
//
// Create a popup menu for the widget. This menu is activated by right-mouse click
@@ -2416,8 +2411,6 @@ QWidget *G4OpenGLQtViewer::getParentWidget()
{
// launch Qt if not
G4Qt* interactorManager = G4Qt::getInstance ();
// G4UImanager* UI =
// G4UImanager::GetUIpointer();
bool found = false;
QDialog* dialog = NULL;
@@ -2815,9 +2808,7 @@ void G4OpenGLQtViewer::DrawText(const G4Text& g4text)
if (!fGLWidget) return;
#ifdef G4MULTITHREADED
if (G4Threading::G4GetThreadId() != G4Threading::MASTER_ID) return;
#endif
if (!G4Threading::IsMasterThread()) return;
G4VSceneHandler::MarkerSizeType sizeType;
G4double size = fSceneHandler.GetMarkerSize(g4text,sizeType);
@@ -2833,8 +2824,8 @@ void G4OpenGLQtViewer::DrawText(const G4Text& g4text)
const char* textCString = textString.c_str();
// Calculate move for centre and right adjustment
QFontMetrics* f = new QFontMetrics (font);
G4double span = f->boundingRect(textCString).width();
QFontMetrics f(font);
G4double span = f.boundingRect(textCString).width();
G4double xmove = 0.;
G4double ymove = 0.;
@@ -4714,10 +4705,10 @@ void G4OpenGLQtViewer::toggleSceneTreeComponentPickingCout(int pickItem) {
void G4OpenGLQtViewer::currentTabActivated(int currentTab) {
if (fUiQt->GetViewerTabWidget()->tabText(currentTab) == GetName()) {
if (fUiQt->GetViewerTabWidget()->tabText(currentTab) == GetName().data()) {
createViewerPropertiesWidget();
createPickInfosWidget();
createSceneTreeWidget();
// createPickInfosWidget(); // Causes a /vis/set/touchable command to do with...
// createSceneTreeWidget(); // ...this old scene tree widget (no longer used)
}
}
@@ -4797,101 +4788,100 @@ QString G4OpenGLQtViewer::GetCommandParameterList (
#ifdef G4MULTITHREADED
namespace {
G4Mutex visSubThreadMutex = G4MUTEX_INITIALIZER;
G4Condition waitForVisSubThreadInitialized = G4CONDITION_INITIALIZER;
G4bool visSubThreadEstablished = false;
G4bool qObjectsSwitched = false;
G4QGLWidgetType* qGLWidget = nullptr;
}
void G4OpenGLQtViewer::DoneWithMasterThread()
{
// Called by Main Thread !
// Useful to avoid two vis thread at the same time
//G4MUTEXLOCK(&fmWaitForVisSubThreadQtOpenGLContextInitialized);
if(!flWaitForVisSubThreadQtOpenGLContextInitialized->owns_lock())
flWaitForVisSubThreadQtOpenGLContextInitialized->lock();
// Initialise and check qGLWidget - no need to check in subsequent functions
qGLWidget = dynamic_cast<G4QGLWidgetType*>(fGLWidget);
if (qGLWidget == nullptr) return;
// Done with master thread
qGLWidget->doneCurrent();
// Set current QThread for the way back
fQGLContextMainThread = QThread::currentThread();
}
void G4OpenGLQtViewer::MovingToVisSubThread()
{
// Still on master thread but vis thread has been launched
if (qGLWidget == nullptr) return;
// Wait until SwitchToVisSubThread has found vis sub-thread QThread
{
G4AutoLock lock(&visSubThreadMutex);
G4CONDITIONWAITLAMBDA(&waitForVisSubThreadInitialized, &lock, []{return visSubThreadEstablished;})
}
// Move stuff to sub-thread
if(qGLWidget->context()) qGLWidget->context()->moveToThread(fQGLContextVisSubThread);
// Inform sub-thread
G4AutoLock lock(&visSubThreadMutex);
qObjectsSwitched = true;
lock.unlock();
G4CONDITIONBROADCAST(&waitForVisSubThreadInitialized);
}
void G4OpenGLQtViewer::SwitchToVisSubThread()
{
// Called by VisSub Thread !
auto qGLW = dynamic_cast<G4QGLWidgetType*> (fGLWidget) ;
if (! qGLW) {
return;
}
if (qGLWidget == nullptr) return;
// Set the current QThread to its static variable
SetQGLContextVisSubThread(QThread::currentThread());
fQGLContextVisSubThread = QThread::currentThread();
// - Wait for the vis thread to set its QThread
G4CONDITIONBROADCAST(&fc1_VisSubThreadQtOpenGLContextInitialized);
// a condition without a locked mutex is an undefined behavior.
// we check if the mutex owns the lock, and if not, we lock it
if(!flWaitForVisSubThreadQtOpenGLContextMoved->owns_lock())
flWaitForVisSubThreadQtOpenGLContextMoved->lock();
// Let MovingToVisSubThread know we have the QThread
{
G4AutoLock lock(&visSubThreadMutex);
visSubThreadEstablished = true;
G4CONDITIONBROADCAST(&waitForVisSubThreadInitialized);
}
// Unlock the vis thread if it is Qt Viewer
G4CONDITIONWAIT(&fc2_VisSubThreadQtOpenGLContextMoved,
flWaitForVisSubThreadQtOpenGLContextMoved);
// Wait until MovingToVisSubThread has moved stuff
{
G4AutoLock lock(&visSubThreadMutex);
G4CONDITIONWAITLAMBDA(&waitForVisSubThreadInitialized, &lock, []{return qObjectsSwitched;})
}
// make context current
qGLW->makeCurrent();
qGLWidget->makeCurrent();
}
void G4OpenGLQtViewer::DoneWithVisSubThread()
{
// Called by vis sub thread
auto qGLW = dynamic_cast<G4QGLWidgetType*> (fGLWidget) ;
if (! qGLW) {
return;
}
if (qGLWidget == nullptr) return;
// finish with this vis sub thread context
qGLW->doneCurrent();
qGLWidget->doneCurrent();
// and move it back to the main thread
qGLW->context()->moveToThread(fQGLContextMainThread);
// and move stuff back to the main thread
if(qGLWidget->context()) qGLWidget->context()->moveToThread(fQGLContextMainThread);
}
void G4OpenGLQtViewer::SwitchToMasterThread()
{
// Called by VisSub Thread !
// Called by master Thread !
auto qGLW = dynamic_cast<G4QGLWidgetType*> (fGLWidget) ;
if (! qGLW) {
return;
}
if (qGLWidget == nullptr) return;
// Useful to avoid two vis thread at the same time
//G4MUTEXUNLOCK(&fmWaitForVisSubThreadQtOpenGLContextInitialized);
if(flWaitForVisSubThreadQtOpenGLContextInitialized->owns_lock())
flWaitForVisSubThreadQtOpenGLContextInitialized->unlock();
qGLWidget->makeCurrent();
qGLW->makeCurrent();
}
void G4OpenGLQtViewer::MovingToVisSubThread(){
// Called by Main Thread !
auto qGLW = dynamic_cast<G4QGLWidgetType*> (fGLWidget) ;
if (! qGLW) {
return;
}
// a condition without a locked mutex is an undefined behavior.
// we check if the mutex owns the lock, and if not, we lock it
if(!flWaitForVisSubThreadQtOpenGLContextInitialized->owns_lock())
flWaitForVisSubThreadQtOpenGLContextInitialized->lock();
// - Wait for the vis sub thread to set its QThread
G4CONDITIONWAIT(&fc1_VisSubThreadQtOpenGLContextInitialized,
flWaitForVisSubThreadQtOpenGLContextInitialized);
// Set current QThread for the way back
SetQGLContextMainThread(QThread::currentThread());
// finish with this main thread context
qGLW->doneCurrent();
qGLW->context()->moveToThread(fQGLContextVisSubThread);
G4CONDITIONBROADCAST(&fc2_VisSubThreadQtOpenGLContextMoved);
visSubThreadEstablished = false;
qObjectsSwitched = false;
}
#endif
@@ -134,12 +134,17 @@ void G4OpenGLStoredQtSceneHandler::ClearStore () {
//G4cout << "G4OpenGLStoredQtSceneHandler::ClearStore" << G4endl;
G4OpenGLStoredSceneHandler::ClearStore (); // Sets need kernel visit, etc.
// Should recreate the tree
G4OpenGLQtViewer* pGLQtViewer = dynamic_cast<G4OpenGLQtViewer*>(fpViewer);
if ( pGLQtViewer ) {
pGLQtViewer->clearTreeWidget();
}
G4OpenGLStoredSceneHandler::ClearStore ();
// Not needed - the old scene tree is currently (partially) disabled - but
// this code somehow affects the view in rare cases, e.g., after twinkling
// the volume does not return to its original colour. So I have disabled
// this, pending a review of the old scene tree. JA 31/10/24
// // Should recreate the tree
// G4OpenGLQtViewer* pGLQtViewer = dynamic_cast<G4OpenGLQtViewer*>(fpViewer);
// if ( pGLQtViewer ) {
// pGLQtViewer->clearTreeWidget();
// }
}
void G4OpenGLStoredQtSceneHandler::ClearTransientStore () {
@@ -33,10 +33,11 @@
#include "G4OpenGLStoredSceneHandler.hh"
#include "G4ios.hh"
#ifdef G4MULTITHREADED
#include "G4Threading.hh"
#endif
#include "G4UIQt.hh"
#if 0x060000 <= QT_VERSION
#include "G4Qt.hh"
#endif
#include <qapplication.h>
#include <qtabwidget.h>
@@ -52,6 +53,7 @@ G4OpenGLStoredQtViewer::G4OpenGLStoredQtViewer
{
if (fViewId < 0) return; // In case error in base class instantiation.
#if QT_VERSION < 0x060000
fQGLWidgetInitialiseCompleted = false;
// Indicates that the widget has no background, i.e. when the widget receives paint events, the background is not automatically repainted. Note: Unlike WA_OpaquePaintEvent, newly exposed areas are never filled with the background (e.g., after showing a window for the first time the user can see "through" it until the application processes the paint events). This flag is set or cleared by the widget's author.
@@ -61,22 +63,23 @@ G4OpenGLStoredQtViewer::G4OpenGLStoredQtViewer
fHasToRepaint = false;
fPaintEventLock = false;
fUpdateGLLock = false;
#else
// Indicates that the widget has no background, i.e. when the widget receives paint events, the background is not automatically repainted. Note: Unlike WA_OpaquePaintEvent, newly exposed areas are never filled with the background (e.g., after showing a window for the first time the user can see "through" it until the application processes the paint events). This flag is set or cleared by the widget's author.
G4QGLWidgetType::setAttribute (Qt::WA_NoSystemBackground);
setFocusPolicy(Qt::StrongFocus); // enable keybord events
#endif
}
G4OpenGLStoredQtViewer::~G4OpenGLStoredQtViewer() {
// makeCurrent(); // Not sure why this - commented out 12-Apr-2021 JA
// this is connect to the Dialog for deleting it properly
// when close event.
// ((QDialog*)window())->reject();
}
G4OpenGLStoredQtViewer::~G4OpenGLStoredQtViewer() {}
void G4OpenGLStoredQtViewer::Initialise() {
#if QT_VERSION < 0x060000
makeCurrent();
fQGLWidgetInitialiseCompleted = false;
CreateMainWindow (this,QString(GetName()));
makeCurrent();
glDrawBuffer (GL_BACK);
// set the good tab active
@@ -89,16 +92,13 @@ void G4OpenGLStoredQtViewer::Initialise() {
fQGLWidgetInitialiseCompleted = true;
#else
fQGLWidgetInitialiseCompleted = false;
CreateMainWindow (this,QString(GetName()));
if(G4QGLWidgetType::isValid()) { //G.Barrand: macOS: isValid() needed at startup.
makeCurrent();
glDrawBuffer (GL_BACK);
}
fQGLWidgetInitialiseCompleted = true;
// Set jpg as default export format for Qt viewer
setExportImageFormat("jpg");
#endif
}
#if QT_VERSION < 0x060000
void G4OpenGLStoredQtViewer::initializeGL () {
InitializeGLView ();
@@ -115,6 +115,7 @@ void G4OpenGLStoredQtViewer::initializeGL () {
// Set jpg as default export format for Qt viewer
setExportImageFormat("jpg");
}
#endif
G4bool G4OpenGLStoredQtViewer::CompareForKernelVisit(G4ViewParameters& lastVP)
{
@@ -228,7 +229,7 @@ void G4OpenGLStoredQtViewer::DrawView () {
#if (QT_VERSION < 0x060000) || !defined(G4MULTITHREADED)
updateQWidget();
#else
if (G4Threading::G4GetThreadId() == G4Threading::MASTER_ID) {
if (G4Threading::IsMasterThread()) {
updateQWidget();
} else {
update(); //G.Barrand: updateQWidget() induces a crash on run beamOn.
@@ -238,7 +239,10 @@ void G4OpenGLStoredQtViewer::DrawView () {
void G4OpenGLStoredQtViewer::ComputeView () {
#if QT_VERSION < 0x060000
makeCurrent();
#endif
G4ViewParameters::DrawingStyle dstyle = GetViewParameters().GetDrawingStyle();
//Make sure current viewer is attached and clean...
@@ -296,7 +300,9 @@ void G4OpenGLStoredQtViewer::ComputeView () {
savePPMToTemp();
}
#if QT_VERSION < 0x060000
fHasToRepaint = true;
#endif
}
@@ -311,10 +317,10 @@ void G4OpenGLStoredQtViewer::resizeGL(
if ((aWidth > 0) && (aHeight > 0)) {
#if QT_VERSION < 0x060000
ResizeWindow(aWidth,aHeight);
fHasToRepaint = sizeHasChanged();
#else
ResizeWindow(devicePixelRatio()*aWidth,devicePixelRatio()*aHeight);
#endif
fHasToRepaint = sizeHasChanged();
}
}
@@ -332,6 +338,7 @@ void G4OpenGLStoredQtViewer::paintGL()
//G.Barrand: don't do any change in the GUI here, just "paint" this widget!
#endif
#if QT_VERSION < 0x060000
if (fPaintEventLock) {
// return ;
}
@@ -345,7 +352,6 @@ void G4OpenGLStoredQtViewer::paintGL()
return;
}
#if QT_VERSION < 0x060000
// DO NOT RESIZE IF SIZE HAS NOT CHANGE :
// WHEN CLICK ON THE FRAME FOR EXAMPLE
// EXECEPT WHEN MOUSE MOVE EVENT
@@ -365,6 +371,8 @@ void G4OpenGLStoredQtViewer::paintGL()
return;
}
}
#else
if ((getWinWidth() == 0) && (getWinHeight() == 0)) return; //G.Barrand: needed?
#endif
#if QT_VERSION < 0x060000
@@ -380,9 +388,11 @@ void G4OpenGLStoredQtViewer::paintGL()
ClearView (); //ok, put the background correct
ComputeView();
#if QT_VERSION < 0x060000
fHasToRepaint = false;
fPaintEventLock = false;
#endif
}
#if QT_VERSION < 0x060000
@@ -427,12 +437,14 @@ void G4OpenGLStoredQtViewer::wheelEvent (QWheelEvent * event)
G4wheelEvent(event);
}
#if QT_VERSION < 0x060000
void G4OpenGLStoredQtViewer::showEvent (QShowEvent *)
{
if (fQGLWidgetInitialiseCompleted) {
fHasToRepaint = true;
}
}
#endif
/**
* This function was build in order to make a zoom on double clic event.
@@ -460,6 +472,7 @@ void G4OpenGLStoredQtViewer::contextMenuEvent(QContextMenuEvent *e)
}
void G4OpenGLStoredQtViewer::updateQWidget() {
#if QT_VERSION < 0x060000
if (fUpdateGLLock) {
return;
}
@@ -474,34 +487,24 @@ void G4OpenGLStoredQtViewer::updateQWidget() {
// The widget's rendering context will become the current context and initializeGL()
// will be called if it hasn't already been called.
// Copies the back buffer of a double-buffered context to the front buffer.
#if QT_VERSION < 0x060000
repaint(); // will read scene tree state
// updateGL() // From J.Allison picking branch
updateViewerPropertiesTableWidget();
updateSceneTreeWidget();
fUpdateGLLock = false;
#else
//if (!isCurrentWidget()) return; //G.Barrand: Qt must know if it has to activate paintGL() if the widget is not visible.
//G.Barrand: don't do any change in the GUI here, just ask to "paint" this widget!
update();
#endif
fUpdateGLLock = false;
}
void G4OpenGLStoredQtViewer::ShowView (
)
//////////////////////////////////////////////////////////////////////////////
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
void G4OpenGLStoredQtViewer::ShowView ()
{
// glFlush (); // Tentativley offered by JA 29/04/16.
// Some X servers fail to draw all trajectories, particularly Mac
// XQuartz. Revisit this at a future date. Meanwhile, issue an
// extra...
// ClearView(); // Necessary? JA 29/04/16
// DrawView(); // Necessary? JA 29/04/16
activateWindow();
// glFlush(); // NO NEED and as drawView will already cause a flush
// that could do a double flush
#if 0x060000 <= QT_VERSION
((QApplication*)G4Qt::getInstance ())->processEvents();
#endif
}
@@ -89,24 +89,15 @@ extern "C" {
}
void G4OpenGLXViewer::SetView () {
#ifdef G4MULTITHREADED
if (G4Threading::IsMasterThread()) {
glXMakeCurrent (dpy, win, cxMaster);
} else {
glXMakeCurrent (dpy, win, cxVisSubThread);
}
#else
glXMakeCurrent (dpy, win, cxMaster);
#endif
G4OpenGLViewer::SetView ();
}
void G4OpenGLXViewer::ShowView () {
#ifdef G4MULTITHREADED
// G4int thread_id = G4Threading::G4GetThreadId();
// G4cout << "G4OpenGLXViewer::ShowView: thread " << thread_id << G4endl;
#endif
// glXWaitGL (); //Wait for effects of all previous OpenGL commands to
//be propagated before progressing.
// JA: Commented out July 2021 - slows rendering down in some cases and I
@@ -131,24 +122,22 @@ void G4OpenGLXViewer::ShowView () {
}
}
#ifdef G4MULTITHREADED
void G4OpenGLXViewer::SwitchToVisSubThread()
{
// G4cout << "G4OpenGLXViewer::SwitchToVisSubThread" << G4endl;
#ifdef G4MULTITHREADED
cxVisSubThread = glXCreateContext (dpy, vi, cxMaster, true);
glXMakeCurrent (dpy, win, cxVisSubThread);
#endif
}
void G4OpenGLXViewer::SwitchToMasterThread()
{
// G4cout << "G4OpenGLXViewer::SwitchToMasterThread" << G4endl;
#ifdef G4MULTITHREADED
glXMakeCurrent (dpy, win, cxMaster);
// and destroy sub-thread context
glXDestroyContext (dpy, cxVisSubThread);
}
#endif
}
void G4OpenGLXViewer::GetXConnection () {
// get a connection.
+12
View File
@@ -6,6 +6,18 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2024-08-14 John Allison (visQt3D-V11-02-03)
- G4Qt3DViewer:
- Resolve the timing issues around switching to the vis sub-thread with the
use of G4CONDITIONWAITLAMBDA.
## 2024-07-12 Guy Barrand (visQt3D-V11-02-02)
- G4Qt3DViewer: implement a resizeEvent() method to avoid a bad aspect ratio at viewer creation.
- G4Qt3DSceneHandler: in AddPrimitive(G4Polyline), stay with the Qt5 code. The one for Qt6 using
Qt3DCore::QGeometryView is crashy.
- G4Qt3DViewer: in MovingToVisSubThread(), SwitchToMasterThread() protect against nullptr for p1, p2.
It permits to avoid crash in case of doing /run/beamOn in vis.mac at startup.
## 2024-05-23 Guy Barrand (visQt3D-V11-02-01)
- G4Qt3DSceneHandler::EstablishG4Qt3DQEntities(): have a missing:
fpPhysicalVolumeObjects.clear();
@@ -53,6 +53,7 @@ public:
void SwitchToMasterThread();
protected:
virtual void resizeEvent(QResizeEvent*);
void KernelVisitDecision ();
G4bool CompareForKernelVisit(G4ViewParameters&);
@@ -361,19 +361,10 @@ void G4Qt3DSceneHandler::AddPrimitive(const G4Polyline& polyline)
polylineEntity->addComponent(material);
auto renderer = new Qt3DRender::QGeometryRenderer;
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
auto geometryView = new Qt3DCore::QGeometryView(polylineGeometry);
geometryView->setObjectName("polylineGeometryView");
geometryView->setGeometry(polylineGeometry);
geometryView->setVertexCount((G4int)(2*nLines));
geometryView->setPrimitiveType(Qt3DCore::QGeometryView::Lines);
renderer->setView(geometryView);
#else
renderer->setObjectName("polylineRenderer");
renderer->setGeometry(polylineGeometry);
renderer->setVertexCount(2*(G4int)nLines);
renderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Lines);
#endif
polylineEntity->addComponent(renderer);
}
+77 -30
View File
@@ -63,9 +63,6 @@ void G4Qt3DViewer::Initialise()
return;
}
fUIWidget = QWidget::createWindowContainer(this);
fUIWidget->setMinimumSize(QSize(200, 100));
fUIWidget->setMaximumSize(screen()->size());
// fUIWidget->setFocusPolicy(Qt::NoFocus); //??
uiQt->AddTabWidget(fUIWidget,QString(fName));
setRootEntity(fQt3DSceneHandler.fpQt3DScene);
@@ -76,6 +73,10 @@ G4Qt3DViewer::~G4Qt3DViewer()
setRootEntity(nullptr);
}
void G4Qt3DViewer::resizeEvent(QResizeEvent*) {
SetView();
}
void G4Qt3DViewer::SetView()
{
// Background colour
@@ -158,77 +159,123 @@ void G4Qt3DViewer::DrawView()
void G4Qt3DViewer::ShowView()
{
#if QT_VERSION < 0x060000
// show() may only be called from master thread
if (G4Threading::IsMasterThread()) {
show();
}
// The way Qt seems to work, we don't seem to need a show() anyway, but
// we'll leave it in - it seems not to have any effect, good or bad.
#endif
}
void G4Qt3DViewer::FinishView()
{
#if QT_VERSION < 0x060000
if (G4Threading::IsMasterThread()) {
show();
}
#endif
}
// Note: the order of calling of MovingToVisSubThread and SwitchToVisSubThread
// is undefined. The order of calling is
// DoneWithMasterThread
// MovingToVisSubThread ) or ( SwitchToVisSubThread
// SwitchToVisSubThread ) ( MovingToVisSubThread
// DoneWithVisSubThread
// MovingToMasterThread
// SwitchToMasterThread
// So regarding the move/switch to the vis sub-thread, we have to employ mutex locks and conditions.
// If the viewer wishes to accept drawing from the vis sub-thread, Qt3D has to moveToThread.
// But at this point we are still on the master thread and the value of the sub-thread's QThread is
// not known. So it has to wait - a conditional wait, conditional on establishment of the sub-thread
// and the provision of a pointer to the QThread version of the vis sub-thread. In turn, the
// sub-thread has to wait until the QObjects have been moved to the sub-thread.
namespace {
QThread* masterQThread = nullptr;
QThread* visSubThreadQThread = nullptr;
G4Mutex visSubThreadMutex = G4MUTEX_INITIALIZER;
G4Condition waitForVisSubThreadInitialized = G4CONDITION_INITIALIZER;
G4bool visSubThreadEstablished = false;
G4bool qObjectsSwitched = false;
}
# include <chrono>
void G4Qt3DViewer::MovingToVisSubThread()
// Still on master thread but vis thread has been launched
{
#ifdef G4QT3DDEBUG
G4cout << "G4Qt3DViewer::MovingToVisSubThread" << G4endl;
#endif
// Still on master thread but vis thread has been launched
// Make note of master QThread
masterQThread = QThread::currentThread();
// Wait until SwitchToVisSubThread has found vis sub-thread QThread
std::this_thread::sleep_for(std::chrono::milliseconds(100));
{
G4AutoLock lock(&visSubThreadMutex);
G4CONDITIONWAITLAMBDA(&waitForVisSubThreadInitialized, &lock, []{return visSubThreadEstablished;})
}
// Move relevant stuff to vis sub-thread QThread
auto p1 = fQt3DSceneHandler.fpQt3DScene->parent();
auto p2 = p1->parent();
p2->moveToThread(visSubThreadQThread);
if(p1) {
auto p2 = p1->parent();
if(p2) {
p2->moveToThread(visSubThreadQThread);
} else {
p1->moveToThread(visSubThreadQThread);
}
}
// Inform sub-thread
G4AutoLock lock(&visSubThreadMutex);
qObjectsSwitched = true;
lock.unlock();
G4CONDITIONBROADCAST(&waitForVisSubThreadInitialized);
}
void G4Qt3DViewer::SwitchToVisSubThread()
// On vis sub-thread before any drawing
{
#ifdef G4QT3DDEBUG
G4cout << "G4Qt3DViewer::SwitchToVisSubThread" << G4endl;
#endif
// On vis sub-thread before any drawing
// Make note of vis-subthread QThread for MovingToVisSubThread
visSubThreadQThread = QThread::currentThread();
// Wait until SwitchToVisSubThread has moved stuff
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// Let MovingToVisSubThread know we have the QThread
{
G4AutoLock lock(&visSubThreadMutex);
visSubThreadEstablished = true;
G4CONDITIONBROADCAST(&waitForVisSubThreadInitialized);
}
// Wait until MovingToVisSubThread has moved stuff
{
G4AutoLock lock(&visSubThreadMutex);
G4CONDITIONWAITLAMBDA(&waitForVisSubThreadInitialized, &lock, []{return qObjectsSwitched;})
}
}
void G4Qt3DViewer::MovingToMasterThread()
// On vis sub-thread just before exit
{
#ifdef G4QT3DDEBUG
G4cout << "G4Qt3DViewer::MovingToMasterThread" << G4endl;
#endif
// On vis sub-thread just before exit
// Move relevant stuff to master QThread.
auto p1 = fQt3DSceneHandler.fpQt3DScene->parent();
auto p2 = p1->parent();
p2->moveToThread(masterQThread);
// Zero - will be different next run
if(p1) {
auto p2 = p1->parent();
if(p2) {
p2->moveToThread(masterQThread);
} else {
p1->moveToThread(masterQThread);
}
}
// Reset
visSubThreadQThread = nullptr;
qObjectsSwitched = false;
}
void G4Qt3DViewer::SwitchToMasterThread()
// On master thread after vis sub-thread has terminated
{
#ifdef G4QT3DDEBUG
G4cout << "G4Qt3DViewer::SwitchToMasterThread" << G4endl;
#endif
// On master thread after vis sub-thread has terminated
// Nothing to do
visSubThreadEstablished = false;
}
void G4Qt3DViewer::KernelVisitDecision () {
+3
View File
@@ -6,6 +6,9 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2024-06-21 Ben Morgan (vis_toolssg-V1-02-02)
- Use runtime checks for MT mode.
## 2024-04-30 Ben Morgan (vis_toolssg-V11-02-01)
- Replace TOOLSSG vis driver variables that are just synonyms for more
fundamental config options (e.g. GEANT4_USE_QT) with the underlying
@@ -296,7 +296,6 @@ public:
}
}
#ifdef G4MULTITHREADED
virtual void SwitchToVisSubThread() {}
virtual void SwitchToMasterThread() {
@@ -321,7 +320,6 @@ public:
}
}
}
#endif
//SG_VIEWER* sg_viewer() {return fSGViewer;}
protected:
@@ -123,9 +123,7 @@ tools::sg::separator* G4ToolsSGSceneHandler::GetOrCreateNode()
{ // Retrieve or create a G4ToolsSGNode node suitable for next solid or primitive
// For time being, avoid errors in MT mode - see G4ToolsSGViewer::SwitchToMasterThread
#ifdef G4MULTITHREADED
if (!G4Threading::IsMasterThread()) return nullptr;
#endif
if (fReadyForTransients) { // All transients hang from this node
tools::sg::separator* sep = new tools::sg::separator;
+19
View File
@@ -6,6 +6,25 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2024-10-17 John Allison (visVtk-V11-02-07)
- G4VtkMessenger.cc:
- Added x3d to /vis/vtk/export format parameter guidance.
- Set parameter omitables to false.
## 2024-10-07 Stewart Boogert (visVtk-V11-02-06)
- G4VtkViewer:
- Added export for X3D file format
## 2024-08-13 John Allison (visVtk-V11-02-05)
- G4VtkQtViewer:
- Resolve the timing issues around switching to the vis sub-thread with the
use of G4CONDITIONWAITLAMBDA.
## 2024-07-12 Guy Barrand (visVtk-V11-02-04)
- G4VtkQtViewer: in DoneWithVisSubThread(), SwitchToMasterThread() protect against a
possible null qGLW->context(). It permits to avoid a crash in case of doing /run/beamOn
in vis.mac at startup.
## 2024-05-27 Guy Barrand (visVtk-V11-02-03)
- G4VtxQtViewer: MT: have the variables mWaitForVisSubThreadQtOpenGLContextMoved,
mWaitForVisSubThreadQtOpenGLContextInitialized,
@@ -59,7 +59,17 @@ class G4VtkQtViewer : public QVTKOpenGLNativeWidget, public G4VtkViewer
void Initialise() override;
virtual void CreateMainWindow(QVTKOpenGLNativeWidget*, const QString&);
#ifdef G4MULTITHREADED
// In MT mode these functions are called in the following order for each run:
// For switching threads in MT mode
// Note: the order of calling of MovingToVisSubThread and SwitchToVisSubThread
// is undefined, so we have to use mutexes to ensure required information,
// namely the vis sub-thread address, is available before moving objects.
// To summarise, the order of calling is
// DoneWithMasterThread
// MovingToVisSubThread ) or ( SwitchToVisSubThread
// SwitchToVisSubThread ) ( MovingToVisSubThread
// DoneWithVisSubThread
// MovingToMasterThread
// SwitchToMasterThread
// Called on the master thread before starting the vis sub-thread.
void DoneWithMasterThread() override;
// Called on the master thread after starting the vis sub-thread.
@@ -69,12 +79,9 @@ class G4VtkQtViewer : public QVTKOpenGLNativeWidget, public G4VtkViewer
// Called on the vis sub-thread when all events have been processed.
void DoneWithVisSubThread() override;
// Called on the vis sub-thread when all events have been processed.
// virtual void MovingToMasterThread (); Not used in G4OpenGLQtViewer.
// virtual void MovingToMasterThread (); Not used in G4VtkQtViewer.
// Called on the master thread after the vis sub-thread has terminated.
void SwitchToMasterThread() override;
inline void SetQGLContextVisSubThread(QThread* th) { fQGLContextVisSubThread = th; }
inline void SetQGLContextMainThread(QThread* th) { fQGLContextMainThread = th; }
#endif
void FinishView() override;
@@ -103,14 +110,8 @@ class G4VtkQtViewer : public QVTKOpenGLNativeWidget, public G4VtkViewer
QWidget* fGLWidget;
#ifdef G4MULTITHREADED
QThread* fQGLContextVisSubThread;
QThread* fQGLContextMainThread;
G4Mutex fmWaitForVisSubThreadQtOpenGLContextMoved;
G4Mutex fmWaitForVisSubThreadQtOpenGLContextInitialized;
G4Condition fc1_VisSubThreadQtOpenGLContextInitialized;
G4Condition fc2_VisSubThreadQtOpenGLContextMoved;
G4AutoLock* flWaitForVisSubThreadQtOpenGLContextInitialized;
G4AutoLock* flWaitForVisSubThreadQtOpenGLContextMoved;
QThread* fQVtkContextVisSubThread;
QThread* fQVtkContextMainThread;
#endif
};
@@ -229,6 +229,7 @@ class G4VtkViewer : public G4VViewer
void ExportVRMLScene(G4String);
void ExportVTPScene(G4String);
void ExportGLTFScene(G4String);
void ExportX3DScene(G4String);
void ExportJSONRenderWindowScene(G4String);
void ExportVTPCutter(G4String fileName);
void ExportFormatStore(G4String fileName, G4String store);
@@ -62,12 +62,12 @@ G4VtkMessenger::G4VtkMessenger()
fpCommandExport->SetGuidance("Export a screenshot or OBJ file of current Vtk viewer");
// File type for export
auto parameterExport = new G4UIparameter("format", 's', omitable = true);
fpCommandExport->SetGuidance("File type (jpg,tiff,eps,ps,obj,vtp,gltf,vrml)");
auto parameterExport = new G4UIparameter("format", 's', omitable = false);
fpCommandExport->SetGuidance("File type (jpg,tiff,eps,ps,obj,vtp,gltf,vrml,x3d)");
fpCommandExport->SetParameter(parameterExport);
// File name for export
parameterExport = new G4UIparameter("file-name", 's', omitable = true);
parameterExport = new G4UIparameter("file-name", 's', omitable = false);
fpCommandExport->SetGuidance("File name");
fpCommandExport->SetParameter(parameterExport);
@@ -332,6 +332,8 @@ void G4VtkMessenger::SetNewValue(G4UIcommand* command, G4String newValue)
pVtkViewer->ExportVTPScene(name);
else if (format == "gltf")
pVtkViewer->ExportGLTFScene(name);
else if (format == "x3d")
pVtkViewer->ExportX3DScene(name);
else
G4cout << "Unknown /vis/vtk/export file format" << G4endl;
}
+62 -71
View File
@@ -58,22 +58,12 @@
G4VtkQtViewer::G4VtkQtViewer(G4VSceneHandler& sceneHandler, const G4String& name)
: G4VtkViewer(sceneHandler, name)
{
#ifdef G4MULTITHREADED
flWaitForVisSubThreadQtOpenGLContextInitialized =
new G4AutoLock(fmWaitForVisSubThreadQtOpenGLContextInitialized, std::defer_lock);
flWaitForVisSubThreadQtOpenGLContextMoved =
new G4AutoLock(fmWaitForVisSubThreadQtOpenGLContextMoved, std::defer_lock);
#endif
G4Qt::getInstance();
//this->setFormat(QVTKOpenGLNativeWidget::defaultFormat());
}
G4VtkQtViewer::~G4VtkQtViewer()
{
#ifdef G4MULTITHREADED
delete flWaitForVisSubThreadQtOpenGLContextInitialized;
delete flWaitForVisSubThreadQtOpenGLContextMoved;
#endif
}
void G4VtkQtViewer::Initialise()
@@ -113,100 +103,101 @@ void G4VtkQtViewer::CreateMainWindow(QVTKOpenGLNativeWidget* vtkWidget, const QS
#ifdef G4MULTITHREADED
namespace {
G4Mutex visSubThreadMutex = G4MUTEX_INITIALIZER;
G4Condition waitForVisSubThreadInitialized = G4CONDITION_INITIALIZER;
G4bool visSubThreadEstablished = false;
G4bool qObjectsSwitched = false;
QVTKOpenGLNativeWidget* qVtkW = nullptr;
}
void G4VtkQtViewer::DoneWithMasterThread()
{
// Called by Main Thread !
// Useful to avoid two vis thread at the same time
// G4MUTEXLOCK(&fmWaitForVisSubThreadQtOpenGLContextInitialized);
if (!flWaitForVisSubThreadQtOpenGLContextInitialized->owns_lock())
flWaitForVisSubThreadQtOpenGLContextInitialized->lock();
// Initialise and check qVtkW - no need to check in subsequent functions
qVtkW = dynamic_cast<QVTKOpenGLNativeWidget*>(fGLWidget);
if (qVtkW == nullptr) return;
// Done with master thread
qVtkW->doneCurrent();
// Set current QThread for the way back
fQVtkContextMainThread = QThread::currentThread();
}
void G4VtkQtViewer::MovingToVisSubThread()
{
// Still on master thread but vis thread has been launched
if (qVtkW == nullptr) return;
// Wait until SwitchToVisSubThread has found vis sub-thread QThread
{
G4AutoLock lock(&visSubThreadMutex);
G4CONDITIONWAITLAMBDA(&waitForVisSubThreadInitialized, &lock, []{return visSubThreadEstablished;})
}
// Move stuff to sub-thread
if(qVtkW->context()) qVtkW->context()->moveToThread(fQVtkContextVisSubThread);
// Inform sub-thread
G4AutoLock lock(&visSubThreadMutex);
qObjectsSwitched = true;
lock.unlock();
G4CONDITIONBROADCAST(&waitForVisSubThreadInitialized);
}
void G4VtkQtViewer::SwitchToVisSubThread()
{
// Called by VisSub Thread !
auto qGLW = dynamic_cast<QVTKOpenGLNativeWidget*>(fGLWidget);
if (qGLW == nullptr) {
return;
if (qVtkW == nullptr) return;
fQVtkContextVisSubThread = QThread::currentThread();
// Let MovingToVisSubThread know we have the QThread
{
G4AutoLock lock(&visSubThreadMutex);
visSubThreadEstablished = true;
G4CONDITIONBROADCAST(&waitForVisSubThreadInitialized);
}
// Set the current QThread to its static variable
SetQGLContextVisSubThread(QThread::currentThread());
// - Wait for the vis thread to set its QThread
G4CONDITIONBROADCAST(&fc1_VisSubThreadQtOpenGLContextInitialized);
// a condition without a locked mutex is an undefined behavior.
// we check if the mutex owns the lock, and if not, we lock it
if (!flWaitForVisSubThreadQtOpenGLContextMoved->owns_lock())
flWaitForVisSubThreadQtOpenGLContextMoved->lock();
// Unlock the vis thread if it is Qt Viewer
G4CONDITIONWAIT(&fc2_VisSubThreadQtOpenGLContextMoved, flWaitForVisSubThreadQtOpenGLContextMoved);
// Wait until MovingToVisSubThread has moved stuff
{
G4AutoLock lock(&visSubThreadMutex);
G4CONDITIONWAITLAMBDA(&waitForVisSubThreadInitialized, &lock, []{return qObjectsSwitched;})
}
// make context current
qGLW->makeCurrent();
qVtkW->makeCurrent();
}
void G4VtkQtViewer::DoneWithVisSubThread()
{
// Called by vis sub thread
auto qGLW = dynamic_cast<QVTKOpenGLNativeWidget*>(fGLWidget);
if (qGLW == nullptr) {
return;
}
if (qVtkW == nullptr) return;
// finish with this vis sub thread context
qGLW->doneCurrent();
qVtkW->doneCurrent();
// and move it back to the main thread
qGLW->context()->moveToThread(fQGLContextMainThread);
if(qVtkW->context()) qVtkW->context()->moveToThread(fQVtkContextMainThread);
}
void G4VtkQtViewer::SwitchToMasterThread()
{
// Called by VisSub Thread !
auto qGLW = dynamic_cast<QVTKOpenGLNativeWidget*>(fGLWidget);
if (qGLW == nullptr) {
return;
}
if (qVtkW == nullptr) return;
// Useful to avoid two vis thread at the same time
// G4MUTEXUNLOCK(&fmWaitForVisSubThreadQtOpenGLContextInitialized);
if (flWaitForVisSubThreadQtOpenGLContextInitialized->owns_lock())
flWaitForVisSubThreadQtOpenGLContextInitialized->unlock();
qVtkW->makeCurrent();
qGLW->makeCurrent();
visSubThreadEstablished = false;
qObjectsSwitched = false;
}
void G4VtkQtViewer::MovingToVisSubThread()
{
// Called by Main Thread !
auto qGLW = dynamic_cast<QVTKOpenGLNativeWidget*>(fGLWidget);
if (qGLW == nullptr) {
return;
}
// a condition without a locked mutex is an undefined behavior.
// we check if the mutex owns the lock, and if not, we lock it
if (!flWaitForVisSubThreadQtOpenGLContextInitialized->owns_lock())
flWaitForVisSubThreadQtOpenGLContextInitialized->lock();
// - Wait for the vis sub thread to set its QThread
G4CONDITIONWAIT(&fc1_VisSubThreadQtOpenGLContextInitialized,
flWaitForVisSubThreadQtOpenGLContextInitialized);
// Set current QThread for the way back
SetQGLContextMainThread(QThread::currentThread());
// finish with this main thread context
qGLW->doneCurrent();
qGLW->context()->moveToThread(fQGLContextVisSubThread);
G4CONDITIONBROADCAST(&fc2_VisSubThreadQtOpenGLContextMoved);
}
#endif
void G4VtkQtViewer::FinishView()
@@ -52,6 +52,7 @@
#include <vtkOBJImporter.h>
#include <vtkGLTFExporter.h>
#include <vtkOOGLExporter.h>
#include <vtkX3DExporter.h>
#include <vtkJSONRenderWindowExporter.h>
#include <vtkVtkJSSceneGraphSerializer.h>
//#include <vtkBufferedArchiver.h>
@@ -417,6 +418,14 @@ void G4VtkViewer::ExportGLTFScene(G4String fileName) {
exporter->Write();
}
void G4VtkViewer::ExportX3DScene(G4String fileName) {
vtkSmartPointer<vtkX3DExporter> exporter = vtkSmartPointer<vtkX3DExporter>::New();
exporter->SetRenderWindow(_renderWindow);
exporter->SetFileName((fileName+".x3d").c_str());
exporter->Write();
}
void G4VtkViewer::ExportJSONRenderWindowScene(G4String /*fileName*/) {
vtkSmartPointer<vtkJSONRenderWindowExporter> exporter = vtkSmartPointer<vtkJSONRenderWindowExporter>::New();
vtkSmartPointer<vtkVtkJSSceneGraphSerializer> serializer = vtkSmartPointer<vtkVtkJSSceneGraphSerializer>::New();
+9
View File
@@ -6,6 +6,15 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2024-09-29 John Allison (gMocren-V11-02-02)
- More Coverity fixes
## 2024-08-31 John Allison (gMocren-V11-02-01)
- More Coverity fixes
## 2024-07-17 John Allison (gMocren-V11-02-00)
- Coverity fixes
## 2023-02-06 Ben Morgan (gMocren-V11-01-00)
- Isolate private headers and update dependencies
@@ -90,6 +90,8 @@
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include <utility>
//----- constants
const char GDD_FILE_HEADER [] = "g4_";
const char DEFAULT_GDD_FILE_NAME[] = "g4_00.gdd";
@@ -1713,7 +1715,7 @@ void G4GMocrenFileSceneHandler::AddCompound( const G4VHit & hit) {
} else {
std::map<Index3D, G4double> hits;
hits.insert(std::map<Index3D, G4double>::value_type(id, value));
kNestedHitsList[hitNames[i]] = hits;
kNestedHitsList[hitNames[i]] = std::move(hits);
}
@@ -1775,7 +1777,7 @@ void G4GMocrenFileSceneHandler::AddCompound(const G4THitsMap<G4double> & hits) {
} else {
std::map<Index3D, G4double> hit;
hit.insert(std::map<Index3D, G4double>::value_type(id, *(itr->second)));
kNestedHitsList[scorername] = hit;
kNestedHitsList[scorername] = std::move(hit);
}
}
@@ -1847,7 +1849,7 @@ void G4GMocrenFileSceneHandler::AddCompound(const G4THitsMap<G4StatDouble> & hit
} else {
std::map<Index3D, G4double> hit;
hit.insert(std::map<Index3D, G4double>::value_type(id, itr->second->sum_wx()));
kNestedHitsList[scorername] = hit;
kNestedHitsList[scorername] = std::move(hit);
}
}
@@ -37,6 +37,8 @@
#include "G4UIcommand.hh"
#include "G4Tokenizer.hh"
#include <utility>
G4GMocrenMessenger::G4GMocrenMessenger()
: suffix (""), geometry(true), pointAttributes(false), solids(true), invisibles(true),
kgMocrenVolumeName("gMocrenVolume"),
@@ -198,7 +200,7 @@ G4String G4GMocrenMessenger::GetCurrentValue(G4UIcommand * command) {
void G4GMocrenMessenger::SetNewValue(G4UIcommand * command, G4String newValue) {
if (command==setEventNumberSuffixCommand) {
suffix = newValue;
suffix = std::move(newValue);
} else if (command==appendGeometryCommand) {
geometry = appendGeometryCommand->GetNewBoolValue(newValue);
} else if (command==addPointAttributesCommand) {
@@ -208,15 +210,15 @@ void G4GMocrenMessenger::SetNewValue(G4UIcommand * command, G4String newValue) {
// } else if (command==writeInvisiblesCommand) {
// invisibles = writeInvisiblesCommand->GetNewBoolValue(newValue);
} else if (command == kSetgMocrenVolumeNameCommand) {
kgMocrenVolumeName = newValue;
kgMocrenVolumeName = std::move(newValue);
} else if (command == kAddgMocrenHitNameCommand) {
kgMocrenHitNames.push_back(newValue);
kgMocrenHitNames.push_back(std::move(newValue));
} else if (command == kResetgMocrenHitNameCommand) {
kgMocrenHitNames.clear();
} else if (command == kSetgMocrenScoringMeshNameCommand) {
kgMocrenScoringMeshName = newValue;
kgMocrenScoringMeshName = std::move(newValue);
} else if (command == kAddgMocrenHitScorerNameCommand) {
kgMocrenHitScorerNames.push_back(newValue);
kgMocrenHitScorerNames.push_back(std::move(newValue));
} else if (command == kResetgMocrenHitScorerNameCommand) {
kgMocrenHitScorerNames.clear();
} else if (command == kListgMocrenCommand) {
+134
View File
@@ -6,6 +6,140 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2024-10-27 John Allison (visman-V11-02-28)
- G4VisExecutive.icc:
- Remove #include <QtGlobal> - no longer needed.
- Was included to resolve some Qt5/6 issues in 11.2.
## 2024-10-16 John Allison (visman-V11-02-27)
- G4VSceneHandler.cc:
- Move some printing outside the loop over models - more hygenic
- Improve indentation.
## 2024-10-03 John Allison (visman-V11-02-26)
- Introduce TOOLS_USE_FREETYPE flag in vis management for /vis/plot command
- sources.cmake:
- Add geant4_module_compile_definitions.
- Set cpp flag TOOLS_USE_FREETYPE if built with GEANT4_USE_FREETYPE.
- G4VisCommandsCompound.cc:
- If TOOLS_USE_FREETYPE, augment /vis/plot command to take "style" argument.
- Candidates are: "none ROOT_default hippodraw".
- Default is: "ROOT_default".
## 2024-10-02 John Allison (visman-V11-02-25)
- G4VisManager.cc:
- Protect KeepForPostProcessing() with an mtVisSubThreadMutex lock.
- KeepForPostProcessing() is called on a worker thread, PostProcessingFinished()
is called on the vis sub-thread, so should be protected.
- Not sure about sub-event parallelism, because KeepForPostProcessing() is still
called on a worker thread, but PostProcessingFinished() is called from the
G4SubEvtRunManager. But having a short piece of code locked does no harm, so
let's do this.
- G4VisManager.cc, G4VisCommandsSceneAdd.cc:
- Tidied redundant comments and corrected some.
## 2024-09-30 Makoto Asai (visman-V11-02-24)
- G4VisManager.cc, G4VisCommandsSceneAdd.cc:
- Optimize the timing of G4Event::KeepForPostProcessing() and
G4Event::PostProcessingFinished() so that event object that are not
requested to be kept are cleanly deleted at the end of each run.
Kept events are deleted at the beginning of the next run or when the
program terminates.
- Use G4Run::GetNumberOfKeptEvent() to properly display the number of kept
events.
- Co-working with run-V11-02-18
## 2024-09-12 John Allison (visman-V11-02-23)
- G4ViewParameters.cc: Minor improvements to messages in output operator<<.
- G4VisCommandsSceneAdd.cc:
- G4VisCommandSceneAddLogo::SetNewValue (/vis/scene/add/logo):
- Ensure the logo respects the current requested number of sides per circle.
- G4VisCommandsViewer.cc:
- G4VisCommandViewerCreate::SetNewValue (/vis/viewer/create):
- Simplify the use of view parameters of a pre-existing viewer.
- Use the parameters of the most recent viewer whatever its type.
- Exclude GlobalMarkerScale from parameters copied from pre-existing viewer.
- Thus each viewer is allowed to specify its own GlobalMarkerScale.
- Mostly viewers use the default value of 1, but ToolsSG sets it to 2
to handle special displays such as Apple's Retina.
## 2024-08-31 John Allison (visman-V11-02-22)
- Coverity fixes.
- Some checks, which gave Coverity concern, are no longer needed, because
Begin/EndOfRun/Event are protected by flag set once and for all in
BeginOfRun.
## 2024-08-26 John Allison (visman-V11-02-21)
- G4VisManager.cc:
- Protect Begin/EndOfRun against invalid view (includes check on
existence of a scene).
- A dead-lock in MT mode if there is a view but no scene with OGL.
- Seems viewer has trouble changing threads.
- Some tidying and streamlining.
- Introduced local booleans isValidViewForRun and isFakeRun.
## 2024-08-18 John Allison (visman-V11-02-20)
- Improve messaging around /vis/verbose and /vis/list.
- G4VisManager:
- Introduce PrintAvailableVerbosity().
- GetVerbosityValue: Print verbosity options on unknown or empty argument
- G4VisCommands.cc:
- /vis/list: Add printing of verbosity options.
- /vis/verbose: Change default value to empty string (triggers printing
of verbosity options in G4VisManager::GetVerbosityValue().
## 2024-08-04 John Allison (visman-V11-02-19)
- Fix "accumulate" bug in Serial mode, and other small improvements.
- G4VisManager.cc:
- Bug fix: In Serial mode, "accumulate" fails (behaves like "refresh").
- This relates to end-of-event action, e.g., trajectory drawing.
- Bug was introduced in visman-V11-02-18.
- Fix and rationalise by moving the following to EndOfEventCleanup():
if (pScene->GetRefreshAtEndOfEvent()) {
pViewer->ShowView();
pSceneHandler->SetMarkForClearingTransientStore(true);
}
- Improve printing of colours in PrintAvailableColours and advise on use.
- Used in /vis/list.
- Tidy further:
- Remove some commented-out debug printing to make code cleaner to read.
- Fix some errant indentations.
- G4VisCommandsSceneAdd.cc:
- Move date model (/vis/scene/add/date) from run-duration to end-of-event list.
- Thus date and time are updated for every event displayed.
## 2024-07-21 John Allison (visman-V11-02-18)
- G4VisManager: Further rationalising and tidying after visman-V11-02-12.
- Replace method `G4bool Relinquishable` (used only if false) by its logical
opposite, `G4bool RequiredToBeKeptForVis` - clearer.
- Move `void EventReadyForVis` (invoked by G4SubEvtRunManager) to improve
readability of code.
- Improve some messaging.
## 2024-07-21 John Allison (visman-V11-02-17)
- G4VisExecutive.icc:
- Remove duplicate instantiation of TOOLSSG_OFFSCREEN
## 2024-07-17 John Allison (visman-V11-02-16)
- With gMocren-V11-02-00, modeling-V11-02-02
- Coverity fixes
## 2024-07-12 Guy Barrand (visman-V11-02-15)
- G4VViewer.hh: add virtual ReadyToDraw(). It helps avoiding a crash on macOS
if doing /run/beamOn in vis.mac at startup.
- G4VSceneHandler.cc: DrawEvent(), DrawEndOfRunModels(): check if viewer is
ReadyToDraw() at begin of method.
## 2024-07-06 John Allison (visman-V11-02-14)
- G4VisManager:
- Call PostProcessingFinished for _every_ event in EndOfEventCleanup.
- Write lengthy comment about different end-of-event scenarios.
- Tidy up previous tag visman-V11-02-12.
## 2024-06-21 Ben Morgan (visman-V11-02-13)
- Remove use of G4MULTITHREADED symbol where not required, using runtime checks
as far as possible.
## 2024-06-04 John Allison (visman-V11-02-12)
- G4VisManager:
- Implement EventReadyForVis, used by G4SubEvtRunManager.
@@ -105,9 +105,10 @@ public: // With description
// It is not yet the end of all drawing; that is signalled by
// ShowView ().)
virtual G4bool ReadyToDraw() {return true;}
std::vector<G4ThreeVector> ComputeFlyThrough(G4Vector3D*);
#ifdef G4MULTITHREADED
// Note: the order of calling of MovingToVisSubThread and SwitchToVisSubThread
// is undefined, so you may need to implement mutexes to ensure your preferred
// order - see, e.g., G4OpenGLQtViewer. To summarise, the order of calling is
@@ -120,23 +121,22 @@ public: // With description
// SwitchToMasterThread
// Called on the master thread before starting the vis sub-thread.
virtual void DoneWithMasterThread ();
virtual void DoneWithMasterThread () {}
// Called on the master thread after starting the vis sub-thread.
virtual void MovingToVisSubThread ();
virtual void MovingToVisSubThread () {}
// Called on the vis sub-thread at start of vis sub-thread.
virtual void SwitchToVisSubThread ();
virtual void SwitchToVisSubThread () {}
// Called on the vis sub-thread when all events have been processed.
virtual void DoneWithVisSubThread ();
virtual void DoneWithVisSubThread () {}
// Called on the vis sub-thread when all events have been processed.
virtual void MovingToMasterThread ();
virtual void MovingToMasterThread () {}
// Called on the master thread after the vis sub-thread has terminated.
virtual void SwitchToMasterThread ();
#endif
virtual void SwitchToMasterThread () {}
//////////////////////////////////////////////////////////////
// Stuff for scene tree.
@@ -70,10 +70,10 @@ protected:
void InterpolateViews
(G4VViewer* currentViewer,
std::vector<G4ViewParameters> viewVector,
const std::vector<G4ViewParameters>& viewVector,
const G4int nInterpolationPoints = 50,
const G4int waitTimePerPointmilliseconds = 20,
const G4String exportString = "");
const G4String& exportString = "");
void InterpolateToNewView
(G4VViewer* currentViewer,
@@ -81,7 +81,7 @@ protected:
const G4ViewParameters& newVP,
const G4int nInterpolationPoints = 50,
const G4int waitTimePerPointmilliseconds = 20,
const G4String exportString = "");
const G4String& exportString = "");
void Twinkle
// Twinkles the touchables in paths
@@ -186,7 +186,7 @@ private:
class G4VVisCommandGeometrySet: public G4VVisCommandGeometry {
protected:
void Set(G4String logVolName, const G4VVisCommandGeometrySetFunction&,
void Set(const G4String& logVolName, const G4VVisCommandGeometrySetFunction&,
G4int requestedDepth);
void SetLVVisAtts(G4LogicalVolume*, const G4VVisCommandGeometrySetFunction&,
G4int depth, G4int requestedDepth);
@@ -27,8 +27,6 @@
// /vis/multithreading commands - John Allison 29th September 2015
#ifdef G4MULTITHREADED
#ifndef G4VISCOMMANDSMULTITHREADING_HH
#define G4VISCOMMANDSMULTITHREADING_HH
@@ -66,5 +64,3 @@ private:
};
#endif
#endif
@@ -138,10 +138,6 @@
#include "G4VtkQt.hh" // no_geant4_module_check
#endif
#if defined (G4VIS_USE_OPENGLQT) || (G4VIS_USE_TOOLSSG_QT_GLES)
#include <QtGlobal>
#endif
#include "G4UImanager.hh"
#include "G4UIsession.hh"
#include "G4UIbatch.hh"
@@ -346,7 +342,6 @@ void G4VisExecutive::RegisterGraphicsSystems () {
RegisterGraphicsSystem (new G4RayTracer);
RegisterGraphicsSystem (new G4VRML2File);
RegisterGraphicsSystem (new G4GMocrenFile);
RegisterGraphicsSystem (new G4ToolsSGOffscreen);
G4VGraphicsSystem* tsg_offscreen = new G4ToolsSGOffscreen;
RegisterGraphicsSystem(tsg_offscreen);
tsg_offscreen->AddNickname("TSG_FILE");
@@ -333,8 +333,6 @@ public: // With description
G4bool FilterHit(const G4VHit&);
G4bool FilterDigi(const G4VDigi&);
#ifdef G4MULTITHREADED
virtual void SetUpForAThread();
// This method is invoked by G4WorkerRunManager
@@ -345,7 +343,6 @@ public: // With description
static G4ThreadFunReturnType G4VisSubThread(G4ThreadFunArgType);
// Vis sub-thread function.
#endif
////////////////////////////////////////////////////////////////////////
// Administration routines.
@@ -363,14 +360,10 @@ private:
void BeginOfEvent ();
void EndOfEvent ();
// 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 EndOfEventKernel (const G4Event* currentEvent);
void EndOfEventCleanup (const G4Event* currentEvent);
G4bool RequiredToBeKeptForVis (G4int eventID);
// Cluster of methods to handle end of event.
void EndOfRun ();
@@ -419,10 +412,8 @@ public: // With description
G4bool GetReviewingPlots () const;
G4bool GetAbortReviewPlots () const;
const G4ViewParameters& GetDefaultViewParameters () const;
#ifdef G4MULTITHREADED
G4int GetMaxEventQueueSize () const;
G4bool GetWaitOnEventQueueFull () const;
#endif
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
@@ -452,10 +443,8 @@ public: // With description
void SetReviewingPlots (G4bool);
void SetAbortReviewPlots (G4bool);
void SetDefaultViewParameters (const G4ViewParameters&);
#ifdef G4MULTITHREADED
void SetMaxEventQueueSize (G4int);
void SetWaitOnEventQueueFull (G4bool);
#endif
void SetDefaultGraphicsSystemName(const G4String&);
void SetDefaultXGeometryString (const G4String&);
void SetDefaultGraphicsSystemBasis(const G4String&);
@@ -485,6 +474,8 @@ public: // With description
static std::vector<G4String> VerbosityGuidanceStrings;
// Guidance on the use of visualization verbosity.
static void PrintAvailableVerbosity (std::ostream& os);
void PrintAvailableGraphicsSystems (Verbosity, std::ostream& = G4cout) const;
protected:
@@ -564,10 +555,8 @@ private:
G4bool fIsDrawGroup;
G4int fDrawGroupNestingDepth;
G4bool fIgnoreStateChanges;
#ifdef G4MULTITHREADED
G4int fMaxEventQueueSize;
G4bool fWaitOnEventQueueFull;
#endif
// Trajectory draw model manager
G4VisModelManager<G4VTrajectoryModel>* fpTrajDrawModelMgr;
@@ -126,8 +126,6 @@ inline const G4ViewParameters& G4VisManager::GetDefaultViewParameters() const {
return fDefaultViewParameters;
}
#ifdef G4MULTITHREADED
inline G4int G4VisManager::GetMaxEventQueueSize() const {
return fMaxEventQueueSize;
}
@@ -136,8 +134,6 @@ inline G4bool G4VisManager::GetWaitOnEventQueueFull () const {
return fWaitOnEventQueueFull;
}
#endif
inline const G4String& G4VisManager::GetDefaultGraphicsSystemName () {
return fDefaultGraphicsSystemName;
}
@@ -212,8 +208,6 @@ inline void G4VisManager::SetDefaultViewParameters
fDefaultViewParameters = vp;
}
#ifdef G4MULTITHREADED
inline void G4VisManager::SetMaxEventQueueSize (G4int size) {
fMaxEventQueueSize = size;
}
@@ -222,8 +216,6 @@ inline void G4VisManager::SetWaitOnEventQueueFull (G4bool wait) {
fWaitOnEventQueueFull = wait;
}
#endif
inline void G4VisManager::SetDefaultGraphicsSystemName (const G4String& name) {
fDefaultGraphicsSystemName = name;
}
@@ -102,3 +102,7 @@ geant4_module_link_libraries(G4vis_management
if(GEANT4_BUILD_MULTITHREADED)
geant4_module_link_libraries(G4vis_management PRIVATE G4volumes)
endif()
if(GEANT4_USE_FREETYPE)
geant4_module_compile_definitions(G4vis_management PRIVATE TOOLS_USE_FREETYPE)
endif()
@@ -754,39 +754,39 @@ void G4VSceneHandler::ProcessScene()
}
}
// 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;
}
}
fpModel = 0;
delete pMP;
EndModeling();
}
// 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;
}
}
fReadyForTransients = true;
// Refresh event from end-of-event model list.
@@ -869,6 +869,7 @@ void G4VSceneHandler::ProcessScene()
void G4VSceneHandler::DrawEvent(const G4Event* event)
{
if(!fpViewer->ReadyToDraw()) return;
const std::vector<G4Scene::Model>& EOEModelList =
fpScene -> GetEndOfEventModelList ();
std::size_t nModels = EOEModelList.size();
@@ -887,7 +888,7 @@ void G4VSceneHandler::DrawEvent(const G4Event* event)
fpViewer->InsertModelInSceneTree(fpModel);
// Reset modeling parameters pointer
fpModel -> SetModelingParameters(0);
fpModel -> SetModelingParameters(0);
}
}
fpModel = 0;
@@ -897,6 +898,7 @@ void G4VSceneHandler::DrawEvent(const G4Event* event)
void G4VSceneHandler::DrawEndOfRunModels()
{
if(!fpViewer->ReadyToDraw()) return;
const std::vector<G4Scene::Model>& EORModelList =
fpScene -> GetEndOfRunModelList ();
std::size_t nModels = EORModelList.size();
@@ -909,7 +911,7 @@ void G4VSceneHandler::DrawEndOfRunModels()
fpModel -> SetModelingParameters(pMP);
// Describe to the current scene handler
fpModel -> DescribeYourselfTo (*this);
fpModel -> DescribeYourselfTo (*this);
// Enter models in the scene tree
fpViewer->InsertModelInSceneTree(fpModel);
@@ -234,8 +234,8 @@ void G4VViewer::UpdateGUISceneTree()
void G4VViewer::InsertModelInSceneTree(G4VModel* model)
{
auto modelType = model->GetType();
auto modelDescription = model->GetGlobalDescription();
const auto& modelType = model->GetType();
const auto& modelDescription = model->GetGlobalDescription();
auto type = G4SceneTreeItem::model;
auto pvModel = dynamic_cast<G4PhysicalVolumeModel*>(model);
@@ -443,40 +443,6 @@ std::list<G4SceneTreeItem>::iterator G4VViewer::SceneTreeScene::FindOrInsertTouc
}
// clang-format on
#ifdef G4MULTITHREADED
void G4VViewer::DoneWithMasterThread()
{
// G4cout << "G4VViewer::DoneWithMasterThread" << G4endl;
}
void G4VViewer::MovingToMasterThread()
{
// G4cout << "G4VViewer::MovingToMasterThread" << G4endl;
}
void G4VViewer::SwitchToVisSubThread()
{
// G4cout << "G4VViewer::SwitchToVisSubThread" << G4endl;
}
void G4VViewer::DoneWithVisSubThread()
{
// G4cout << "G4VViewer::DoneWithVisSubThread" << G4endl;
}
void G4VViewer::MovingToVisSubThread()
{
// G4cout << "G4VViewer::MovingToVisSubThread" << G4endl;
}
void G4VViewer::SwitchToMasterThread()
{
// G4cout << "G4VViewer::SwitchToMasterThread" << G4endl;
}
#endif
std::ostream& operator<<(std::ostream& os, const G4VViewer& v)
{
os << "View " << v.fName << ":\n";
@@ -293,10 +293,10 @@ void G4VVisCommand::RefreshIfRequired(G4VViewer* viewer) {
void G4VVisCommand::InterpolateViews
(G4VViewer* currentViewer,
std::vector<G4ViewParameters> viewVector,
const std::vector<G4ViewParameters>& viewVector,
const G4int nInterpolationPoints,
const G4int waitTimePerPointmilliseconds,
const G4String exportString)
const G4String& exportString)
{
const G4int safety = (G4int)viewVector.size()*nInterpolationPoints;
G4int safetyCount = 0;
@@ -322,7 +322,7 @@ void G4VVisCommand::InterpolateToNewView
const G4ViewParameters& newVP,
const G4int nInterpolationPoints,
const G4int waitTimePerPointmilliseconds,
const G4String exportString)
const G4String& exportString)
{
std::vector<G4ViewParameters> viewVector;
viewVector.push_back(oldVP);
@@ -1011,7 +1011,7 @@ std::ostream& operator << (std::ostream& os, const G4ViewParameters& v) {
os << "\n Default TextVisAttributes:\n " << v.fDefaultTextVisAttributes;
os << "\n Default marker: " << v.fDefaultMarker;
os << "\n Default marker:\n " << v.fDefaultMarker;
os << "\n Global marker scale: " << v.fGlobalMarkerScale;
@@ -1048,7 +1048,7 @@ std::ostream& operator << (std::ostream& os, const G4ViewParameters& v) {
default: os << "unrecognised"; break;
}
os << "\n Vis attributes modifiers: ";
os << "\nVis attributes modifiers: ";
const std::vector<G4ModelingParameters::VisAttributesModifier>& vams =
v.fVisAttributesModifiers;
if (vams.empty()) {
@@ -1057,7 +1057,7 @@ std::ostream& operator << (std::ostream& os, const G4ViewParameters& v) {
os << vams;
}
os << "\n Time window parameters:"
os << "\nTime window parameters:"
<< "\n Start time: " << v.fStartTime/ns << " ns"
<< "\n End time: " << v.fEndTime/ns << " ns"
<< "\n Fade factor: " << v.fFadeFactor;
@@ -1083,7 +1083,7 @@ std::ostream& operator << (std::ostream& os, const G4ViewParameters& v) {
<< ' ' << v.fDisplayLightFrontGreen << ' ' << v.fDisplayLightFrontBlue;
}
os << "\n Special Mesh Rendering";
os << "\nSpecial Mesh Rendering";
if (v.fSpecialMeshRendering) {
os << " requested with option \"" << v.fSpecialMeshRenderingOption;
os << "\" for ";
@@ -214,10 +214,10 @@ G4String G4VisCommandList::GetCurrentValue (G4UIcommand*)
void G4VisCommandList::SetNewValue (G4UIcommand*, G4String newValue)
{
G4String& verbosityString = newValue;
G4VisManager::Verbosity verbosity =
fpVisManager->GetVerbosityValue(verbosityString);
G4VisManager::Verbosity verbosity = fpVisManager->GetVerbosityValue(newValue);
G4VisManager::PrintAvailableVerbosity(G4cout);
G4cout << G4endl;
fpVisManager->PrintAvailableGraphicsSystems(verbosity);
G4cout << G4endl;
fpVisManager->PrintAvailableModels(verbosity);
@@ -228,6 +228,7 @@ void G4VisCommandList::SetNewValue (G4UIcommand*, G4String newValue)
G4cout << G4endl;
G4UImanager* UImanager = G4UImanager::GetUIpointer();
UImanager->ApplyCommand("/vis/scene/list ! " + newValue);
G4cout << G4endl;
UImanager->ApplyCommand("/vis/viewer/list ! " + newValue);
G4cout <<
@@ -563,7 +564,7 @@ G4VisCommandVerbose::G4VisCommandVerbose () {
fpCommand -> SetGuidance(G4VisManager::VerbosityGuidanceStrings[i]);
}
fpCommand -> SetParameterName("verbosity", omitable=true);
fpCommand -> SetDefaultValue("warnings");
fpCommand -> SetDefaultValue("");
}
G4VisCommandVerbose::~G4VisCommandVerbose () {
@@ -580,6 +581,6 @@ void G4VisCommandVerbose::SetNewValue (G4UIcommand*,
fpVisManager->GetVerbosityValue(newValue);
fpVisManager->SetVerboseLevel(verbosity);
// Always prints whatever the verbosity...
G4cout << "Visualization verbosity changed to "
G4cout << "Visualization verbosity is now "
<< G4VisManager::VerbosityString(verbosity) << G4endl;
}
@@ -414,6 +414,12 @@ G4VisCommandPlot::G4VisCommandPlot ()
fpCommand -> SetParameter (parameter);
parameter = new G4UIparameter ("id", 'i', omitable = false);
fpCommand -> SetParameter (parameter);
#ifdef TOOLS_USE_FREETYPE
parameter = new G4UIparameter ("style", 's', omitable = true);
parameter -> SetParameterCandidates("none ROOT_default hippodraw");
parameter -> SetDefaultValue("ROOT_default");
fpCommand -> SetParameter (parameter);
#endif
}
G4VisCommandPlot::~G4VisCommandPlot ()
@@ -437,9 +443,13 @@ void G4VisCommandPlot::SetNewValue (G4UIcommand*, G4String newValue)
return;
}
G4String type, id;
std::istringstream is (newValue);
G4String type, id;
is >> type >> id;
#ifdef TOOLS_USE_FREETYPE
G4String style;
is >> style;
#endif
auto keepEnable = fpVisManager->IsEnabled();
@@ -455,6 +465,11 @@ void G4VisCommandPlot::SetNewValue (G4UIcommand*, G4String newValue)
ui->ApplyCommand("/vis/plotter/create " + plotterName);
ui->ApplyCommand("/vis/scene/add/plotter " + plotterName);
ui->ApplyCommand("/vis/plotter/add/" + type + ' ' + id + ' ' + plotterName);
#ifdef TOOLS_USE_FREETYPE
if (style != "none") {
ui->ApplyCommand("/vis/plotter/addStyle " + plotterName + ' ' + style);
}
#endif
ui->ApplyCommand("/vis/sceneHandler/attach");
if (!keepEnable) {
@@ -39,7 +39,7 @@
#define G4warn G4cout
void G4VVisCommandGeometrySet::Set
(G4String requestedName,
(const G4String& requestedName,
const G4VVisCommandGeometrySetFunction& setFunction,
G4int requestedDepth)
{
@@ -27,15 +27,16 @@
// /vis/multithreading commands - John Allison 29th September 2015
#include "G4Types.hh"
#ifdef G4MULTITHREADED
#include "G4VisCommandsMultithreading.hh"
#include "G4Threading.hh"
#include "G4UIcmdWithAnInteger.hh"
#include "G4UIcmdWithAString.hh"
#include "G4VisManager.hh"
// For future use with additional G4ios logging streams
#define G4warn G4cout
////////////// /vis/multithreading/actionOnEventQueueFull ///////////////////////////////////////
G4VisCommandMultithreadingActionOnEventQueueFull::G4VisCommandMultithreadingActionOnEventQueueFull()
@@ -64,6 +65,14 @@ void G4VisCommandMultithreadingActionOnEventQueueFull::SetNewValue(G4UIcommand*,
{
G4VisManager::Verbosity verbosity = fpVisManager->GetVerbosity();
// Only relevant in a MT application
if(!G4Threading::IsMultithreadedApplication()) {
if (verbosity >= G4VisManager::warnings) {
G4warn << "command /vis/multithreading/actionOnEventQueueFull ignored in sequential mode" << G4endl;
}
return;
}
if (newValue == "wait") {
fpVisManager->SetWaitOnEventQueueFull(true);
} else {
@@ -116,6 +125,14 @@ void G4VisCommandMultithreadingMaxEventQueueSize::SetNewValue(G4UIcommand*, G4St
{
G4VisManager::Verbosity verbosity = fpVisManager->GetVerbosity();
// Only relevant in a MT application
if(!G4Threading::IsMultithreadedApplication()) {
if (verbosity >= G4VisManager::warnings) {
G4warn << "command /vis/multithreading/maxEventQueueSize ignored in sequential mode" << G4endl;
}
return;
}
G4int maxEventQueueSize = fpCommand->GetNewIntValue(newValue);
fpVisManager->SetMaxEventQueueSize(maxEventQueueSize);
@@ -126,5 +143,3 @@ void G4VisCommandMultithreadingMaxEventQueueSize::SetNewValue(G4UIcommand*, G4St
<< G4endl;
}
}
#endif
@@ -448,7 +448,7 @@ void G4VisCommandSceneAddDate::SetNewValue (G4UIcommand*, G4String newValue)
model->SetGlobalTag("Date");
model->SetGlobalDescription("Date: " + newValue);
const G4String& currentSceneName = pScene -> GetName ();
G4bool successful = pScene -> AddRunDurationModel (model, warn);
G4bool successful = pScene -> AddEndOfEventModel(model, warn);
if (successful) {
if (verbosity >= G4VisManager::confirmations) {
G4cout << "Date has been added to scene \""
@@ -745,8 +745,7 @@ void G4VisCommandSceneAddEventID::EventID::operator()
// Only use if NOT reviewing kept events
if (fpVisManager->GetReviewingKeptEvents()) return;
const G4int nEvents = currentRun->GetNumberOfEventToBeProcessed();
const auto* events = currentRun->GetEventVector();
size_t nKeptEvents = events? events->size(): 0;
size_t nKeptEvents = (size_t)(currentRun->GetNumberOfKeptEvents());
oss << "Run " << currentRunID << " (" << nEvents << " event";
if (nEvents != 1) oss << 's';
oss << ", " << nKeptEvents << " kept)";
@@ -1883,7 +1882,11 @@ G4VisCommandSceneAddLogo::G4Logo::G4Logo
G4Tubs tG("tG",ri,ro,d2,0.15*pi,1.85*pi);
G4Box bG("bG",w2,ro2,d2);
G4UnionSolid logoG("logoG",&tG,&bG,G4Translate3D(ri+w2,-ro2,0.));
// Create with these vis atts (force solid) and current no of sides per circle.
G4Polyhedron::SetNumberOfRotationSteps
(fpVisManager->GetCurrentViewer()->GetViewParameters().GetNoOfSides());
fpG = logoG.CreatePolyhedron();
G4Polyhedron::ResetNumberOfRotationSteps ();
fpG->SetVisAttributes(visAtts);
fpG->Transform(G4Translate3D(-0.55*h,0.,0.));
fpG->Transform(transform);
@@ -38,7 +38,9 @@
#include "G4TouchablePropertiesScene.hh"
#include "G4TransportationManager.hh"
#include "G4BoundingExtentScene.hh"
#include <sstream>
#include <utility>
#define G4warn G4cout
@@ -440,7 +442,7 @@ void G4VisCommandSetTouchable::SetNewValue (G4UIcommand*, G4String newValue)
if (iEnd == G4String::npos) {
iEnd = newValue.length();
}
G4String name(newValue.substr(iBegin,iEnd-iBegin));
const G4String& name(newValue.substr(iBegin,iEnd-iBegin));
iBegin = newValue.find_first_not_of(' ',iEnd);
if (iBegin == G4String::npos) {
if (verbosity >= G4VisManager::warnings) {
@@ -1073,16 +1073,6 @@ void G4VisCommandViewerCreate::SetNewValue (G4UIcommand* command, G4String newVa
}
}
if (fThereWasAViewer) {
// ...and if it's still current...
auto existingViewer = fpVisManager->GetCurrentViewer();
if (existingViewer) {
// ...bring view parameters up to date...
fExistingVP = existingViewer->GetViewParameters();
fExistingSceneTree = existingViewer->GetSceneTree();
}
}
if (fThereWasAViewer && windowSizeHintString == "none") {
// The user did not specify a window size hint - get from existing VPs
windowSizeHintString = fExistingVP.GetXGeometryString();
@@ -1099,6 +1089,7 @@ void G4VisCommandViewerCreate::SetNewValue (G4UIcommand* command, G4String newVa
// Copy view parameters from existing viewer, except for...
fExistingVP.SetAutoRefresh(vp.IsAutoRefresh());
fExistingVP.SetBackgroundColour(vp.GetBackgroundColour());
fExistingVP.SetGlobalMarkerScale(vp.GetGlobalMarkerScale());
// ...including window hint paramaters that have been set already above...
fExistingVP.SetXGeometryString(vp.GetXGeometryString());
vp = fExistingVP;
@@ -43,6 +43,7 @@
#include <sstream>
#include <iomanip>
#include <utility>
#define G4warn G4cout
@@ -1302,7 +1303,7 @@ void G4VisCommandsViewerSet::SetNewValue
if (iEnd == G4String::npos) {
iEnd = newValue.length();
}
G4String name(newValue.substr(iBegin,iEnd-iBegin));
const G4String& name(newValue.substr(iBegin,iEnd-iBegin));
iBegin = newValue.find_first_not_of(' ',iEnd);
if (iBegin == G4String::npos) {
if (verbosity >= G4VisManager::warnings) {
@@ -80,19 +80,34 @@
#include <vector>
#include <sstream>
#ifdef G4MULTITHREADED
# include "G4Threading.hh"
# include "G4AutoLock.hh"
# include "G4GeometryWorkspace.hh" // no_geant4_module_check(!G4MULTITHREADED)
# include "G4SolidsWorkspace.hh"
# include <deque>
# include <typeinfo>
# include <chrono>
# include <thread>
#endif
#include "G4Threading.hh"
#include "G4AutoLock.hh"
#include "G4GeometryWorkspace.hh" // no_geant4_module_check(!G4MULTITHREADED)
#include "G4SolidsWorkspace.hh"
#include <deque>
#include <typeinfo>
#include <chrono>
#include <thread>
#include <utility>
#define G4warn G4cout
// Local threading related variables
namespace {
G4bool mtRunInProgress = false;
std::deque<const G4Event*> mtVisEventQueue;
G4Thread* mtVisSubThread = 0;
[[maybe_unused]] G4Mutex mtVisSubThreadMutex = G4MUTEX_INITIALIZER;
// G4Mutex visBeginOfRunMutex = G4MUTEX_INITIALIZER;
// G4Mutex visBeginOfEventMutex = G4MUTEX_INITIALIZER;
G4Mutex visEndOfEventMutex = G4MUTEX_INITIALIZER;
// G4Mutex visEndOfRunMutex = G4MUTEX_INITIALIZER;
G4bool isSubEventRunManagerType = false;
G4bool isValidViewForRun = false;
G4bool isFakeRun = false;
}
// Class statics
G4VisManager* G4VisManager::fpInstance = 0;
G4VisManager::Verbosity G4VisManager::fVerbosity = G4VisManager::warnings;
@@ -125,10 +140,8 @@ G4VisManager::G4VisManager (const G4String& verbosityString)
, fIsDrawGroup (false)
, fDrawGroupNestingDepth (0)
, fIgnoreStateChanges (false)
#ifdef G4MULTITHREADED
, fMaxEventQueueSize (100)
, fWaitOnEventQueueFull (true)
#endif
// All other objects use default constructors.
{
fpTrajDrawModelMgr = new G4VisModelManager<G4VTrajectoryModel>("/vis/modeling/trajectories");
@@ -494,13 +507,11 @@ void G4VisManager::RegisterMessengers () {
RegisterMessenger(new G4VisCommandGeometrySetForceWireframe);
RegisterMessenger(new G4VisCommandGeometrySetVisibility);
#ifdef G4MULTITHREADED
directory = new G4UIdirectory ("/vis/multithreading/");
directory -> SetGuidance("Commands unique to multithreading mode.");
fDirectoryList.push_back (directory);
RegisterMessenger(new G4VisCommandMultithreadingActionOnEventQueueFull);
RegisterMessenger(new G4VisCommandMultithreadingMaxEventQueueSize);
#endif
directory = new G4UIdirectory ("/vis/set/");
directory -> SetGuidance
@@ -745,7 +756,7 @@ void G4VisManager::Enable() {
if (fVerbosity >= warnings) {
std::size_t nKeptEvents = 0;
const G4Run* run = G4RunManager::GetRunManager()->GetCurrentRun();
if (run) nKeptEvents = run->GetEventVector()->size();
if (run) nKeptEvents = run->GetNumberOfKeptEvents();
G4String isare("are"),plural("s");
if (nKeptEvents == 1) {isare = "is"; plural = "";}
G4cout <<
@@ -913,9 +924,8 @@ void G4VisManager::SelectTrajectoryModel(const G4String& model)
void G4VisManager::BeginDraw (const G4Transform3D& objectTransform)
{
#ifdef G4MULTITHREADED
if (G4Threading::IsWorkerThread()) return;
#endif
fDrawGroupNestingDepth++;
if (fDrawGroupNestingDepth > 1) {
G4Exception
@@ -934,9 +944,8 @@ void G4VisManager::BeginDraw (const G4Transform3D& objectTransform)
void G4VisManager::EndDraw ()
{
#ifdef G4MULTITHREADED
if (G4Threading::IsWorkerThread()) return;
#endif
fDrawGroupNestingDepth--;
if (fDrawGroupNestingDepth != 0) {
if (fDrawGroupNestingDepth < 0) fDrawGroupNestingDepth = 0;
@@ -950,9 +959,8 @@ void G4VisManager::EndDraw ()
void G4VisManager::BeginDraw2D (const G4Transform3D& objectTransform)
{
#ifdef G4MULTITHREADED
if (G4Threading::IsWorkerThread()) return;
#endif
fDrawGroupNestingDepth++;
if (fDrawGroupNestingDepth > 1) {
G4Exception
@@ -971,9 +979,8 @@ void G4VisManager::BeginDraw2D (const G4Transform3D& objectTransform)
void G4VisManager::EndDraw2D ()
{
#ifdef G4MULTITHREADED
if (G4Threading::IsWorkerThread()) return;
#endif
fDrawGroupNestingDepth--;
if (fDrawGroupNestingDepth != 0) {
if (fDrawGroupNestingDepth < 0) fDrawGroupNestingDepth = 0;
@@ -987,9 +994,8 @@ void G4VisManager::EndDraw2D ()
template <class T> void G4VisManager::DrawT
(const T& graphics_primitive, const G4Transform3D& objectTransform) {
#ifdef G4MULTITHREADED
if (G4Threading::IsWorkerThread()) return;
#endif
if (fIsDrawGroup) {
if (objectTransform != fpSceneHandler->GetObjectTransformation()) {
G4Exception
@@ -1010,9 +1016,8 @@ template <class T> void G4VisManager::DrawT
template <class T> void G4VisManager::DrawT2D
(const T& graphics_primitive, const G4Transform3D& objectTransform) {
#ifdef G4MULTITHREADED
if (G4Threading::IsWorkerThread()) return;
#endif
if (fIsDrawGroup) {
if (objectTransform != fpSceneHandler->GetObjectTransformation()) {
G4Exception
@@ -1104,9 +1109,8 @@ void G4VisManager::Draw2D (const G4Text& text,
}
void G4VisManager::Draw (const G4VHit& hit) {
#ifdef G4MULTITHREADED
if (G4Threading::IsWorkerThread()) return;
#endif
if (fIsDrawGroup) {
fpSceneHandler -> AddCompound (hit);
} else {
@@ -1118,9 +1122,8 @@ void G4VisManager::Draw (const G4VHit& hit) {
}
void G4VisManager::Draw (const G4VDigi& digi) {
#ifdef G4MULTITHREADED
if (G4Threading::IsWorkerThread()) return;
#endif
if (fIsDrawGroup) {
fpSceneHandler -> AddCompound (digi);
} else {
@@ -1132,9 +1135,8 @@ void G4VisManager::Draw (const G4VDigi& digi) {
}
void G4VisManager::Draw (const G4VTrajectory& traj) {
#ifdef G4MULTITHREADED
if (G4Threading::IsWorkerThread()) return;
#endif
// A trajectory needs a trajectories model to provide G4Atts, etc.
static G4TrajectoriesModel trajectoriesModel;
trajectoriesModel.SetCurrentTrajectory(&traj);
@@ -1165,9 +1167,8 @@ void G4VisManager::Draw (const G4VTrajectory& traj) {
void G4VisManager::Draw (const G4LogicalVolume& logicalVol,
const G4VisAttributes& attribs,
const G4Transform3D& objectTransform) {
#ifdef G4MULTITHREADED
if (G4Threading::IsWorkerThread()) return;
#endif
// Find corresponding solid.
G4VSolid* pSol = logicalVol.GetSolid ();
Draw (*pSol, attribs, objectTransform);
@@ -1176,9 +1177,8 @@ void G4VisManager::Draw (const G4LogicalVolume& logicalVol,
void G4VisManager::Draw (const G4VSolid& solid,
const G4VisAttributes& attribs,
const G4Transform3D& objectTransform) {
#ifdef G4MULTITHREADED
if (G4Threading::IsWorkerThread()) return;
#endif
if (fIsDrawGroup) {
fpSceneHandler -> PreAddSolid (objectTransform, attribs);
solid.DescribeYourselfTo (*fpSceneHandler);
@@ -1196,9 +1196,8 @@ void G4VisManager::Draw (const G4VSolid& solid,
void G4VisManager::Draw (const G4VPhysicalVolume& physicalVol,
const G4VisAttributes& attribs,
const G4Transform3D& objectTransform) {
#ifdef G4MULTITHREADED
if (G4Threading::IsWorkerThread()) return;
#endif
// Note: It is tempting to use a temporary model here, as for
// trajectories, in order to get at the G4Atts of the physical
// volume. I tried it (JA). But it's not easy to pass the
@@ -1867,13 +1866,15 @@ void G4VisManager::PrintAvailableUserVisActions (Verbosity) const
void G4VisManager::PrintAvailableColours (Verbosity) const {
G4cout <<
"Some /vis commands (optionally) take a string to specify colour."
"\nAvailable colours:\n ";
const std::map<G4String, G4Colour>& map = G4Colour::GetMap();
for (std::map<G4String, G4Colour>::const_iterator i = map.begin();
i != map.end();) {
G4cout << i->first;
if (++i != map.end()) G4cout << ", ";
"Some /vis commands (optionally) take a string to specify colour."
"\nThey are also available in your C++ code, e.g:"
"\n G4Colour niceColour; // Default - white"
"\n G4Colour::GetColour(\"pink\", niceColour);"
"\n logical->SetVisAttributes(niceColour);"
"\nSee G4Colour.hh."
"\nAvailable colours";
for (const auto& i: G4Colour::GetMap()) {
G4cout << ", " << i.first;
}
G4cout << G4endl;
}
@@ -1903,17 +1904,10 @@ void G4VisManager::PrintInvalidPointers () const {
}
}
#ifdef G4MULTITHREADED
namespace {
G4bool mtRunInProgress = false;
std::deque<const G4Event*> mtVisEventQueue;
G4Thread* mtVisSubThread = 0;
G4Mutex mtVisSubThreadMutex = G4MUTEX_INITIALIZER;
}
G4ThreadFunReturnType G4VisManager::G4VisSubThread(G4ThreadFunArgType p)
{
#ifdef G4MULTITHREADED
G4VisManager* pVisManager = (G4VisManager*)p;
G4VSceneHandler* pSceneHandler = pVisManager->GetCurrentSceneHandler();
if (!pSceneHandler) return 0;
@@ -1924,9 +1918,6 @@ G4ThreadFunReturnType G4VisManager::G4VisSubThread(G4ThreadFunArgType p)
G4UImanager::GetUIpointer()->SetUpForSpecialThread("G4VIS");
// G4cout << "G4VisManager::G4VisSubThread: thread: "
// << G4Threading::G4GetThreadId() << std::endl;
// Set up geometry and navigation for a thread
G4GeometryWorkspace::GetPool()->CreateAndUseWorkspace();
G4SolidsWorkspace::GetPool()->CreateAndUseWorkspace();
@@ -1949,11 +1940,6 @@ G4ThreadFunReturnType G4VisManager::G4VisSubThread(G4ThreadFunArgType p)
G4MUTEXLOCK(&mtVisSubThreadMutex);
const G4Event* event = mtVisEventQueue.front();
G4MUTEXUNLOCK(&mtVisSubThreadMutex);
// G4int eventID = event->GetEventID();
// G4cout
// << "G4VisManager::G4VisSubThread: Vis sub-thread: Dealing with event:
// "
// << eventID << G4endl;
// Here comes the event drawing
pVisManager->SetTransientsDrawnThisEvent(false);
@@ -1973,26 +1959,12 @@ G4ThreadFunReturnType G4VisManager::G4VisSubThread(G4ThreadFunArgType p)
pSceneHandler->DrawEvent(event);
++pVisManager->fNoOfEventsDrawnThisRun;
if (pScene->GetRefreshAtEndOfEvent()) {
// 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.
pViewer->ShowView();
pSceneHandler->SetMarkForClearingTransientStore(true);
}
// Testing.
// std::this_thread::sleep_for(std::chrono::seconds(5));
// Then pop and release event
G4MUTEXLOCK(&mtVisSubThreadMutex);
mtVisEventQueue.pop_front();
pVisManager->EndOfEventCleanup(event, event->GetEventID());
pVisManager->EndOfEventCleanup(event);
eventQueueSize = mtVisEventQueue.size();
G4MUTEXUNLOCK(&mtVisSubThreadMutex);
// G4cout << "Event queue size (B): " << eventQueueSize << G4endl;
}
G4MUTEXLOCK(&mtVisSubThreadMutex);
@@ -2011,46 +1983,35 @@ G4ThreadFunReturnType G4VisManager::G4VisSubThread(G4ThreadFunArgType p)
// Inform viewer that we have finished all sub-thread drawing
pViewer->DoneWithVisSubThread();
pViewer->MovingToMasterThread();
// G4cout << "G4VisManager::G4VisSubThread: Vis sub-thread: ending" << G4endl;
return nullptr;
}
namespace {
// G4Mutex visBeginOfRunMutex = G4MUTEX_INITIALIZER;
// G4Mutex visBeginOfEventMutex = G4MUTEX_INITIALIZER;
G4Mutex visEndOfEventMutex = G4MUTEX_INITIALIZER;
// G4Mutex visEndOfRunMutex = G4MUTEX_INITIALIZER;
}
#else
G4ConsumeParameters(p);
#endif
namespace {
G4bool isSubEventRunManagerType = false;
return nullptr;
}
void G4VisManager::BeginOfRun ()
{
if (fIgnoreStateChanges) return;
#ifdef G4MULTITHREADED
if (G4Threading::IsWorkerThread()) return;
#endif
// G4cout << "G4VisManager::BeginOfRun: thread: "
// << G4Threading::G4GetThreadId() << G4endl;
if (!GetConcreteInstance()) return;
// Check if view is valid
// Protect IsValidView() with fpSceneHandler to prevent warning messages in batch
isValidViewForRun = fpSceneHandler && IsValidView();
if (!isValidViewForRun) return;
// For a fake run...
G4RunManager* runManager = G4RunManagerFactory::GetMasterRunManager();
G4int nEventsToBeProcessed = runManager->GetNumberOfEventsToBeProcessed();
isFakeRun = (nEventsToBeProcessed == 0);
if (isFakeRun) return;
// Is the run manager a sub-event type?
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;
fNKeepForPostProcessingRequests = 0;
fNKeepTheEventRequests = 0;
fEventKeepingSuspended = false;
@@ -2064,19 +2025,13 @@ void G4VisManager::BeginOfRun ()
// The function is called again later when needed.
CurrentTrajDrawModel();
#ifdef G4MULTITHREADED
// There is a static method G4Threading::IsMultithreadedApplication()
// that returns true only if G4MTRunManager is instantiated with MT
// installation. Thus method returns false if G4RunManager base class is
// instantiated even with the MT installation, or of course with sequential
// installation.
// Actions only in MT mode
if (G4Threading::IsMultithreadedApplication()) {
// Inform viewer that we have finished all master thread drawing for now...
if (fpViewer) fpViewer->DoneWithMasterThread();
// Start vis sub-thread
// G4cout << "G4VisManager::BeginOfRun: Starting vis sub-thread" << G4endl;
G4MUTEXLOCK(&mtVisSubThreadMutex);
mtRunInProgress = true;
G4MUTEXUNLOCK(&mtVisSubThreadMutex);
@@ -2091,21 +2046,17 @@ void G4VisManager::BeginOfRun ()
// - Go ahead
if (fpViewer) fpViewer->MovingToVisSubThread();
}
#endif
}
void G4VisManager::BeginOfEvent ()
{
if (fIgnoreStateChanges) return;
if (!GetConcreteInstance()) return;
if (isSubEventRunManagerType) return;
// G4cout << "G4VisManager::BeginOfEvent: thread: "
// << G4Threading::G4GetThreadId() << G4endl;
if (!isValidViewForRun) return;
if (isFakeRun) return;
// Some instructions that should NOT be in multithreaded version.
// TODO: protect with G4Threading::IsMultithreadedApplication() instead?
#ifndef G4MULTITHREADED
// These instructions are in G4VisSubThread for multithreading.
fTransientsDrawnThisEvent = false;
@@ -2113,52 +2064,51 @@ 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
// Here begins a sequence of functions that deal with end-of-event.
// Sequential/Serial mode:
// EndOfEvent is invoked by a state change on the master thread:
// EndOfEvent pulls the event from the Event Manager and calls EndOfEventKernel.
// EndOfEventKernel draws the event and calls EndOfEventCleanup.
// (Unless the user him/herself has requested keeping, EndOfEventKernel
// also sets KeepTheEvent for a certain number (adjustable, default 100)
// of events. The run manager keeps these events until the beginning of the next
// run, so, for example, the vis manager can redraw/rebuild if required.)
// Multithreading/Tasking:
// EndOfEvent is invoked by a state change on each worker thread:
// EndOfEvent pulls the event from the (worker) Event Manager and calls EndOfEventKernel.
// EndOfEventKernel pushes it to the vis queue, and returns. The events
// are marked KeepForPostProcessing so that the worker does not delete them until
// PostProcessingFinished in EndOfEventCleanup.
// EndOfEventKernel also sets KeepTheEvent as above.
// The vis sub thread pulls events from the vis queue, draws them and
// calls EndOfEventCleanup, which calls PostProcessingFinished.
// Sub-event parallelism:
// EndOfEvent is invoked by a state change on each worker thread, as for
// multithreading, but actually, the event is not complete. Workers are
// employed on sub-events, so we ignore such state changes. Only
// G4SubEvtRunManager knows when the event is complete.
// Events are pushed to the Vis Manager by G4SubEvtRunManager via EventReadyForVis
// when the event is ready. EventReadyForVis calls EndOfEventKernel and
// processsing continues as for Multithreading.
void G4VisManager::EndOfEvent ()
{
if (fIgnoreStateChanges) return;
if (!GetConcreteInstance()) return;
if (!isValidViewForRun) return;
if (isFakeRun) return;
// For sub-event parallelism, this is not the true end of event
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));
#endif
// Don't call IsValidView unless there is a scene handler. This
// avoids WARNING message at end of event and run when the user has
// not instantiated a scene handler, e.g., in batch mode.
G4bool valid = fpSceneHandler && IsValidView();
if (!valid) return;
G4RunManager* runManager = G4RunManagerFactory::GetMasterRunManager();
const G4Run* currentRun = runManager->GetCurrentRun();
if (!currentRun) return;
// This gets the thread-local event manager
// This gets the appropriate event manager
G4EventManager* eventManager = G4EventManager::GetEventManager();
const G4Event* currentEvent = eventManager->GetConstCurrentEvent();
if (!currentEvent) return;
@@ -2167,72 +2117,22 @@ void G4VisManager::EndOfEvent ()
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.
void G4VisManager::EventReadyForVis(const G4Event* event)
// This is invoked by G4SubEvtRunManager.
// The event is passed to EndOfEventKernel.
{
G4bool relinquishable = false;
if (fIgnoreStateChanges) return;
if (!GetConcreteInstance()) return;
if (!isValidViewForRun) return;
if (isFakeRun) return;
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;
G4AutoLock al(&visEndOfEventMutex);
EndOfEventKernel(event);
}
void G4VisManager::EndOfEventKernel (const G4Event* currentEvent)
{
G4RunManager* runManager = G4RunManagerFactory::GetMasterRunManager();
const G4Run* currentRun = runManager->GetCurrentRun();
G4EventManager* eventManager = G4EventManager::GetEventManager();
// Note: we are still subject to the mutex lock with visEndOfEventMutex
// Discard event if fDrawEventOnlyIfToBeKept flag is set unless the
// user has requested the event to be kept.
@@ -2242,19 +2142,16 @@ void G4VisManager::EndOfEventKernel (const G4Event* currentEvent)
if (G4Threading::IsMultithreadedApplication()) {
#ifdef G4MULTITHREADED
// Wait if too many events in the queue.
G4MUTEXLOCK(&mtVisSubThreadMutex);
std::size_t eventQueueSize = mtVisEventQueue.size();
G4MUTEXUNLOCK(&mtVisSubThreadMutex);
// G4cout << "Event queue size (1): " << eventQueueSize << G4endl;
G4bool eventQueueFull = false;
while (fMaxEventQueueSize > 0 && (G4int)eventQueueSize >= fMaxEventQueueSize) {
// G4cout << "Event queue size (2): " << eventQueueSize << G4endl;
if (fWaitOnEventQueueFull) {
static G4bool warned = false;
if (!warned) {
G4warn <<
@@ -2274,11 +2171,12 @@ void G4VisManager::EndOfEventKernel (const G4Event* currentEvent)
<< G4endl;
warned = true;
}
// G4cout << "Event queue size (3): " << eventQueueSize << G4endl;
// Wait a while to give event drawing time to reduce the queue...
std::this_thread::sleep_for(std::chrono::milliseconds(100));
// G4cout << "Event queue size (4): " << eventQueueSize << G4endl;
} else {
static G4bool warned = false;
if (!warned) {
G4warn <<
@@ -2292,6 +2190,7 @@ void G4VisManager::EndOfEventKernel (const G4Event* currentEvent)
<< G4endl;
warned = true;
}
eventQueueFull = true; // Causes event to be discarded for drawing.
break;
}
@@ -2302,37 +2201,29 @@ void G4VisManager::EndOfEventKernel (const G4Event* currentEvent)
}
if (!eventQueueFull) {
if (RequiredToBeKeptForVis(currentEvent->GetEventID())) {
currentEvent->KeepTheEvent();
fNKeepTheEventRequests++; // Counts number of calls to KeepTheEvent
}
G4MUTEXLOCK(&mtVisSubThreadMutex);
// Keep while post processing (i.e., drawing), relinquished in EndOfEventCleanup
// Make sure the event is not deleted by the run manager while in the vis queue
currentEvent->KeepForPostProcessing();
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;
#endif
} else {
// Sequential mode
G4int eventID = -2; // (If no run manager, triggers ShowView as normal.)
if (currentRun) {
eventID = currentEvent->GetEventID();
}
// We are about to draw the event (trajectories, etc.), but first we
// have to clear the previous event(s) if necessary. If this event
// needs to be drawn afresh, e.g., the first event or any event when
@@ -2343,59 +2234,103 @@ void G4VisManager::EndOfEventKernel (const G4Event* currentEvent)
// See, for example, G4HepRepFileSceneHandler::ClearTransientStore.
ClearTransientStoreIfMarked();
// Keep - but relinquish (PostProcessingFinished) later if not needed
// Keep while post processing (i.e., drawing), relinquished in EndOfEventCleanup
currentEvent->KeepForPostProcessing();
if (!Relinquishable(currentEvent->GetEventID(),
(G4int)currentRun->GetEventVector()->size(),
fNKeepTheEventRequests)) {
eventManager->KeepTheCurrentEvent();
fNKeepTheEventRequests++; // Counts number of calls to KeepTheCurrentEvent
fNKeepForPostProcessingRequests++;
if (RequiredToBeKeptForVis(currentEvent->GetEventID())) {
currentEvent->KeepTheEvent();
fNKeepTheEventRequests++; // Counts number of calls to KeepTheEvent
}
// Now draw the event...
fpSceneHandler->DrawEvent(currentEvent);
++fNoOfEventsDrawnThisRun;
EndOfEventCleanup(currentEvent,eventID);
EndOfEventCleanup(currentEvent);
}
}
void G4VisManager::EndOfEventCleanup
(const G4Event* currentEvent,
G4int eventID) // See EndOfEventKernel: can be == -2?
void G4VisManager::EndOfEventCleanup(const G4Event* currentEvent)
{
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();
if (fpScene->GetRefreshAtEndOfEvent()) {
fpSceneHandler->SetMarkForClearingTransientStore(true);
// ShowView guarantees the view is flushed to the screen. It also
// triggers other features such as picking (if enabled) and allows
// file-writing viewers to close the file.
fpViewer->ShowView();
}
// 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();
currentEvent->PostProcessingFinished();
}
G4bool G4VisManager::RequiredToBeKeptForVis (G4int eventID)
// i.e., kept by the run manager at least to the beginning of the next run.
{
G4bool requiredToBeKept = false;
G4RunManager* runManager = G4RunManagerFactory::GetMasterRunManager();
G4int nEventsToBeProcessed = runManager->GetNumberOfEventsToBeProcessed();
if (fpScene->GetRefreshAtEndOfEvent()) { // Refreshing every event
// Keep last event only
if (eventID == nEventsToBeProcessed - 1) {
requiredToBeKept = true;
}
} else { // Accumulating events
G4int maxNumberOfKeptEvents = fpScene->GetMaxNumberOfKeptEvents();
if (maxNumberOfKeptEvents >= 0) { // Event keeping requested
if (fNKeepTheEventRequests < maxNumberOfKeptEvents) {
// Not yet reached the limit
requiredToBeKept = true;
} else {
// We have already reached the limit
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 { // Indefinite event keeping (maxNumberOfKeptEvents < 0)
requiredToBeKept = true;
}
}
return requiredToBeKept;
}
void G4VisManager::EndOfRun ()
{
if (fIgnoreStateChanges) return;
#ifdef G4MULTITHREADED
if (G4Threading::IsWorkerThread()) return;
#endif
// G4cout << "G4VisManager::EndOfRun: thread: "
// << G4Threading::G4GetThreadId() << G4endl;
if (!GetConcreteInstance()) return;
if (!isValidViewForRun) return;
if (isFakeRun) return;
G4RunManager* runManager = G4RunManagerFactory::GetMasterRunManager();
@@ -2406,7 +2341,6 @@ void G4VisManager::EndOfRun ()
const G4Run* currentRun = runManager->GetCurrentRun();
if (!currentRun) return;
#ifdef G4MULTITHREADED
// G4AutoLock al(&visEndOfRunMutex); ???
if (G4Threading::IsMultithreadedApplication()) {
// Reset flag so that sub-thread exits when it has finished processing.
@@ -2416,16 +2350,10 @@ void G4VisManager::EndOfRun ()
// Wait for sub-thread to finish.
G4THREADJOIN(*mtVisSubThread);
delete mtVisSubThread;
if (fpViewer) fpViewer->SwitchToMasterThread();
fpViewer->SwitchToMasterThread();
}
#endif
#ifdef G4MULTITHREADED
// Print warning about discarded events, if any.
// Don't call IsValidView unless there is a scene handler. This
// avoids WARNING message from IsValidView() when the user has
// not instantiated a scene handler, e.g., in batch mode.
if (fpSceneHandler && IsValidView()) { // Events should have been drawn
if (G4Threading::IsMultithreadedApplication()) {
G4int noOfEventsRequested = runManager->GetNumberOfEventsToBeProcessed();
if (fNoOfEventsDrawnThisRun != noOfEventsRequested) {
if (!fWaitOnEventQueueFull && fVerbosity >= warnings) {
@@ -2438,18 +2366,14 @@ void G4VisManager::EndOfRun ()
}
}
}
#endif
G4int nKeptEvents = 0;
const std::vector<const G4Event*>* events = currentRun->GetEventVector();
if (events) nKeptEvents = (G4int)events->size();
G4int nKeptEvents = currentRun->GetNumberOfKeptEvents();
if (fVerbosity >= warnings && nKeptEvents > 0) {
G4warn << nKeptEvents;
if (nKeptEvents == 1) G4warn << " event has";
else G4warn << " events have";
G4warn << " been kept for refreshing and/or reviewing." << G4endl;
if (nKeptEvents != fNKeepTheEventRequests) {
G4warn << " (Note: ";
if (fNKeepTheEventRequests == 0) {
G4warn << "No keep requests were";
} else if (fNKeepTheEventRequests == 1) {
@@ -2460,10 +2384,12 @@ void G4VisManager::EndOfRun ()
G4warn << " made by the vis manager.";
if (fNKeepTheEventRequests == 0) {
G4warn <<
"\n The kept events are those you have asked to be kept in your user action(s).)";
"\n The kept events are those you have asked to be kept in your user action(s).";
} else {
G4warn <<
"\n The same or further events may have been kept by you in your user action(s).)";
"\n The same or further events may have been kept by you in your user action(s)."
"\n To turn off event keeping by the vis manager: /vis/drawOnlyToBeKeptEvents"
"\n or use /vis/scene/endOfEventAction <refresh|accumulate> 0";
}
G4warn << G4endl;
}
@@ -2491,39 +2417,32 @@ void G4VisManager::EndOfRun ()
}
}
// Don't call IsValidView unless there is a scene handler. This
// avoids WARNING message at end of event and run when the user has
// not instantiated a scene handler, e.g., in batch mode.
G4bool valid = fpSceneHandler && IsValidView();
if (GetConcreteInstance() && valid) {
// // ???? I can't remember why
// // if (!fpSceneHandler->GetMarkForClearingTransientStore()) {
// // is here. It prevents ShowView at end of run, which seems to be OK
// // for sequential mode, but MT mode seems to need it (I have not
// // figured out why). ???? JA ????
// if (!fpSceneHandler->GetMarkForClearingTransientStore()) {
if (fpScene->GetRefreshAtEndOfRun()) {
fpSceneHandler->DrawEndOfRunModels();
// An extra refresh for auto-refresh viewers.
// ???? I DON'T WHY THIS IS NECESSARY ???? JA ????
if (fpViewer->GetViewParameters().IsAutoRefresh()) {
fpViewer->RefreshView();
}
// 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();
fpSceneHandler->SetMarkForClearingTransientStore(true);
} else {
if (fpGraphicsSystem->GetFunctionality() ==
G4VGraphicsSystem::fileWriter) {
if (fVerbosity >= warnings) {
G4warn << "\"/vis/viewer/update\" to close file." << G4endl;
}
}
if (fpScene->GetRefreshAtEndOfRun()) {
fpSceneHandler->DrawEndOfRunModels();
// An extra refresh for auto-refresh viewers.
// ???? I DON'T WHY THIS IS NECESSARY ???? JA ????
if (fpViewer->GetViewParameters().IsAutoRefresh()) {
fpViewer->RefreshView();
}
// 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();
fpSceneHandler->SetMarkForClearingTransientStore(true);
} else {
if (fpGraphicsSystem->GetFunctionality() ==
G4VGraphicsSystem::fileWriter) {
if (fVerbosity >= warnings) {
G4warn << "\"/vis/viewer/update\" to close file." << G4endl;
}
// }
}
}
//}
fEventRefreshing = false;
}
@@ -2554,7 +2473,7 @@ void G4VisManager::ResetTransientsDrawnFlags()
}
G4String G4VisManager::ViewerShortName (const G4String& viewerName) const {
G4String viewerShortName = viewerName.substr(0, viewerName.find (' '));
const G4String& viewerShortName = viewerName.substr(0, viewerName.find (' '));
return G4StrUtil::strip_copy(viewerShortName);
}
@@ -2596,9 +2515,19 @@ G4String G4VisManager::VerbosityString(Verbosity verbosity) {
return rs;
}
void G4VisManager::PrintAvailableVerbosity(std::ostream& os)
{
os << "Available verbosity options:";
for (std::size_t i = 0; i < VerbosityGuidanceStrings.size(); ++i) {
os << '\n' << VerbosityGuidanceStrings[i];
}
os << "\nCurrent verbosity: " << G4VisManager::VerbosityString(fVerbosity);
os << std::endl;
}
G4VisManager::Verbosity
G4VisManager::GetVerbosityValue(const G4String& verbosityString) {
G4String ss = G4StrUtil::to_lower_copy(verbosityString);
G4String ss = G4StrUtil::to_lower_copy(verbosityString);
Verbosity verbosity;
if (ss[0] == 'q') verbosity = quiet;
else if (ss[0] == 's') verbosity = startup;
@@ -2608,18 +2537,16 @@ G4VisManager::GetVerbosityValue(const G4String& verbosityString) {
else if (ss[0] == 'p') verbosity = parameters;
else if (ss[0] == 'a') verbosity = all;
else {
// Could be an integer
G4int intVerbosity;
std::istringstream is(ss);
is >> intVerbosity;
if (!is) {
G4warn << "ERROR: G4VisManager::GetVerbosityValue: invalid verbosity \""
<< verbosityString << "\"";
for (std::size_t i = 0; i < VerbosityGuidanceStrings.size(); ++i) {
G4warn << '\n' << VerbosityGuidanceStrings[i];
}
verbosity = warnings;
G4warn << "\n Returning " << VerbosityString(verbosity)
<< G4endl;
<< verbosityString << "\"\n";
PrintAvailableVerbosity(G4warn);
// Return existing verbosity
return fVerbosity;
}
else {
verbosity = GetVerbosityValue(intVerbosity);
@@ -2767,12 +2694,13 @@ G4VisManager::RegisterModelFactories()
}
}
#ifdef G4MULTITHREADED
void G4VisManager::SetUpForAThread()
{
// TODO: protect with G4Threading::IsMultithreadedApplication() instead?
#ifdef G4MULTITHREADED
new G4VisStateDependent(this);
}
#endif
}
void G4VisManager::IgnoreStateChanges(G4bool val)
{
+15
View File
@@ -6,6 +6,21 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2024-10-22 John Allison (modeling-V11-02-05)
- G4PhysicalVolumeModel.cc:
- Fixed some ragged indentations.
## 2024-10-16 John Allison (modeling-V11-02-04)
- G4TrajectoryDrawByEncounteredVolume.cc, G4TrajectoryEncounteredVolumeFilter.cc:
- Replace check on trajectory type using dynamic_cast with a simple check
on the existence on the required G4Att.
## 2024-08-31 John Allison (modeling-V11-02-03)
- More Coverity fixes
## 2024-07-17 John Allison (modeling-V11-02-02)
- Coverity fixes
## 2024-01-22 John Allison (modeling-V11-02-01)
- Coworks with visman-V11-02-04, greps-V11-02-00 and interfaces-V11-02-01.
- G4PhysicalVolumeModel:
@@ -36,6 +36,8 @@
#include "G4ConversionFatalError.hh"
#include "G4ConversionUtils.hh"
#include <utility>
namespace {
// Helper classes
@@ -168,8 +170,7 @@ G4AttValueFilterT<T, ConversionErrorPolicy>::LoadIntervalElement(const G4String&
if (!G4ConversionUtils::Convert(input, min, max)) ConversionErrorPolicy::ReportError(input, "Invalid format. Was the input data formatted correctly ?");
std::pair<T, T> myPair(min, max);
fIntervalMap[input] = myPair;
fIntervalMap[input] = std::pair<T, T> (min, max);
}
template <typename T, typename ConversionErrorPolicy>
@@ -180,7 +181,7 @@ G4AttValueFilterT<T, ConversionErrorPolicy>::LoadSingleValueElement(const G4Stri
if (!G4ConversionUtils::Convert(input, output)) ConversionErrorPolicy::ReportError(input, "Invalid format. Was the input data formatted correctly ?");
fSingleValueMap[input] = output;
fSingleValueMap[input] = std::move(output);
}
template <typename T, typename ConversionErrorPolicy>
@@ -37,7 +37,9 @@
#include "G4AttValue.hh"
#include "G4SmartFilter.hh"
#include "G4VAttValueFilter.hh"
#include <vector>
#include <utility>
template <typename T>
class G4AttributeFilterT : public G4SmartFilter<T> {
@@ -208,7 +210,7 @@ G4AttributeFilterT<T>::AddInterval(const G4String& interval)
return;
}
fConfigVect.push_back(myPair);
fConfigVect.push_back(std::move(myPair));
}
template <typename T>
@@ -226,7 +228,7 @@ G4AttributeFilterT<T>::AddValue(const G4String& value)
("G4AttributeFilterT::AddValue", "modeling0105", JustWarning, ed);
return;
}
fConfigVect.push_back(myPair);
fConfigVect.push_back(std::move(myPair));
}
#endif
@@ -86,7 +86,7 @@ public: // With description
class PVNameCopyNo {
public:
// Normal constructor
PVNameCopyNo(G4String name, G4int copyNo)
PVNameCopyNo(const G4String& name, G4int copyNo)
: fName(name), fCopyNo(copyNo) {}
const G4String& GetName() const {return fName;}
G4int GetCopyNo() const {return fCopyNo;}
@@ -61,13 +61,11 @@ public:
G4VPhysicalVolume* pFoundPV,
G4int foundPVCopyNo = 0,
G4int foundDepth = 0,
std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>
foundBasePVPath =
std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>(),
std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>
foundFullPVPath =
std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>(),
G4Transform3D foundObjectTransformation = G4Transform3D())
const std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>&
foundBasePVPath = std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>(),
const std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>&
foundFullPVPath = std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>(),
const G4Transform3D& foundObjectTransformation = G4Transform3D())
: fpSearchPV(pSearchPV)
, fpFoundPV(pFoundPV)
, fFoundPVCopyNo(foundPVCopyNo)
@@ -305,18 +305,18 @@ void G4PhysicalVolumeModel::VisitGeometryAndGetVisReps
G4VPVParameterisation* pP = pVPV -> GetParameterisation ();
if (pP) { // Parametrised volume.
for (int n = nBegin; n < nEnd; n++) {
pSol = pP -> ComputeSolid (n, pVPV);
pP -> ComputeTransformation (n, pVPV);
pSol -> ComputeDimensions (pP, n, pVPV);
pVPV -> SetCopyNo (n);
pSol = pP -> ComputeSolid (n, pVPV);
pP -> ComputeTransformation (n, pVPV);
pSol -> ComputeDimensions (pP, n, pVPV);
pVPV -> SetCopyNo (n);
fCurrentPVCopyNo = n;
// Create a touchable of current parent for ComputeMaterial.
// fFullPVPath has not been updated yet so at this point it
// corresponds to the parent.
G4PhysicalVolumeModelTouchable parentTouchable(fFullPVPath);
pMaterial = pP -> ComputeMaterial (n, pVPV, &parentTouchable);
DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
theAT, sceneHandler);
// Create a touchable of current parent for ComputeMaterial.
// fFullPVPath has not been updated yet so at this point it
// corresponds to the parent.
G4PhysicalVolumeModelTouchable parentTouchable(fFullPVPath);
pMaterial = pP -> ComputeMaterial (n, pVPV, &parentTouchable);
DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
theAT, sceneHandler);
}
}
else { // Plain replicated volume. From geometry_guide.txt...
@@ -347,64 +347,64 @@ void G4PhysicalVolumeModel::VisitGeometryAndGetVisReps
G4RotationMatrix* pOriginalRotation = pVPV -> GetRotation ();
G4double originalRMin = 0., originalRMax = 0.;
if (axis == kRho && pSol->GetEntityType() == "G4Tubs") {
originalRMin = ((G4Tubs*)pSol)->GetInnerRadius();
originalRMax = ((G4Tubs*)pSol)->GetOuterRadius();
originalRMin = ((G4Tubs*)pSol)->GetInnerRadius();
originalRMax = ((G4Tubs*)pSol)->GetOuterRadius();
}
G4bool visualisable = true;
for (int n = nBegin; n < nEnd; n++) {
G4ThreeVector translation; // Identity.
G4RotationMatrix rotation; // Identity - life enough for visualizing.
G4RotationMatrix* pRotation = 0;
switch (axis) {
default:
case kXAxis:
translation = G4ThreeVector (-width*(nReplicas-1)*0.5+n*width,0,0);
break;
case kYAxis:
translation = G4ThreeVector (0,-width*(nReplicas-1)*0.5+n*width,0);
break;
case kZAxis:
translation = G4ThreeVector (0,0,-width*(nReplicas-1)*0.5+n*width);
break;
case kRho:
if (pSol->GetEntityType() == "G4Tubs") {
((G4Tubs*)pSol)->SetInnerRadius(width*n+offset);
((G4Tubs*)pSol)->SetOuterRadius(width*(n+1)+offset);
} else {
if (fpMP->IsWarning())
G4warn <<
"G4PhysicalVolumeModel::VisitGeometryAndGetVisReps: WARNING:"
"\n built-in replicated volumes replicated in radius for "
<< pSol->GetEntityType() <<
"-type\n solids (your solid \""
<< pSol->GetName() <<
"\") are not visualisable."
<< G4endl;
visualisable = false;
}
break;
case kPhi:
rotation.rotateZ (-(offset+(n+0.5)*width));
// Minus Sign because for the physical volume we need the
// coordinate system rotation.
pRotation = &rotation;
break;
}
pVPV -> SetTranslation (translation);
pVPV -> SetRotation (pRotation);
pVPV -> SetCopyNo (n);
G4ThreeVector translation; // Identity.
G4RotationMatrix rotation; // Identity - life enough for visualizing.
G4RotationMatrix* pRotation = 0;
switch (axis) {
default:
case kXAxis:
translation = G4ThreeVector (-width*(nReplicas-1)*0.5+n*width,0,0);
break;
case kYAxis:
translation = G4ThreeVector (0,-width*(nReplicas-1)*0.5+n*width,0);
break;
case kZAxis:
translation = G4ThreeVector (0,0,-width*(nReplicas-1)*0.5+n*width);
break;
case kRho:
if (pSol->GetEntityType() == "G4Tubs") {
((G4Tubs*)pSol)->SetInnerRadius(width*n+offset);
((G4Tubs*)pSol)->SetOuterRadius(width*(n+1)+offset);
} else {
if (fpMP->IsWarning())
G4warn <<
"G4PhysicalVolumeModel::VisitGeometryAndGetVisReps: WARNING:"
"\n built-in replicated volumes replicated in radius for "
<< pSol->GetEntityType() <<
"-type\n solids (your solid \""
<< pSol->GetName() <<
"\") are not visualisable."
<< G4endl;
visualisable = false;
}
break;
case kPhi:
rotation.rotateZ (-(offset+(n+0.5)*width));
// Minus Sign because for the physical volume we need the
// coordinate system rotation.
pRotation = &rotation;
break;
}
pVPV -> SetTranslation (translation);
pVPV -> SetRotation (pRotation);
pVPV -> SetCopyNo (n);
fCurrentPVCopyNo = n;
if (visualisable) {
DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
theAT, sceneHandler);
}
if (visualisable) {
DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
theAT, sceneHandler);
}
}
// Restore originals...
pVPV -> SetTranslation (originalTranslation);
pVPV -> SetRotation (pOriginalRotation);
if (axis == kRho && pSol->GetEntityType() == "G4Tubs") {
((G4Tubs*)pSol)->SetInnerRadius(originalRMin);
((G4Tubs*)pSol)->SetOuterRadius(originalRMax);
((G4Tubs*)pSol)->SetInnerRadius(originalRMin);
((G4Tubs*)pSol)->SetOuterRadius(originalRMax);
}
}
}
@@ -32,8 +32,8 @@
#include "G4VTrajectory.hh"
#include "G4VisTrajContext.hh"
#include "G4VTrajectoryPoint.hh"
#include "G4AttDef.hh"
#include "G4AttValue.hh"
#include "G4RichTrajectory.hh"
G4TrajectoryDrawByEncounteredVolume::G4TrajectoryDrawByEncounteredVolume
(const G4String& name, G4VisTrajContext* context)
@@ -46,9 +46,12 @@ G4TrajectoryDrawByEncounteredVolume::~G4TrajectoryDrawByEncounteredVolume() {}
void
G4TrajectoryDrawByEncounteredVolume::Draw(const G4VTrajectory& traj, const G4bool& /*visible*/) const
{
try
{
const G4RichTrajectory& richTrajectory = dynamic_cast<const G4RichTrajectory&>(traj);
// Check the required G4Att exists
const auto& aPointAttDefs = traj.GetPoint(0)->GetAttDefs();
if (aPointAttDefs->find("PostVPath") != aPointAttDefs->end()) {
// Must be a rich trajectory
const auto& richTrajectory = traj;
G4Colour colour(fDefault);
G4String soughtPVName("none");
@@ -82,20 +85,18 @@ G4TrajectoryDrawByEncounteredVolume::Draw(const G4VTrajectory& traj, const G4boo
<< ", with configuration:" << G4endl;
myContext.Print(G4cout);
}
G4TrajectoryDrawerUtils::DrawLineAndPoints(richTrajectory, myContext);
}
catch (const std::bad_cast&)
{
G4TrajectoryDrawerUtils::DrawLineAndPoints(richTrajectory, myContext);
} else {
G4ExceptionDescription ed;
ed << "Requires G4RichTrajectory - \"/vis/scene/add/trajectories rich\"";
G4Exception
("G4TrajectoryDrawByEncounteredVolume::Draw(const G4VTrajectory& traj,...",
"modeling0125",
JustWarning, ed);
return;
}
}
@@ -38,6 +38,8 @@
#include "G4UIcommand.hh"
#include "G4AttValue.hh"
#include <utility>
#define G4warn G4cout
namespace G4TrajectoryDrawerUtils {
@@ -203,8 +205,8 @@ namespace G4TrajectoryDrawerUtils {
}
}
trajectoryLine = newTrajectoryLine;
trajectoryLineTimes = newTrajectoryLineTimes;
trajectoryLine = std::move(newTrajectoryLine);
trajectoryLineTimes = std::move(newTrajectoryLineTimes);
}
static void DrawWithoutTime(const G4VisTrajContext& myContext,
@@ -32,8 +32,8 @@
#include "G4TrajectoryEncounteredVolumeFilter.hh"
#include "G4TransportationManager.hh"
#include "G4VTrajectoryPoint.hh"
#include "G4AttDef.hh"
#include "G4AttValue.hh"
#include "G4RichTrajectory.hh"
G4TrajectoryEncounteredVolumeFilter::G4TrajectoryEncounteredVolumeFilter(const G4String& name)
:G4SmartFilter<G4VTrajectory>(name)
@@ -44,10 +44,13 @@ G4TrajectoryEncounteredVolumeFilter::~G4TrajectoryEncounteredVolumeFilter() {}
bool
G4TrajectoryEncounteredVolumeFilter::Evaluate(const G4VTrajectory& traj) const
{
try
{
const G4RichTrajectory& richTrajectory = dynamic_cast<const G4RichTrajectory&>(traj);
// Check the required G4Att exists
const auto& aPointAttDefs = traj.GetPoint(0)->GetAttDefs();
if (aPointAttDefs->find("PostVPath") != aPointAttDefs->end()) {
// Must be a rich trajectory
const auto& richTrajectory = traj;
for (const auto& pvname: fVolumes) {
for (G4int iPoint = 0; iPoint < richTrajectory.GetPointEntries(); iPoint++) {
G4VTrajectoryPoint* point = richTrajectory.GetPoint(iPoint);
@@ -64,10 +67,9 @@ G4TrajectoryEncounteredVolumeFilter::Evaluate(const G4VTrajectory& traj) const
}
}
return false;
}
catch (const std::bad_cast&)
{
} else {
G4ExceptionDescription ed;
ed << "Requires G4RichTrajectory - \"/vis/scene/add/trajectories rich\"";
G4Exception
@@ -75,6 +77,7 @@ G4TrajectoryEncounteredVolumeFilter::Evaluate(const G4VTrajectory& traj) const
"modeling0126",
JustWarning, ed);
return false;
}
}