Appendix B: Extending GAMOS functionality with C++ utilities

Converting a Geant4 example into a GAMOS example

Converting a Geant4 example into a GAMOS examples usually requires only adding a few lines to transform the different simulation components into plug-in’s. In examples/N02 you can see the official Geant4 example novice/N02 transformed into a GAMOS example. We will use it to illustrate the procedure to follow.

The first thing to do is to substitute the Geant4 GNUmakefile by a GAMOS GNUmakefile. You can use the file in this example for any other example you want to transform, just substitute the line

name := exampleN02

by the name of your example (indeed you can use any name you want, it will be automatically detected by GAMOS).

Then you have to add a file, that we called src/plugin.cc where all the plug-in’s are created. The first line of this file (after the corresponding ‘includes’), must be

#include “Reflex/PluginService.h”

For the detector construction it is only needed to add a line (plus the corresponding include files)

PLUGINSVC_FACTORY (ExN02DetectorConstruction,G4VUserDetectorConstruction*())

For the physics, in a similar way, we add

PLUGINSVC_FACTORY(ExN02PhysicsList,G4VUserPhysicsList*());

The primary generator requires some more changes. As you can see ExN02PrimaryGeneratorAction constructor receives as argument the detector construction class, so that it can then ask it for the dimensions of the world. This is not needed in GAMOS because all volumes are available in any class through the singleton class GmGeometryUtils. Therefore we have deleted the detector construction argument in the constructor, and then we have substituted the line

G4double position = -0.5*(myDetector->GetWorldFullLength());

by this one

G4Box* worldBox = (G4Box*)(GmGeometryUtils::GetInstance()->
GetLogicalVolumes("World")[0]->GetSolid());

G4double position = -0.5*worldBox->GetXHalfLength();

After this in the src/module.cc a line has to be included

PLUGINSVC_FACTORY (ExN02PrimaryGeneratorAction,G4VUserPrimaryGeneratorAction*());

For the user actions, we have first to transform then into GAMOS user actions, what requires simply to edit the .hh classes and make them inherit from GmUserXXXAction, instead of G4UserXXXAction. Then we have to add the following lines in module.cc

PLUGINSVC_FACTORY(ExN02RunAction,GmUserAction*());

PLUGINSVC_FACTORY(ExN02EventAction,GmUserAction*());

PLUGINSVC_FACTORY(ExN02SteppingAction,GmUserAction*());

It is not needed to converr the sensitive detector into a plug-in, that could be called in the user command file, because it is explicitly called in the detector construction class. Indeed, if you want to do it, you should delete the lines that instantiate it there and then you can write

PLUGINSVC_FACTORY(ExN02TrackerSD,G4VSensitiveDetector*(G4String));

The main class, exampleN02.cc is not needed any more. We use the GAMOS main and a user command file, that we may exampleN02_GAMOS.in, with the user commands that select the example components, like the following one:

/gamos/geometry ExN02DetectorConstruction
/gamos/physicsList ExN02PhysicsList
/gamos/generator ExN02PrimaryGeneratorAction
/gamos/userAction ExN02RunAction
/gamos/userAction ExN02EventAction
/gamos/userAction ExN02SteppingAction
/run/initialize
/run/beamOn 10

You can then run gamos exampleN02_GAMOS.in and you will get the same results as if you run the original Geant4 example.

Creating your plug-in

