diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1ef999d..b022039 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,6 +8,7 @@ repos: rev: v5.0.0 hooks: - id: check-added-large-files + args: ['--maxkb=600'] - id: check-case-conflict - id: check-executables-have-shebangs - id: check-merge-conflict diff --git a/README.md b/README.md index dd400bb..1450578 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,6 @@ setup (supported specification languages are C++, GDML and more). The user can then benefit from a predefined set of tools to perform common actions (physics generators, standard output classes, etc). -> [!WARNING] -> *remage* is still under heavy development. Users are advised to use a tagged -> release for any workloads unrelated to remage development, if possible. - ### Main features * Support for modern [Geant4](https://geant4.web.cern.ch), including diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 0209dc3..803db3c 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -34,9 +34,26 @@ set(SPHINX_SOURCE ${CMAKE_CURRENT_BINARY_DIR}) set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/_build) set(SPHINX_INDEX_FILE ${SPHINX_BUILD}/index.html) -set(SPHINX_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/index.rst) +# FIXME: the logic here to handle sources is not really clean, needs some more +# serious thought! one important requirement is CMake being able to copy the +# sources again if they change +file( + GLOB SPHINX_SOURCES + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + *.rst *.md) + foreach(_file ${SPHINX_SOURCES}) - configure_file(${_file} ${SPHINX_SOURCE} COPYONLY) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${_file} ${SPHINX_SOURCE} COPYONLY) +endforeach() + +file( + GLOB SPHINX_IMAGES + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + img/*) + +file(MAKE_DIRECTORY ${SPHINX_SOURCE}/img) +foreach(_file ${SPHINX_IMAGES}) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${_file} ${SPHINX_SOURCE}/img COPYONLY) endforeach() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in ${SPHINX_SOURCE}/conf.py @ONLY) @@ -46,7 +63,7 @@ add_custom_command( COMMAND ${SPHINX_EXECUTABLE} -b html -Dbreathe_projects.remage=${DOXYGEN_OUTPUT_DIR}/xml ${SPHINX_SOURCE} ${SPHINX_BUILD} WORKING_DIRECTORY ${SPHINX_SOURCE} - DEPENDS ${SPHINX_SOURCES} ${DOXYGEN_INDEX_FILE} + DEPENDS ${SPHINX_SOURCES} ${SPHINX_IMAGES} ${DOXYGEN_INDEX_FILE} MAIN_DEPENDENCY ${SPHINX_SOURCE}/conf.py ${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in COMMENT "Generating Sphinx docs") diff --git a/docs/conf.py.in b/docs/conf.py.in index fa150f3..c5338d8 100644 --- a/docs/conf.py.in +++ b/docs/conf.py.in @@ -20,6 +20,7 @@ extensions = [ "sphinx.ext.intersphinx", "sphinx.ext.graphviz", "sphinx_copybutton", + "sphinx_togglebutton", "sphinx_inline_tabs", "exhale", "breathe", @@ -38,6 +39,8 @@ exhale_args = { breathe_projects = {} +myst_enable_extensions = ["colon_fence"] + if on_rtd: # assume build has been prepared in .readthedocs.yml breathe_projects["remage"] = "_doxygen/xml" diff --git a/docs/developer.rst b/docs/developer.rst index 5417ba2..cfba3ec 100644 --- a/docs/developer.rst +++ b/docs/developer.rst @@ -96,6 +96,18 @@ following: other) must be provided as separate pages in ``docs/`` and linked in the table of contents. +To generate documentation locally, run + +.. code-block:: console + + $ cd remage/build/ + $ cmake .. -DRMG_BUILD_DOCS=ON + $ make sphinx + +You'll need a Doxygen installation and Python software dependencies specified +in ``docs/environment.yml``. The generated documentation can be viewed by +pointing your browser to ``docs/_build/index.html``. + Writing documentation ^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/environment.yml b/docs/environment.yml index 892dcb4..c94317b 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -15,4 +15,5 @@ dependencies: - setuptools-scm - sphinx - sphinx-copybutton + - sphinx-togglebutton - sphinx-inline-tabs diff --git a/docs/img/hpge-edep.jpg b/docs/img/hpge-edep.jpg new file mode 100644 index 0000000..e78cb54 Binary files /dev/null and b/docs/img/hpge-edep.jpg differ diff --git a/docs/img/hpge-hits.jpg b/docs/img/hpge-hits.jpg new file mode 100644 index 0000000..1b98521 Binary files /dev/null and b/docs/img/hpge-hits.jpg differ diff --git a/docs/img/tutorial-g4-view.jpg b/docs/img/tutorial-g4-view.jpg new file mode 100644 index 0000000..d13917f Binary files /dev/null and b/docs/img/tutorial-g4-view.jpg differ diff --git a/docs/img/tutorial-pyg4-view.jpg b/docs/img/tutorial-pyg4-view.jpg new file mode 100644 index 0000000..8f43a70 Binary files /dev/null and b/docs/img/tutorial-pyg4-view.jpg differ diff --git a/docs/index.rst b/docs/index.rst index d4c9500..81e51b7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,55 +3,14 @@ remage |remage| is a modern C++ simulation framework for germanium experiments. -Pre-built binaries ------------------- - -The recommended and fastest way of running |remage| is through pre-built -software containers. Stable releases are regularly made available `on Docker -Hub `_. To obtain and -run the latest just do: - -.. code-block:: console - - $ docker run gipert/remage --help # just prints a help message - -If you prefer `Apptainer `_, you can easily generate an image locally: - -.. code-block:: console - - $ apptainer build remage_latest.sif docker://gipert/remage:latest - $ apptainer run remage_latest.sif --help - -If containers do not work for you, see the next section to learn how to build -and install from source. - -Building from source --------------------- - -In preparation for the actual build, users are required to obtain some -dependencies. - -.. include:: _dependencies.rst - -Building -^^^^^^^^ - -The build system is based on CMake: - -.. code-block:: console - - $ git clone https://github.com/legend-exp/remage - $ cd remage - $ mkdir build && cd build - $ cmake -DCMAKE_INSTALL_PREFIX= .. - $ make install - Quick start ----------- +The installation process is documented in :doc:`install`. + .. warning:: A proper user guide is not available yet. In the meanwhile, users can have a - look at the `examples + look at the :doc:`tutorial` or the provided `examples `_. In the simplest application, the user can simulate in an existing GDML geometry @@ -98,6 +57,8 @@ Next steps .. toctree:: :maxdepth: 2 + install + tutorial Geant4 command interface Output structure & LH5 output diff --git a/docs/install.rst b/docs/install.rst new file mode 100644 index 0000000..da20e23 --- /dev/null +++ b/docs/install.rst @@ -0,0 +1,47 @@ +Installation +============ + +Pre-built binaries +------------------ + +The recommended and fastest way of running |remage| is through pre-built +software containers. Stable releases are regularly made available `on Docker +Hub `_. To obtain and +run the latest just do: + +.. code-block:: console + + $ docker run legendexp/remage:latest --help # just prints a help message + +If you prefer `Apptainer `_, you can easily generate an image locally: + +.. code-block:: console + + $ apptainer build remage_latest.sif docker://legendexp/remage:latest + $ apptainer run remage_latest.sif --help + +If containers do not work for you, see the next section to learn how to build +and install from source. + +Building from source +-------------------- + +In preparation for the actual build, users are required to obtain some +dependencies. + +.. include:: _dependencies.rst + +Building +^^^^^^^^ + +The build system is based on CMake: + +.. code-block:: console + + $ git clone https://github.com/legend-exp/remage + $ cd remage + $ mkdir build && cd build + $ cmake -DCMAKE_INSTALL_PREFIX= .. + $ make install + +.. |remage| replace:: *remage* diff --git a/docs/tutorial.md b/docs/tutorial.md new file mode 100644 index 0000000..cb3783d --- /dev/null +++ b/docs/tutorial.md @@ -0,0 +1,430 @@ +# Basic Tutorial + +In this tutorial we are going to demonstrate the basic functionality of +*remage* by simulating a series of particle physics processes in a simple setup. + +## Experimental geometry + +We need to develop a geometry, and we will be using the +[pyg4ometry](https://pyg4ometry.readthedocs.io) library for this purpose. This +library is well-suited for creating geometries that are compatible with the +Geant4 framework, as it closely mirrors the Geant4 interface, making it easy +for those familiar with Geant4 to use. Importantly, pyg4ometry is independent +of Geant4 itself, meaning it doesn't require Geant4 as a dependency. +Additionally, it offers the flexibility to export the developed geometry in +GDML format, which is widely compatible for simulations and analyses in +high-energy physics applications. + +The geometry consist in two high-purity germanium detectors (HPGes) immersed in +a liquid argon balloon. The +[legend-pygeom-hpges](https://legend-pygeom-hpges.readthedocs.io) package will +help us creating the HPGe volumes. Let's start by importing the Python +packages, declaring a geometry registry and specifying the dimensions and types +of the two detectors as dictionaries: + +```python +import legendhpges as hpges +import pyg4ometry as pg4 +from numpy import pi + + +reg = pg4.geant4.Registry() + +bege_meta = { + "name": "B00000B", + "type": "bege", + "production": { + "enrichment": {"val": 0.874, "unc": 0.003}, + "mass_in_g": 697.0, + }, + "geometry": { + "height_in_mm": 29.46, + "radius_in_mm": 36.98, + "groove": {"depth_in_mm": 2.0, "radius_in_mm": {"outer": 10.5, "inner": 7.5}}, + "pp_contact": {"radius_in_mm": 7.5, "depth_in_mm": 0}, + "taper": { + "top": {"angle_in_deg": 0.0, "height_in_mm": 0.0}, + "bottom": {"angle_in_deg": 0.0, "height_in_mm": 0.0}, + }, + }, +} + +coax_meta = { + "name": "C000RG1", + "type": "coax", + "production": { + "enrichment": {"val": 0.855, "unc": 0.015}, + }, + "geometry": { + "height_in_mm": 84, + "radius_in_mm": 38.25, + "borehole": {"radius_in_mm": 6.75, "depth_in_mm": 73}, + "groove": {"depth_in_mm": 2, "radius_in_mm": {"outer": 20, "inner": 17}}, + "pp_contact": {"radius_in_mm": 17, "depth_in_mm": 0}, + "taper": { + "top": {"angle_in_deg": 45, "height_in_mm": 5}, + "bottom": {"angle_in_deg": 45, "height_in_mm": 2}, + "borehole": {"angle_in_deg": 0, "height_in_mm": 0}, + }, + } +} +``` + +Now we can build all the logical volumes and place them in the world volume: + +```python +# create logical volumes for the two HPGe detectors +bege_l = hpges.make_hpge(bege_meta, name="BEGe_L", registry=reg) +coax_l = hpges.make_hpge(coax_meta, name="Coax_L", registry=reg) + +# create a world volume +world_s = pg4.geant4.solid.Orb("World_s", 20, registry=reg, lunit="cm") +world_l = pg4.geant4.LogicalVolume(world_s, "G4_Galactic", "World", registry=reg) +reg.setWorld(world_l) + +# let's make a liquid argon balloon +lar_s = pg4.geant4.solid.Orb("LAr_s", 15, registry=reg, lunit="cm") +lar_l = pg4.geant4.LogicalVolume(lar_s, "G4_lAr", "LAr_l", registry=reg) +pg4.geant4.PhysicalVolume([0, 0, 0], [0, 0, 0], lar_l, "LAr", world_l, registry=reg) + +# now place the two HPGe detectors in the argon +pg4.geant4.PhysicalVolume([0, 0, 0], [5, 0, -3, "cm"], bege_l, "BEGe", lar_l, registry=reg) +pg4.geant4.PhysicalVolume([0, 0, 0], [-5, 0, -3, "cm"], coax_l, "Coax", lar_l, registry=reg) + +# finally create a small radioactive source +source_s = pg4.geant4.solid.Tubs("Source_s", 0, 1, 1, 0, 2*pi, registry=reg) +source_l = pg4.geant4.LogicalVolume(source_s, "G4_BRAIN_ICRP", "Source_L", registry=reg) +pg4.geant4.PhysicalVolume([0, 0, 0], [0, 5, 0, "cm"], source_l, "Source", lar_l, registry=reg) +``` + +Note how we also created a small cylinder to represent a radioactive source +later in the simulation. + +Now we can quickly visualize the result, still with *pyg4ometry*: + +```python +# start an interactive VTK viewer instance +viewer = pg4.visualisation.VtkViewerColoured(materialVisOptions={"G4_lAr": [0, 0, 1, 0.1]}) +viewer.addLogicalVolume(reg.getWorldVolume()) +viewer.view() +``` + +![Geometry visualization](img/tutorial-pyg4-view.jpg) + +## Visualizing a simple simulation + +By following instructions in the [installation](./install.rst) section, you should +have access to the `remage` executable. We are now ready to simulate some +particle physics with it. + +Like any other Geant4-based application, we need to configure the simulation +with a macro file. Standard Geant4 commands as well as custom commands (see the +[command interface](<./rmg-commands.rst>)) are available. + +At the beginning of the file, we can set some global application options, like +the verbosity. Let's increase it a bit (compared to the default `summary`) to +be more informed on what's going on by *remage*: + +```text +/RMG/Manager/Logging/LogLevel detail +``` + +Then we have to register the "sensitive detectors" (in our simple case, the two +HPGes and the LAr). *remage* offers several types of predefined detectors, +targeting different physical quantities of the particles that interact with +them. HPGes are of type `Germanium`, while the LAr is of type `Scintillator`. +Their difference in terms of simulation output will be clear later, while +inspecting it. As per specification of the `/RMG/Geometry/RegisterDetector` +command, we need to provide a unique numeric identifier that will be used to +label the detector data in the simulation output: + +```text +/RMG/Geometry/RegisterDetector Germanium BEGe 001 +/RMG/Geometry/RegisterDetector Germanium Coax 002 +/RMG/Geometry/RegisterDetector Scintillator LAr 003 +``` + +Now we can initialize the simulation. Additionally, let's setup some Geant4 +visualization to look at the tracks: + +```text +/run/initialize + +# create a scene +/vis/open OI +/vis/scene/create +/vis/sceneHandler/attach + +# draw the geometry +/vis/drawVolume + +# setup better colors +/vis/viewer/set/defaultColour black +/vis/viewer/set/background white + +# and also show trajectories and particle hits +/vis/scene/add/trajectories smooth +/vis/scene/add/hits +/vis/scene/endOfEventAction accumulate +``` + +Now with the actual physics. We want to start ten 1 MeV gammas from the +radioactive source: + +```text +/RMG/Generator/Confine Volume +/RMG/Generator/Confinement/Physical/AddVolume Source + +/RMG/Generator/Select GPS +/gps/particle gamma +/gps/ang/type iso +/gps/energy 1000 keV + +/run/beamOn 50 +``` + +:::{admonition} Complete macro file (`vis-gammas.mac`) +:class: dropdown + +```text +/RMG/Manager/Logging/LogLevel detail + +/RMG/Geometry/RegisterDetector Germanium BEGe 001 +/RMG/Geometry/RegisterDetector Germanium Coax 002 +/RMG/Geometry/RegisterDetector Scintillator LAr 003 + +/run/initialize + +/vis/open OI +/vis/scene/create +/vis/sceneHandler/attach + +/vis/drawVolume + +/vis/viewer/set/defaultColour black +/vis/viewer/set/background white + +/vis/scene/add/trajectories smooth +/vis/scene/add/hits +/vis/scene/endOfEventAction accumulate + +/RMG/Generator/Confine Volume +/RMG/Generator/Confinement/Physical/AddVolume Source + +/RMG/Generator/Select GPS +/gps/particle gamma +/gps/ang/type iso +/gps/energy 1000 keV + +/run/beamOn 10 +``` +::: + +We can finally pass the GDML geometry and the macro to the `remage` executable +and look at the result! + +```console +$ remage --interactive --gdml-files geometry.gdml -- vis-gammas.mac + _ __ ___ _ __ ___ __ _ __ _ ___ + | '__/ _ \ '_ ` _ \ / _` |/ _` |/ _ \ + | | | __/ | | | | | (_| | (_| | __/ + |_| \___|_| |_| |_|\__,_|\__, |\___| v0.1.0 + |___/ + +[Summary -> Realm set to DoubleBetaDecay +[Summary -> CLHEP::HepRandom seed set to: 647993209 +[Summary -> Loading macro file: vis-gammas.mac +... +``` + +:::{note} +Interactive visualization requires passing `--interactive` to the `remage` executable. +::: + +Interactions in HPGes and in LAr are marked in red and blue, respectively. + +![Simulation visualization](img/tutorial-g4-view.jpg) + +:::{tip} +With Apptainer, additional tweaks are required in order to allow for graphics to be displayed, e.g. +```console +$ apptainer run \ + --env DISPLAY=$DISPLAY \ + --env XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \ + --env XAUTHORITY=$XAUTHORITY \ + -B $XDG_RUNTIME_DIR \ + path/to/remage_latest.sif --interactive [...] +``` +and similarly with Docker. +::: + +:::{tip} +If `remage` from the Apptainer image refuses to run simulations, this might be +due to some of your environment variables from outside the container. Give +`--cleanenv` a try. +::: + +## Storing simulated data on disk + +Let's now simulate more events in batch mode and store Geant4 step information +in an output file. Using the same macro as before, without the visualization +commands: + +```text +/RMG/Manager/Logging/LogLevel detail + +/RMG/Geometry/RegisterDetector Germanium BEGe 001 +/RMG/Geometry/RegisterDetector Germanium Coax 002 +/RMG/Geometry/RegisterDetector Scintillator LAr 003 + +/run/initialize + +/RMG/Generator/Confine Volume +/RMG/Generator/Confinement/Physical/AddVolume Source + +/RMG/Generator/Select GPS +/gps/particle gamma +/gps/ang/type iso +/gps/energy 1000 keV + +/run/beamOn 100000 +``` + +We will simulate 10^5 events. Profiting from Geant4's multithreading +capabilities, we can speed up the simulation but running it on several threads +in parallel. The number of threads is specified with the `--threads` command +line option. + +Now we only need to tell `remage` which file name to use for the output. +`remage` supports multiple file formats, including [LEGEND's +HDF5](https://legend-exp.github.io/legend-data-format-specs). We are going to +select the latter by supplying a file name with `.lh5` extension: + +```console +$ remage --threads 8 --gdml-files geometry.gdml --output output.lh5 -- gammas.mac +``` + +Geant4 does not support merging LH5 files created by different threads, so +we're left with 8 output files: `output_t0.lh5 ... output_t7.lh5`. This seems a +bit annoying, but it's easy to chain them when reading data into memory. + +We'll use the [legend-pydataobj](https://legend-pydataobj.readthedocs.io) +Python package to read the data from disk. Let's first have a look at the +data layout with the `lh5ls` utility: + +```console +$ lh5ls output_t0.lh5 +/ +└── hit · HDF5 group + ├── det001 · table{evtid,particle,edep,time,xloc,yloc,zloc} + │ ├── edep · array<1>{real} ── {'units': 'keV'} + │ ├── evtid · array<1>{real} + │ ├── particle · array<1>{real} + │ ├── time · array<1>{real} ── {'units': 'ns'} + │ ├── xloc · array<1>{real} ── {'units': 'm'} + │ ├── yloc · array<1>{real} ── {'units': 'm'} + │ └── zloc · array<1>{real} ── {'units': 'm'} + ├── det002 · table{evtid,particle,edep,time,xloc,yloc,zloc} + │ ├── edep · array<1>{real} ── {'units': 'keV'} + │ ├── evtid · array<1>{real} + │ ├── particle · array<1>{real} + │ ├── time · array<1>{real} ── {'units': 'ns'} + │ ├── xloc · array<1>{real} ── {'units': 'm'} + │ ├── yloc · array<1>{real} ── {'units': 'm'} + │ └── zloc · array<1>{real} ── {'units': 'm'} + ├── det003 · table{evtid,particle,edep,time,xloc_pre,yloc_pre,zloc_pre,xloc_post,yloc_post,zloc_post,v_pre,v_post} + │ ├── edep · array<1>{real} ── {'units': 'keV'} + │ ├── evtid · array<1>{real} + │ ├── particle · array<1>{real} + │ ├── time · array<1>{real} ── {'units': 'ns'} + │ ├── v_post · array<1>{real} ── {'units': 'm/ns'} + │ ├── v_pre · array<1>{real} ── {'units': 'm/ns'} + │ ├── xloc_post · array<1>{real} ── {'units': 'm'} + │ ├── xloc_pre · array<1>{real} ── {'units': 'm'} + │ ├── yloc_post · array<1>{real} ── {'units': 'm'} + │ ├── yloc_pre · array<1>{real} ── {'units': 'm'} + │ ├── zloc_post · array<1>{real} ── {'units': 'm'} + │ └── zloc_pre · array<1>{real} ── {'units': 'm'} + └── vertices · table{evtid,time,xloc,yloc,zloc,n_part} + ├── evtid · array<1>{real} + ├── n_part · array<1>{real} + ├── time · array<1>{real} ── {'units': 'ns'} + ├── xloc · array<1>{real} ── {'units': 'm'} + ├── yloc · array<1>{real} ── {'units': 'm'} + └── zloc · array<1>{real} ── {'units': 'm'} +``` + +The step information is organized into data tables, one per sensitive detector. +The table format is specified by the detector type (`Germanium` or +`Scintillator`). Event vertex information is stored in a separate table, +`vertices`. Note the physical units specified as attributes, as per LH5 +specification. + +Let's make an histogram of the total energy deposited in the HPGe detectors in +each event. Check out the [legend-pydataobj +documentation](https://legend-pydataobj.readthedocs.io) for more details. + +```python +from lgdo import lh5 +import awkward as ak +import glob +import hist +import matplotlib.pyplot as plt + +plt.rcParams["figure.figsize"] = (10, 3) + +def plot_edep(detid): + # read the data from detector "detid". pass all 8 files to concatenate them + # in addition, view it as and Awkward Array + data = lh5.read_as(f"hit/{detid}", glob.glob("output_t*.lh5"), "ak") + + # with awkward arrays, we can easily "build events" by grouping by the event identifier + evt = ak.unflatten(data, ak.run_lengths(data.evtid)) + + # make and plot an histogram + hist.new.Reg(551, 0, 1005, name="energy [keV]").Double().fill(ak.sum(evt.edep, axis=-1)).plot(yerr=False, label=detid) + +plot_edep("det001") +plot_edep("det002") +plt.ylabel("counts / 5 keV") +plt.yscale("log") +plt.legend() +``` + +![plot](./img/hpge-edep.jpg) + +The expected spectrum, composed by full-energy peak at 1 MeV and Compton +shoulder. We can also plot the interaction points: + +```python +def plot_hits(detid): + data = lh5.read_as(f"hit/{detid}", glob.glob("output_t*.lh5"), "ak")[:20_000] + plt.scatter(data.xloc, data.yloc, marker="o", s=1, label=detid) + +plot_hits("det001") +plot_hits("det002") +plt.xlabel("[mm]") +plt.ylabel("[mm]") +plt.legend() +plt.axis("equal") +``` + +![plot](./img/hpge-hits.jpg) + +## Advanced usage + +*remage* can do much more than this! While we prepare more documentation, be +aware that a lot of the simulation and the output can be customized: + +- commands below `/RMG/Output` are available to filter steps, isotopes, store + all steps in a single table etc. +- physics list settings can be adjusted +- the randomization can be controlled +- advanced vertex confinement modes are implemented +- many interesting event generators, related to germanium detector experiments + are available +- vertex coordinates can be read from an input file +- the simulation of optical physics can be optimized + +Have a look at the [API reference](./api/index.rst) and the [macro command +reference](./rmg-commands.rst). diff --git a/src/RMGScintillatorDetector.cc b/src/RMGScintillatorDetector.cc index 2485520..a857fe0 100644 --- a/src/RMGScintillatorDetector.cc +++ b/src/RMGScintillatorDetector.cc @@ -52,7 +52,7 @@ void RMGScintillatorDetectorHit::Draw() { G4Circle circle(this->global_position_pre); circle.SetScreenSize(5); circle.SetFillStyle(G4Circle::filled); - circle.SetVisAttributes(G4VisAttributes(G4Colour(1, 0, 0))); + circle.SetVisAttributes(G4VisAttributes(G4Colour(0, 0, 1))); vis_man->Draw(circle); } }