Skip to content

Commit 84d12da

Browse files
authored
Merge branch 'main' into julia-1.11
2 parents b51b46c + d725f97 commit 84d12da

File tree

57 files changed

+1184
-206
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1184
-206
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ jobs:
8989
- uses: actions/checkout@v4
9090
- uses: julia-actions/setup-julia@v2
9191
with:
92-
version: '1'
92+
version: '1.10'
9393
- uses: julia-actions/cache@v2
9494
- uses: julia-actions/julia-buildpkg@v1
9595
env:

Project.toml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
name = "SolidStateDetectors"
22
uuid = "71e43887-2bd9-5f77-aebd-47f656f0a3f0"
3-
version = "0.10.8"
3+
version = "0.10.16"
44

55
[deps]
66
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
77
ArraysOfArrays = "65a8f2f4-9b39-5baf-92e2-a9cc46fdf018"
88
Clustering = "aaaa29a8-35af-508c-8bc3-b662a17a0fe5"
9+
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
910
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
1011
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
1112
Format = "1fa38f19-a742-5d3f-a2b9-30dd87b9d5f8"
@@ -48,12 +49,13 @@ SolidStateDetectorsGeant4Ext = "Geant4"
4849
Adapt = "3, 4"
4950
ArraysOfArrays = "0.5, 0.6"
5051
Clustering = "0.15"
51-
Distributions = "0.25.49"
52+
DataStructures = "0.17, 0.18"
53+
Distributions = "0.24.5, 0.25"
5254
FillArrays = "0.13.8, 1"
5355
Format = "1.2"
5456
GPUArrays = "8, 9, 10, 11"
5557
Geant4 = "0.1.13, 0.2"
56-
Interpolations = "0.14, 0.15"
58+
Interpolations = "0.14, 0.15, 0.16"
5759
IntervalSets = "0.6, 0.7"
5860
JSON = "0.21.2"
5961
KernelAbstractions = "0.8, 0.9"
@@ -63,7 +65,7 @@ LinearAlgebra = "<0.0.1, 1"
6365
OrderedCollections = "1.1"
6466
ParallelProcessingTools = "0.4"
6567
Parameters = "0.12"
66-
PolygonOps = "0.1"
68+
PolygonOps = "0.1.1"
6769
Polynomials = "2, 3, 4"
6870
ProgressMeter = "1.5"
6971
RadiationDetectorSignals = "0.3.5"

docs/Project.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ 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

1011
[compat]
11-
Documenter = "0.27"
12+
Documenter = "1"

docs/make.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,11 @@ makedocs(
5252
"API" => "api.md",
5353
"LICENSE" => "LICENSE.md",
5454
],
55-
doctest = ("fixdoctests" in ARGS) ? :fix : true,
56-
format = Documenter.HTML(canonical = "https://JuliaPhysics.github.io/SolidStateDetectors.jl/stable/", prettyurls = !("local" in ARGS)),
55+
doctest = ("fixdoctests" in ARGS) ? :fix : true,
56+
format = Documenter.HTML(canonical = "https://JuliaPhysics.github.io/SolidStateDetectors.jl/stable/",
57+
prettyurls = !("local" in ARGS), size_threshold = nothing, size_threshold_warn = nothing, example_size_threshold = nothing),
5758
linkcheck = ("linkcheck" in ARGS),
58-
strict = !("local" in ARGS),
59+
warnonly = ("nonstrict" in ARGS),
5960
)
6061