There are several ``factories’’ in GAMOS that take care of the different plug-in types. To transform your class into a plug-in you have to follow the instructions in this section, using the relevant ``factory’’ and class as indicated in the relevant section of this guide (e.g. GmPhysicsFactory and G4VUserPhysicsList for a geometry plug-in, GmVerbosityFactory and GmVerbosityMgr for a verbosity plug-in, etc.

To write a new plug-in of any type follow these steps

  1. Create your class or use one of the existing Geant4 classes. This class should inherit from the corresponding Geant4 or GAMOS class: - G4VUserDetectorConstruction: geometry - G4VUserPhysicsList: physics list - G4VUserPrimaryGeneratorAction: primary generator - GmVGenerDistPosition: primary particles position distribution - GmVGenerDistDirection: primary particles direction distribution - GmVGenerDistEnergy: primary particles energy distribution - GmVGenerDistTime: primary particles time distribution - GmVUserXXXAction: user action (XXX can be Run, Event, Tracking, Stepping or Stacking) - G4VSensitiveDetector: sensitive detector - GmVDigitizer: hits digitizer - GmVRecHitBuilder: reconstructed hits builder - GmVPrimitiveScorer: scorer - GmVPSPrinter: scorer printer - GmVFilter: filter - GmVClassifier: classifier - GmVVerbosityMgr: verbosity If you are creating a new class you can use as example one of the classes at directory examples/PlugInTemplates, that are nearly-empty classes that contain the necessary methods that you have to implement for each plug-in type. .. COMMENT: %\item {\bf GmGeometryFactory, GmPhysicsFactory, GmGeneratorFactory, GmGenerDistEnergyFactory, GmGenerDistTimeFactory, GmGenerDistPositionFactory, GmGenerDistDirectionFactory, GmUserActionFactory, GmSensDetFactory, GmDigitizerFactory, GmRecHitBuilderFactory, GmPrimitiveScorerFactory, GmFilterFactory, GmClassifierFactory, GmPSPrinterFactory and GmVerbosityFactory}

  2. Include the ROOT plug-in module definition:

    #include "Reflex/PluginService.h"
    

    Then you simply you have to create a plugin writing which is the base class, for example, if it is a geometry (detector construction in Geant4’s terminology

    PLUGINSVC_FACTORY (MY_GEOMETRY,G4VUserDetectorConstruction*())
    

    And the plug-in name will be the same as your class name

  3. Once this is done, you can select your geometry with the command: /gamos/xxx MY_GEOMETRY

NOTE: If you are creating a plug-in in a new directory you have created, you have to be sure to have the ``plugin’’ option in the GNUmakefile, as explained in the section Compiling your new code.

Using a parameter in your C++ code

We describe in this section how to create and use a new parameter if you are creating a new C++ class.

GAMOS provides an utility that allows you to change the value of a parameter in the input file, together with the line commands, and use it in any of your classes (even in several of them). There are four classes of parameters: numbers, string, list of numbers, list of strings.

To change the value of a parameter (of any of the four types) in your input file, you have to use the command

/gamos/setParam MY_PARAM_NAME MY_PARAM_VALUE(S)

Then you can use this parameter in your class with a line like this:

G4double value  = GmParameterMgr::GetInstance()->
GetNumericValue("MY_PARAM_NAME",DEFAULT_VALUE);

if it is a number, or

G4String value = GmParameterMgr::GetInstance()->
GetStringValue("MY_PARAM_NAME","DEFAULT_VALUE");

if it is a string, or

std::vector < G4double > vdefault;
std::vector < G4double > values  = GmParameterMgr::GetInstance()->
GetVNumericValue("MY_PARAM_NAME",vdefault);

if it is a list of numbers, or

std::vector < G4String > vdefault;
std::vector < G4String > values = GmParameterMgr::GetInstance()->
GetVStringValue("MY_PARAM_NAME",vdefault);

if it is a list of strings.

Event classification by interaction types

There is a utility in GAMOS that helps you in counting and classifying the tracks by the type of interactions they have suffered. You just have to create at each step a new GmTrajPoint and at the end of track pass this list to a GmVSimuEventClassifier that will return the classification.

You can see an example at GamosCore/GamosAnalysis/src/GmHistosGammaAtSD.cc, that we explain here in detail:

This class counts the type of interaction of the photons in the sensitive detectors of your geometry.

The first thing it does, at the PreUserTrackingAction is checking if the current track is an ‘original’ gamma. To do this it gets the help of the GmCheckOriginalGamma class, that classifies the gammas as

  • 0: not an ‘original’ gamma

  • 1: it is a primary particle, created at the beginning of the event

  • 2: is is created at the annihilation of the positron (it is assumed that the positron is a primary particle)

At each step, the UserSteppingAction method checks that it is inside a volume declared as sensitive detector. In this case, it adds a new GmTrajPoint for this track, with all the information of the track at this moment (plus it adds at the beginning another point with the vertex information).

At the end of track, if it is an original gamma, it asks the class GmClassifierByInteraction to classify it based on the type and number of interactions. The method Classify() of this class returns an integer with the meaning: 100*100 Number of LowEnPhotoElec interactions + 100 * Number of LowEnCompton interactions + Number of LowEnRayleigh interactions*.

See PET section for more details on the concrete class GmHistosGammaAtSD.

Structure of GAMOS

Although the origin of GAMOS is the medical physics field, the latest additions, specially the many utilities to extract detail information of many types, make it likely that you can profit from GAMOS to do your simulation in other field of physics, as already several people are doing.

Although you will not need to know anything about the C++ code, unless you want to develop new code for GAMOS, we explain here how the GAMOS source code is organized in the subsystems, each one subdivided in the packages:

  • GamosCore: core software covering main Geant4 functionality - GamosBase

    • Base: parameter manager, analysis manager, CSV histograms and other basic functionalities

    • Filters: filters

    • Classifiers: classifiers

    • GamosGeometry: geometry-related utilities and support for text detector description

    • GamosMovement: support for displacements, rotations or general movements of volumes during a job

    • GamosSD: classes for sensitive detectors, hits and digitization

    • GamosGenerator: utilities to support single particle and isotope source generators as well as different initial particle distributions

    • GamosPhysics - PhysicsList: example of

      electromagnetic physics list, supporting standard, low-energy and Penelope classes, and example of hadronic physics list (meant for hadrontherapy)

      • OtherPhysicsLists: other examples of electromagnetic and hadronic physics lists

      • Cuts: management of production cuts and user limits, including tools to automatically optimise them

      • VarianceReduction: implementation of several variance reduction techniques

    • GamosUserActionMgr: user action management, to allow several user actions of the same type, selectable by user commands

    • GamosScoring: scoring manager and messenger and examples of scoring plug-in classes (scorers, filters and printers) - Management: scoring manager and messenger and base class for scorer and scorer printers - Scorers: scorers - Printers: scorer printers - PointDector: point detector scoring

    • GamosData - Management: data management and base data classes - Data: data - Users: data users

    • GamosAnalysis: utilities that can help the advanced user to analyse results

    • GamosReadDICOM: code to read in DICOM files containing patient data

    • GamosUtilsUA: user action utilities (tracking verbosity control, track counting, process counting, time study, …)

    • GamosUtils: general C++ utilities

    • <listitem> <para><emphasis>GamosVisIguana</emphasis>: support of IGUANA visualisation</para> </listitem>

    • GamosApplication: GAMOS run manager and the ``main’’ program

  • %CITACA \item {\bf Itaca}: example of ITACA simulation %CITACA \begin{itemize} %CITACA \item {\bf ItacaGeometry}: ITACA geometry %CITACA \item {\bf ItacaAnalysis}: ITACA histograms and ITACA event classifier %CITACA \end{itemize}

  • PET: example of PET simulation - PETGeometry: example to simulate the

    most common PET devices by defining its properties in a few-lines text file

    • PETAnalysis: PET event classifier and PET histograms

  • RadioTherapy: example of radiotherapy simulation, including writing and reading phase space files

Each package has the following subdirectories:

  • src: the source code

  • include: the header files

You do not need to follow this file distribution if you want to create a new package, but we recommend you to do so.