2.12.  Visualisation

2.12.1.  Design Philosophy

The visualisation category consists of the classes required to display detector geometry, particle trajectories, tracking steps, and hits. It also provides visualisation drivers, which are interfaces to external graphics systems.

A wide variety of user requirements went into the design of the visualisation category, for example:

  • very quick response in surveying successive events,
  • high-quality output for presentation and documentation,
  • flexible camera control for debugging detector geometry and physics,
  • selection of visualisable objects,
  • interactive picking of graphical objects for attribute editing or feedback to the associated data,
  • highlighting incorrect intersections of physical volumes,
  • co-working with graphical user interfaces.

Because it is very difficult to respond to all of these requirements with only one built-in visualiser, an abstract interface was developed which supports several complementary graphics systems. Here the term graphics system means either an application running as a process independent of Geant4 or a graphics library to be compiled with Geant4. A concrete implementation of the interface is called a visualisation driver, which can use a graphics library directly, communicate with an independent process via pipe or socket, or simply write an intermediate file for a separate viewer.

2.12.2.  The Graphics Interfaces

  • G4VVisManager: All user code writes to the graphics systems through this pure abstract interface. It contains Draw methods for all the graphics primitives in the graphics_reps category (G4Polyline, G4Circle, etc.), geometry objects (through their base classes, G4VSolid, G4PhysicalVolume and G4LogicalVolume) and hits and trajectories (through their base classes, G4VHit and G4VTrajectory).

    Since this is an abstract interface, all user code must check that there exists a concrete instantiation of it. A static method is provided, so a typical user code fragment is:

      G4VVisManager* pVVisManager = G4VVisManager::GetConcreteInstance();
      if(pVVisManager) {
        pVVisManager->Draw(G4Circle...
        ...
        

    Note that this allows the building an application without a concrete implementation, for example for a batch job, even if some code, like the above, is still included. Most of the novice examples can be built this way if G4VIS_NONE is specified.

    The concrete implementation of this interface is hereafter referred to as the visualisation manager.

  • G4VGraphicsScene: The visualisation manager must also provide a concrete implementation of the subsidiary interface, G4VGraphicsScene. It is only for use by the kernel and the modeling category. It offers direct access to a ``scene handler'' through a reference provided by the visualisation manager. It is described in more detail in the section on extending the toolkit functionality.

The Geant4 distribution includes implementations of the above interfaces, namely G4VisManager and G4VSceneHandler respectively, and their associated classes. These define further abstract base classes for visualisation drivers. Together they form the Geant4 Visualisation System. A variety of concrete visualisation drivers are also included in the distribution. Details of how to implement a visualisation driver are given in Section 3.7. Of course, it is always possible for a user to implement his or her own concrete implementations of G4VVisManager and G4VGraphicsScene replacing the Geant4 Visualisation System altogether.

2.12.3.  The Geant4 Visualisation System

The Geant4 Visualisation System consists of

  • G4VisManager: An implementation of the G4VVisManager interface. It manages multiple graphics systems and defines three more concepts -- the scene (G4Scene), the scene handler (base class G4VSceneHandler, itself a sub-class of G4VGraphicsScene) and the viewer (base class G4VViewer) -- see below. G4VisManager is a singleton and an abstract class, requiring the user to derive from it a concrete visualisation manager (G4VisExecutive is provided -- see below). Roles and structure of the visualisation manager are described in Chapter 8 of the User's Guide for Application Developers.

  • G4VisExecutive: A concrete visualisation manager that implements the virtual functions RegisterGraphicsSystems and RegisterModelFactories. These functions must be in the users' domain, since the graphics systems and models that are instantiated by them are, in many cases, provided by the user (graphics libraries, etc.). It is therefore implemented as a .hh-.icc combination that is designed to be included in the users' code. Of course, the user may write his or her own.

  • G4Scene The scene is a list if models for physical volumes, axes, hits, trajectories, etc. - see Section Section 2.12.4. They are distinguished according to their lifetime -- ``run-duration'' for physical volumes, etc., ``end-of-event'' for hits and trajectories, etc. The end-of-event models are only to be used when the Geant4 state indicates the end of event has been reached. The scene has an extent (G4VisExtent), which is updated by the scene when a new model is added (each model itself has an extent), and a ``standard'' target point; these are used to define the standard view -- see below. In addition, the scene keeps flags which indicate whether end-of-event objects should be accumulated or refreshed for each event or run.

  • G4VGraphicsSystem: This is an abstract base class for scene handler and viewer factories. It is used by the visualisation manager to create scene handlers and viewers on request.

  • G4VSceneHandler: A sub-class of G4VGraphicsScene, itself an abstract base class for specific scene handlers, whose job is to convert the scene into graphics-system-specific code for the viewer. For example, the scene handler may create a graphical database, taking care to separate run-duration (persistent) and end-of-event (transient) information (this is described further in Section 3.7.1.6.

  • G4VViewer: An abstract base class for specific viewers. Its job is to create windows or files and identify where and how the final view should be rendered. It has view parameters (G4ViewParameters) which specify viewpoint direction, type of rendering (wireframe or surface), etc. It is the view's responsibility, noting the scene's extent and target point, to choose a camera position and magnification that ensures that the scene is automatically and comfortably rendered in the viewing window. This is then the standard view, and any further operations requested by the user - zoom, pan, etc. - are relative to this standard view. The class G4ViewParameters has utility routines to assist this procedure; it is strongly advised that toolkit developers writing a viewer should study the G4ViewParameters class, whose header file contains much useful information (also preserved in the Software Reference Manual).

    The viewer is messaged by the vis manager when the user issues commands, such as /vis/viewer/refresh. This invokes methods such as SetView, ClearView and DrawView. A detailed description of the call sequences is given in Section 3.7.1.2- Section 3.7.1.5.

Note there is no restriction on the number or type of scene handlers or viewers. There may be several scene handlers processing the same or different scenes, each with several viewers (for example, the same scene from differing viewpoints).

By defining a set of three C++ classes inheriting from the virtual base classes - G4VGraphicsSystem, G4VSceneHandler and G4VViewer - an arbitrary graphics system can easily be plugged in to Geant4. The plugged-in graphics system is then available for visualising detector simulations. Together, this set of three concrete classes is called a "visualisation driver". The DAWN-File driver, for example, is the interface to the Fukui Renderer DAWN, and is implemented by the following set of classes:

  1. G4DAWNFILE : public G4VGraphicsSystem for creation of the scene handlers and viewers
  2. G4DAWNFILESceneHandler : public G4VSceneHandler for modeling 3D scenes
  3. G4DAWNFILEView : public G4VView for rendering 3D scenes

Several visualisation drivers are distributed with Geant4. They are complementary to each other in many aspects. For details, see Chapter 8 of the User's Guide for Application Developers.

2.12.4.  Modeling sub-category

  • G4VModel - a base class for visualisation models. A model is a graphics-system-independent description of a Geant4 component.

    The sub-category visualisation/modeling defines how to model a 3D scene for visualisation. The term "3D scene" indicates a set of visualisable component objects put in a 3D world. A concrete class inheriting from the abstract base class G4VModel defines a "model", which describes how to visualise the corresponding component object belonging to a 3D scene. G4ModelingParameters defines various associated parameters.

    For example, G4PhysicalVolumeModel knows how to visualise a physical volume. It describes a physical volume and its daughters to any desired depth. G4HitsModel knows how to visualise hits. G4TrajectoriesModel knows how to visualise trajectories.

    The main task of a model is to describe itself to a 3D scene by giving a concrete implementation of the following virtual method of G4VModel:

        virtual void DescribeYourselfTo (G4VGraphicsScene&) = 0;
        

    The argument class G4VGraphicsScene is a minimal abstract interface of a 3D scene for the Geant4 kernel defined in the graphics_reps category. Since G4VSceneHandler and its concrete descendants inherit from G4VGraphicsScene, the method DescribeYourselfTo() can pass information of a 3D scene to a visualisation driver.

    It is easy for a toolkit developer of Geant4 to add a new kind of visualisable component object. It is done by implementing a new class inheriting from G4VModel.

  • G4VTrajectoryModel - an abstract base class for trajectory drawing models.

    A trajectory model governs how an individual trajectory is drawn. Concrete models inheriting from G4VTrajectoryModel must implement two pure virtual functions:

        virtual void Draw(const G4VTrajectory&, G4int i_mode = 0) const = 0;
        virtual void Print(std::ostream& ostr) const = 0;
        

    See for example G4TrajectoryDrawByParticleID.

  • G4VModelFactory - an abstract base class for factories creating models and associated messengers.

    It is not necessary to generate messengers for a trajectory model that will be constructed and configured directly in compiled code. If the user requires model creation and configuration features through interactive commands, however, there must be a mechanism to generate both models and their associated messengers. This is the role of G4VModelFactory. Concrete factories inheriting from G4VModelFactory are responsible for creating a concrete model and concrete messengers. To help ensure a type safe messenger to model interaction on the command line, the messengers should inherit from G4VModelCommand.

    Concrete factories must implement one pure virtual function:

        virtual ModelAndMessengers 
        Create(const G4String& placement, const G4String& modelName) = 0;
        

    where placement indicates which directory space the commands should occupy. See for example G4TrajectoryDrawByParticleIDFactory.

2.12.5.  View parameters

View parameters such as camera parameters, drawing styles (wireframe/surface etc) are held by G4ViewParameters. Each viewer holds a view parameters object which can be changed interactively and a default object (for use in the /vis/viewer/reset command).

If a toolkit developer of Geant4 wants to add entries of view parameters, he should add fields and methods to G4ViewParameters.

2.12.6.  Visualisation Attributes

All drawable objects (should) have a method:

  const G4VisAttributes* GetVisAttributes() const;

A drawable object might be:

  • a "visible" (i.e., inheriting G4Visible), such as a polyhedron, polyline, circle, etc. (note that text is a slightly special case - see below) or
  • a solid whose vis attributes are held in its logical volume.

2.12.6.1.  Finding the applicable vis attributes

This is an issue for all scene handlers. The scene handler is where the colour, style, auxiliary edge visibility, marker size, etc., of individual drawable objects are needed.

2.12.6.1.1.  Visibles

If the vis attributes pointer is zero, drivers should pick up the default vis attributes from the viewer:

  const G4VisAttributes* pVisAtts = visible.GetVisAttributes();
  if (!pVisAtts) 
    pVisAtts = fpViewer->GetViewParameters().GetDefaultVisAttributes();

where visible denotes any visible object (polyhedron, circle, etc.).

There is a utility function G4VViewer::GetApplicableVisAttributes which does this, so an alternative is:

  const G4VisAttributes* pVisAtts =
    fpViewer->GetApplicableVisAttributes(visible.GetVisAttributes());

Confusingly, there is a utility function G4VSceneHandler::GetColour which also does this, so if it's only colour you need, the following suffices:

  const G4Colour& colour GetColour(visible);

but equally well:

  const G4VisAttributes* pVisAtts =
    fpViewer->GetApplicableVisAttributes(visible.GetVisAttributes());
  const G4Colour& colour pVisAtts->GetColour();

or even:

  const G4VisAttributes* pVisAtts = visible.GetVisAttributes();
  if (!pVisAtts) 
    pVisAtts = fpViewer->GetViewParameters().GetDefaultVisAttributes();
  const G4Colour& colour pVisAtts->GetColour();

2.12.6.1.2.  Text

Text is a special case because it has its own default vis attributes:

  const G4VisAttributes* pVisAtts = text.GetVisAttributes();
  if (!pVisAtts) 
    pVisAtts = fpViewer->GetViewParameters().GetDefaultTextVisAttributes();
  const G4Colour& colour pVisAtts->GetColour();

and there is a utility function G4VSceneHandler::GetTextColour:

  const G4Colour& colour GetTextColour(text);

2.12.6.1.3.  Solids

For specific solids, the G4PhysicalVolumeModel that provides the solids also provides, via PreAddSolid, a pointer to its vis attributes. If the vis attribites pointer in the logical volume is zero, it provides a pointer to the default vis attributes in the model, which in turn is (currently) provided by the viewer's vis attributes (see G4VSceneHandler::CreateModelingParameters). So the vis attributes pointer is guaranteed to be pertinent.

If the concrete driver does not implement AddSolid for any particular solid, the base class converts it to primitives (usually a G4Polyhedron) and again, the vis attributes pointer is guaranteed.

2.12.6.1.4.  Drawing style

The drawing style is normally determined by the view parameters but for individual drawable objects it may be overridden by the forced drawing style flags in the vis attributes. A utility function G4ViewParameters::DrawingStyle G4VSceneHandler::GetDrawingStyle is provided:

  G4ViewParameters::DrawingStyle drawing_style = GetDrawingStyle(pVisAtts);

2.12.6.1.5.  Auxiliary edges

Similarly, the visibility of auxiliary/soft edges is normally determined by the view parameters but may be overridden by the forced auxiliary edge visible flag in the vis attributes. Again, a utility function G4VSceneHandler::GetAuxEdgeVisible is provided:

  G4bool isAuxEdgeVisible = GetAuxEdgeVisible (pVisAtts);

2.12.6.1.6.  LineSegmentsPerCircle

Also, the precision of rendering curved edges in the polyhedral representation of volumes is normally determined by the view parameters but may be overridden by a forced attribute. A utility function that respects this, G4VSceneHandler::GetNoOfSides, is provided. For example:

  G4Polyhedron::SetNumberOfRotationSteps (GetNoOfSides (pVisAttribs));

2.12.6.1.7.  Marker size

These have nothing to do with vis attributes; they are an extra property of markers, i.e., objects that inherit G4VMarker (circles, squares, text, etc.). However, the algorithm for the actual size is quite complicated and a utility function G4VSceneHandler::GetMarkerSize is provided:

  MarkerSizeType sizeType;
  G4double size = GetMarkerSize (text, sizeType);

sizeType is world or screen, signifying that the size is in world coordinates or screen coordinates respectively.