6162
deploydocs(

docs/src/man/IO.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,4 @@ The data stored in the HDF5 file can be read using [`ssd_read`](@ref):
4747
using SolidStateDetectors
4848
using LegendHDF5IO
4949
ssd_read("<name-of-simulation-file>.h5", Simulation)
50-
```
51-
52-
!!! note
53-
`LegendHDF5IO` must be loaded **after** loading `SolidStateDetectors`!
50+
```

docs/src/man/csg.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,22 @@ cone = CSG.Geometry(T, cfn)
7373
plot(cone)
7474
````
7575

76+
#### Polycone
77+
78+
79+
````@example primitives
80+
cfn = joinpath(path_to_example_primitives_config_files, "Polycone.yaml")
81+
print(open(f -> read(f, String), cfn))
82+
````
83+
84+
Load the primitive from the configuration file via `CSG.Geometry`
85+
86+
````@example primitives
87+
polycone = CSG.Geometry(T, cfn)
88+
plot(polycone)
89+
````
90+
91+
7692
### Ellipsoid
7793
#### Sphere
7894

docs/src/man/electric_potential.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,47 @@ impurity_density:
105105
Here, the impurity density at the origin is $10^{10}$cm$^{-3}$ and it increases radially with the gradient $10^{10}$cm$^{-4}$.
106106
If no units are given, `init` is parsed in units of `units.length`$^{-3}$ and `gradient` in units of `units.length`$^{-4}$.
107107

108+
### Boule Impurity Densities
109+
110+
Boule impurity densities are meant to be used when the impurity density is defined in the boule coordinates, where the z-axis is aligned with the boule growth direction.
111+
Different models are provided. In each the field `det_z0` is the z-coordinate of the detector origin in boule coordinates.
112+
The z-direction of the detector is opposite to the z-direction of the boule coordinates.
113+
In this matter the detector impurities are automatically determined from those of the boule, depending on `det_z0`.
114+
```yaml
115+
impurity_density:
116+
name: linear_exponential_boule
117+
a: -1e10cm^-3
118+
b: -1e9cm^-4
119+
n: -2e9cm^-3
120+
l: 5cm
121+
m: 3cm
122+
det_z0: 120cm
123+
```
124+
In this example, the impurity density is modeled along the boule as a linear plus an exponential term: $a + b*z + n*e^{(z - l)/m}$ with $z$ in boule coordinates.
125+
The impurity density of the detector will in turn be modeled by: $a + b*(z_0 - z) + n*e^{(z_0 - z - l)/m}$ with $z$ in detector coordinates.
126+
If no units are given, `a` and `n` are parsed in units of `units.length`$^{-3}$, `b` in units of `units.length`$^{-4}$ and `l`, `m` and `det_z0` in units of `units.length`.
127+
128+
### Correcting Impurity Densities
129+
130+
When simulating real detectors, the simulated depletion voltage often differs from the measured value. This discrepancy arises primarily from the high uncertainty in impurity density measurements. A straightforward approach to improve the agreement is to apply a scaling factor and an offset to the impurity density.
131+
The scaling factor accounts for potential systematic errors in impurity density measurements.
132+
The offset is motivated by the thermal release of impurities from deep hole traps, which leads to a shift in the effective impurity density throughout the detector after biasing. In steady-state operation, this effect can be approximated as a uniform offset
133+
These terms can be added to the configuration file under `corrections`.
134+
```yaml
135+
impurity_density:
136+
name: linear_exponential_boule
137+
a: -1e10cm^-3
138+
b: -1e9cm^-4
139+
n: -2e9cm^-3
140+
l: 5cm
141+
m: 3cm
142+
det_z0: 120cm
143+
corrections:
144+
scale: 0.9
145+
offset: -1e9cm^-3
146+
```
147+
If no units are given, `offset` is parsed in units of `units.length`$^{-3}$.
148+
Corrections can be applied to any impurity density model. Given an originally calculated impurity density $\rho$, the corrected impurity density used in the simulation is $f*\rho+t$ where $f$ and $t$ are the scale and offset respectively.
108149

109150
### Custom Impurity Density
110151

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)

examples/example_config_files/ivc_splitted_config/detector_geometry.yaml

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,7 @@
11
geometry:
2-
difference:
3-
- tube:
4-
r: 35
5-
h: 80
6-
origin:
7-
z: 40
8-
- cone:
9-
r:
10-
bottom:
11-
from: 35
12-
to: 36
13-
top:
14-
from: 23.71
15-
to: 36
16-
h: 64
17-
origin:
18-
z: 52
19-
- tube:
20-
r: 5
21-
h: 80
22-
origin:
23-
z: 65
2+
polycone:
3+
r: [0, 35, 35, 24.42, 5, 5, 0]
4+
z: [0, 0, 20, 80, 80, 25, 25]
245
contacts:
256
- material: HPGe
267
id: 1

examples/example_config_files/public_ivc_config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,4 @@ surroundings:
151151
- -0.05
152152
charge_density:
153153
name: constant
154-
value: 0 # Reasonable density: +2e-11 # => 2*10⁻¹1 C/m³
154+
value: 0C/m^3 # Reasonable density: +2e-11 # => 2*10⁻¹¹ C/m³

0 commit comments

Comments
 (0)