Skip to content

Commit 2a75aa6

Browse files
authored
Merge pull request #470 from benedikt-nagler/main
Geant4 tutorial page: reformatting, error fixing
2 parents 854342a + 2ab6e84 commit 2a75aa6

File tree

2 files changed

+20
-22
lines changed

2 files changed

+20
-22
lines changed

docs/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Geant4 = "559df036-b7a0-42fd-85df-7d5dd9d70f44"
44
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
55
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
66
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
7+
SolidStateDetectors = "71e43887-2bd9-5f77-aebd-47f656f0a3f0"
78
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
89
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
910

docs/src/tutorials/geant4_ssd_lit.jl

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
# # Geant4 Support
22

33
# SolidStateDetectors.jl provides an extension for Geant4.jl.
4-
# This extension allows to simulate realistic event distributions resulting from particles emitted by a given source, which can be used as input to the waveform simulation.
4+
# The extension allows users to generate realistic event distributions resulting from particles emitted by a specified source, which could then in turn also be used as input for a waveform simulation.
55
#
66
# To use the extension, both `SolidStateDetectors` and `Geant4` have to be loaded.
77

88
using SolidStateDetectors
99
using Geant4
1010

11-
# In order to run `Geant4` simulations, a `Geant4.G4JLApplication` needs to be defined based on the detector geometry and the particle source.
12-
# The extension features a function that creates a `Geant4.G4JLApplcation` from an SSD `Simulation` object and a particle source.
11+
# In order to run Geant4 simulations, a `Geant4.G4JLApplication` needs to be defined, which needs to include both the detector geometry and the particle source.
12+
# The extension features a function that creates a `Geant4.G4JLApplcation` object from a SSD `Simulation` object and a particle source.
1313

1414
using Plots
1515
using Unitful
@@ -18,7 +18,7 @@ using Unitful
1818
#
1919
# #### 1. `MonoenergeticSource`
2020
#
21-
# This source emits particles of the same type and same energy.
21+
# This source emits particles with a fixed type and energy.
2222

2323
source_1 = MonoenergeticSource(
2424
"gamma", # Type of particle beam
@@ -29,11 +29,10 @@ source_1 = MonoenergeticSource(
2929
)
3030

3131
# - The particle type is given as a string (e.g. `"e-"` or `"gamma"`) and directly passed to `Geant4`. See the `Geant4` documentation on how to name the desired particle type.
32-
# - The energy of the emitted particles is passed as a number with unit.
32+
# - The energy of the emitted particles is passed as a number with the required unit.
3333
# - The `position` of the particle source relative to the origin is defined by a `CartesianPoint` (in units of `m`).
34-
# - The source can emit particles in a given `direction` if a `CartesianVector` is provided.
35-
# If not, the emission is isotropic.
36-
# - If an `opening_angle` is provided, the source emits via a directed cone with the defined opening angle.
34+
# - The source emits particles in a given `direction`, specified by a `CartesianVector` object. If the user provides no direction, the emission will be isotropic.
35+
# - If an `opening_angle` is provided, the particles are emitted in a directed cone with the specified opening angle.
3736

3837
# #### 2. `IsotopeSource`
3938
#
@@ -50,7 +49,7 @@ source_2 = IsotopeSource(
5049
)
5150

5251
# The source is defined using
53-
# - The number of protons `Z` and the number of nucleons `A` in the isotope. <br/>
52+
# - The number of protons `Z` and the number of nucleons `A` in the isotope.
5453
# - The excitation energy
5554
# - The charge of the isotope
5655
# - The position, direction and opening angle from the source can be defined in the same way as for a `MonoenergeticSource`
@@ -69,13 +68,12 @@ plot!(source_1)
6968

7069
# A `Geant4.G4JLApplication` is built from a SSD `Simulation` `sim` and one of the previously defined particle sources, e.g. `source_1`.
7170
#
72-
# Internally, a GDML file is created that is subsequently read in by `Geant4.jl`. <br/>
73-
# If needed, the resulting GDML file can also be saved by using the `Geant4.G4JLDetector(sim, "output_filename.gdml")` command.
71+
# Internally, the translated geometry description is written to a temporary GDML file. This file will in turn be read in by `Geant4.jl` and deleted afterwards. However, if needed, the resulting GDML file can also be saved by using the `Geant4.G4JLDetector(sim, "output_filename.gdml", save_gdml = true)` function.
7472

7573
app = G4JLApplication(sim, source_1, verbose = false);
7674

7775

78-
# The method `run_geant4_simulation` is used to generate a given number of events.
76+
# Having defined a `G4JLApplication`, it is now possible to generate events using the `run_geant4_simulation` function. The function will continue running until the desired number of energy depositions have been recorded.
7977

8078
N_events = 50000
8179
events = run_geant4_simulation(app, N_events)
@@ -87,7 +85,7 @@ events = run_geant4_simulation(app, N_events)
8785
# - `edep`: Amount of energy that was deposited in the detector
8886
# - `pos`: Position where the interaction happened
8987

90-
# By extracting the position of each energy deposition from `events`, the spatial distribution of the events inside the detector can be plotted:
88+
# By extracting the position of each energy deposition from `events`, the spatial distribution of the events inside the detector can be visualized:
9189

9290
plot(sim.detector, show_passives = false, size = (500,500), fmt = :png)
9391
plot!(source_1)
@@ -99,19 +97,19 @@ plot!(CartesianPoint.(broadcast(p -> ustrip.(u"m", p), events[1:1000].pos.data))
9997

10098
# The output of `run_geant4_simulation` can be stored using the `LegendHDF5IO` package:
10199

102-
# ```
100+
# ```Julia
103101
# using LegendHDF5IO
104-
#
102+
#
105103
# lh5open("simulation_output.lh5", "w") do h
106-
# LegendHDF5IO.writedata(h.data_store, "SimulationData", events)
104+
# LegendHDF5IO.writedata(h.data_store, "SimulationData", events)
107105
# end
108-
#
106+
109107
# events_in = lh5open("simulation_output.lh5", "r") do h
110108
# LegendHDF5IO.readdata(h.data_store, "SimulationData")
111109
# end
112110
# ```
113111

114-
# In order to visualize the energy spectrum of the events in a histogram, you can use the following code:
112+
# In order to visualize the energy spectrum of the events in a histogram, the following code can be used:
115113

116114
using StatsBase
117115

@@ -125,16 +123,16 @@ xlims!(0,3000, xlabel = "E in keV", ylabel = "counts")
125123
#md # [![spectrum](spectrum.svg)](spectrum.pdf)
126124

127125

128-
# Now that the energy depositions in the detector are simulated, they can be passed to SSD to calculate the corresponding waveforms.
129-
# This requires to calculate the electric potential, the electric field and the weighting potential of the detector first.
126+
# Now that a realistic event distribution has been generated, it can be used as input for the waveform simulation.
127+
# To perform the waveform simulation, the detectors electric field and weighting potential have to be calculated first.
130128

131129
sim.detector = SolidStateDetector(sim.detector, ADLChargeDriftModel(T=T))
132130
calculate_electric_potential!(sim, refinement_limits = [0.4,0.2,0.1,0.06], verbose = false)
133131
calculate_electric_field!(sim, n_points_in_φ = 10)
134132
calculate_weighting_potential!(sim, 1, refinement_limits = [0.4,0.2,0.1,0.06], verbose = false)
135133

136134

137-
# The waveforms can be simulated using `simulate_waveforms`:
135+
# The previously generated events from the Geant4 simulation can now be used as input for the `simulate_waveforms` function:
138136

139137
wf = simulate_waveforms(events[1:100], sim, Δt = 1u"ns", max_nsteps = 2000)
140138
plot(wf[1:20].waveform, label = "")
@@ -145,7 +143,6 @@ plot(wf[1:20].waveform, label = "")
145143

146144

147145

148-
149146
# We can add some baseline and tail to the pulses to match their lengths (in this case to 2000ns):
150147

151148
w = add_baseline_and_extend_tail.(wf.waveform, 100, 2000)

0 commit comments

Comments
 (0)